Merge branch 'master' into kimkulling/use_float_for_material_parameters_issue-4685
|
@ -6,6 +6,9 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
job:
|
job:
|
||||||
name: ${{ matrix.name }}-build-and-test
|
name: ${{ matrix.name }}-build-and-test
|
||||||
|
|
|
@ -6,6 +6,9 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
job1:
|
job1:
|
||||||
name: adress-sanitizer
|
name: adress-sanitizer
|
||||||
|
|
4
Build.md
|
@ -7,7 +7,7 @@ You can download and install assimp using the [vcpkg](https://github.com/Microso
|
||||||
cd vcpkg
|
cd vcpkg
|
||||||
./bootstrap-vcpkg.sh
|
./bootstrap-vcpkg.sh
|
||||||
./vcpkg integrate install
|
./vcpkg integrate install
|
||||||
vcpkg install assimp
|
./vcpkg install assimp
|
||||||
```
|
```
|
||||||
The assimp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
The assimp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ The cmake-build-environment provides options to configure the build. The followi
|
||||||
- **ASSIMP_BUILD_ZLIB (default OFF)**: Build our own zlib.
|
- **ASSIMP_BUILD_ZLIB (default OFF)**: Build our own zlib.
|
||||||
- **ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all exporter senabled.
|
- **ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all exporter senabled.
|
||||||
- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all importer senabled.
|
- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all importer senabled.
|
||||||
- **ASSIMP_BUILD_ASSIMP_TOOLS (default ON)**: If the supplementary tools for Assimp are built in addition to the library.
|
- **ASSIMP_BUILD_ASSIMP_TOOLS (default OFF)**: If the supplementary tools for Assimp are built in addition to the library.
|
||||||
- **ASSIMP_BUILD_SAMPLES (default OFF)**: If the official samples are built as well (needs Glut).
|
- **ASSIMP_BUILD_SAMPLES (default OFF)**: If the official samples are built as well (needs Glut).
|
||||||
- **ASSIMP_BUILD_TESTS (default ON)**: If the test suite for Assimp is built in addition to the library.
|
- **ASSIMP_BUILD_TESTS (default ON)**: If the test suite for Assimp is built in addition to the library.
|
||||||
- **ASSIMP_COVERALLS (default OFF)**: Enable this to measure test coverage.
|
- **ASSIMP_COVERALLS (default OFF)**: Enable this to measure test coverage.
|
||||||
|
|
|
@ -56,7 +56,7 @@ IF(ASSIMP_HUNTER_ENABLED)
|
||||||
add_definitions(-DASSIMP_USE_HUNTER)
|
add_definitions(-DASSIMP_USE_HUNTER)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
PROJECT(Assimp VERSION 5.2.4)
|
PROJECT(Assimp VERSION 5.2.5)
|
||||||
|
|
||||||
# All supported options ###############################################
|
# All supported options ###############################################
|
||||||
|
|
||||||
|
@ -393,6 +393,7 @@ if(${BUILD_SHARED_LIBS})
|
||||||
set(BUILD_LIB_TYPE SHARED)
|
set(BUILD_LIB_TYPE SHARED)
|
||||||
else()
|
else()
|
||||||
set(BUILD_LIB_TYPE STATIC)
|
set(BUILD_LIB_TYPE STATIC)
|
||||||
|
add_definitions(-DDDL_STATIC_LIBRARY=OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
IF( UNIX )
|
IF( UNIX )
|
||||||
|
@ -560,7 +561,11 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||||
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
|
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
|
||||||
|
|
||||||
# pick the correct prebuilt library
|
# pick the correct prebuilt library
|
||||||
IF(MSVC15)
|
IF(MSVC143)
|
||||||
|
SET(C4D_LIB_POSTFIX "_2022")
|
||||||
|
ELSEIF(MSV142)
|
||||||
|
SET(C4D_LIB_POSTFIX "_2019")
|
||||||
|
ELSEIF(MSVC15)
|
||||||
SET(C4D_LIB_POSTFIX "_2017")
|
SET(C4D_LIB_POSTFIX "_2017")
|
||||||
ELSEIF(MSVC14)
|
ELSEIF(MSVC14)
|
||||||
SET(C4D_LIB_POSTFIX "_2015")
|
SET(C4D_LIB_POSTFIX "_2015")
|
||||||
|
@ -572,7 +577,7 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||||
SET(C4D_LIB_POSTFIX "_2010")
|
SET(C4D_LIB_POSTFIX "_2010")
|
||||||
ELSE()
|
ELSE()
|
||||||
MESSAGE( FATAL_ERROR
|
MESSAGE( FATAL_ERROR
|
||||||
"C4D is currently only supported with MSVC 10, 11, 12, 14"
|
"C4D is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3"
|
||||||
)
|
)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
@ -804,6 +809,10 @@ if(WIN32)
|
||||||
SET(ASSIMP_MSVC_VERSION "vc140")
|
SET(ASSIMP_MSVC_VERSION "vc140")
|
||||||
ELSEIF(MSVC15)
|
ELSEIF(MSVC15)
|
||||||
SET(ASSIMP_MSVC_VERSION "vc141")
|
SET(ASSIMP_MSVC_VERSION "vc141")
|
||||||
|
ELSEIF(MSV142)
|
||||||
|
SET(ASSIMP_MSVC_VERSION "vc142")
|
||||||
|
ELSEIF(MSVC143)
|
||||||
|
SET(ASSIMP_MSVC_VERSION "vc143")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information
|
||||||
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
|
||||||
|
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
|
#include <assimp/ai_assert.h>
|
||||||
#include <assimp/Exporter.hpp>
|
#include <assimp/Exporter.hpp>
|
||||||
#include <assimp/IOStream.hpp>
|
#include <assimp/IOStream.hpp>
|
||||||
#include <assimp/IOSystem.hpp>
|
#include <assimp/IOSystem.hpp>
|
||||||
|
@ -23,16 +24,15 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information
|
||||||
|
|
||||||
#define CURRENT_FORMAT_VERSION 100
|
#define CURRENT_FORMAT_VERSION 100
|
||||||
|
|
||||||
// grab scoped_ptr from assimp to avoid a dependency on boost.
|
|
||||||
//#include <assimp/../../code/BoostWorkaround/boost/scoped_ptr.hpp>
|
|
||||||
|
|
||||||
#include "mesh_splitter.h"
|
#include "mesh_splitter.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "cencode.h"
|
# include "cencode.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
void ExportAssimp2Json(const char *, Assimp::IOSystem *, const aiScene *, const Assimp::ExportProperties *);
|
void ExportAssimp2Json(const char *, Assimp::IOSystem *, const aiScene *, const Assimp::ExportProperties *);
|
||||||
|
|
||||||
// small utility class to simplify serializing the aiScene to Json
|
// small utility class to simplify serializing the aiScene to Json
|
||||||
|
@ -179,7 +179,6 @@ private:
|
||||||
// escape backslashes and single quotes, both would render the JSON invalid if left as is
|
// escape backslashes and single quotes, both would render the JSON invalid if left as is
|
||||||
t.reserve(s.length);
|
t.reserve(s.length);
|
||||||
for (size_t i = 0; i < s.length; ++i) {
|
for (size_t i = 0; i < s.length; ++i) {
|
||||||
|
|
||||||
if (s.data[i] == '\\' || s.data[i] == '\'' || s.data[i] == '\"') {
|
if (s.data[i] == '\\' || s.data[i] == '\'' || s.data[i] == '\"') {
|
||||||
t.push_back('\\');
|
t.push_back('\\');
|
||||||
}
|
}
|
||||||
|
@ -241,7 +240,7 @@ private:
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiVector3D &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiVector3D &ai, bool is_elem = true) {
|
||||||
out.StartArray(is_elem);
|
out.StartArray(is_elem);
|
||||||
out.Element(ai.x);
|
out.Element(ai.x);
|
||||||
out.Element(ai.y);
|
out.Element(ai.y);
|
||||||
|
@ -249,7 +248,7 @@ void Write(JSONWriter &out, const aiVector3D &ai, bool is_elem = true) {
|
||||||
out.EndArray();
|
out.EndArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiQuaternion &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiQuaternion &ai, bool is_elem = true) {
|
||||||
out.StartArray(is_elem);
|
out.StartArray(is_elem);
|
||||||
out.Element(ai.w);
|
out.Element(ai.w);
|
||||||
out.Element(ai.x);
|
out.Element(ai.x);
|
||||||
|
@ -258,7 +257,7 @@ void Write(JSONWriter &out, const aiQuaternion &ai, bool is_elem = true) {
|
||||||
out.EndArray();
|
out.EndArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiColor3D &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiColor3D &ai, bool is_elem = true) {
|
||||||
out.StartArray(is_elem);
|
out.StartArray(is_elem);
|
||||||
out.Element(ai.r);
|
out.Element(ai.r);
|
||||||
out.Element(ai.g);
|
out.Element(ai.g);
|
||||||
|
@ -266,7 +265,7 @@ void Write(JSONWriter &out, const aiColor3D &ai, bool is_elem = true) {
|
||||||
out.EndArray();
|
out.EndArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiMatrix4x4 &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiMatrix4x4 &ai, bool is_elem = true) {
|
||||||
out.StartArray(is_elem);
|
out.StartArray(is_elem);
|
||||||
for (unsigned int x = 0; x < 4; ++x) {
|
for (unsigned int x = 0; x < 4; ++x) {
|
||||||
for (unsigned int y = 0; y < 4; ++y) {
|
for (unsigned int y = 0; y < 4; ++y) {
|
||||||
|
@ -276,7 +275,7 @@ void Write(JSONWriter &out, const aiMatrix4x4 &ai, bool is_elem = true) {
|
||||||
out.EndArray();
|
out.EndArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiBone &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiBone &ai, bool is_elem = true) {
|
||||||
out.StartObj(is_elem);
|
out.StartObj(is_elem);
|
||||||
|
|
||||||
out.Key("name");
|
out.Key("name");
|
||||||
|
@ -297,7 +296,7 @@ void Write(JSONWriter &out, const aiBone &ai, bool is_elem = true) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiFace &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiFace &ai, bool is_elem = true) {
|
||||||
out.StartArray(is_elem);
|
out.StartArray(is_elem);
|
||||||
for (unsigned int i = 0; i < ai.mNumIndices; ++i) {
|
for (unsigned int i = 0; i < ai.mNumIndices; ++i) {
|
||||||
out.Element(ai.mIndices[i]);
|
out.Element(ai.mIndices[i]);
|
||||||
|
@ -305,7 +304,7 @@ void Write(JSONWriter &out, const aiFace &ai, bool is_elem = true) {
|
||||||
out.EndArray();
|
out.EndArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiMesh &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiMesh &ai, bool is_elem = true) {
|
||||||
out.StartObj(is_elem);
|
out.StartObj(is_elem);
|
||||||
|
|
||||||
out.Key("name");
|
out.Key("name");
|
||||||
|
@ -416,7 +415,7 @@ void Write(JSONWriter &out, const aiMesh &ai, bool is_elem = true) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiNode &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiNode &ai, bool is_elem = true) {
|
||||||
out.StartObj(is_elem);
|
out.StartObj(is_elem);
|
||||||
|
|
||||||
out.Key("name");
|
out.Key("name");
|
||||||
|
@ -446,7 +445,7 @@ void Write(JSONWriter &out, const aiNode &ai, bool is_elem = true) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
|
||||||
out.StartObj(is_elem);
|
out.StartObj(is_elem);
|
||||||
|
|
||||||
out.Key("properties");
|
out.Key("properties");
|
||||||
|
@ -477,7 +476,17 @@ void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
|
||||||
out.SimpleValue(*reinterpret_cast<float *>(prop->mData));
|
out.SimpleValue(*reinterpret_cast<float *>(prop->mData));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case aiPTI_Double:
|
||||||
|
if (prop->mDataLength / sizeof(double) > 1) {
|
||||||
|
out.StartArray();
|
||||||
|
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(double); ++ii) {
|
||||||
|
out.Element(reinterpret_cast<double*>(prop->mData)[ii]);
|
||||||
|
}
|
||||||
|
out.EndArray();
|
||||||
|
} else {
|
||||||
|
out.SimpleValue(*reinterpret_cast<double*>(prop->mData));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case aiPTI_Integer:
|
case aiPTI_Integer:
|
||||||
if (prop->mDataLength / sizeof(int) > 1) {
|
if (prop->mDataLength / sizeof(int) > 1) {
|
||||||
out.StartArray();
|
out.StartArray();
|
||||||
|
@ -490,17 +499,21 @@ void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aiPTI_String: {
|
case aiPTI_String:
|
||||||
|
{
|
||||||
aiString s;
|
aiString s;
|
||||||
aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
|
aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
|
||||||
out.SimpleValue(s);
|
out.SimpleValue(s);
|
||||||
} break;
|
}
|
||||||
case aiPTI_Buffer: {
|
break;
|
||||||
|
case aiPTI_Buffer:
|
||||||
|
{
|
||||||
// binary data is written as series of hex-encoded octets
|
// binary data is written as series of hex-encoded octets
|
||||||
out.SimpleValue(prop->mData, prop->mDataLength);
|
out.SimpleValue(prop->mData, prop->mDataLength);
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
ai_assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
|
@ -510,7 +523,7 @@ void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiTexture &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiTexture &ai, bool is_elem = true) {
|
||||||
out.StartObj(is_elem);
|
out.StartObj(is_elem);
|
||||||
|
|
||||||
out.Key("width");
|
out.Key("width");
|
||||||
|
@ -546,7 +559,7 @@ void Write(JSONWriter &out, const aiTexture &ai, bool is_elem = true) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiLight &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiLight &ai, bool is_elem = true) {
|
||||||
out.StartObj(is_elem);
|
out.StartObj(is_elem);
|
||||||
|
|
||||||
out.Key("name");
|
out.Key("name");
|
||||||
|
@ -594,7 +607,7 @@ void Write(JSONWriter &out, const aiLight &ai, bool is_elem = true) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiNodeAnim &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiNodeAnim &ai, bool is_elem = true) {
|
||||||
out.StartObj(is_elem);
|
out.StartObj(is_elem);
|
||||||
|
|
||||||
out.Key("name");
|
out.Key("name");
|
||||||
|
@ -647,7 +660,7 @@ void Write(JSONWriter &out, const aiNodeAnim &ai, bool is_elem = true) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiAnimation &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiAnimation &ai, bool is_elem = true) {
|
||||||
out.StartObj(is_elem);
|
out.StartObj(is_elem);
|
||||||
|
|
||||||
out.Key("name");
|
out.Key("name");
|
||||||
|
@ -668,7 +681,7 @@ void Write(JSONWriter &out, const aiAnimation &ai, bool is_elem = true) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiCamera &ai, bool is_elem = true) {
|
static void Write(JSONWriter &out, const aiCamera &ai, bool is_elem = true) {
|
||||||
out.StartObj(is_elem);
|
out.StartObj(is_elem);
|
||||||
|
|
||||||
out.Key("name");
|
out.Key("name");
|
||||||
|
@ -695,7 +708,7 @@ void Write(JSONWriter &out, const aiCamera &ai, bool is_elem = true) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteFormatInfo(JSONWriter &out) {
|
static void WriteFormatInfo(JSONWriter &out) {
|
||||||
out.StartObj();
|
out.StartObj();
|
||||||
out.Key("format");
|
out.Key("format");
|
||||||
out.SimpleValue("\"assimp2json\"");
|
out.SimpleValue("\"assimp2json\"");
|
||||||
|
@ -704,7 +717,7 @@ void WriteFormatInfo(JSONWriter &out) {
|
||||||
out.EndObj();
|
out.EndObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(JSONWriter &out, const aiScene &ai) {
|
static void Write(JSONWriter &out, const aiScene &ai) {
|
||||||
out.StartObj();
|
out.StartObj();
|
||||||
|
|
||||||
out.Key("__metadata__");
|
out.Key("__metadata__");
|
||||||
|
|
|
@ -67,7 +67,7 @@ static void ReportWarning(const char *msg, ...) {
|
||||||
va_start(args, msg);
|
va_start(args, msg);
|
||||||
|
|
||||||
char szBuffer[3000];
|
char szBuffer[3000];
|
||||||
const int iLen = vsprintf(szBuffer, msg, args);
|
const int iLen = vsnprintf(szBuffer, sizeof(szBuffer), msg, args);
|
||||||
ai_assert(iLen > 0);
|
ai_assert(iLen > 0);
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
|
@ -305,19 +305,16 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodes.size()) {
|
if (nodes.empty()) {
|
||||||
parent->mChildren = new aiNode *[nodes.size()]();
|
|
||||||
parent->mNumChildren = static_cast<unsigned int>(nodes.size());
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < nodes.size(); ++i)
|
|
||||||
{
|
|
||||||
parent->mChildren[i] = nodes[i].mOwnership.release();
|
|
||||||
}
|
|
||||||
nodes.clear();
|
|
||||||
} else {
|
|
||||||
parent->mNumChildren = 0;
|
parent->mNumChildren = 0;
|
||||||
parent->mChildren = nullptr;
|
parent->mChildren = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent->mChildren = new aiNode *[nodes.size()]();
|
||||||
|
parent->mNumChildren = static_cast<unsigned int>(nodes.size());
|
||||||
|
for (unsigned int i = 0; i < nodes.size(); ++i) {
|
||||||
|
parent->mChildren[i] = nodes[i].mOwnership.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXConverter::ConvertLights(const Model &model, const std::string &orig_name) {
|
void FBXConverter::ConvertLights(const Model &model, const std::string &orig_name) {
|
||||||
|
|
|
@ -1228,7 +1228,7 @@ void FBXExporter::WriteObjects ()
|
||||||
"Version", int32_t(101), outstream, binary, indent
|
"Version", int32_t(101), outstream, binary, indent
|
||||||
);
|
);
|
||||||
char layerName[8];
|
char layerName[8];
|
||||||
sprintf(layerName, "COLOR_%d", colorChannelIndex);
|
snprintf(layerName, sizeof(layerName), "COLOR_%d", colorChannelIndex);
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"Name", (const char*)layerName, outstream, binary, indent
|
"Name", (const char*)layerName, outstream, binary, indent
|
||||||
);
|
);
|
||||||
|
|
|
@ -415,9 +415,11 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||||
{
|
{
|
||||||
bool isDirect = ReferenceInformationType == "Direct";
|
bool isDirect = ReferenceInformationType == "Direct";
|
||||||
bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
|
bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
|
||||||
|
const bool hasDataElement = HasElement(source, dataElementName);
|
||||||
|
const bool hasIndexDataElement = HasElement(source, indexDataElementName);
|
||||||
|
|
||||||
// fall-back to direct data if there is no index data element
|
// fall-back to direct data if there is no index data element
|
||||||
if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) {
|
if (isIndexToDirect && !hasIndexDataElement) {
|
||||||
isDirect = true;
|
isDirect = true;
|
||||||
isIndexToDirect = false;
|
isIndexToDirect = false;
|
||||||
}
|
}
|
||||||
|
@ -426,7 +428,8 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||||
// deal with this more elegantly and with less redundancy, but right
|
// deal with this more elegantly and with less redundancy, but right
|
||||||
// now it seems unavoidable.
|
// now it seems unavoidable.
|
||||||
if (MappingInformationType == "ByVertice" && isDirect) {
|
if (MappingInformationType == "ByVertice" && isDirect) {
|
||||||
if (!HasElement(source, dataElementName)) {
|
if (!hasDataElement) {
|
||||||
|
FBXImporter::LogWarn("missing data element: ", dataElementName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<T> tempData;
|
std::vector<T> tempData;
|
||||||
|
@ -448,6 +451,14 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||||
}
|
}
|
||||||
else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
|
else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
|
||||||
std::vector<T> tempData;
|
std::vector<T> tempData;
|
||||||
|
if (!hasDataElement || !hasIndexDataElement) {
|
||||||
|
if (!hasDataElement)
|
||||||
|
FBXImporter::LogWarn("missing data element: ", dataElementName);
|
||||||
|
if (!hasIndexDataElement)
|
||||||
|
FBXImporter::LogWarn("missing index data element: ", indexDataElementName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||||
|
|
||||||
std::vector<int> uvIndices;
|
std::vector<int> uvIndices;
|
||||||
|
@ -473,6 +484,11 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
|
else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
|
||||||
|
if (!hasDataElement) {
|
||||||
|
FBXImporter::LogWarn("missing data element: ", dataElementName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<T> tempData;
|
std::vector<T> tempData;
|
||||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||||
|
|
||||||
|
@ -487,6 +503,13 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
|
||||||
}
|
}
|
||||||
else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
|
else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
|
||||||
std::vector<T> tempData;
|
std::vector<T> tempData;
|
||||||
|
if (!hasDataElement || !hasIndexDataElement) {
|
||||||
|
if (!hasDataElement)
|
||||||
|
FBXImporter::LogWarn("missing data element: ", dataElementName);
|
||||||
|
if (!hasIndexDataElement)
|
||||||
|
FBXImporter::LogWarn("missing index data element: ", indexDataElementName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
|
||||||
|
|
||||||
std::vector<int> uvIndices;
|
std::vector<int> uvIndices;
|
||||||
|
|
|
@ -60,14 +60,11 @@ using namespace Assimp::MD5;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Parse the segment structure for an MD5 file
|
// Parse the segment structure for an MD5 file
|
||||||
MD5Parser::MD5Parser(char *_buffer, unsigned int _fileSize) {
|
MD5Parser::MD5Parser(char *_buffer, unsigned int _fileSize) : buffer(_buffer), bufferEnd(nullptr), fileSize(_fileSize), lineNumber(0) {
|
||||||
ai_assert(nullptr != _buffer);
|
ai_assert(nullptr != _buffer);
|
||||||
ai_assert(0 != _fileSize);
|
ai_assert(0 != _fileSize);
|
||||||
|
|
||||||
buffer = _buffer;
|
bufferEnd = buffer + fileSize;
|
||||||
fileSize = _fileSize;
|
|
||||||
lineNumber = 0;
|
|
||||||
|
|
||||||
ASSIMP_LOG_DEBUG("MD5Parser begin");
|
ASSIMP_LOG_DEBUG("MD5Parser begin");
|
||||||
|
|
||||||
// parse the file header
|
// parse the file header
|
||||||
|
@ -102,7 +99,7 @@ MD5Parser::MD5Parser(char *_buffer, unsigned int _fileSize) {
|
||||||
// Report warning to the log stream
|
// Report warning to the log stream
|
||||||
/*static*/ void MD5Parser::ReportWarning(const char *warn, unsigned int line) {
|
/*static*/ void MD5Parser::ReportWarning(const char *warn, unsigned int line) {
|
||||||
char szBuffer[1024];
|
char szBuffer[1024];
|
||||||
::sprintf(szBuffer, "[MD5] Line %u: %s", line, warn);
|
::snprintf(szBuffer, sizeof(szBuffer), "[MD5] Line %u: %s", line, warn);
|
||||||
ASSIMP_LOG_WARN(szBuffer);
|
ASSIMP_LOG_WARN(szBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
/** @file MD5Parser.h
|
/** @file MD5Parser.h
|
||||||
* @brief Definition of the .MD5 parser class.
|
* @brief Definition of the .MD5 parser class.
|
||||||
|
@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/types.h>
|
#include <assimp/types.h>
|
||||||
#include <assimp/ParsingUtils.h>
|
#include <assimp/ParsingUtils.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
|
|
||||||
struct aiFace;
|
struct aiFace;
|
||||||
|
|
||||||
|
@ -63,8 +63,7 @@ namespace MD5 {
|
||||||
*
|
*
|
||||||
* Elements are always contained in sections.
|
* Elements are always contained in sections.
|
||||||
*/
|
*/
|
||||||
struct Element
|
struct Element {
|
||||||
{
|
|
||||||
//! Points to the starting point of the element
|
//! Points to the starting point of the element
|
||||||
//! Whitespace at the beginning and at the end have been removed,
|
//! Whitespace at the beginning and at the end have been removed,
|
||||||
//! Elements are terminated with \0
|
//! Elements are terminated with \0
|
||||||
|
@ -75,15 +74,14 @@ struct Element
|
||||||
unsigned int iLineNumber;
|
unsigned int iLineNumber;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< Element > ElementList;
|
using ElementList = std::vector<Element>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a section of a MD5 file (such as the mesh or the joints section)
|
/** Represents a section of a MD5 file (such as the mesh or the joints section)
|
||||||
*
|
*
|
||||||
* A section is always enclosed in { and } brackets.
|
* A section is always enclosed in { and } brackets.
|
||||||
*/
|
*/
|
||||||
struct Section
|
struct Section {
|
||||||
{
|
|
||||||
//! Original line number (can be used in error messages
|
//! Original line number (can be used in error messages
|
||||||
//! if a parsing error occurs)
|
//! if a parsing error occurs)
|
||||||
unsigned int iLineNumber;
|
unsigned int iLineNumber;
|
||||||
|
@ -99,13 +97,12 @@ struct Section
|
||||||
std::string mGlobalValue;
|
std::string mGlobalValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< Section> SectionList;
|
using SectionList = std::vector<Section>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Basic information about a joint
|
/** Basic information about a joint
|
||||||
*/
|
*/
|
||||||
struct BaseJointDescription
|
struct BaseJointDescription {
|
||||||
{
|
|
||||||
//! Name of the bone
|
//! Name of the bone
|
||||||
aiString mName;
|
aiString mName;
|
||||||
|
|
||||||
|
@ -116,8 +113,7 @@ struct BaseJointDescription
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a bone (joint) descriptor in a MD5Mesh file
|
/** Represents a bone (joint) descriptor in a MD5Mesh file
|
||||||
*/
|
*/
|
||||||
struct BoneDesc : BaseJointDescription
|
struct BoneDesc : BaseJointDescription {
|
||||||
{
|
|
||||||
//! Absolute position of the bone
|
//! Absolute position of the bone
|
||||||
aiVector3D mPositionXYZ;
|
aiVector3D mPositionXYZ;
|
||||||
|
|
||||||
|
@ -137,13 +133,12 @@ struct BoneDesc : BaseJointDescription
|
||||||
unsigned int mMap;
|
unsigned int mMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< BoneDesc > BoneList;
|
using BoneList = std::vector<BoneDesc>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a bone (joint) descriptor in a MD5Anim file
|
/** Represents a bone (joint) descriptor in a MD5Anim file
|
||||||
*/
|
*/
|
||||||
struct AnimBoneDesc : BaseJointDescription
|
struct AnimBoneDesc : BaseJointDescription {
|
||||||
{
|
|
||||||
//! Flags (AI_MD5_ANIMATION_FLAG_xxx)
|
//! Flags (AI_MD5_ANIMATION_FLAG_xxx)
|
||||||
unsigned int iFlags;
|
unsigned int iFlags;
|
||||||
|
|
||||||
|
@ -151,35 +146,31 @@ struct AnimBoneDesc : BaseJointDescription
|
||||||
unsigned int iFirstKeyIndex;
|
unsigned int iFirstKeyIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< AnimBoneDesc > AnimBoneList;
|
using AnimBoneList = std::vector< AnimBoneDesc >;
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a base frame descriptor in a MD5Anim file
|
/** Represents a base frame descriptor in a MD5Anim file
|
||||||
*/
|
*/
|
||||||
struct BaseFrameDesc
|
struct BaseFrameDesc {
|
||||||
{
|
|
||||||
aiVector3D vPositionXYZ;
|
aiVector3D vPositionXYZ;
|
||||||
aiVector3D vRotationQuat;
|
aiVector3D vRotationQuat;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< BaseFrameDesc > BaseFrameList;
|
using BaseFrameList = std::vector<BaseFrameDesc>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a camera animation frame in a MDCamera file
|
/** Represents a camera animation frame in a MDCamera file
|
||||||
*/
|
*/
|
||||||
struct CameraAnimFrameDesc : BaseFrameDesc
|
struct CameraAnimFrameDesc : BaseFrameDesc {
|
||||||
{
|
|
||||||
float fFOV;
|
float fFOV;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< CameraAnimFrameDesc > CameraFrameList;
|
using CameraFrameList = std::vector<CameraAnimFrameDesc>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a frame descriptor in a MD5Anim file
|
/** Represents a frame descriptor in a MD5Anim file
|
||||||
*/
|
*/
|
||||||
struct FrameDesc
|
struct FrameDesc {
|
||||||
{
|
|
||||||
//! Index of the frame
|
//! Index of the frame
|
||||||
unsigned int iIndex;
|
unsigned int iIndex;
|
||||||
|
|
||||||
|
@ -187,15 +178,14 @@ struct FrameDesc
|
||||||
std::vector< float > mValues;
|
std::vector< float > mValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< FrameDesc > FrameList;
|
using FrameList = std::vector<FrameDesc>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a vertex descriptor in a MD5 file
|
/** Represents a vertex descriptor in a MD5 file
|
||||||
*/
|
*/
|
||||||
struct VertexDesc {
|
struct VertexDesc {
|
||||||
VertexDesc() AI_NO_EXCEPT
|
VertexDesc() AI_NO_EXCEPT
|
||||||
: mFirstWeight(0)
|
: mFirstWeight(0), mNumWeights(0) {
|
||||||
, mNumWeights(0) {
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,13 +200,12 @@ struct VertexDesc {
|
||||||
unsigned int mNumWeights;
|
unsigned int mNumWeights;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< VertexDesc > VertexList;
|
using VertexList = std::vector<VertexDesc>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a vertex weight descriptor in a MD5 file
|
/** Represents a vertex weight descriptor in a MD5 file
|
||||||
*/
|
*/
|
||||||
struct WeightDesc
|
struct WeightDesc {
|
||||||
{
|
|
||||||
//! Index of the bone to which this weight refers
|
//! Index of the bone to which this weight refers
|
||||||
unsigned int mBone;
|
unsigned int mBone;
|
||||||
|
|
||||||
|
@ -228,14 +217,13 @@ struct WeightDesc
|
||||||
aiVector3D vOffsetPosition;
|
aiVector3D vOffsetPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< WeightDesc > WeightList;
|
using WeightList = std::vector<WeightDesc>;
|
||||||
typedef std::vector< aiFace > FaceList;
|
using FaceList = std::vector<aiFace>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a mesh in a MD5 file
|
/** Represents a mesh in a MD5 file
|
||||||
*/
|
*/
|
||||||
struct MeshDesc
|
struct MeshDesc {
|
||||||
{
|
|
||||||
//! Weights of the mesh
|
//! Weights of the mesh
|
||||||
WeightList mWeights;
|
WeightList mWeights;
|
||||||
|
|
||||||
|
@ -249,7 +237,7 @@ struct MeshDesc
|
||||||
aiString mShader;
|
aiString mShader;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector< MeshDesc > MeshList;
|
using MeshList = std::vector<MeshDesc>;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Convert a quaternion to its usual representation
|
// Convert a quaternion to its usual representation
|
||||||
|
@ -261,9 +249,11 @@ inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) {
|
||||||
|
|
||||||
const float t = 1.0f - (in.x*in.x) - (in.y*in.y) - (in.z*in.z);
|
const float t = 1.0f - (in.x*in.x) - (in.y*in.y) - (in.z*in.z);
|
||||||
|
|
||||||
if (t < 0.0f)
|
if (t < 0.0f) {
|
||||||
out.w = 0.0f;
|
out.w = 0.0f;
|
||||||
else out.w = std::sqrt (t);
|
} else {
|
||||||
|
out.w = std::sqrt (t);
|
||||||
|
}
|
||||||
|
|
||||||
// Assimp convention.
|
// Assimp convention.
|
||||||
out.w *= -1.f;
|
out.w *= -1.f;
|
||||||
|
@ -272,10 +262,8 @@ inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Parses the data sections of a MD5 mesh file
|
/** Parses the data sections of a MD5 mesh file
|
||||||
*/
|
*/
|
||||||
class MD5MeshParser
|
class MD5MeshParser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Constructs a new MD5MeshParser instance from an existing
|
/** Constructs a new MD5MeshParser instance from an existing
|
||||||
* preparsed list of file sections.
|
* preparsed list of file sections.
|
||||||
|
@ -297,10 +285,8 @@ public:
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Parses the data sections of a MD5 animation file
|
/** Parses the data sections of a MD5 animation file
|
||||||
*/
|
*/
|
||||||
class MD5AnimParser
|
class MD5AnimParser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Constructs a new MD5AnimParser instance from an existing
|
/** Constructs a new MD5AnimParser instance from an existing
|
||||||
* preparsed list of file sections.
|
* preparsed list of file sections.
|
||||||
|
@ -329,10 +315,8 @@ public:
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Parses the data sections of a MD5 camera animation file
|
/** Parses the data sections of a MD5 camera animation file
|
||||||
*/
|
*/
|
||||||
class MD5CameraParser
|
class MD5CameraParser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Constructs a new MD5CameraParser instance from an existing
|
/** Constructs a new MD5CameraParser instance from an existing
|
||||||
* preparsed list of file sections.
|
* preparsed list of file sections.
|
||||||
|
@ -341,7 +325,6 @@ public:
|
||||||
*/
|
*/
|
||||||
explicit MD5CameraParser(SectionList& mSections);
|
explicit MD5CameraParser(SectionList& mSections);
|
||||||
|
|
||||||
|
|
||||||
//! Output frame rate
|
//! Output frame rate
|
||||||
float fFrameRate;
|
float fFrameRate;
|
||||||
|
|
||||||
|
@ -356,10 +339,8 @@ public:
|
||||||
/** Parses the block structure of MD5MESH and MD5ANIM files (but does no
|
/** Parses the block structure of MD5MESH and MD5ANIM files (but does no
|
||||||
* further processing)
|
* further processing)
|
||||||
*/
|
*/
|
||||||
class MD5Parser
|
class MD5Parser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Constructs a new MD5Parser instance from an existing buffer.
|
/** Constructs a new MD5Parser instance from an existing buffer.
|
||||||
*
|
*
|
||||||
|
@ -392,13 +373,10 @@ public:
|
||||||
return ReportWarning(warn, lineNumber);
|
return ReportWarning(warn, lineNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//! List of all sections which have been read
|
//! List of all sections which have been read
|
||||||
SectionList mSections;
|
SectionList mSections;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Parses a file section. The current file pointer must be outside
|
/** Parses a file section. The current file pointer must be outside
|
||||||
* of a section.
|
* of a section.
|
||||||
|
@ -414,22 +392,31 @@ private:
|
||||||
*/
|
*/
|
||||||
void ParseHeader();
|
void ParseHeader();
|
||||||
|
|
||||||
|
bool SkipLine(const char* in, const char** out);
|
||||||
|
bool SkipLine( );
|
||||||
|
bool SkipSpacesAndLineEnd( const char* in, const char** out);
|
||||||
|
bool SkipSpacesAndLineEnd();
|
||||||
|
bool SkipSpaces();
|
||||||
|
|
||||||
// override these functions to make sure the line counter gets incremented
|
char* buffer;
|
||||||
// -------------------------------------------------------------------
|
char* bufferEnd;
|
||||||
bool SkipLine( const char* in, const char** out)
|
unsigned int fileSize;
|
||||||
{
|
unsigned int lineNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
inline bool MD5Parser::SkipLine(const char* in, const char** out) {
|
||||||
++lineNumber;
|
++lineNumber;
|
||||||
return Assimp::SkipLine(in,out);
|
return Assimp::SkipLine(in ,out);
|
||||||
}
|
}
|
||||||
// -------------------------------------------------------------------
|
|
||||||
bool SkipLine( )
|
// -------------------------------------------------------------------
|
||||||
{
|
inline bool MD5Parser::SkipLine( ) {
|
||||||
return SkipLine(buffer,(const char**)&buffer);
|
return SkipLine(buffer,(const char**)&buffer);
|
||||||
}
|
}
|
||||||
// -------------------------------------------------------------------
|
|
||||||
bool SkipSpacesAndLineEnd( const char* in, const char** out)
|
// -------------------------------------------------------------------
|
||||||
{
|
inline bool MD5Parser::SkipSpacesAndLineEnd( const char* in, const char** out) {
|
||||||
bool bHad = false;
|
bool bHad = false;
|
||||||
bool running = true;
|
bool running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
|
@ -442,26 +429,26 @@ private:
|
||||||
}
|
}
|
||||||
else if (*in == '\t' || *in == ' ')bHad = false;
|
else if (*in == '\t' || *in == ' ')bHad = false;
|
||||||
else break;
|
else break;
|
||||||
in++;
|
++in;
|
||||||
|
if (in == bufferEnd) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*out = in;
|
*out = in;
|
||||||
return *in != '\0';
|
return *in != '\0';
|
||||||
}
|
}
|
||||||
// -------------------------------------------------------------------
|
|
||||||
bool SkipSpacesAndLineEnd( )
|
|
||||||
{
|
|
||||||
return SkipSpacesAndLineEnd(buffer,(const char**)&buffer);
|
|
||||||
}
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
bool SkipSpaces( )
|
|
||||||
{
|
|
||||||
return Assimp::SkipSpaces((const char**)&buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buffer;
|
// -------------------------------------------------------------------
|
||||||
unsigned int fileSize;
|
inline bool MD5Parser::SkipSpacesAndLineEnd() {
|
||||||
unsigned int lineNumber;
|
return SkipSpacesAndLineEnd(buffer,(const char**)&buffer);
|
||||||
};
|
}
|
||||||
}}
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
inline bool MD5Parser::SkipSpaces() {
|
||||||
|
return Assimp::SkipSpaces((const char**)&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Assimp
|
||||||
|
} // namespace MD5
|
||||||
|
|
||||||
#endif // AI_MD5PARSER_H_INCLUDED
|
#endif // AI_MD5PARSER_H_INCLUDED
|
||||||
|
|
|
@ -298,7 +298,7 @@ void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int
|
||||||
}
|
}
|
||||||
|
|
||||||
char szBuffer[1024];
|
char szBuffer[1024];
|
||||||
::sprintf(szBuffer, "Invalid MDL file. The file is too small "
|
::snprintf(szBuffer, sizeof(szBuffer), "Invalid MDL file. The file is too small "
|
||||||
"or contains invalid data (File: %s Line: %u)",
|
"or contains invalid data (File: %s Line: %u)",
|
||||||
szFilePtr, iLine);
|
szFilePtr, iLine);
|
||||||
|
|
||||||
|
|
|
@ -501,10 +501,6 @@ bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM *p_pc
|
||||||
|
|
||||||
streamBuffer.getNextBlock(buffer);
|
streamBuffer.getNextBlock(buffer);
|
||||||
|
|
||||||
// remove first char if it's /n in case of file with /r/n
|
|
||||||
if (((char *)&buffer[0])[0] == '\n')
|
|
||||||
buffer.erase(buffer.begin(), buffer.begin() + 1);
|
|
||||||
|
|
||||||
unsigned int bufferSize = static_cast<unsigned int>(buffer.size());
|
unsigned int bufferSize = static_cast<unsigned int>(buffer.size());
|
||||||
const char *pCur = (char *)&buffer[0];
|
const char *pCur = (char *)&buffer[0];
|
||||||
if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) {
|
if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) {
|
||||||
|
|
|
@ -75,15 +75,10 @@ static const aiImporterDesc desc = {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
XFileImporter::XFileImporter()
|
XFileImporter::XFileImporter() : mBuffer() {
|
||||||
: mBuffer() {
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Destructor, private as well
|
|
||||||
XFileImporter::~XFileImporter() = default;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Returns whether the class can handle the format of the given file.
|
// Returns whether the class can handle the format of the given file.
|
||||||
bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const {
|
bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const {
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace XFile {
|
||||||
class XFileImporter : public BaseImporter {
|
class XFileImporter : public BaseImporter {
|
||||||
public:
|
public:
|
||||||
XFileImporter();
|
XFileImporter();
|
||||||
~XFileImporter() override;
|
~XFileImporter() override = default;
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Returns whether the class can handle the format of the given file.
|
/** Returns whether the class can handle the format of the given file.
|
||||||
|
|
|
@ -1273,11 +1273,13 @@ ASSIMP_API void aiQuaternionInterpolate(
|
||||||
#define ASSIMP_HAS_PBRT_EXPORT (!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_PBRT_EXPORTER)
|
#define ASSIMP_HAS_PBRT_EXPORT (!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_PBRT_EXPORTER)
|
||||||
#define ASSIMP_HAS_M3D ((!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER)
|
#define ASSIMP_HAS_M3D ((!ASSIMP_BUILD_NO_EXPORT && !ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER)
|
||||||
|
|
||||||
#if ASSIMP_HAS_PBRT_EXPORT
|
#ifndef STB_USE_HUNTER
|
||||||
|
# if ASSIMP_HAS_PBRT_EXPORT
|
||||||
# define ASSIMP_NEEDS_STB_IMAGE 1
|
# define ASSIMP_NEEDS_STB_IMAGE 1
|
||||||
#elif ASSIMP_HAS_M3D
|
# elif ASSIMP_HAS_M3D
|
||||||
# define ASSIMP_NEEDS_STB_IMAGE 1
|
# define ASSIMP_NEEDS_STB_IMAGE 1
|
||||||
# define STBI_ONLY_PNG
|
# define STBI_ONLY_PNG
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Ensure all symbols are linked correctly
|
// Ensure all symbols are linked correctly
|
||||||
|
|
|
@ -42,9 +42,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
||||||
#include <zlib.h>
|
# include <zlib.h>
|
||||||
#else
|
#else
|
||||||
#include "../contrib/zlib/zlib.h"
|
# include "../contrib/zlib/zlib.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
|
@ -1,29 +1,92 @@
|
||||||
#pragma once
|
/*
|
||||||
#include <assimp/ai_assert.h>
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software 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 the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assimp/ai_assert.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
/// @brief This class implements an optional type
|
||||||
|
/// @tparam T The type to store.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Maybe {
|
struct Maybe {
|
||||||
private:
|
/// @brief
|
||||||
T _val;
|
Maybe() = default;
|
||||||
bool _valid;
|
|
||||||
|
|
||||||
public:
|
/// @brief
|
||||||
Maybe() :
|
/// @param val
|
||||||
_valid(false) {}
|
template <typename U>
|
||||||
|
explicit Maybe(U &&val) :
|
||||||
explicit Maybe(const T &val) :
|
_val(std::forward<U>(val)), _valid(true) {}
|
||||||
_val(val), _valid(true) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// @brief Validate the value
|
||||||
|
/// @return true if valid.
|
||||||
operator bool() const {
|
operator bool() const {
|
||||||
return _valid;
|
return _valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Will assign a value.
|
||||||
|
/// @param v The new valid value.
|
||||||
|
template <typename U>
|
||||||
|
void Set(U &&v) {
|
||||||
|
ai_assert(!_valid);
|
||||||
|
|
||||||
|
_valid = true;
|
||||||
|
_val = std::forward<U>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Will return the value when it is valid.
|
||||||
|
/// @return The value.
|
||||||
const T &Get() const {
|
const T &Get() const {
|
||||||
ai_assert(_valid);
|
ai_assert(_valid);
|
||||||
return _val;
|
return _val;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
Maybe &operator&() = delete;
|
Maybe &operator&() = delete;
|
||||||
|
Maybe(const Maybe &) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
T _val;
|
||||||
|
bool _valid = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace Assimp
|
||||||
|
|
|
@ -48,6 +48,64 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef STB_USE_HUNTER
|
||||||
|
/* Use prefixed names for the symbols from stb_image as it is a very commonly embedded library.
|
||||||
|
Including vanilla stb_image symbols causes duplicate symbol problems if assimp is linked
|
||||||
|
statically together with another library or executable that also embeds stb_image.
|
||||||
|
|
||||||
|
Symbols are not prefixed if using Hunter because in such case there exists a single true
|
||||||
|
stb_image library on the system that is used by assimp and can be used by all the other
|
||||||
|
libraries and executables.
|
||||||
|
|
||||||
|
The list can be regenerated using the following:
|
||||||
|
|
||||||
|
cat <path/to/stb/stb_image.h> | fgrep STBIDEF | fgrep '(' | sed -E 's/\*|\(.+//g' | \
|
||||||
|
awk '{print "#define " $(NF) " assimp_" $(NF) }' | sort | uniq"
|
||||||
|
*/
|
||||||
|
#define stbi_convert_iphone_png_to_rgb assimp_stbi_convert_iphone_png_to_rgb
|
||||||
|
#define stbi_convert_wchar_to_utf8 assimp_stbi_convert_wchar_to_utf8
|
||||||
|
#define stbi_failure_reason assimp_stbi_failure_reason
|
||||||
|
#define stbi_hdr_to_ldr_gamma assimp_stbi_hdr_to_ldr_gamma
|
||||||
|
#define stbi_hdr_to_ldr_scale assimp_stbi_hdr_to_ldr_scale
|
||||||
|
#define stbi_image_free assimp_stbi_image_free
|
||||||
|
#define stbi_info assimp_stbi_info
|
||||||
|
#define stbi_info_from_callbacks assimp_stbi_info_from_callbacks
|
||||||
|
#define stbi_info_from_file assimp_stbi_info_from_file
|
||||||
|
#define stbi_info_from_memory assimp_stbi_info_from_memory
|
||||||
|
#define stbi_is_16_bit assimp_stbi_is_16_bit
|
||||||
|
#define stbi_is_16_bit_from_callbacks assimp_stbi_is_16_bit_from_callbacks
|
||||||
|
#define stbi_is_16_bit_from_file assimp_stbi_is_16_bit_from_file
|
||||||
|
#define stbi_is_16_bit_from_memory assimp_stbi_is_16_bit_from_memory
|
||||||
|
#define stbi_is_hdr assimp_stbi_is_hdr
|
||||||
|
#define stbi_is_hdr_from_callbacks assimp_stbi_is_hdr_from_callbacks
|
||||||
|
#define stbi_is_hdr_from_file assimp_stbi_is_hdr_from_file
|
||||||
|
#define stbi_is_hdr_from_memory assimp_stbi_is_hdr_from_memory
|
||||||
|
#define stbi_ldr_to_hdr_gamma assimp_stbi_ldr_to_hdr_gamma
|
||||||
|
#define stbi_ldr_to_hdr_scale assimp_stbi_ldr_to_hdr_scale
|
||||||
|
#define stbi_load_16 assimp_stbi_load_16
|
||||||
|
#define stbi_load_16_from_callbacks assimp_stbi_load_16_from_callbacks
|
||||||
|
#define stbi_load_16_from_memory assimp_stbi_load_16_from_memory
|
||||||
|
#define stbi_load assimp_stbi_load
|
||||||
|
#define stbi_loadf assimp_stbi_loadf
|
||||||
|
#define stbi_loadf_from_callbacks assimp_stbi_loadf_from_callbacks
|
||||||
|
#define stbi_loadf_from_file assimp_stbi_loadf_from_file
|
||||||
|
#define stbi_loadf_from_memory assimp_stbi_loadf_from_memory
|
||||||
|
#define stbi_load_from_callbacks assimp_stbi_load_from_callbacks
|
||||||
|
#define stbi_load_from_file_16 assimp_stbi_load_from_file_16
|
||||||
|
#define stbi_load_from_file assimp_stbi_load_from_file
|
||||||
|
#define stbi_load_from_memory assimp_stbi_load_from_memory
|
||||||
|
#define stbi_load_gif_from_memory assimp_stbi_load_gif_from_memory
|
||||||
|
#define stbi_set_flip_vertically_on_load assimp_stbi_set_flip_vertically_on_load
|
||||||
|
#define stbi_set_flip_vertically_on_load_thread assimp_stbi_set_flip_vertically_on_load_thread
|
||||||
|
#define stbi_set_unpremultiply_on_load assimp_stbi_set_unpremultiply_on_load
|
||||||
|
#define stbi_zlib_decode_buffer assimp_stbi_zlib_decode_buffer
|
||||||
|
#define stbi_zlib_decode_malloc assimp_stbi_zlib_decode_malloc
|
||||||
|
#define stbi_zlib_decode_malloc_guesssize assimp_stbi_zlib_decode_malloc_guesssize
|
||||||
|
#define stbi_zlib_decode_malloc_guesssize_headerflag assimp_stbi_zlib_decode_malloc_guesssize_headerflag
|
||||||
|
#define stbi_zlib_decode_noheader_buffer assimp_stbi_zlib_decode_noheader_buffer
|
||||||
|
#define stbi_zlib_decode_noheader_malloc assimp_stbi_zlib_decode_noheader_malloc
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "stb/stb_image.h"
|
#include "stb/stb_image.h"
|
||||||
|
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2022, assimp team
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
|
|
@ -80,7 +80,7 @@ AI_WONT_RETURN void ValidateDSProcess::ReportError(const char *msg, ...) {
|
||||||
va_start(args, msg);
|
va_start(args, msg);
|
||||||
|
|
||||||
char szBuffer[3000];
|
char szBuffer[3000];
|
||||||
const int iLen = vsprintf(szBuffer, msg, args);
|
const int iLen = vsnprintf(szBuffer, sizeof(szBuffer), msg, args);
|
||||||
ai_assert(iLen > 0);
|
ai_assert(iLen > 0);
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
@ -95,7 +95,7 @@ void ValidateDSProcess::ReportWarning(const char *msg, ...) {
|
||||||
va_start(args, msg);
|
va_start(args, msg);
|
||||||
|
|
||||||
char szBuffer[3000];
|
char szBuffer[3000];
|
||||||
const int iLen = vsprintf(szBuffer, msg, args);
|
const int iLen = vsnprintf(szBuffer, sizeof(szBuffer), msg, args);
|
||||||
ai_assert(iLen > 0);
|
ai_assert(iLen > 0);
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
|
@ -46,14 +46,9 @@ endif()
|
||||||
|
|
||||||
# Project version:
|
# Project version:
|
||||||
|
|
||||||
if (CMAKE_VERSION VERSION_LESS 3.0)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
project(gtest CXX C)
|
cmake_policy(SET CMP0048 NEW)
|
||||||
set(PROJECT_VERSION ${GOOGLETEST_VERSION})
|
project(gtest VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C)
|
||||||
else()
|
|
||||||
cmake_policy(SET CMP0048 NEW)
|
|
||||||
project(gtest VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C)
|
|
||||||
endif()
|
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
|
||||||
|
|
||||||
if (POLICY CMP0063) # Visibility
|
if (POLICY CMP0063) # Visibility
|
||||||
cmake_policy(SET CMP0063 NEW)
|
cmake_policy(SET CMP0063 NEW)
|
||||||
|
@ -136,13 +131,17 @@ set_target_properties(gtest_main PROPERTIES VERSION ${GOOGLETEST_VERSION})
|
||||||
# to the targets for when we are part of a parent build (ie being pulled
|
# to the targets for when we are part of a parent build (ie being pulled
|
||||||
# in via add_subdirectory() rather than being a standalone build).
|
# in via add_subdirectory() rather than being a standalone build).
|
||||||
if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11")
|
if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11")
|
||||||
|
string(REPLACE ";" "$<SEMICOLON>" dirs "${gtest_build_include_dirs}")
|
||||||
target_include_directories(gtest SYSTEM INTERFACE
|
target_include_directories(gtest SYSTEM INTERFACE
|
||||||
"$<BUILD_INTERFACE:${gtest_build_include_dirs}>"
|
"$<BUILD_INTERFACE:${dirs}>"
|
||||||
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||||
target_include_directories(gtest_main SYSTEM INTERFACE
|
target_include_directories(gtest_main SYSTEM INTERFACE
|
||||||
"$<BUILD_INTERFACE:${gtest_build_include_dirs}>"
|
"$<BUILD_INTERFACE:${dirs}>"
|
||||||
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||||
endif()
|
endif()
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "QNX")
|
||||||
|
target_link_libraries(gtest PUBLIC regex)
|
||||||
|
endif()
|
||||||
target_link_libraries(gtest_main PUBLIC gtest)
|
target_link_libraries(gtest_main PUBLIC gtest)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
|
@ -25,7 +25,7 @@ When building GoogleTest as a standalone project, the typical workflow starts
|
||||||
with
|
with
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone https://github.com/google/googletest.git -b release-1.10.0
|
git clone https://github.com/google/googletest.git -b release-1.11.0
|
||||||
cd googletest # Main directory of the cloned repository.
|
cd googletest # Main directory of the cloned repository.
|
||||||
mkdir build # Create a directory to hold the build output.
|
mkdir build # Create a directory to hold the build output.
|
||||||
cd build
|
cd build
|
||||||
|
@ -94,7 +94,7 @@ include(FetchContent)
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
googletest
|
googletest
|
||||||
# Specify the commit you depend on and update it regularly.
|
# Specify the commit you depend on and update it regularly.
|
||||||
URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
|
URL https://github.com/google/googletest/archive/e2239ee6043f73722e7aa812a459f54a28552929.zip
|
||||||
)
|
)
|
||||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
|
@ -203,7 +203,9 @@ add
|
||||||
-DGTEST_DONT_DEFINE_FOO=1
|
-DGTEST_DONT_DEFINE_FOO=1
|
||||||
|
|
||||||
to the compiler flags to tell GoogleTest to change the macro's name from `FOO`
|
to the compiler flags to tell GoogleTest to change the macro's name from `FOO`
|
||||||
to `GTEST_FOO`. Currently `FOO` can be `FAIL`, `SUCCEED`, or `TEST`. For
|
to `GTEST_FOO`. Currently `FOO` can be `ASSERT_EQ`, `ASSERT_FALSE`, `ASSERT_GE`,
|
||||||
|
`ASSERT_GT`, `ASSERT_LE`, `ASSERT_LT`, `ASSERT_NE`, `ASSERT_TRUE`,
|
||||||
|
`EXPECT_FALSE`, `EXPECT_TRUE`, `FAIL`, `SUCCEED`, `TEST`, or `TEST_F`. For
|
||||||
example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write
|
example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write
|
||||||
|
|
||||||
GTEST_TEST(SomeTest, DoesThis) { ... }
|
GTEST_TEST(SomeTest, DoesThis) { ... }
|
||||||
|
|
|
@ -84,13 +84,13 @@ macro(config_compiler_and_linker)
|
||||||
# Ensure MSVC treats source files as UTF-8 encoded.
|
# Ensure MSVC treats source files as UTF-8 encoded.
|
||||||
set(cxx_base_flags "${cxx_base_flags} -utf-8")
|
set(cxx_base_flags "${cxx_base_flags} -utf-8")
|
||||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
set(cxx_base_flags "-Wall -Wshadow -Werror -Wconversion")
|
set(cxx_base_flags "-Wall -Wshadow -Wconversion")
|
||||||
set(cxx_exception_flags "-fexceptions")
|
set(cxx_exception_flags "-fexceptions")
|
||||||
set(cxx_no_exception_flags "-fno-exceptions")
|
set(cxx_no_exception_flags "-fno-exceptions")
|
||||||
set(cxx_strict_flags "-W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls")
|
set(cxx_strict_flags "-W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls")
|
||||||
set(cxx_no_rtti_flags "-fno-rtti")
|
set(cxx_no_rtti_flags "-fno-rtti")
|
||||||
elseif (CMAKE_COMPILER_IS_GNUCXX)
|
elseif (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
set(cxx_base_flags "-Wall -Wshadow -Werror")
|
set(cxx_base_flags "-Wall -Wshadow")
|
||||||
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0)
|
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0)
|
||||||
set(cxx_base_flags "${cxx_base_flags} -Wno-error=dangling-else")
|
set(cxx_base_flags "${cxx_base_flags} -Wno-error=dangling-else")
|
||||||
endif()
|
endif()
|
||||||
|
@ -154,10 +154,6 @@ function(cxx_library_with_type name type cxx_flags)
|
||||||
set_target_properties(${name}
|
set_target_properties(${name}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
COMPILE_FLAGS "${cxx_flags}")
|
COMPILE_FLAGS "${cxx_flags}")
|
||||||
# Generate debug library name with a postfix.
|
|
||||||
set_target_properties(${name}
|
|
||||||
PROPERTIES
|
|
||||||
DEBUG_POSTFIX "d")
|
|
||||||
# Set the output directory for build artifacts
|
# Set the output directory for build artifacts
|
||||||
set_target_properties(${name}
|
set_target_properties(${name}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
@ -304,6 +300,8 @@ function(py_test name)
|
||||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
|
||||||
--build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE} ${ARGN})
|
--build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE} ${ARGN})
|
||||||
endif()
|
endif()
|
||||||
|
# Make the Python import path consistent between Bazel and CMake.
|
||||||
|
set_tests_properties(${name} PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_SOURCE_DIR})
|
||||||
endif(PYTHONINTERP_FOUND)
|
endif(PYTHONINTERP_FOUND)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,237 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
|
//
|
||||||
|
// This file implements the AssertionResult type.
|
||||||
|
|
||||||
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_ASSERTION_RESULT_H_
|
||||||
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_ASSERTION_RESULT_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "gtest/gtest-message.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||||
|
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// A class for indicating whether an assertion was successful. When
|
||||||
|
// the assertion wasn't successful, the AssertionResult object
|
||||||
|
// remembers a non-empty message that describes how it failed.
|
||||||
|
//
|
||||||
|
// To create an instance of this class, use one of the factory functions
|
||||||
|
// (AssertionSuccess() and AssertionFailure()).
|
||||||
|
//
|
||||||
|
// This class is useful for two purposes:
|
||||||
|
// 1. Defining predicate functions to be used with Boolean test assertions
|
||||||
|
// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
|
||||||
|
// 2. Defining predicate-format functions to be
|
||||||
|
// used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
|
||||||
|
//
|
||||||
|
// For example, if you define IsEven predicate:
|
||||||
|
//
|
||||||
|
// testing::AssertionResult IsEven(int n) {
|
||||||
|
// if ((n % 2) == 0)
|
||||||
|
// return testing::AssertionSuccess();
|
||||||
|
// else
|
||||||
|
// return testing::AssertionFailure() << n << " is odd";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
|
||||||
|
// will print the message
|
||||||
|
//
|
||||||
|
// Value of: IsEven(Fib(5))
|
||||||
|
// Actual: false (5 is odd)
|
||||||
|
// Expected: true
|
||||||
|
//
|
||||||
|
// instead of a more opaque
|
||||||
|
//
|
||||||
|
// Value of: IsEven(Fib(5))
|
||||||
|
// Actual: false
|
||||||
|
// Expected: true
|
||||||
|
//
|
||||||
|
// in case IsEven is a simple Boolean predicate.
|
||||||
|
//
|
||||||
|
// If you expect your predicate to be reused and want to support informative
|
||||||
|
// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
|
||||||
|
// about half as often as positive ones in our tests), supply messages for
|
||||||
|
// both success and failure cases:
|
||||||
|
//
|
||||||
|
// testing::AssertionResult IsEven(int n) {
|
||||||
|
// if ((n % 2) == 0)
|
||||||
|
// return testing::AssertionSuccess() << n << " is even";
|
||||||
|
// else
|
||||||
|
// return testing::AssertionFailure() << n << " is odd";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
|
||||||
|
//
|
||||||
|
// Value of: IsEven(Fib(6))
|
||||||
|
// Actual: true (8 is even)
|
||||||
|
// Expected: false
|
||||||
|
//
|
||||||
|
// NB: Predicates that support negative Boolean assertions have reduced
|
||||||
|
// performance in positive ones so be careful not to use them in tests
|
||||||
|
// that have lots (tens of thousands) of positive Boolean assertions.
|
||||||
|
//
|
||||||
|
// To use this class with EXPECT_PRED_FORMAT assertions such as:
|
||||||
|
//
|
||||||
|
// // Verifies that Foo() returns an even number.
|
||||||
|
// EXPECT_PRED_FORMAT1(IsEven, Foo());
|
||||||
|
//
|
||||||
|
// you need to define:
|
||||||
|
//
|
||||||
|
// testing::AssertionResult IsEven(const char* expr, int n) {
|
||||||
|
// if ((n % 2) == 0)
|
||||||
|
// return testing::AssertionSuccess();
|
||||||
|
// else
|
||||||
|
// return testing::AssertionFailure()
|
||||||
|
// << "Expected: " << expr << " is even\n Actual: it's " << n;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// If Foo() returns 5, you will see the following message:
|
||||||
|
//
|
||||||
|
// Expected: Foo() is even
|
||||||
|
// Actual: it's 5
|
||||||
|
//
|
||||||
|
class GTEST_API_ AssertionResult {
|
||||||
|
public:
|
||||||
|
// Copy constructor.
|
||||||
|
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
||||||
|
AssertionResult(const AssertionResult& other);
|
||||||
|
|
||||||
|
// C4800 is a level 3 warning in Visual Studio 2015 and earlier.
|
||||||
|
// This warning is not emitted in Visual Studio 2017.
|
||||||
|
// This warning is off by default starting in Visual Studio 2019 but can be
|
||||||
|
// enabled with command-line options.
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
|
||||||
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Used in the EXPECT_TRUE/FALSE(bool_expression).
|
||||||
|
//
|
||||||
|
// T must be contextually convertible to bool.
|
||||||
|
//
|
||||||
|
// The second parameter prevents this overload from being considered if
|
||||||
|
// the argument is implicitly convertible to AssertionResult. In that case
|
||||||
|
// we want AssertionResult's copy constructor to be used.
|
||||||
|
template <typename T>
|
||||||
|
explicit AssertionResult(
|
||||||
|
const T& success,
|
||||||
|
typename std::enable_if<
|
||||||
|
!std::is_convertible<T, AssertionResult>::value>::type*
|
||||||
|
/*enabler*/
|
||||||
|
= nullptr)
|
||||||
|
: success_(success) {}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
|
||||||
|
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Assignment operator.
|
||||||
|
AssertionResult& operator=(AssertionResult other) {
|
||||||
|
swap(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if and only if the assertion succeeded.
|
||||||
|
operator bool() const { return success_; } // NOLINT
|
||||||
|
|
||||||
|
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
|
||||||
|
AssertionResult operator!() const;
|
||||||
|
|
||||||
|
// Returns the text streamed into this AssertionResult. Test assertions
|
||||||
|
// use it when they fail (i.e., the predicate's outcome doesn't match the
|
||||||
|
// assertion's expectation). When nothing has been streamed into the
|
||||||
|
// object, returns an empty string.
|
||||||
|
const char* message() const {
|
||||||
|
return message_.get() != nullptr ? message_->c_str() : "";
|
||||||
|
}
|
||||||
|
// Deprecated; please use message() instead.
|
||||||
|
const char* failure_message() const { return message(); }
|
||||||
|
|
||||||
|
// Streams a custom failure message into this object.
|
||||||
|
template <typename T>
|
||||||
|
AssertionResult& operator<<(const T& value) {
|
||||||
|
AppendMessage(Message() << value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allows streaming basic output manipulators such as endl or flush into
|
||||||
|
// this object.
|
||||||
|
AssertionResult& operator<<(
|
||||||
|
::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
|
||||||
|
AppendMessage(Message() << basic_manipulator);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Appends the contents of message to message_.
|
||||||
|
void AppendMessage(const Message& a_message) {
|
||||||
|
if (message_.get() == nullptr) message_.reset(new ::std::string);
|
||||||
|
message_->append(a_message.GetString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap the contents of this AssertionResult with other.
|
||||||
|
void swap(AssertionResult& other);
|
||||||
|
|
||||||
|
// Stores result of the assertion predicate.
|
||||||
|
bool success_;
|
||||||
|
// Stores the message describing the condition in case the expectation
|
||||||
|
// construct is not satisfied with the predicate's outcome.
|
||||||
|
// Referenced via a pointer to avoid taking too much stack frame space
|
||||||
|
// with test assertions.
|
||||||
|
std::unique_ptr< ::std::string> message_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Makes a successful assertion result.
|
||||||
|
GTEST_API_ AssertionResult AssertionSuccess();
|
||||||
|
|
||||||
|
// Makes a failed assertion result.
|
||||||
|
GTEST_API_ AssertionResult AssertionFailure();
|
||||||
|
|
||||||
|
// Makes a failed assertion result with the given failure message.
|
||||||
|
// Deprecated; use AssertionFailure() << msg.
|
||||||
|
GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
|
|
||||||
|
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_ASSERTION_RESULT_H_
|
|
@ -27,21 +27,21 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
|
||||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file defines the public API for death tests. It is
|
// 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
|
// #included by gtest.h so a user doesn't need to include this
|
||||||
// directly.
|
// directly.
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
|
||||||
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||||
|
|
||||||
#include "gtest/internal/gtest-death-test-internal.h"
|
#include "gtest/internal/gtest-death-test-internal.h"
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
|
|
||||||
// This flag controls the style of death tests. Valid values are "threadsafe",
|
// 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
|
// meaning that the death test child process will re-execute the test binary
|
||||||
// from the start, running only a single death test, or "fast",
|
// from the start, running only a single death test, or "fast",
|
||||||
|
@ -49,6 +49,8 @@ namespace testing {
|
||||||
// after forking.
|
// after forking.
|
||||||
GTEST_DECLARE_string_(death_test_style);
|
GTEST_DECLARE_string_(death_test_style);
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -103,7 +105,6 @@ GTEST_API_ bool InDeathTestChild();
|
||||||
//
|
//
|
||||||
// On the regular expressions used in death tests:
|
// On the regular expressions used in death tests:
|
||||||
//
|
//
|
||||||
// GOOGLETEST_CM0005 DO NOT DELETE
|
|
||||||
// On POSIX-compliant systems (*nix), we use the <regex.h> library,
|
// On POSIX-compliant systems (*nix), we use the <regex.h> library,
|
||||||
// which uses the POSIX extended regex syntax.
|
// which uses the POSIX extended regex syntax.
|
||||||
//
|
//
|
||||||
|
@ -169,23 +170,23 @@ GTEST_API_ bool InDeathTestChild();
|
||||||
// Asserts that a given `statement` causes the program to exit, with an
|
// Asserts that a given `statement` causes the program to exit, with an
|
||||||
// integer exit status that satisfies `predicate`, and emitting error output
|
// integer exit status that satisfies `predicate`, and emitting error output
|
||||||
// that matches `matcher`.
|
// that matches `matcher`.
|
||||||
# define ASSERT_EXIT(statement, predicate, matcher) \
|
#define ASSERT_EXIT(statement, predicate, matcher) \
|
||||||
GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_FATAL_FAILURE_)
|
GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
// Like `ASSERT_EXIT`, but continues on to successive tests in the
|
// Like `ASSERT_EXIT`, but continues on to successive tests in the
|
||||||
// test suite, if any:
|
// test suite, if any:
|
||||||
# define EXPECT_EXIT(statement, predicate, matcher) \
|
#define EXPECT_EXIT(statement, predicate, matcher) \
|
||||||
GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_NONFATAL_FAILURE_)
|
GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_NONFATAL_FAILURE_)
|
||||||
|
|
||||||
// Asserts that a given `statement` causes the program to exit, either by
|
// Asserts that a given `statement` causes the program to exit, either by
|
||||||
// explicitly exiting with a nonzero exit code or being killed by a
|
// explicitly exiting with a nonzero exit code or being killed by a
|
||||||
// signal, and emitting error output that matches `matcher`.
|
// signal, and emitting error output that matches `matcher`.
|
||||||
# define ASSERT_DEATH(statement, matcher) \
|
#define ASSERT_DEATH(statement, matcher) \
|
||||||
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
|
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
|
||||||
|
|
||||||
// Like `ASSERT_DEATH`, but continues on to successive tests in the
|
// Like `ASSERT_DEATH`, but continues on to successive tests in the
|
||||||
// test suite, if any:
|
// test suite, if any:
|
||||||
# define EXPECT_DEATH(statement, matcher) \
|
#define EXPECT_DEATH(statement, matcher) \
|
||||||
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
|
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher)
|
||||||
|
|
||||||
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
|
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
|
||||||
|
@ -197,22 +198,23 @@ class GTEST_API_ ExitedWithCode {
|
||||||
ExitedWithCode(const ExitedWithCode&) = default;
|
ExitedWithCode(const ExitedWithCode&) = default;
|
||||||
void operator=(const ExitedWithCode& other) = delete;
|
void operator=(const ExitedWithCode& other) = delete;
|
||||||
bool operator()(int exit_status) const;
|
bool operator()(int exit_status) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const int exit_code_;
|
const int exit_code_;
|
||||||
};
|
};
|
||||||
|
|
||||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
#if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||||
// Tests that an exit code describes an exit due to termination by a
|
// Tests that an exit code describes an exit due to termination by a
|
||||||
// given signal.
|
// given signal.
|
||||||
// GOOGLETEST_CM0006 DO NOT DELETE
|
|
||||||
class GTEST_API_ KilledBySignal {
|
class GTEST_API_ KilledBySignal {
|
||||||
public:
|
public:
|
||||||
explicit KilledBySignal(int signum);
|
explicit KilledBySignal(int signum);
|
||||||
bool operator()(int exit_status) const;
|
bool operator()(int exit_status) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const int signum_;
|
const int signum_;
|
||||||
};
|
};
|
||||||
# endif // !GTEST_OS_WINDOWS
|
#endif // !GTEST_OS_WINDOWS
|
||||||
|
|
||||||
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
|
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
|
||||||
// The death testing framework causes this to have interesting semantics,
|
// The death testing framework causes this to have interesting semantics,
|
||||||
|
@ -257,23 +259,21 @@ class GTEST_API_ KilledBySignal {
|
||||||
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
|
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
|
||||||
// }, "death");
|
// }, "death");
|
||||||
//
|
//
|
||||||
# ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
|
|
||||||
# define EXPECT_DEBUG_DEATH(statement, regex) \
|
#define EXPECT_DEBUG_DEATH(statement, regex) \
|
||||||
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
||||||
|
|
||||||
# define ASSERT_DEBUG_DEATH(statement, regex) \
|
#define ASSERT_DEBUG_DEATH(statement, regex) \
|
||||||
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
||||||
|
|
||||||
# else
|
#else
|
||||||
|
|
||||||
# define EXPECT_DEBUG_DEATH(statement, regex) \
|
#define EXPECT_DEBUG_DEATH(statement, regex) EXPECT_DEATH(statement, regex)
|
||||||
EXPECT_DEATH(statement, regex)
|
|
||||||
|
|
||||||
# define ASSERT_DEBUG_DEATH(statement, regex) \
|
#define ASSERT_DEBUG_DEATH(statement, regex) ASSERT_DEATH(statement, regex)
|
||||||
ASSERT_DEATH(statement, regex)
|
|
||||||
|
|
||||||
# endif // NDEBUG for EXPECT_DEBUG_DEATH
|
#endif // NDEBUG for EXPECT_DEBUG_DEATH
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
// This macro is used for implementing macros such as
|
// This macro is used for implementing macros such as
|
||||||
|
@ -311,11 +311,10 @@ class GTEST_API_ KilledBySignal {
|
||||||
// statement unconditionally returns or throws. The Message constructor at
|
// statement unconditionally returns or throws. The Message constructor at
|
||||||
// the end allows the syntax of streaming additional messages into the
|
// the end allows the syntax of streaming additional messages into the
|
||||||
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
|
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
|
||||||
# define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \
|
#define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
if (::testing::internal::AlwaysTrue()) { \
|
if (::testing::internal::AlwaysTrue()) { \
|
||||||
GTEST_LOG_(WARNING) \
|
GTEST_LOG_(WARNING) << "Death tests are not supported on this platform.\n" \
|
||||||
<< "Death tests are not supported on this platform.\n" \
|
|
||||||
<< "Statement '" #statement "' cannot be verified."; \
|
<< "Statement '" #statement "' cannot be verified."; \
|
||||||
} else if (::testing::internal::AlwaysFalse()) { \
|
} else if (::testing::internal::AlwaysFalse()) { \
|
||||||
::testing::internal::RE::PartialMatch(".*", (regex)); \
|
::testing::internal::RE::PartialMatch(".*", (regex)); \
|
||||||
|
@ -330,14 +329,14 @@ class GTEST_API_ KilledBySignal {
|
||||||
// useful when you are combining death test assertions with normal test
|
// useful when you are combining death test assertions with normal test
|
||||||
// assertions in one test.
|
// assertions in one test.
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
EXPECT_DEATH(statement, regex)
|
EXPECT_DEATH(statement, regex)
|
||||||
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
ASSERT_DEATH(statement, regex)
|
ASSERT_DEATH(statement, regex)
|
||||||
#else
|
#else
|
||||||
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, )
|
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, )
|
||||||
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return)
|
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
// This file implements just enough of the matcher interface to allow
|
// This file implements just enough of the matcher interface to allow
|
||||||
// EXPECT_DEATH and friends to accept a matcher argument.
|
// EXPECT_DEATH and friends to accept a matcher argument.
|
||||||
|
|
||||||
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||||
|
|
||||||
|
@ -98,11 +102,11 @@ class MatchResultListener {
|
||||||
private:
|
private:
|
||||||
::std::ostream* const stream_;
|
::std::ostream* const stream_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener);
|
MatchResultListener(const MatchResultListener&) = delete;
|
||||||
|
MatchResultListener& operator=(const MatchResultListener&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline MatchResultListener::~MatchResultListener() {
|
inline MatchResultListener::~MatchResultListener() {}
|
||||||
}
|
|
||||||
|
|
||||||
// An instance of a subclass of this knows how to describe itself as a
|
// An instance of a subclass of this knows how to describe itself as a
|
||||||
// matcher.
|
// matcher.
|
||||||
|
@ -176,27 +180,39 @@ namespace internal {
|
||||||
|
|
||||||
struct AnyEq {
|
struct AnyEq {
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
bool operator()(const A& a, const B& b) const { return a == b; }
|
bool operator()(const A& a, const B& b) const {
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct AnyNe {
|
struct AnyNe {
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
bool operator()(const A& a, const B& b) const { return a != b; }
|
bool operator()(const A& a, const B& b) const {
|
||||||
|
return a != b;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct AnyLt {
|
struct AnyLt {
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
bool operator()(const A& a, const B& b) const { return a < b; }
|
bool operator()(const A& a, const B& b) const {
|
||||||
|
return a < b;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct AnyGt {
|
struct AnyGt {
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
bool operator()(const A& a, const B& b) const { return a > b; }
|
bool operator()(const A& a, const B& b) const {
|
||||||
|
return a > b;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct AnyLe {
|
struct AnyLe {
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
bool operator()(const A& a, const B& b) const { return a <= b; }
|
bool operator()(const A& a, const B& b) const {
|
||||||
|
return a <= b;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct AnyGe {
|
struct AnyGe {
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
bool operator()(const A& a, const B& b) const { return a >= b; }
|
bool operator()(const A& a, const B& b) const {
|
||||||
|
return a >= b;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// A match result listener that ignores the explanation.
|
// A match result listener that ignores the explanation.
|
||||||
|
@ -205,7 +221,8 @@ class DummyMatchResultListener : public MatchResultListener {
|
||||||
DummyMatchResultListener() : MatchResultListener(nullptr) {}
|
DummyMatchResultListener() : MatchResultListener(nullptr) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener);
|
DummyMatchResultListener(const DummyMatchResultListener&) = delete;
|
||||||
|
DummyMatchResultListener& operator=(const DummyMatchResultListener&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A match result listener that forwards the explanation to a given
|
// A match result listener that forwards the explanation to a given
|
||||||
|
@ -217,7 +234,9 @@ class StreamMatchResultListener : public MatchResultListener {
|
||||||
: MatchResultListener(os) {}
|
: MatchResultListener(os) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
|
StreamMatchResultListener(const StreamMatchResultListener&) = delete;
|
||||||
|
StreamMatchResultListener& operator=(const StreamMatchResultListener&) =
|
||||||
|
delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SharedPayloadBase {
|
struct SharedPayloadBase {
|
||||||
|
@ -284,17 +303,18 @@ class MatcherBase : private MatcherDescriberInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MatcherBase() : vtable_(nullptr) {}
|
MatcherBase() : vtable_(nullptr), buffer_() {}
|
||||||
|
|
||||||
// Constructs a matcher from its implementation.
|
// Constructs a matcher from its implementation.
|
||||||
template <typename U>
|
template <typename U>
|
||||||
explicit MatcherBase(const MatcherInterface<U>* impl) {
|
explicit MatcherBase(const MatcherInterface<U>* impl)
|
||||||
|
: vtable_(nullptr), buffer_() {
|
||||||
Init(impl);
|
Init(impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename M, typename = typename std::remove_reference<
|
template <typename M, typename = typename std::remove_reference<
|
||||||
M>::type::is_gtest_matcher>
|
M>::type::is_gtest_matcher>
|
||||||
MatcherBase(M&& m) { // NOLINT
|
MatcherBase(M&& m) : vtable_(nullptr), buffer_() { // NOLINT
|
||||||
Init(std::forward<M>(m));
|
Init(std::forward<M>(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,8 +440,8 @@ class MatcherBase : private MatcherDescriberInterface {
|
||||||
static const M& Get(const MatcherBase& m) {
|
static const M& Get(const MatcherBase& m) {
|
||||||
// When inlined along with Init, need to be explicit to avoid violating
|
// When inlined along with Init, need to be explicit to avoid violating
|
||||||
// strict aliasing rules.
|
// strict aliasing rules.
|
||||||
const M *ptr = static_cast<const M*>(
|
const M* ptr =
|
||||||
static_cast<const void*>(&m.buffer_));
|
static_cast<const M*>(static_cast<const void*>(&m.buffer_));
|
||||||
return *ptr;
|
return *ptr;
|
||||||
}
|
}
|
||||||
static void Init(MatcherBase& m, M impl) {
|
static void Init(MatcherBase& m, M impl) {
|
||||||
|
@ -741,7 +761,7 @@ template <typename Rhs>
|
||||||
class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> {
|
class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> {
|
||||||
public:
|
public:
|
||||||
explicit EqMatcher(const Rhs& rhs)
|
explicit EqMatcher(const Rhs& rhs)
|
||||||
: ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) { }
|
: ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) {}
|
||||||
static const char* Desc() { return "is equal to"; }
|
static const char* Desc() { return "is equal to"; }
|
||||||
static const char* NegatedDesc() { return "isn't equal to"; }
|
static const char* NegatedDesc() { return "isn't equal to"; }
|
||||||
};
|
};
|
||||||
|
@ -749,7 +769,7 @@ template <typename Rhs>
|
||||||
class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> {
|
class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> {
|
||||||
public:
|
public:
|
||||||
explicit NeMatcher(const Rhs& rhs)
|
explicit NeMatcher(const Rhs& rhs)
|
||||||
: ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) { }
|
: ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) {}
|
||||||
static const char* Desc() { return "isn't equal to"; }
|
static const char* Desc() { return "isn't equal to"; }
|
||||||
static const char* NegatedDesc() { return "is equal to"; }
|
static const char* NegatedDesc() { return "is equal to"; }
|
||||||
};
|
};
|
||||||
|
@ -757,7 +777,7 @@ template <typename Rhs>
|
||||||
class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> {
|
class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> {
|
||||||
public:
|
public:
|
||||||
explicit LtMatcher(const Rhs& rhs)
|
explicit LtMatcher(const Rhs& rhs)
|
||||||
: ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) { }
|
: ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) {}
|
||||||
static const char* Desc() { return "is <"; }
|
static const char* Desc() { return "is <"; }
|
||||||
static const char* NegatedDesc() { return "isn't <"; }
|
static const char* NegatedDesc() { return "isn't <"; }
|
||||||
};
|
};
|
||||||
|
@ -765,7 +785,7 @@ template <typename Rhs>
|
||||||
class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> {
|
class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> {
|
||||||
public:
|
public:
|
||||||
explicit GtMatcher(const Rhs& rhs)
|
explicit GtMatcher(const Rhs& rhs)
|
||||||
: ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) { }
|
: ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) {}
|
||||||
static const char* Desc() { return "is >"; }
|
static const char* Desc() { return "is >"; }
|
||||||
static const char* NegatedDesc() { return "isn't >"; }
|
static const char* NegatedDesc() { return "isn't >"; }
|
||||||
};
|
};
|
||||||
|
@ -773,7 +793,7 @@ template <typename Rhs>
|
||||||
class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> {
|
class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> {
|
||||||
public:
|
public:
|
||||||
explicit LeMatcher(const Rhs& rhs)
|
explicit LeMatcher(const Rhs& rhs)
|
||||||
: ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) { }
|
: ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) {}
|
||||||
static const char* Desc() { return "is <="; }
|
static const char* Desc() { return "is <="; }
|
||||||
static const char* NegatedDesc() { return "isn't <="; }
|
static const char* NegatedDesc() { return "isn't <="; }
|
||||||
};
|
};
|
||||||
|
@ -781,7 +801,7 @@ template <typename Rhs>
|
||||||
class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
|
class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
|
||||||
public:
|
public:
|
||||||
explicit GeMatcher(const Rhs& rhs)
|
explicit GeMatcher(const Rhs& rhs)
|
||||||
: ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) { }
|
: ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) {}
|
||||||
static const char* Desc() { return "is >="; }
|
static const char* Desc() { return "is >="; }
|
||||||
static const char* NegatedDesc() { return "isn't >="; }
|
static const char* NegatedDesc() { return "isn't >="; }
|
||||||
};
|
};
|
||||||
|
@ -872,12 +892,16 @@ PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
|
||||||
// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
|
// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
|
||||||
// wouldn't compile.
|
// wouldn't compile.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
|
inline internal::EqMatcher<T> Eq(T x) {
|
||||||
|
return internal::EqMatcher<T>(x);
|
||||||
|
}
|
||||||
|
|
||||||
// Constructs a Matcher<T> from a 'value' of type T. The constructed
|
// Constructs a Matcher<T> from a 'value' of type T. The constructed
|
||||||
// matcher matches any value that's equal to 'value'.
|
// matcher matches any value that's equal to 'value'.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Matcher<T>::Matcher(T value) { *this = Eq(value); }
|
Matcher<T>::Matcher(T value) {
|
||||||
|
*this = Eq(value);
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a monomorphic matcher that matches anything with type Lhs
|
// Creates a monomorphic matcher that matches anything with type Lhs
|
||||||
// and equal to rhs. A user may need to use this instead of Eq(...)
|
// and equal to rhs. A user may need to use this instead of Eq(...)
|
||||||
|
@ -892,7 +916,9 @@ Matcher<T>::Matcher(T value) { *this = Eq(value); }
|
||||||
// can always write Matcher<T>(Lt(5)) to be explicit about the type,
|
// can always write Matcher<T>(Lt(5)) to be explicit about the type,
|
||||||
// for example.
|
// for example.
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); }
|
inline Matcher<Lhs> TypedEq(const Rhs& rhs) {
|
||||||
|
return Eq(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a polymorphic matcher that matches anything >= x.
|
// Creates a polymorphic matcher that matches anything >= x.
|
||||||
template <typename Rhs>
|
template <typename Rhs>
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
|
||||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file defines the Message class.
|
// This header file defines the Message class.
|
||||||
|
@ -42,7 +41,9 @@
|
||||||
// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
|
// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
|
||||||
// program!
|
// program!
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||||
|
@ -110,7 +111,7 @@ class GTEST_API_ Message {
|
||||||
|
|
||||||
// Streams a non-pointer value to this object.
|
// Streams a non-pointer value to this object.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Message& operator <<(const T& val) {
|
inline Message& operator<<(const T& val) {
|
||||||
// Some libraries overload << for STL containers. These
|
// Some libraries overload << for STL containers. These
|
||||||
// overloads are defined in the global namespace instead of ::std.
|
// overloads are defined in the global namespace instead of ::std.
|
||||||
//
|
//
|
||||||
|
@ -125,7 +126,7 @@ class GTEST_API_ Message {
|
||||||
// from the global namespace. With this using declaration,
|
// from the global namespace. With this using declaration,
|
||||||
// overloads of << defined in the global namespace and those
|
// overloads of << defined in the global namespace and those
|
||||||
// visible via Koenig lookup are both exposed in this function.
|
// visible via Koenig lookup are both exposed in this function.
|
||||||
using ::operator <<;
|
using ::operator<<;
|
||||||
*ss_ << val;
|
*ss_ << val;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +145,7 @@ class GTEST_API_ Message {
|
||||||
// ensure consistent result across compilers, we always treat NULL
|
// ensure consistent result across compilers, we always treat NULL
|
||||||
// as "(null)".
|
// as "(null)".
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Message& operator <<(T* const& pointer) { // NOLINT
|
inline Message& operator<<(T* const& pointer) { // NOLINT
|
||||||
if (pointer == nullptr) {
|
if (pointer == nullptr) {
|
||||||
*ss_ << "(null)";
|
*ss_ << "(null)";
|
||||||
} else {
|
} else {
|
||||||
|
@ -159,25 +160,23 @@ class GTEST_API_ Message {
|
||||||
// templatized version above. Without this definition, streaming
|
// templatized version above. Without this definition, streaming
|
||||||
// endl or other basic IO manipulators to Message will confuse the
|
// endl or other basic IO manipulators to Message will confuse the
|
||||||
// compiler.
|
// compiler.
|
||||||
Message& operator <<(BasicNarrowIoManip val) {
|
Message& operator<<(BasicNarrowIoManip val) {
|
||||||
*ss_ << val;
|
*ss_ << val;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instead of 1/0, we want to see true/false for bool values.
|
// Instead of 1/0, we want to see true/false for bool values.
|
||||||
Message& operator <<(bool b) {
|
Message& operator<<(bool b) { return *this << (b ? "true" : "false"); }
|
||||||
return *this << (b ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
// These two overloads allow streaming a wide C string to a Message
|
// These two overloads allow streaming a wide C string to a Message
|
||||||
// using the UTF-8 encoding.
|
// using the UTF-8 encoding.
|
||||||
Message& operator <<(const wchar_t* wide_c_str);
|
Message& operator<<(const wchar_t* wide_c_str);
|
||||||
Message& operator <<(wchar_t* wide_c_str);
|
Message& operator<<(wchar_t* wide_c_str);
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
// Converts the given wide string to a narrow string using the UTF-8
|
// Converts the given wide string to a narrow string using the UTF-8
|
||||||
// encoding, and streams the result to this Message object.
|
// encoding, and streams the result to this Message object.
|
||||||
Message& operator <<(const ::std::wstring& wstr);
|
Message& operator<<(const ::std::wstring& wstr);
|
||||||
#endif // GTEST_HAS_STD_WSTRING
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|
||||||
// Gets the text streamed to this object so far as an std::string.
|
// Gets the text streamed to this object so far as an std::string.
|
||||||
|
@ -196,7 +195,7 @@ class GTEST_API_ Message {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Streams a Message to an ostream.
|
// Streams a Message to an ostream.
|
||||||
inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
|
inline std::ostream& operator<<(std::ostream& os, const Message& sb) {
|
||||||
return os << sb.GetString();
|
return os << sb.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,14 @@
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Macros and functions for implementing parameterized tests
|
// Macros and functions for implementing parameterized tests
|
||||||
// in Google C++ Testing and Mocking Framework (Google Test)
|
// in Google C++ Testing and Mocking Framework (Google Test)
|
||||||
//
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||||
|
|
||||||
|
@ -353,9 +356,7 @@ internal::ValueArray<T...> Values(T... v) {
|
||||||
// }
|
// }
|
||||||
// INSTANTIATE_TEST_SUITE_P(BoolSequence, FlagDependentTest, Bool());
|
// INSTANTIATE_TEST_SUITE_P(BoolSequence, FlagDependentTest, Bool());
|
||||||
//
|
//
|
||||||
inline internal::ParamGenerator<bool> Bool() {
|
inline internal::ParamGenerator<bool> Bool() { return Values(false, true); }
|
||||||
return Values(false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combine() allows the user to combine two or more sequences to produce
|
// Combine() allows the user to combine two or more sequences to produce
|
||||||
// values of a Cartesian product of those sequences' elements.
|
// values of a Cartesian product of those sequences' elements.
|
||||||
|
@ -428,8 +429,11 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
|
static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
|
||||||
test_name)); \
|
(const GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) &) = delete; \
|
||||||
|
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) & operator=( \
|
||||||
|
const GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||||
|
test_name) &) = delete; /* NOLINT */ \
|
||||||
}; \
|
}; \
|
||||||
int GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
int GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||||
test_name)::gtest_registering_dummy_ = \
|
test_name)::gtest_registering_dummy_ = \
|
||||||
|
@ -487,7 +491,6 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
||||||
>est_##prefix##test_suite_name##_EvalGenerateName_, \
|
>est_##prefix##test_suite_name##_EvalGenerateName_, \
|
||||||
__FILE__, __LINE__)
|
__FILE__, __LINE__)
|
||||||
|
|
||||||
|
|
||||||
// Allow Marking a Parameterized test class as not needing to be instantiated.
|
// Allow Marking a Parameterized test class as not needing to be instantiated.
|
||||||
#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \
|
#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \
|
||||||
namespace gtest_do_not_use_outside_namespace_scope {} \
|
namespace gtest_do_not_use_outside_namespace_scope {} \
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// Google Test - The Google C++ Testing and Mocking Framework
|
// Google Test - The Google C++ Testing and Mocking Framework
|
||||||
//
|
//
|
||||||
// This file implements a universal value printer that can print a
|
// This file implements a universal value printer that can print a
|
||||||
|
@ -95,7 +94,9 @@
|
||||||
// being defined as many user-defined container types don't have
|
// being defined as many user-defined container types don't have
|
||||||
// value_type.
|
// value_type.
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||||
|
@ -257,12 +258,10 @@ struct ConvertibleToStringViewPrinter {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Prints the given number of bytes in the given object to the given
|
// Prints the given number of bytes in the given object to the given
|
||||||
// ostream.
|
// ostream.
|
||||||
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
|
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
|
||||||
size_t count,
|
size_t count, ::std::ostream* os);
|
||||||
::std::ostream* os);
|
|
||||||
struct RawBytesPrinter {
|
struct RawBytesPrinter {
|
||||||
// SFINAE on `sizeof` to make sure we have a complete type.
|
// SFINAE on `sizeof` to make sure we have a complete type.
|
||||||
template <typename T, size_t = sizeof(T)>
|
template <typename T, size_t = sizeof(T)>
|
||||||
|
@ -360,7 +359,7 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
|
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
|
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
|
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
|
||||||
#ifdef __cpp_char8_t
|
#ifdef __cpp_lib_char8_t
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char8_t);
|
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char8_t);
|
||||||
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char8_t);
|
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char8_t);
|
||||||
#endif
|
#endif
|
||||||
|
@ -410,8 +409,8 @@ GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
std::string FormatForComparisonFailureMessage(
|
std::string FormatForComparisonFailureMessage(const T1& value,
|
||||||
const T1& value, const T2& /* other_operand */) {
|
const T2& /* other_operand */) {
|
||||||
return FormatForComparison<T1, T2>::Format(value);
|
return FormatForComparison<T1, T2>::Format(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,6 +478,12 @@ inline void PrintTo(char8_t c, ::std::ostream* os) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// gcc/clang __{u,}int128_t
|
||||||
|
#if defined(__SIZEOF_INT128__)
|
||||||
|
GTEST_API_ void PrintTo(__uint128_t v, ::std::ostream* os);
|
||||||
|
GTEST_API_ void PrintTo(__int128_t v, ::std::ostream* os);
|
||||||
|
#endif // __SIZEOF_INT128__
|
||||||
|
|
||||||
// Overloads for C strings.
|
// Overloads for C strings.
|
||||||
GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
|
GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
|
||||||
inline void PrintTo(char* s, ::std::ostream* os) {
|
inline void PrintTo(char* s, ::std::ostream* os) {
|
||||||
|
@ -545,7 +550,7 @@ void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overloads for ::std::string.
|
// Overloads for ::std::string.
|
||||||
GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
|
GTEST_API_ void PrintStringTo(const ::std::string& s, ::std::ostream* os);
|
||||||
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
|
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
|
||||||
PrintStringTo(s, os);
|
PrintStringTo(s, os);
|
||||||
}
|
}
|
||||||
|
@ -572,7 +577,7 @@ inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) {
|
||||||
|
|
||||||
// Overloads for ::std::wstring.
|
// Overloads for ::std::wstring.
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
|
GTEST_API_ void PrintWideStringTo(const ::std::wstring& s, ::std::ostream* os);
|
||||||
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
|
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
|
||||||
PrintWideStringTo(s, os);
|
PrintWideStringTo(s, os);
|
||||||
}
|
}
|
||||||
|
@ -587,6 +592,12 @@ inline void PrintTo(internal::StringView sp, ::std::ostream* os) {
|
||||||
|
|
||||||
inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
|
inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
|
||||||
|
|
||||||
|
#if GTEST_HAS_RTTI
|
||||||
|
inline void PrintTo(const std::type_info& info, std::ostream* os) {
|
||||||
|
*os << internal::GetTypeName(info);
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_RTTI
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) {
|
void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) {
|
||||||
UniversalPrinter<T&>::Print(ref.get(), os);
|
UniversalPrinter<T&>::Print(ref.get(), os);
|
||||||
|
@ -744,6 +755,14 @@ class UniversalPrinter<Optional<T>> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class UniversalPrinter<decltype(Nullopt())> {
|
||||||
|
public:
|
||||||
|
static void Print(decltype(Nullopt()), ::std::ostream* os) {
|
||||||
|
*os << "(nullopt)";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // GTEST_INTERNAL_HAS_OPTIONAL
|
#endif // GTEST_INTERNAL_HAS_OPTIONAL
|
||||||
|
|
||||||
#if GTEST_INTERNAL_HAS_VARIANT
|
#if GTEST_INTERNAL_HAS_VARIANT
|
||||||
|
@ -802,8 +821,8 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// This overload prints a (const) char array compactly.
|
// This overload prints a (const) char array compactly.
|
||||||
GTEST_API_ void UniversalPrintArray(
|
GTEST_API_ void UniversalPrintArray(const char* begin, size_t len,
|
||||||
const char* begin, size_t len, ::std::ostream* os);
|
::std::ostream* os);
|
||||||
|
|
||||||
#ifdef __cpp_char8_t
|
#ifdef __cpp_char8_t
|
||||||
// This overload prints a (const) char8_t array compactly.
|
// This overload prints a (const) char8_t array compactly.
|
||||||
|
@ -820,8 +839,8 @@ GTEST_API_ void UniversalPrintArray(const char32_t* begin, size_t len,
|
||||||
::std::ostream* os);
|
::std::ostream* os);
|
||||||
|
|
||||||
// This overload prints a (const) wchar_t array compactly.
|
// This overload prints a (const) wchar_t array compactly.
|
||||||
GTEST_API_ void UniversalPrintArray(
|
GTEST_API_ void UniversalPrintArray(const wchar_t* begin, size_t len,
|
||||||
const wchar_t* begin, size_t len, ::std::ostream* os);
|
::std::ostream* os);
|
||||||
|
|
||||||
// Implements printing an array type T[N].
|
// Implements printing an array type T[N].
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
|
@ -980,10 +999,10 @@ void UniversalPrint(const T& value, ::std::ostream* os) {
|
||||||
UniversalPrinter<T1>::Print(value, os);
|
UniversalPrinter<T1>::Print(value, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef ::std::vector< ::std::string> Strings;
|
typedef ::std::vector<::std::string> Strings;
|
||||||
|
|
||||||
// Tersely prints the first N fields of a tuple to a string vector,
|
// Tersely prints the first N fields of a tuple to a string vector,
|
||||||
// one element for each field.
|
// one element for each field.
|
||||||
template <typename Tuple>
|
template <typename Tuple>
|
||||||
void TersePrintPrefixToStrings(const Tuple&, std::integral_constant<size_t, 0>,
|
void TersePrintPrefixToStrings(const Tuple&, std::integral_constant<size_t, 0>,
|
||||||
Strings*) {}
|
Strings*) {}
|
||||||
|
|
|
@ -27,12 +27,9 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
|
||||||
// Utilities for testing Google Test itself and code that uses Google Test
|
// Utilities for testing Google Test itself and code that uses Google Test
|
||||||
// (e.g. frameworks built on top of Google Test).
|
// (e.g. frameworks built on top of Google Test).
|
||||||
|
|
||||||
// GOOGLETEST_CM0004 DO NOT DELETE
|
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||||
|
|
||||||
|
@ -88,7 +85,10 @@ class GTEST_API_ ScopedFakeTestPartResultReporter
|
||||||
TestPartResultReporterInterface* old_reporter_;
|
TestPartResultReporterInterface* old_reporter_;
|
||||||
TestPartResultArray* const result_;
|
TestPartResultArray* const result_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
|
ScopedFakeTestPartResultReporter(const ScopedFakeTestPartResultReporter&) =
|
||||||
|
delete;
|
||||||
|
ScopedFakeTestPartResultReporter& operator=(
|
||||||
|
const ScopedFakeTestPartResultReporter&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -104,12 +104,14 @@ class GTEST_API_ SingleFailureChecker {
|
||||||
SingleFailureChecker(const TestPartResultArray* results,
|
SingleFailureChecker(const TestPartResultArray* results,
|
||||||
TestPartResult::Type type, const std::string& substr);
|
TestPartResult::Type type, const std::string& substr);
|
||||||
~SingleFailureChecker();
|
~SingleFailureChecker();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const TestPartResultArray* const results_;
|
const TestPartResultArray* const results_;
|
||||||
const TestPartResult::Type type_;
|
const TestPartResult::Type type_;
|
||||||
const std::string substr_;
|
const std::string substr_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
|
SingleFailureChecker(const SingleFailureChecker&) = delete;
|
||||||
|
SingleFailureChecker& operator=(const SingleFailureChecker&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -119,7 +121,8 @@ class GTEST_API_ SingleFailureChecker {
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
|
|
||||||
// A set of macros for testing Google Test assertions or code that's expected
|
// 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
|
// to generate Google Test fatal failures (e.g. a failure from an ASSERT_EQ, but
|
||||||
|
// not a non-fatal failure, as from EXPECT_EQ). It verifies that the given
|
||||||
// statement will cause exactly one fatal Google Test failure with 'substr'
|
// statement will cause exactly one fatal Google Test failure with 'substr'
|
||||||
// being part of the failure message.
|
// being part of the failure message.
|
||||||
//
|
//
|
||||||
|
@ -143,42 +146,44 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
// gtest_unittest.cc will fail to compile if we do that.
|
// gtest_unittest.cc will fail to compile if we do that.
|
||||||
#define EXPECT_FATAL_FAILURE(statement, substr) \
|
#define EXPECT_FATAL_FAILURE(statement, substr) \
|
||||||
do { \
|
do { \
|
||||||
class GTestExpectFatalFailureHelper {\
|
class GTestExpectFatalFailureHelper { \
|
||||||
public:\
|
public: \
|
||||||
static void Execute() { statement; }\
|
static void Execute() { statement; } \
|
||||||
};\
|
}; \
|
||||||
::testing::TestPartResultArray gtest_failures;\
|
::testing::TestPartResultArray gtest_failures; \
|
||||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
::testing::internal::SingleFailureChecker gtest_checker( \
|
||||||
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr)); \
|
||||||
{\
|
{ \
|
||||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
|
||||||
::testing::ScopedFakeTestPartResultReporter:: \
|
::testing::ScopedFakeTestPartResultReporter:: \
|
||||||
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
INTERCEPT_ONLY_CURRENT_THREAD, \
|
||||||
GTestExpectFatalFailureHelper::Execute();\
|
>est_failures); \
|
||||||
}\
|
GTestExpectFatalFailureHelper::Execute(); \
|
||||||
|
} \
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||||
do { \
|
do { \
|
||||||
class GTestExpectFatalFailureHelper {\
|
class GTestExpectFatalFailureHelper { \
|
||||||
public:\
|
public: \
|
||||||
static void Execute() { statement; }\
|
static void Execute() { statement; } \
|
||||||
};\
|
}; \
|
||||||
::testing::TestPartResultArray gtest_failures;\
|
::testing::TestPartResultArray gtest_failures; \
|
||||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
::testing::internal::SingleFailureChecker gtest_checker( \
|
||||||
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr)); \
|
||||||
{\
|
{ \
|
||||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
|
||||||
::testing::ScopedFakeTestPartResultReporter:: \
|
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
|
||||||
INTERCEPT_ALL_THREADS, >est_failures);\
|
>est_failures); \
|
||||||
GTestExpectFatalFailureHelper::Execute();\
|
GTestExpectFatalFailureHelper::Execute(); \
|
||||||
}\
|
} \
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
// A macro for testing Google Test assertions or code that's expected to
|
// A macro for testing Google Test assertions or code that's expected to
|
||||||
// generate Google Test non-fatal failures. It asserts that the given
|
// generate Google Test non-fatal failures (e.g. a failure from an EXPECT_EQ,
|
||||||
// statement will cause exactly one non-fatal Google Test failure with 'substr'
|
// but not from an ASSERT_EQ). It asserts that the given statement will cause
|
||||||
// being part of the failure message.
|
// 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
|
// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
|
||||||
// affects and considers failures generated in the current thread and
|
// affects and considers failures generated in the current thread and
|
||||||
|
@ -208,31 +213,36 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
||||||
// to avoid an MSVC warning on unreachable code.
|
// to avoid an MSVC warning on unreachable code.
|
||||||
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
|
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
|
||||||
do {\
|
do { \
|
||||||
::testing::TestPartResultArray gtest_failures;\
|
::testing::TestPartResultArray gtest_failures; \
|
||||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
::testing::internal::SingleFailureChecker gtest_checker( \
|
||||||
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
||||||
(substr));\
|
(substr)); \
|
||||||
{\
|
{ \
|
||||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
|
||||||
::testing::ScopedFakeTestPartResultReporter:: \
|
::testing::ScopedFakeTestPartResultReporter:: \
|
||||||
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
INTERCEPT_ONLY_CURRENT_THREAD, \
|
||||||
if (::testing::internal::AlwaysTrue()) { statement; }\
|
>est_failures); \
|
||||||
}\
|
if (::testing::internal::AlwaysTrue()) { \
|
||||||
|
statement; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||||
do {\
|
do { \
|
||||||
::testing::TestPartResultArray gtest_failures;\
|
::testing::TestPartResultArray gtest_failures; \
|
||||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
::testing::internal::SingleFailureChecker gtest_checker( \
|
||||||
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
||||||
(substr));\
|
(substr)); \
|
||||||
{\
|
{ \
|
||||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
|
||||||
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
|
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
|
||||||
>est_failures);\
|
>est_failures); \
|
||||||
if (::testing::internal::AlwaysTrue()) { statement; }\
|
if (::testing::internal::AlwaysTrue()) { \
|
||||||
}\
|
statement; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||||
|
|
|
@ -26,14 +26,17 @@
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
#include "gtest/internal/gtest-string.h"
|
#include "gtest/internal/gtest-string.h"
|
||||||
|
|
||||||
|
@ -142,7 +145,8 @@ class GTEST_API_ TestPartResultArray {
|
||||||
private:
|
private:
|
||||||
std::vector<TestPartResult> array_;
|
std::vector<TestPartResult> array_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
|
TestPartResultArray(const TestPartResultArray&) = delete;
|
||||||
|
TestPartResultArray& operator=(const TestPartResultArray&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This interface knows how to report a test part result.
|
// This interface knows how to report a test part result.
|
||||||
|
@ -168,11 +172,13 @@ class GTEST_API_ HasNewFatalFailureHelper
|
||||||
~HasNewFatalFailureHelper() override;
|
~HasNewFatalFailureHelper() override;
|
||||||
void ReportTestPartResult(const TestPartResult& result) override;
|
void ReportTestPartResult(const TestPartResult& result) override;
|
||||||
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
|
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool has_new_fatal_failure_;
|
bool has_new_fatal_failure_;
|
||||||
TestPartResultReporterInterface* original_reporter_;
|
TestPartResultReporterInterface* original_reporter_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
|
HasNewFatalFailureHelper(const HasNewFatalFailureHelper&) = delete;
|
||||||
|
HasNewFatalFailureHelper& operator=(const HasNewFatalFailureHelper&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
|
@ -27,7 +27,9 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
|
||||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file defines the public API for Google Test. It should be
|
// This header file defines the public API for Google Test. It should be
|
||||||
|
@ -47,8 +46,6 @@
|
||||||
// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
|
// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
|
||||||
// easyUnit framework.
|
// easyUnit framework.
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_H_
|
||||||
|
|
||||||
|
@ -59,31 +56,22 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/gtest-assertion-result.h"
|
||||||
#include "gtest/internal/gtest-string.h"
|
|
||||||
#include "gtest/gtest-death-test.h"
|
#include "gtest/gtest-death-test.h"
|
||||||
#include "gtest/gtest-matchers.h"
|
#include "gtest/gtest-matchers.h"
|
||||||
#include "gtest/gtest-message.h"
|
#include "gtest/gtest-message.h"
|
||||||
#include "gtest/gtest-param-test.h"
|
#include "gtest/gtest-param-test.h"
|
||||||
#include "gtest/gtest-printers.h"
|
#include "gtest/gtest-printers.h"
|
||||||
#include "gtest/gtest_prod.h"
|
|
||||||
#include "gtest/gtest-test-part.h"
|
#include "gtest/gtest-test-part.h"
|
||||||
#include "gtest/gtest-typed-test.h"
|
#include "gtest/gtest-typed-test.h"
|
||||||
|
#include "gtest/gtest_pred_impl.h"
|
||||||
|
#include "gtest/gtest_prod.h"
|
||||||
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
#include "gtest/internal/gtest-string.h"
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
|
|
||||||
// Silence C4100 (unreferenced formal parameter) and 4805
|
|
||||||
// unsafe mix of type 'const int' and type 'const bool'
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# pragma warning(push)
|
|
||||||
# pragma warning(disable:4805)
|
|
||||||
# pragma warning(disable:4100)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Declares the flags.
|
// Declares the flags.
|
||||||
|
|
||||||
// This flag temporary enables the disabled tests.
|
// This flag temporary enables the disabled tests.
|
||||||
|
@ -138,6 +126,12 @@ GTEST_DECLARE_int32_(random_seed);
|
||||||
// is 1. If the value is -1 the tests are repeating forever.
|
// is 1. If the value is -1 the tests are repeating forever.
|
||||||
GTEST_DECLARE_int32_(repeat);
|
GTEST_DECLARE_int32_(repeat);
|
||||||
|
|
||||||
|
// This flag controls whether Google Test Environments are recreated for each
|
||||||
|
// repeat of the tests. The default value is true. If set to false the global
|
||||||
|
// test Environment objects are only set up once, for the first iteration, and
|
||||||
|
// only torn down once, for the last.
|
||||||
|
GTEST_DECLARE_bool_(recreate_environments_when_repeating);
|
||||||
|
|
||||||
// This flag controls whether Google Test includes Google Test internal
|
// This flag controls whether Google Test includes Google Test internal
|
||||||
// stack frames in failure stack traces.
|
// stack frames in failure stack traces.
|
||||||
GTEST_DECLARE_bool_(show_internal_stack_frames);
|
GTEST_DECLARE_bool_(show_internal_stack_frames);
|
||||||
|
@ -163,6 +157,16 @@ GTEST_DECLARE_string_(stream_result_to);
|
||||||
GTEST_DECLARE_string_(flagfile);
|
GTEST_DECLARE_string_(flagfile);
|
||||||
#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
|
#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Silence C4100 (unreferenced formal parameter) and 4805
|
||||||
|
// unsafe mix of type 'const int' and type 'const bool'
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4805)
|
||||||
|
#pragma warning(disable : 4100)
|
||||||
|
#endif
|
||||||
|
|
||||||
// The upper limit for valid stack trace depths.
|
// The upper limit for valid stack trace depths.
|
||||||
const int kMaxStackTraceDepth = 100;
|
const int kMaxStackTraceDepth = 100;
|
||||||
|
|
||||||
|
@ -201,193 +205,6 @@ using TestCase = TestSuite;
|
||||||
class TestInfo;
|
class TestInfo;
|
||||||
class UnitTest;
|
class UnitTest;
|
||||||
|
|
||||||
// A class for indicating whether an assertion was successful. When
|
|
||||||
// the assertion wasn't successful, the AssertionResult object
|
|
||||||
// remembers a non-empty message that describes how it failed.
|
|
||||||
//
|
|
||||||
// To create an instance of this class, use one of the factory functions
|
|
||||||
// (AssertionSuccess() and AssertionFailure()).
|
|
||||||
//
|
|
||||||
// This class is useful for two purposes:
|
|
||||||
// 1. Defining predicate functions to be used with Boolean test assertions
|
|
||||||
// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
|
|
||||||
// 2. Defining predicate-format functions to be
|
|
||||||
// used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
|
|
||||||
//
|
|
||||||
// For example, if you define IsEven predicate:
|
|
||||||
//
|
|
||||||
// testing::AssertionResult IsEven(int n) {
|
|
||||||
// if ((n % 2) == 0)
|
|
||||||
// return testing::AssertionSuccess();
|
|
||||||
// else
|
|
||||||
// return testing::AssertionFailure() << n << " is odd";
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
|
|
||||||
// will print the message
|
|
||||||
//
|
|
||||||
// Value of: IsEven(Fib(5))
|
|
||||||
// Actual: false (5 is odd)
|
|
||||||
// Expected: true
|
|
||||||
//
|
|
||||||
// instead of a more opaque
|
|
||||||
//
|
|
||||||
// Value of: IsEven(Fib(5))
|
|
||||||
// Actual: false
|
|
||||||
// Expected: true
|
|
||||||
//
|
|
||||||
// in case IsEven is a simple Boolean predicate.
|
|
||||||
//
|
|
||||||
// If you expect your predicate to be reused and want to support informative
|
|
||||||
// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
|
|
||||||
// about half as often as positive ones in our tests), supply messages for
|
|
||||||
// both success and failure cases:
|
|
||||||
//
|
|
||||||
// testing::AssertionResult IsEven(int n) {
|
|
||||||
// if ((n % 2) == 0)
|
|
||||||
// return testing::AssertionSuccess() << n << " is even";
|
|
||||||
// else
|
|
||||||
// return testing::AssertionFailure() << n << " is odd";
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
|
|
||||||
//
|
|
||||||
// Value of: IsEven(Fib(6))
|
|
||||||
// Actual: true (8 is even)
|
|
||||||
// Expected: false
|
|
||||||
//
|
|
||||||
// NB: Predicates that support negative Boolean assertions have reduced
|
|
||||||
// performance in positive ones so be careful not to use them in tests
|
|
||||||
// that have lots (tens of thousands) of positive Boolean assertions.
|
|
||||||
//
|
|
||||||
// To use this class with EXPECT_PRED_FORMAT assertions such as:
|
|
||||||
//
|
|
||||||
// // Verifies that Foo() returns an even number.
|
|
||||||
// EXPECT_PRED_FORMAT1(IsEven, Foo());
|
|
||||||
//
|
|
||||||
// you need to define:
|
|
||||||
//
|
|
||||||
// testing::AssertionResult IsEven(const char* expr, int n) {
|
|
||||||
// if ((n % 2) == 0)
|
|
||||||
// return testing::AssertionSuccess();
|
|
||||||
// else
|
|
||||||
// return testing::AssertionFailure()
|
|
||||||
// << "Expected: " << expr << " is even\n Actual: it's " << n;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// If Foo() returns 5, you will see the following message:
|
|
||||||
//
|
|
||||||
// Expected: Foo() is even
|
|
||||||
// Actual: it's 5
|
|
||||||
//
|
|
||||||
class GTEST_API_ AssertionResult {
|
|
||||||
public:
|
|
||||||
// Copy constructor.
|
|
||||||
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
|
||||||
AssertionResult(const AssertionResult& other);
|
|
||||||
|
|
||||||
// C4800 is a level 3 warning in Visual Studio 2015 and earlier.
|
|
||||||
// This warning is not emitted in Visual Studio 2017.
|
|
||||||
// This warning is off by default starting in Visual Studio 2019 but can be
|
|
||||||
// enabled with command-line options.
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Used in the EXPECT_TRUE/FALSE(bool_expression).
|
|
||||||
//
|
|
||||||
// T must be contextually convertible to bool.
|
|
||||||
//
|
|
||||||
// The second parameter prevents this overload from being considered if
|
|
||||||
// the argument is implicitly convertible to AssertionResult. In that case
|
|
||||||
// we want AssertionResult's copy constructor to be used.
|
|
||||||
template <typename T>
|
|
||||||
explicit AssertionResult(
|
|
||||||
const T& success,
|
|
||||||
typename std::enable_if<
|
|
||||||
!std::is_convertible<T, AssertionResult>::value>::type*
|
|
||||||
/*enabler*/
|
|
||||||
= nullptr)
|
|
||||||
: success_(success) {}
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Assignment operator.
|
|
||||||
AssertionResult& operator=(AssertionResult other) {
|
|
||||||
swap(other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if and only if the assertion succeeded.
|
|
||||||
operator bool() const { return success_; } // NOLINT
|
|
||||||
|
|
||||||
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
|
|
||||||
AssertionResult operator!() const;
|
|
||||||
|
|
||||||
// Returns the text streamed into this AssertionResult. Test assertions
|
|
||||||
// use it when they fail (i.e., the predicate's outcome doesn't match the
|
|
||||||
// assertion's expectation). When nothing has been streamed into the
|
|
||||||
// object, returns an empty string.
|
|
||||||
const char* message() const {
|
|
||||||
return message_.get() != nullptr ? message_->c_str() : "";
|
|
||||||
}
|
|
||||||
// Deprecated; please use message() instead.
|
|
||||||
const char* failure_message() const { return message(); }
|
|
||||||
|
|
||||||
// Streams a custom failure message into this object.
|
|
||||||
template <typename T> AssertionResult& operator<<(const T& value) {
|
|
||||||
AppendMessage(Message() << value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allows streaming basic output manipulators such as endl or flush into
|
|
||||||
// this object.
|
|
||||||
AssertionResult& operator<<(
|
|
||||||
::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
|
|
||||||
AppendMessage(Message() << basic_manipulator);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Appends the contents of message to message_.
|
|
||||||
void AppendMessage(const Message& a_message) {
|
|
||||||
if (message_.get() == nullptr) message_.reset(new ::std::string);
|
|
||||||
message_->append(a_message.GetString().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap the contents of this AssertionResult with other.
|
|
||||||
void swap(AssertionResult& other);
|
|
||||||
|
|
||||||
// Stores result of the assertion predicate.
|
|
||||||
bool success_;
|
|
||||||
// Stores the message describing the condition in case the expectation
|
|
||||||
// construct is not satisfied with the predicate's outcome.
|
|
||||||
// Referenced via a pointer to avoid taking too much stack frame space
|
|
||||||
// with test assertions.
|
|
||||||
std::unique_ptr< ::std::string> message_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Makes a successful assertion result.
|
|
||||||
GTEST_API_ AssertionResult AssertionSuccess();
|
|
||||||
|
|
||||||
// Makes a failed assertion result.
|
|
||||||
GTEST_API_ AssertionResult AssertionFailure();
|
|
||||||
|
|
||||||
// Makes a failed assertion result with the given failure message.
|
|
||||||
// Deprecated; use AssertionFailure() << msg.
|
|
||||||
GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
|
|
||||||
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
// Includes the auto-generated header that implements a family of generic
|
|
||||||
// predicate assertion macros. This include comes late because it relies on
|
|
||||||
// APIs declared above.
|
|
||||||
#include "gtest/gtest_pred_impl.h"
|
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
|
|
||||||
// The abstract class that all tests inherit from.
|
// The abstract class that all tests inherit from.
|
||||||
//
|
//
|
||||||
// In Google Test, a unit test program contains one or many TestSuites, and
|
// In Google Test, a unit test program contains one or many TestSuites, and
|
||||||
|
@ -522,7 +339,8 @@ class GTEST_API_ Test {
|
||||||
virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; }
|
virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; }
|
||||||
|
|
||||||
// We disallow copying Tests.
|
// We disallow copying Tests.
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
|
Test(const Test&) = delete;
|
||||||
|
Test& operator=(const Test&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef internal::TimeInMillis TimeInMillis;
|
typedef internal::TimeInMillis TimeInMillis;
|
||||||
|
@ -536,24 +354,17 @@ class TestProperty {
|
||||||
// C'tor. TestProperty does NOT have a default constructor.
|
// C'tor. TestProperty does NOT have a default constructor.
|
||||||
// Always use this constructor (with parameters) to create a
|
// Always use this constructor (with parameters) to create a
|
||||||
// TestProperty object.
|
// TestProperty object.
|
||||||
TestProperty(const std::string& a_key, const std::string& a_value) :
|
TestProperty(const std::string& a_key, const std::string& a_value)
|
||||||
key_(a_key), value_(a_value) {
|
: key_(a_key), value_(a_value) {}
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the user supplied key.
|
// Gets the user supplied key.
|
||||||
const char* key() const {
|
const char* key() const { return key_.c_str(); }
|
||||||
return key_.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the user supplied value.
|
// Gets the user supplied value.
|
||||||
const char* value() const {
|
const char* value() const { return value_.c_str(); }
|
||||||
return value_.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets a new value, overriding the one supplied in the constructor.
|
// Sets a new value, overriding the one supplied in the constructor.
|
||||||
void SetValue(const std::string& new_value) {
|
void SetValue(const std::string& new_value) { value_ = new_value; }
|
||||||
value_ = new_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The key supplied by the user.
|
// The key supplied by the user.
|
||||||
|
@ -687,7 +498,8 @@ class GTEST_API_ TestResult {
|
||||||
TimeInMillis elapsed_time_;
|
TimeInMillis elapsed_time_;
|
||||||
|
|
||||||
// We disallow copying TestResult.
|
// We disallow copying TestResult.
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
|
TestResult(const TestResult&) = delete;
|
||||||
|
TestResult& operator=(const TestResult&) = delete;
|
||||||
}; // class TestResult
|
}; // class TestResult
|
||||||
|
|
||||||
// A TestInfo object stores the following information about a test:
|
// A TestInfo object stores the following information about a test:
|
||||||
|
@ -833,7 +645,8 @@ class GTEST_API_ TestInfo {
|
||||||
// test for the second time.
|
// test for the second time.
|
||||||
TestResult result_;
|
TestResult result_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
|
TestInfo(const TestInfo&) = delete;
|
||||||
|
TestInfo& operator=(const TestInfo&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A test suite, which consists of a vector of TestInfos.
|
// A test suite, which consists of a vector of TestInfos.
|
||||||
|
@ -941,7 +754,7 @@ class GTEST_API_ TestSuite {
|
||||||
|
|
||||||
// Adds a TestInfo to this test suite. Will delete the TestInfo upon
|
// Adds a TestInfo to this test suite. Will delete the TestInfo upon
|
||||||
// destruction of the TestSuite object.
|
// destruction of the TestSuite object.
|
||||||
void AddTestInfo(TestInfo * test_info);
|
void AddTestInfo(TestInfo* test_info);
|
||||||
|
|
||||||
// Clears the results of all tests in this test suite.
|
// Clears the results of all tests in this test suite.
|
||||||
void ClearResult();
|
void ClearResult();
|
||||||
|
@ -1042,7 +855,8 @@ class GTEST_API_ TestSuite {
|
||||||
TestResult ad_hoc_test_result_;
|
TestResult ad_hoc_test_result_;
|
||||||
|
|
||||||
// We disallow copying TestSuites.
|
// We disallow copying TestSuites.
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestSuite);
|
TestSuite(const TestSuite&) = delete;
|
||||||
|
TestSuite& operator=(const TestSuite&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// An Environment object is capable of setting up and tearing down an
|
// An Environment object is capable of setting up and tearing down an
|
||||||
|
@ -1069,6 +883,7 @@ class Environment {
|
||||||
|
|
||||||
// Override this to define how to tear down the environment.
|
// Override this to define how to tear down the environment.
|
||||||
virtual void TearDown() {}
|
virtual void TearDown() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// If you see an error about overriding the following function or
|
// If you see an error about overriding the following function or
|
||||||
// about it being private, you have mis-spelled SetUp() as Setup().
|
// about it being private, you have mis-spelled SetUp() as Setup().
|
||||||
|
@ -1120,6 +935,9 @@ class TestEventListener {
|
||||||
// Fired before the test starts.
|
// Fired before the test starts.
|
||||||
virtual void OnTestStart(const TestInfo& test_info) = 0;
|
virtual void OnTestStart(const TestInfo& test_info) = 0;
|
||||||
|
|
||||||
|
// Fired when a test is disabled
|
||||||
|
virtual void OnTestDisabled(const TestInfo& /*test_info*/) {}
|
||||||
|
|
||||||
// Fired after a failed assertion or a SUCCEED() invocation.
|
// Fired after a failed assertion or a SUCCEED() invocation.
|
||||||
// If you want to throw an exception from this function to skip to the next
|
// If you want to throw an exception from this function to skip to the next
|
||||||
// TEST, it must be AssertionException defined above, or inherited from it.
|
// TEST, it must be AssertionException defined above, or inherited from it.
|
||||||
|
@ -1143,8 +961,7 @@ class TestEventListener {
|
||||||
virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
|
virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
|
||||||
|
|
||||||
// Fired after each iteration of tests finishes.
|
// Fired after each iteration of tests finishes.
|
||||||
virtual void OnTestIterationEnd(const UnitTest& unit_test,
|
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) = 0;
|
||||||
int iteration) = 0;
|
|
||||||
|
|
||||||
// Fired after all test activities have ended.
|
// Fired after all test activities have ended.
|
||||||
virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
|
virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
|
||||||
|
@ -1169,6 +986,7 @@ class EmptyTestEventListener : public TestEventListener {
|
||||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
|
|
||||||
void OnTestStart(const TestInfo& /*test_info*/) override {}
|
void OnTestStart(const TestInfo& /*test_info*/) override {}
|
||||||
|
void OnTestDisabled(const TestInfo& /*test_info*/) override {}
|
||||||
void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {}
|
void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {}
|
||||||
void OnTestEnd(const TestInfo& /*test_info*/) override {}
|
void OnTestEnd(const TestInfo& /*test_info*/) override {}
|
||||||
void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {}
|
void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {}
|
||||||
|
@ -1258,7 +1076,8 @@ class GTEST_API_ TestEventListeners {
|
||||||
TestEventListener* default_xml_generator_;
|
TestEventListener* default_xml_generator_;
|
||||||
|
|
||||||
// We disallow copying TestEventListeners.
|
// We disallow copying TestEventListeners.
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
|
TestEventListeners(const TestEventListeners&) = delete;
|
||||||
|
TestEventListeners& operator=(const TestEventListeners&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A UnitTest consists of a vector of TestSuites.
|
// A UnitTest consists of a vector of TestSuites.
|
||||||
|
@ -1301,8 +1120,7 @@ class GTEST_API_ UnitTest {
|
||||||
|
|
||||||
// Returns the TestInfo object for the test that's currently running,
|
// Returns the TestInfo object for the test that's currently running,
|
||||||
// or NULL if no test is running.
|
// or NULL if no test is running.
|
||||||
const TestInfo* current_test_info() const
|
const TestInfo* current_test_info() const GTEST_LOCK_EXCLUDED_(mutex_);
|
||||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
|
||||||
|
|
||||||
// Returns the random seed used at the start of the current test run.
|
// Returns the random seed used at the start of the current test run.
|
||||||
int random_seed() const;
|
int random_seed() const;
|
||||||
|
@ -1408,8 +1226,7 @@ class GTEST_API_ UnitTest {
|
||||||
// eventually call this to report their results. The user code
|
// eventually call this to report their results. The user code
|
||||||
// should use the assertion macros instead of calling this directly.
|
// should use the assertion macros instead of calling this directly.
|
||||||
void AddTestPartResult(TestPartResult::Type result_type,
|
void AddTestPartResult(TestPartResult::Type result_type,
|
||||||
const char* file_name,
|
const char* file_name, int line_number,
|
||||||
int line_number,
|
|
||||||
const std::string& message,
|
const std::string& message,
|
||||||
const std::string& os_stack_trace)
|
const std::string& os_stack_trace)
|
||||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||||
|
@ -1440,8 +1257,7 @@ class GTEST_API_ UnitTest {
|
||||||
friend std::set<std::string>* internal::GetIgnoredParameterizedTestSuites();
|
friend std::set<std::string>* internal::GetIgnoredParameterizedTestSuites();
|
||||||
friend internal::UnitTestImpl* internal::GetUnitTestImpl();
|
friend internal::UnitTestImpl* internal::GetUnitTestImpl();
|
||||||
friend void internal::ReportFailureInUnknownLocation(
|
friend void internal::ReportFailureInUnknownLocation(
|
||||||
TestPartResult::Type result_type,
|
TestPartResult::Type result_type, const std::string& message);
|
||||||
const std::string& message);
|
|
||||||
|
|
||||||
// Creates an empty UnitTest.
|
// Creates an empty UnitTest.
|
||||||
UnitTest();
|
UnitTest();
|
||||||
|
@ -1455,8 +1271,7 @@ class GTEST_API_ UnitTest {
|
||||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||||
|
|
||||||
// Pops a trace from the per-thread Google Test trace stack.
|
// Pops a trace from the per-thread Google Test trace stack.
|
||||||
void PopGTestTrace()
|
void PopGTestTrace() GTEST_LOCK_EXCLUDED_(mutex_);
|
||||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
|
||||||
|
|
||||||
// Protects mutable state in *impl_. This is mutable as some const
|
// Protects mutable state in *impl_. This is mutable as some const
|
||||||
// methods need to lock it too.
|
// methods need to lock it too.
|
||||||
|
@ -1469,7 +1284,8 @@ class GTEST_API_ UnitTest {
|
||||||
internal::UnitTestImpl* impl_;
|
internal::UnitTestImpl* impl_;
|
||||||
|
|
||||||
// We disallow copying UnitTest.
|
// We disallow copying UnitTest.
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
|
UnitTest(const UnitTest&) = delete;
|
||||||
|
UnitTest& operator=(const UnitTest&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A convenient wrapper for adding an environment for the test
|
// A convenient wrapper for adding an environment for the test
|
||||||
|
@ -1520,13 +1336,11 @@ namespace internal {
|
||||||
// when calling EXPECT_* in a tight loop.
|
// when calling EXPECT_* in a tight loop.
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
AssertionResult CmpHelperEQFailure(const char* lhs_expression,
|
AssertionResult CmpHelperEQFailure(const char* lhs_expression,
|
||||||
const char* rhs_expression,
|
const char* rhs_expression, const T1& lhs,
|
||||||
const T1& lhs, const T2& rhs) {
|
const T2& rhs) {
|
||||||
return EqFailure(lhs_expression,
|
return EqFailure(lhs_expression, rhs_expression,
|
||||||
rhs_expression,
|
|
||||||
FormatForComparisonFailureMessage(lhs, rhs),
|
FormatForComparisonFailureMessage(lhs, rhs),
|
||||||
FormatForComparisonFailureMessage(rhs, lhs),
|
FormatForComparisonFailureMessage(rhs, lhs), false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This block of code defines operator==/!=
|
// This block of code defines operator==/!=
|
||||||
|
@ -1539,8 +1353,7 @@ inline bool operator!=(faketype, faketype) { return false; }
|
||||||
// The helper function for {ASSERT|EXPECT}_EQ.
|
// The helper function for {ASSERT|EXPECT}_EQ.
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
AssertionResult CmpHelperEQ(const char* lhs_expression,
|
AssertionResult CmpHelperEQ(const char* lhs_expression,
|
||||||
const char* rhs_expression,
|
const char* rhs_expression, const T1& lhs,
|
||||||
const T1& lhs,
|
|
||||||
const T2& rhs) {
|
const T2& rhs) {
|
||||||
if (lhs == rhs) {
|
if (lhs == rhs) {
|
||||||
return AssertionSuccess();
|
return AssertionSuccess();
|
||||||
|
@ -1571,8 +1384,7 @@ class EqHelper {
|
||||||
// Even though its body looks the same as the above version, we
|
// Even though its body looks the same as the above version, we
|
||||||
// cannot merge the two, as it will make anonymous enums unhappy.
|
// cannot merge the two, as it will make anonymous enums unhappy.
|
||||||
static AssertionResult Compare(const char* lhs_expression,
|
static AssertionResult Compare(const char* lhs_expression,
|
||||||
const char* rhs_expression,
|
const char* rhs_expression, BiggestInt lhs,
|
||||||
BiggestInt lhs,
|
|
||||||
BiggestInt rhs) {
|
BiggestInt rhs) {
|
||||||
return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs);
|
return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs);
|
||||||
}
|
}
|
||||||
|
@ -1607,16 +1419,16 @@ AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2,
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
|
|
||||||
#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
|
#define GTEST_IMPL_CMP_HELPER_(op_name, op) \
|
||||||
template <typename T1, typename T2>\
|
template <typename T1, typename T2> \
|
||||||
AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
|
AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
|
||||||
const T1& val1, const T2& val2) {\
|
const T1& val1, const T2& val2) { \
|
||||||
if (val1 op val2) {\
|
if (val1 op val2) { \
|
||||||
return AssertionSuccess();\
|
return AssertionSuccess(); \
|
||||||
} else {\
|
} else { \
|
||||||
return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);\
|
return CmpHelperOpFailure(expr1, expr2, val1, val2, #op); \
|
||||||
}\
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
|
|
||||||
|
@ -1638,49 +1450,42 @@ GTEST_IMPL_CMP_HELPER_(GT, >)
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
|
GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
|
||||||
const char* s2_expression,
|
const char* s2_expression,
|
||||||
const char* s1,
|
const char* s1, const char* s2);
|
||||||
const char* s2);
|
|
||||||
|
|
||||||
// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
|
// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* s1_expression,
|
GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* s1_expression,
|
||||||
const char* s2_expression,
|
const char* s2_expression,
|
||||||
const char* s1,
|
const char* s1, const char* s2);
|
||||||
const char* s2);
|
|
||||||
|
|
||||||
// The helper function for {ASSERT|EXPECT}_STRNE.
|
// The helper function for {ASSERT|EXPECT}_STRNE.
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||||
const char* s2_expression,
|
const char* s2_expression,
|
||||||
const char* s1,
|
const char* s1, const char* s2);
|
||||||
const char* s2);
|
|
||||||
|
|
||||||
// The helper function for {ASSERT|EXPECT}_STRCASENE.
|
// The helper function for {ASSERT|EXPECT}_STRCASENE.
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
|
GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
|
||||||
const char* s2_expression,
|
const char* s2_expression,
|
||||||
const char* s1,
|
const char* s1, const char* s2);
|
||||||
const char* s2);
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function for *_STREQ on wide strings.
|
// Helper function for *_STREQ on wide strings.
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
|
GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
|
||||||
const char* s2_expression,
|
const char* s2_expression,
|
||||||
const wchar_t* s1,
|
const wchar_t* s1, const wchar_t* s2);
|
||||||
const wchar_t* s2);
|
|
||||||
|
|
||||||
// Helper function for *_STRNE on wide strings.
|
// Helper function for *_STRNE on wide strings.
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||||
const char* s2_expression,
|
const char* s2_expression,
|
||||||
const wchar_t* s1,
|
const wchar_t* s1, const wchar_t* s2);
|
||||||
const wchar_t* s2);
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
@ -1692,32 +1497,40 @@ GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||||
//
|
//
|
||||||
// The {needle,haystack}_expr arguments are the stringified
|
// The {needle,haystack}_expr arguments are the stringified
|
||||||
// expressions that generated the two real arguments.
|
// expressions that generated the two real arguments.
|
||||||
GTEST_API_ AssertionResult IsSubstring(
|
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||||
const char* needle_expr, const char* haystack_expr,
|
const char* haystack_expr,
|
||||||
const char* needle, const char* haystack);
|
const char* needle,
|
||||||
GTEST_API_ AssertionResult IsSubstring(
|
const char* haystack);
|
||||||
const char* needle_expr, const char* haystack_expr,
|
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||||
const wchar_t* needle, const wchar_t* haystack);
|
const char* haystack_expr,
|
||||||
GTEST_API_ AssertionResult IsNotSubstring(
|
const wchar_t* needle,
|
||||||
const char* needle_expr, const char* haystack_expr,
|
const wchar_t* haystack);
|
||||||
const char* needle, const char* haystack);
|
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||||
GTEST_API_ AssertionResult IsNotSubstring(
|
const char* haystack_expr,
|
||||||
const char* needle_expr, const char* haystack_expr,
|
const char* needle,
|
||||||
const wchar_t* needle, const wchar_t* haystack);
|
const char* haystack);
|
||||||
GTEST_API_ AssertionResult IsSubstring(
|
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||||
const char* needle_expr, const char* haystack_expr,
|
const char* haystack_expr,
|
||||||
const ::std::string& needle, const ::std::string& haystack);
|
const wchar_t* needle,
|
||||||
GTEST_API_ AssertionResult IsNotSubstring(
|
const wchar_t* haystack);
|
||||||
const char* needle_expr, const char* haystack_expr,
|
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||||
const ::std::string& needle, const ::std::string& haystack);
|
const char* haystack_expr,
|
||||||
|
const ::std::string& needle,
|
||||||
|
const ::std::string& haystack);
|
||||||
|
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||||
|
const char* haystack_expr,
|
||||||
|
const ::std::string& needle,
|
||||||
|
const ::std::string& haystack);
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
GTEST_API_ AssertionResult IsSubstring(
|
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||||
const char* needle_expr, const char* haystack_expr,
|
const char* haystack_expr,
|
||||||
const ::std::wstring& needle, const ::std::wstring& haystack);
|
const ::std::wstring& needle,
|
||||||
GTEST_API_ AssertionResult IsNotSubstring(
|
const ::std::wstring& haystack);
|
||||||
const char* needle_expr, const char* haystack_expr,
|
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||||
const ::std::wstring& needle, const ::std::wstring& haystack);
|
const char* haystack_expr,
|
||||||
|
const ::std::wstring& needle,
|
||||||
|
const ::std::wstring& haystack);
|
||||||
#endif // GTEST_HAS_STD_WSTRING
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -1732,8 +1545,7 @@ namespace internal {
|
||||||
template <typename RawType>
|
template <typename RawType>
|
||||||
AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
|
AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
|
||||||
const char* rhs_expression,
|
const char* rhs_expression,
|
||||||
RawType lhs_value,
|
RawType lhs_value, RawType rhs_value) {
|
||||||
RawType rhs_value) {
|
|
||||||
const FloatingPoint<RawType> lhs(lhs_value), rhs(rhs_value);
|
const FloatingPoint<RawType> lhs(lhs_value), rhs(rhs_value);
|
||||||
|
|
||||||
if (lhs.AlmostEquals(rhs)) {
|
if (lhs.AlmostEquals(rhs)) {
|
||||||
|
@ -1748,10 +1560,8 @@ AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
|
||||||
rhs_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
|
rhs_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
|
||||||
<< rhs_value;
|
<< rhs_value;
|
||||||
|
|
||||||
return EqFailure(lhs_expression,
|
return EqFailure(lhs_expression, rhs_expression,
|
||||||
rhs_expression,
|
StringStreamToString(&lhs_ss), StringStreamToString(&rhs_ss),
|
||||||
StringStreamToString(&lhs_ss),
|
|
||||||
StringStreamToString(&rhs_ss),
|
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1761,8 +1571,7 @@ AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
|
||||||
GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
|
GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
|
||||||
const char* expr2,
|
const char* expr2,
|
||||||
const char* abs_error_expr,
|
const char* abs_error_expr,
|
||||||
double val1,
|
double val1, double val2,
|
||||||
double val2,
|
|
||||||
double abs_error);
|
double abs_error);
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
@ -1770,9 +1579,7 @@ GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
|
||||||
class GTEST_API_ AssertHelper {
|
class GTEST_API_ AssertHelper {
|
||||||
public:
|
public:
|
||||||
// Constructor.
|
// Constructor.
|
||||||
AssertHelper(TestPartResult::Type type,
|
AssertHelper(TestPartResult::Type type, const char* file, int line,
|
||||||
const char* file,
|
|
||||||
int line,
|
|
||||||
const char* message);
|
const char* message);
|
||||||
~AssertHelper();
|
~AssertHelper();
|
||||||
|
|
||||||
|
@ -1786,11 +1593,9 @@ class GTEST_API_ AssertHelper {
|
||||||
// re-using stack space even for temporary variables, so every EXPECT_EQ
|
// re-using stack space even for temporary variables, so every EXPECT_EQ
|
||||||
// reserves stack space for another AssertHelper.
|
// reserves stack space for another AssertHelper.
|
||||||
struct AssertHelperData {
|
struct AssertHelperData {
|
||||||
AssertHelperData(TestPartResult::Type t,
|
AssertHelperData(TestPartResult::Type t, const char* srcfile, int line_num,
|
||||||
const char* srcfile,
|
|
||||||
int line_num,
|
|
||||||
const char* msg)
|
const char* msg)
|
||||||
: type(t), file(srcfile), line(line_num), message(msg) { }
|
: type(t), file(srcfile), line(line_num), message(msg) {}
|
||||||
|
|
||||||
TestPartResult::Type const type;
|
TestPartResult::Type const type;
|
||||||
const char* const file;
|
const char* const file;
|
||||||
|
@ -1798,12 +1603,14 @@ class GTEST_API_ AssertHelper {
|
||||||
std::string const message;
|
std::string const message;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
|
AssertHelperData(const AssertHelperData&) = delete;
|
||||||
|
AssertHelperData& operator=(const AssertHelperData&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
AssertHelperData* const data_;
|
AssertHelperData* const data_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
|
AssertHelper(const AssertHelper&) = delete;
|
||||||
|
AssertHelper& operator=(const AssertHelper&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -1860,15 +1667,14 @@ class WithParamInterface {
|
||||||
private:
|
private:
|
||||||
// Sets parameter value. The caller is responsible for making sure the value
|
// Sets parameter value. The caller is responsible for making sure the value
|
||||||
// remains alive and unchanged throughout the current test.
|
// remains alive and unchanged throughout the current test.
|
||||||
static void SetParam(const ParamType* parameter) {
|
static void SetParam(const ParamType* parameter) { parameter_ = parameter; }
|
||||||
parameter_ = parameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Static value used for accessing parameter during a test lifetime.
|
// Static value used for accessing parameter during a test lifetime.
|
||||||
static const ParamType* parameter_;
|
static const ParamType* parameter_;
|
||||||
|
|
||||||
// TestClass must be a subclass of WithParamInterface<T> and Test.
|
// TestClass must be a subclass of WithParamInterface<T> and Test.
|
||||||
template <class TestClass> friend class internal::ParameterizedTestFactory;
|
template <class TestClass>
|
||||||
|
friend class internal::ParameterizedTestFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -1878,8 +1684,7 @@ const T* WithParamInterface<T>::parameter_ = nullptr;
|
||||||
// WithParamInterface, and can just inherit from ::testing::TestWithParam.
|
// WithParamInterface, and can just inherit from ::testing::TestWithParam.
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TestWithParam : public Test, public WithParamInterface<T> {
|
class TestWithParam : public Test, public WithParamInterface<T> {};
|
||||||
};
|
|
||||||
|
|
||||||
// Macros for indicating success/failure in test code.
|
// Macros for indicating success/failure in test code.
|
||||||
|
|
||||||
|
@ -1925,7 +1730,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {
|
||||||
// Define this macro to 1 to omit the definition of FAIL(), which is a
|
// Define this macro to 1 to omit the definition of FAIL(), which is a
|
||||||
// generic name and clashes with some other libraries.
|
// generic name and clashes with some other libraries.
|
||||||
#if !GTEST_DONT_DEFINE_FAIL
|
#if !GTEST_DONT_DEFINE_FAIL
|
||||||
# define FAIL() GTEST_FAIL()
|
#define FAIL() GTEST_FAIL()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Generates a success with a generic message.
|
// Generates a success with a generic message.
|
||||||
|
@ -1934,7 +1739,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {
|
||||||
// Define this macro to 1 to omit the definition of SUCCEED(), which
|
// Define this macro to 1 to omit the definition of SUCCEED(), which
|
||||||
// is a generic name and clashes with some other libraries.
|
// is a generic name and clashes with some other libraries.
|
||||||
#if !GTEST_DONT_DEFINE_SUCCEED
|
#if !GTEST_DONT_DEFINE_SUCCEED
|
||||||
# define SUCCEED() GTEST_SUCCEED()
|
#define SUCCEED() GTEST_SUCCEED()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Macros for testing exceptions.
|
// Macros for testing exceptions.
|
||||||
|
@ -1969,8 +1774,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {
|
||||||
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
|
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
|
||||||
GTEST_NONFATAL_FAILURE_)
|
GTEST_NONFATAL_FAILURE_)
|
||||||
#define GTEST_ASSERT_TRUE(condition) \
|
#define GTEST_ASSERT_TRUE(condition) \
|
||||||
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
|
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, GTEST_FATAL_FAILURE_)
|
||||||
GTEST_FATAL_FAILURE_)
|
|
||||||
#define GTEST_ASSERT_FALSE(condition) \
|
#define GTEST_ASSERT_FALSE(condition) \
|
||||||
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
|
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
|
||||||
GTEST_FATAL_FAILURE_)
|
GTEST_FATAL_FAILURE_)
|
||||||
|
@ -2070,27 +1874,27 @@ class TestWithParam : public Test, public WithParamInterface<T> {
|
||||||
// ASSERT_XY(), which clashes with some users' own code.
|
// ASSERT_XY(), which clashes with some users' own code.
|
||||||
|
|
||||||
#if !GTEST_DONT_DEFINE_ASSERT_EQ
|
#if !GTEST_DONT_DEFINE_ASSERT_EQ
|
||||||
# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
|
#define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !GTEST_DONT_DEFINE_ASSERT_NE
|
#if !GTEST_DONT_DEFINE_ASSERT_NE
|
||||||
# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
|
#define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !GTEST_DONT_DEFINE_ASSERT_LE
|
#if !GTEST_DONT_DEFINE_ASSERT_LE
|
||||||
# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
|
#define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !GTEST_DONT_DEFINE_ASSERT_LT
|
#if !GTEST_DONT_DEFINE_ASSERT_LT
|
||||||
# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
|
#define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !GTEST_DONT_DEFINE_ASSERT_GE
|
#if !GTEST_DONT_DEFINE_ASSERT_GE
|
||||||
# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
|
#define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !GTEST_DONT_DEFINE_ASSERT_GT
|
#if !GTEST_DONT_DEFINE_ASSERT_GT
|
||||||
# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
|
#define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// C-string Comparisons. All tests treat NULL and any non-NULL string
|
// C-string Comparisons. All tests treat NULL and any non-NULL string
|
||||||
|
@ -2115,7 +1919,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {
|
||||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
|
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
|
||||||
#define EXPECT_STRCASEEQ(s1, s2) \
|
#define EXPECT_STRCASEEQ(s1, s2) \
|
||||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
|
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
|
||||||
#define EXPECT_STRCASENE(s1, s2)\
|
#define EXPECT_STRCASENE(s1, s2) \
|
||||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
|
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
|
||||||
|
|
||||||
#define ASSERT_STREQ(s1, s2) \
|
#define ASSERT_STREQ(s1, s2) \
|
||||||
|
@ -2124,7 +1928,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {
|
||||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
|
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
|
||||||
#define ASSERT_STRCASEEQ(s1, s2) \
|
#define ASSERT_STRCASEEQ(s1, s2) \
|
||||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
|
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
|
||||||
#define ASSERT_STRCASENE(s1, s2)\
|
#define ASSERT_STRCASENE(s1, s2) \
|
||||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
|
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
|
||||||
|
|
||||||
// Macros for comparing floating-point numbers.
|
// Macros for comparing floating-point numbers.
|
||||||
|
@ -2141,29 +1945,29 @@ class TestWithParam : public Test, public WithParamInterface<T> {
|
||||||
// FloatingPoint template class in gtest-internal.h if you are
|
// FloatingPoint template class in gtest-internal.h if you are
|
||||||
// interested in the implementation details.
|
// interested in the implementation details.
|
||||||
|
|
||||||
#define EXPECT_FLOAT_EQ(val1, val2)\
|
#define EXPECT_FLOAT_EQ(val1, val2) \
|
||||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
|
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
|
||||||
val1, val2)
|
val1, val2)
|
||||||
|
|
||||||
#define EXPECT_DOUBLE_EQ(val1, val2)\
|
#define EXPECT_DOUBLE_EQ(val1, val2) \
|
||||||
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
|
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
|
||||||
val1, val2)
|
val1, val2)
|
||||||
|
|
||||||
#define ASSERT_FLOAT_EQ(val1, val2)\
|
#define ASSERT_FLOAT_EQ(val1, val2) \
|
||||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
|
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
|
||||||
val1, val2)
|
val1, val2)
|
||||||
|
|
||||||
#define ASSERT_DOUBLE_EQ(val1, val2)\
|
#define ASSERT_DOUBLE_EQ(val1, val2) \
|
||||||
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
|
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
|
||||||
val1, val2)
|
val1, val2)
|
||||||
|
|
||||||
#define EXPECT_NEAR(val1, val2, abs_error)\
|
#define EXPECT_NEAR(val1, val2, abs_error) \
|
||||||
EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
|
EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, val1, val2, \
|
||||||
val1, val2, abs_error)
|
abs_error)
|
||||||
|
|
||||||
#define ASSERT_NEAR(val1, val2, abs_error)\
|
#define ASSERT_NEAR(val1, val2, abs_error) \
|
||||||
ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
|
ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, val1, val2, \
|
||||||
val1, val2, abs_error)
|
abs_error)
|
||||||
|
|
||||||
// These predicate format functions work on floating-point values, and
|
// These predicate format functions work on floating-point values, and
|
||||||
// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
|
// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
|
||||||
|
@ -2177,7 +1981,6 @@ GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
|
||||||
GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
||||||
double val1, double val2);
|
double val1, double val2);
|
||||||
|
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
|
|
||||||
// Macros that test for HRESULT failure and success, these are only useful
|
// Macros that test for HRESULT failure and success, these are only useful
|
||||||
|
@ -2189,16 +1992,16 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
||||||
// expected result and the actual result with both a human-readable
|
// expected result and the actual result with both a human-readable
|
||||||
// string representation of the error, if available, as well as the
|
// string representation of the error, if available, as well as the
|
||||||
// hex result code.
|
// hex result code.
|
||||||
# define EXPECT_HRESULT_SUCCEEDED(expr) \
|
#define EXPECT_HRESULT_SUCCEEDED(expr) \
|
||||||
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
|
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
|
||||||
|
|
||||||
# define ASSERT_HRESULT_SUCCEEDED(expr) \
|
#define ASSERT_HRESULT_SUCCEEDED(expr) \
|
||||||
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
|
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
|
||||||
|
|
||||||
# define EXPECT_HRESULT_FAILED(expr) \
|
#define EXPECT_HRESULT_FAILED(expr) \
|
||||||
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
|
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
|
||||||
|
|
||||||
# define ASSERT_HRESULT_FAILED(expr) \
|
#define ASSERT_HRESULT_FAILED(expr) \
|
||||||
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
|
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
|
||||||
|
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
@ -2258,7 +2061,8 @@ class GTEST_API_ ScopedTrace {
|
||||||
private:
|
private:
|
||||||
void PushTrace(const char* file, int line, std::string message);
|
void PushTrace(const char* file, int line, std::string message);
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
|
ScopedTrace(const ScopedTrace&) = delete;
|
||||||
|
ScopedTrace& operator=(const ScopedTrace&) = delete;
|
||||||
} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its
|
} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its
|
||||||
// c'tor and d'tor. Therefore it doesn't
|
// c'tor and d'tor. Therefore it doesn't
|
||||||
// need to be used otherwise.
|
// need to be used otherwise.
|
||||||
|
@ -2279,7 +2083,7 @@ class GTEST_API_ ScopedTrace {
|
||||||
// Therefore, a SCOPED_TRACE() would (correctly) only affect the
|
// Therefore, a SCOPED_TRACE() would (correctly) only affect the
|
||||||
// assertions in its own thread.
|
// assertions in its own thread.
|
||||||
#define SCOPED_TRACE(message) \
|
#define SCOPED_TRACE(message) \
|
||||||
::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
|
::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)( \
|
||||||
__FILE__, __LINE__, (message))
|
__FILE__, __LINE__, (message))
|
||||||
|
|
||||||
// Compile-time assertion for type equality.
|
// Compile-time assertion for type equality.
|
||||||
|
@ -2378,20 +2182,19 @@ constexpr bool StaticAssertTypeEq() noexcept {
|
||||||
// EXPECT_EQ(a_.size(), 0);
|
// EXPECT_EQ(a_.size(), 0);
|
||||||
// EXPECT_EQ(b_.size(), 1);
|
// EXPECT_EQ(b_.size(), 1);
|
||||||
// }
|
// }
|
||||||
//
|
#define GTEST_TEST_F(test_fixture, test_name) \
|
||||||
// GOOGLETEST_CM0011 DO NOT DELETE
|
|
||||||
#if !GTEST_DONT_DEFINE_TEST
|
|
||||||
#define TEST_F(test_fixture, test_name)\
|
|
||||||
GTEST_TEST_(test_fixture, test_name, test_fixture, \
|
GTEST_TEST_(test_fixture, test_name, test_fixture, \
|
||||||
::testing::internal::GetTypeId<test_fixture>())
|
::testing::internal::GetTypeId<test_fixture>())
|
||||||
#endif // !GTEST_DONT_DEFINE_TEST
|
#if !GTEST_DONT_DEFINE_TEST_F
|
||||||
|
#define TEST_F(test_fixture, test_name) GTEST_TEST_F(test_fixture, test_name)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Returns a path to temporary directory.
|
// Returns a path to temporary directory.
|
||||||
// Tries to determine an appropriate directory for the platform.
|
// Tries to determine an appropriate directory for the platform.
|
||||||
GTEST_API_ std::string TempDir();
|
GTEST_API_ std::string TempDir();
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Dynamically registers a test with the framework.
|
// Dynamically registers a test with the framework.
|
||||||
|
@ -2445,6 +2248,7 @@ GTEST_API_ std::string TempDir();
|
||||||
// }
|
// }
|
||||||
// ...
|
// ...
|
||||||
// int main(int argc, char** argv) {
|
// int main(int argc, char** argv) {
|
||||||
|
// ::testing::InitGoogleTest(&argc, argv);
|
||||||
// std::vector<int> values_to_test = LoadValuesFromConfig();
|
// std::vector<int> values_to_test = LoadValuesFromConfig();
|
||||||
// RegisterMyTests(values_to_test);
|
// RegisterMyTests(values_to_test);
|
||||||
// ...
|
// ...
|
||||||
|
@ -2486,9 +2290,7 @@ TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
|
||||||
// namespace and has an all-caps name.
|
// namespace and has an all-caps name.
|
||||||
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
|
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
|
||||||
|
|
||||||
inline int RUN_ALL_TESTS() {
|
inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); }
|
||||||
return ::testing::UnitTest::GetInstance()->Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
|
|
||||||
|
|
|
@ -26,17 +26,19 @@
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// This file is AUTOMATICALLY GENERATED on 01/02/2019 by command
|
|
||||||
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
|
|
||||||
//
|
//
|
||||||
// Implements a family of generic predicate assertion macros.
|
// Implements a family of generic predicate assertion macros.
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
|
||||||
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest-assertion-result.h"
|
||||||
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
|
@ -79,15 +81,11 @@ namespace testing {
|
||||||
else \
|
else \
|
||||||
on_failure(gtest_ar.failure_message())
|
on_failure(gtest_ar.failure_message())
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred, typename T1>
|
||||||
typename T1>
|
AssertionResult AssertPred1Helper(const char* pred_text, const char* e1,
|
||||||
AssertionResult AssertPred1Helper(const char* pred_text,
|
Pred pred, const T1& v1) {
|
||||||
const char* e1,
|
|
||||||
Pred pred,
|
|
||||||
const T1& v1) {
|
|
||||||
if (pred(v1)) return AssertionSuccess();
|
if (pred(v1)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure()
|
return AssertionFailure()
|
||||||
|
@ -98,40 +96,27 @@ AssertionResult AssertPred1Helper(const char* pred_text,
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
|
#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure) \
|
||||||
GTEST_ASSERT_(pred_format(#v1, v1), \
|
GTEST_ASSERT_(pred_format(#v1, v1), on_failure)
|
||||||
on_failure)
|
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED1_(pred, v1, on_failure)\
|
#define GTEST_PRED1_(pred, v1, on_failure) \
|
||||||
GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
|
GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, #v1, pred, v1), on_failure)
|
||||||
#v1, \
|
|
||||||
pred, \
|
|
||||||
v1), on_failure)
|
|
||||||
|
|
||||||
// Unary predicate assertion macros.
|
// Unary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT1(pred_format, v1) \
|
#define EXPECT_PRED_FORMAT1(pred_format, v1) \
|
||||||
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
|
||||||
#define EXPECT_PRED1(pred, v1) \
|
#define EXPECT_PRED1(pred, v1) GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
|
||||||
GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
|
|
||||||
#define ASSERT_PRED_FORMAT1(pred_format, v1) \
|
#define ASSERT_PRED_FORMAT1(pred_format, v1) \
|
||||||
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
|
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
|
||||||
#define ASSERT_PRED1(pred, v1) \
|
#define ASSERT_PRED1(pred, v1) GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
|
||||||
GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred, typename T1, typename T2>
|
||||||
typename T1,
|
AssertionResult AssertPred2Helper(const char* pred_text, const char* e1,
|
||||||
typename T2>
|
const char* e2, Pred pred, const T1& v1,
|
||||||
AssertionResult AssertPred2Helper(const char* pred_text,
|
|
||||||
const char* e1,
|
|
||||||
const char* e2,
|
|
||||||
Pred pred,
|
|
||||||
const T1& v1,
|
|
||||||
const T2& v2) {
|
const T2& v2) {
|
||||||
if (pred(v1, v2)) return AssertionSuccess();
|
if (pred(v1, v2)) return AssertionSuccess();
|
||||||
|
|
||||||
|
@ -145,19 +130,14 @@ AssertionResult AssertPred2Helper(const char* pred_text,
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
|
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure) \
|
||||||
GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
|
GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), on_failure)
|
||||||
on_failure)
|
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED2_(pred, v1, v2, on_failure)\
|
#define GTEST_PRED2_(pred, v1, v2, on_failure) \
|
||||||
GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
|
GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, #v1, #v2, pred, v1, v2), \
|
||||||
#v1, \
|
on_failure)
|
||||||
#v2, \
|
|
||||||
pred, \
|
|
||||||
v1, \
|
|
||||||
v2), on_failure)
|
|
||||||
|
|
||||||
// Binary predicate assertion macros.
|
// Binary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
|
#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
|
||||||
|
@ -169,22 +149,12 @@ AssertionResult AssertPred2Helper(const char* pred_text,
|
||||||
#define ASSERT_PRED2(pred, v1, v2) \
|
#define ASSERT_PRED2(pred, v1, v2) \
|
||||||
GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
|
GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred, typename T1, typename T2, typename T3>
|
||||||
typename T1,
|
AssertionResult AssertPred3Helper(const char* pred_text, const char* e1,
|
||||||
typename T2,
|
const char* e2, const char* e3, Pred pred,
|
||||||
typename T3>
|
const T1& v1, const T2& v2, const T3& v3) {
|
||||||
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();
|
if (pred(v1, v2, v3)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure()
|
return AssertionFailure()
|
||||||
|
@ -198,21 +168,15 @@ AssertionResult AssertPred3Helper(const char* pred_text,
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
|
#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure) \
|
||||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
|
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), on_failure)
|
||||||
on_failure)
|
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
|
#define GTEST_PRED3_(pred, v1, v2, v3, on_failure) \
|
||||||
GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
|
GTEST_ASSERT_( \
|
||||||
#v1, \
|
::testing::AssertPred3Helper(#pred, #v1, #v2, #v3, pred, v1, v2, v3), \
|
||||||
#v2, \
|
on_failure)
|
||||||
#v3, \
|
|
||||||
pred, \
|
|
||||||
v1, \
|
|
||||||
v2, \
|
|
||||||
v3), on_failure)
|
|
||||||
|
|
||||||
// Ternary predicate assertion macros.
|
// Ternary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
|
#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
|
||||||
|
@ -224,25 +188,13 @@ AssertionResult AssertPred3Helper(const char* pred_text,
|
||||||
#define ASSERT_PRED3(pred, v1, v2, v3) \
|
#define ASSERT_PRED3(pred, v1, v2, v3) \
|
||||||
GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
|
GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred, typename T1, typename T2, typename T3, typename T4>
|
||||||
typename T1,
|
AssertionResult AssertPred4Helper(const char* pred_text, const char* e1,
|
||||||
typename T2,
|
const char* e2, const char* e3,
|
||||||
typename T3,
|
const char* e4, Pred pred, const T1& v1,
|
||||||
typename T4>
|
const T2& v2, const T3& v3, const T4& v4) {
|
||||||
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();
|
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure()
|
return AssertionFailure()
|
||||||
|
@ -257,23 +209,15 @@ AssertionResult AssertPred4Helper(const char* pred_text,
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
|
#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure) \
|
||||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
|
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), on_failure)
|
||||||
on_failure)
|
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
|
#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure) \
|
||||||
GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
|
GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, #v1, #v2, #v3, #v4, pred, \
|
||||||
#v1, \
|
v1, v2, v3, v4), \
|
||||||
#v2, \
|
on_failure)
|
||||||
#v3, \
|
|
||||||
#v4, \
|
|
||||||
pred, \
|
|
||||||
v1, \
|
|
||||||
v2, \
|
|
||||||
v3, \
|
|
||||||
v4), on_failure)
|
|
||||||
|
|
||||||
// 4-ary predicate assertion macros.
|
// 4-ary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
|
#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
|
||||||
|
@ -285,28 +229,15 @@ AssertionResult AssertPred4Helper(const char* pred_text,
|
||||||
#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
|
#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
|
||||||
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
|
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred, typename T1, typename T2, typename T3, typename T4,
|
||||||
typename T1,
|
|
||||||
typename T2,
|
|
||||||
typename T3,
|
|
||||||
typename T4,
|
|
||||||
typename T5>
|
typename T5>
|
||||||
AssertionResult AssertPred5Helper(const char* pred_text,
|
AssertionResult AssertPred5Helper(const char* pred_text, const char* e1,
|
||||||
const char* e1,
|
const char* e2, const char* e3,
|
||||||
const char* e2,
|
const char* e4, const char* e5, Pred pred,
|
||||||
const char* e3,
|
const T1& v1, const T2& v2, const T3& v3,
|
||||||
const char* e4,
|
const T4& v4, const T5& v5) {
|
||||||
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();
|
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure()
|
return AssertionFailure()
|
||||||
|
@ -322,25 +253,16 @@ AssertionResult AssertPred5Helper(const char* pred_text,
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
|
#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure) \
|
||||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
|
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
|
||||||
on_failure)
|
on_failure)
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
|
#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure) \
|
||||||
GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
|
GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, #v1, #v2, #v3, #v4, #v5, \
|
||||||
#v1, \
|
pred, v1, v2, v3, v4, v5), \
|
||||||
#v2, \
|
on_failure)
|
||||||
#v3, \
|
|
||||||
#v4, \
|
|
||||||
#v5, \
|
|
||||||
pred, \
|
|
||||||
v1, \
|
|
||||||
v2, \
|
|
||||||
v3, \
|
|
||||||
v4, \
|
|
||||||
v5), on_failure)
|
|
||||||
|
|
||||||
// 5-ary predicate assertion macros.
|
// 5-ary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
|
#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
|
||||||
|
@ -352,8 +274,6 @@ AssertionResult AssertPred5Helper(const char* pred_text,
|
||||||
#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
|
#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
|
||||||
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
|
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||||
|
|
|
@ -27,9 +27,8 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
// Google C++ Testing and Mocking Framework definitions useful in production
|
||||||
// Google C++ Testing and Mocking Framework definitions useful in production code.
|
// code.
|
||||||
// GOOGLETEST_CM0003 DO NOT DELETE
|
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||||
|
@ -55,7 +54,7 @@
|
||||||
// Note: The test class must be in the same namespace as the class being tested.
|
// Note: The test class must be in the same namespace as the class being tested.
|
||||||
// For example, putting MyClassTest in an anonymous namespace will not work.
|
// For example, putting MyClassTest in an anonymous namespace will not work.
|
||||||
|
|
||||||
#define FRIEND_TEST(test_case_name, test_name)\
|
#define FRIEND_TEST(test_case_name, test_name) \
|
||||||
friend class test_case_name##_##test_name##_Test
|
friend class test_case_name##_##test_name##_Test
|
||||||
|
|
||||||
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||||
|
|
|
@ -15,18 +15,6 @@ The custom directory is an injection point for custom user configurations.
|
||||||
|
|
||||||
The following macros can be defined:
|
The following macros can be defined:
|
||||||
|
|
||||||
### Flag related macros:
|
|
||||||
|
|
||||||
* `GTEST_FLAG(flag_name)`
|
|
||||||
* `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its
|
|
||||||
own flagfile flag parsing.
|
|
||||||
* `GTEST_DECLARE_bool_(name)`
|
|
||||||
* `GTEST_DECLARE_int32_(name)`
|
|
||||||
* `GTEST_DECLARE_string_(name)`
|
|
||||||
* `GTEST_DEFINE_bool_(name, default_val, doc)`
|
|
||||||
* `GTEST_DEFINE_int32_(name, default_val, doc)`
|
|
||||||
* `GTEST_DEFINE_string_(name, default_val, doc)`
|
|
||||||
|
|
||||||
### Logging:
|
### Logging:
|
||||||
|
|
||||||
* `GTEST_LOG_(severity)`
|
* `GTEST_LOG_(severity)`
|
||||||
|
|
|
@ -26,27 +26,31 @@
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file defines internal utilities needed for implementing
|
// This header file defines internal utilities needed for implementing
|
||||||
// death tests. They are subject to change without notice.
|
// death tests. They are subject to change without notice.
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
|
||||||
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "gtest/gtest-matchers.h"
|
#include "gtest/gtest-matchers.h"
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
GTEST_DECLARE_string_(internal_run_death_test);
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
GTEST_DECLARE_string_(internal_run_death_test);
|
|
||||||
|
|
||||||
// Names of the flags (needed for parsing Google Test flags).
|
// Names of the flags (needed for parsing Google Test flags).
|
||||||
const char kDeathTestStyleFlag[] = "death_test_style";
|
const char kDeathTestStyleFlag[] = "death_test_style";
|
||||||
const char kDeathTestUseFork[] = "death_test_use_fork";
|
const char kDeathTestUseFork[] = "death_test_use_fork";
|
||||||
|
@ -83,16 +87,18 @@ class GTEST_API_ DeathTest {
|
||||||
static bool Create(const char* statement, Matcher<const std::string&> matcher,
|
static bool Create(const char* statement, Matcher<const std::string&> matcher,
|
||||||
const char* file, int line, DeathTest** test);
|
const char* file, int line, DeathTest** test);
|
||||||
DeathTest();
|
DeathTest();
|
||||||
virtual ~DeathTest() { }
|
virtual ~DeathTest() {}
|
||||||
|
|
||||||
// A helper class that aborts a death test when it's deleted.
|
// A helper class that aborts a death test when it's deleted.
|
||||||
class ReturnSentinel {
|
class ReturnSentinel {
|
||||||
public:
|
public:
|
||||||
explicit ReturnSentinel(DeathTest* test) : test_(test) { }
|
explicit ReturnSentinel(DeathTest* test) : test_(test) {}
|
||||||
~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
|
~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeathTest* const test_;
|
DeathTest* const test_;
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
|
ReturnSentinel(const ReturnSentinel&) = delete;
|
||||||
|
ReturnSentinel& operator=(const ReturnSentinel&) = delete;
|
||||||
} GTEST_ATTRIBUTE_UNUSED_;
|
} GTEST_ATTRIBUTE_UNUSED_;
|
||||||
|
|
||||||
// An enumeration of possible roles that may be taken when a death
|
// An enumeration of possible roles that may be taken when a death
|
||||||
|
@ -137,7 +143,8 @@ class GTEST_API_ DeathTest {
|
||||||
// A string containing a description of the outcome of the last death test.
|
// A string containing a description of the outcome of the last death test.
|
||||||
static std::string last_death_test_message_;
|
static std::string last_death_test_message_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
|
DeathTest(const DeathTest&) = delete;
|
||||||
|
DeathTest& operator=(const DeathTest&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
|
@ -145,7 +152,7 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
// Factory interface for death tests. May be mocked out for testing.
|
// Factory interface for death tests. May be mocked out for testing.
|
||||||
class DeathTestFactory {
|
class DeathTestFactory {
|
||||||
public:
|
public:
|
||||||
virtual ~DeathTestFactory() { }
|
virtual ~DeathTestFactory() {}
|
||||||
virtual bool Create(const char* statement,
|
virtual bool Create(const char* statement,
|
||||||
Matcher<const std::string&> matcher, const char* file,
|
Matcher<const std::string&> matcher, const char* file,
|
||||||
int line, DeathTest** test) = 0;
|
int line, DeathTest** test) = 0;
|
||||||
|
@ -186,12 +193,12 @@ inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
||||||
|
|
||||||
// Traps C++ exceptions escaping statement and reports them as test
|
// Traps C++ exceptions escaping statement and reports them as test
|
||||||
// failures. Note that trapping SEH exceptions is not implemented here.
|
// failures. Note that trapping SEH exceptions is not implemented here.
|
||||||
# if GTEST_HAS_EXCEPTIONS
|
#if GTEST_HAS_EXCEPTIONS
|
||||||
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
#define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
||||||
try { \
|
try { \
|
||||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
} catch (const ::std::exception& gtest_exception) { \
|
} catch (const ::std::exception& gtest_exception) { \
|
||||||
fprintf(\
|
fprintf( \
|
||||||
stderr, \
|
stderr, \
|
||||||
"\n%s: Caught std::exception-derived exception escaping the " \
|
"\n%s: Caught std::exception-derived exception escaping the " \
|
||||||
"death test statement. Exception message: %s\n", \
|
"death test statement. Exception message: %s\n", \
|
||||||
|
@ -203,11 +210,11 @@ inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
||||||
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
|
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
|
||||||
}
|
}
|
||||||
|
|
||||||
# else
|
#else
|
||||||
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
#define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
||||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
||||||
|
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
|
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
|
||||||
// ASSERT_EXIT*, and EXPECT_EXIT*.
|
// ASSERT_EXIT*, and EXPECT_EXIT*.
|
||||||
|
@ -236,8 +243,6 @@ inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
||||||
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
|
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
default: \
|
|
||||||
break; \
|
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} else \
|
} else \
|
||||||
|
@ -265,16 +270,12 @@ inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
||||||
// RUN_ALL_TESTS was called.
|
// RUN_ALL_TESTS was called.
|
||||||
class InternalRunDeathTestFlag {
|
class InternalRunDeathTestFlag {
|
||||||
public:
|
public:
|
||||||
InternalRunDeathTestFlag(const std::string& a_file,
|
InternalRunDeathTestFlag(const std::string& a_file, int a_line, int an_index,
|
||||||
int a_line,
|
|
||||||
int an_index,
|
|
||||||
int a_write_fd)
|
int a_write_fd)
|
||||||
: file_(a_file), line_(a_line), index_(an_index),
|
: file_(a_file), line_(a_line), index_(an_index), write_fd_(a_write_fd) {}
|
||||||
write_fd_(a_write_fd) {}
|
|
||||||
|
|
||||||
~InternalRunDeathTestFlag() {
|
~InternalRunDeathTestFlag() {
|
||||||
if (write_fd_ >= 0)
|
if (write_fd_ >= 0) posix::Close(write_fd_);
|
||||||
posix::Close(write_fd_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& file() const { return file_; }
|
const std::string& file() const { return file_; }
|
||||||
|
@ -288,7 +289,8 @@ class InternalRunDeathTestFlag {
|
||||||
int index_;
|
int index_;
|
||||||
int write_fd_;
|
int write_fd_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
|
InternalRunDeathTestFlag(const InternalRunDeathTestFlag&) = delete;
|
||||||
|
InternalRunDeathTestFlag& operator=(const InternalRunDeathTestFlag&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns a newly created InternalRunDeathTestFlag object with fields
|
// Returns a newly created InternalRunDeathTestFlag object with fields
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Google Test filepath utilities
|
// Google Test filepath utilities
|
||||||
//
|
//
|
||||||
// This header file declares classes and functions used internally by
|
// This header file declares classes and functions used internally by
|
||||||
|
@ -35,7 +35,9 @@
|
||||||
// This file is #included in gtest/internal/gtest-internal.h.
|
// This file is #included in gtest/internal/gtest-internal.h.
|
||||||
// Do not include this header file separately!
|
// Do not include this header file separately!
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||||
|
@ -61,8 +63,8 @@ namespace internal {
|
||||||
|
|
||||||
class GTEST_API_ FilePath {
|
class GTEST_API_ FilePath {
|
||||||
public:
|
public:
|
||||||
FilePath() : pathname_("") { }
|
FilePath() : pathname_("") {}
|
||||||
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
|
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) {}
|
||||||
|
|
||||||
explicit FilePath(const std::string& pathname) : pathname_(pathname) {
|
explicit FilePath(const std::string& pathname) : pathname_(pathname) {
|
||||||
Normalize();
|
Normalize();
|
||||||
|
@ -73,9 +75,7 @@ class GTEST_API_ FilePath {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Set(const FilePath& rhs) {
|
void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; }
|
||||||
pathname_ = rhs.pathname_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& string() const { return pathname_; }
|
const std::string& string() const { return pathname_; }
|
||||||
const char* c_str() const { return pathname_.c_str(); }
|
const char* c_str() const { return pathname_.c_str(); }
|
||||||
|
@ -88,8 +88,7 @@ class GTEST_API_ FilePath {
|
||||||
// than zero (e.g., 12), returns "dir/test_12.xml".
|
// than zero (e.g., 12), returns "dir/test_12.xml".
|
||||||
// On Windows platform, uses \ as the separator rather than /.
|
// On Windows platform, uses \ as the separator rather than /.
|
||||||
static FilePath MakeFileName(const FilePath& directory,
|
static FilePath MakeFileName(const FilePath& directory,
|
||||||
const FilePath& base_name,
|
const FilePath& base_name, int number,
|
||||||
int number,
|
|
||||||
const char* extension);
|
const char* extension);
|
||||||
|
|
||||||
// Given directory = "dir", relative_path = "test.xml",
|
// Given directory = "dir", relative_path = "test.xml",
|
||||||
|
|
|
@ -26,13 +26,15 @@
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file declares functions and macros used internally by
|
// This header file declares functions and macros used internally by
|
||||||
// Google Test. They are subject to change without notice.
|
// Google Test. They are subject to change without notice.
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||||
|
@ -40,19 +42,20 @@
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
#if GTEST_OS_LINUX
|
#if GTEST_OS_LINUX
|
||||||
# include <stdlib.h>
|
#include <stdlib.h>
|
||||||
# include <sys/types.h>
|
#include <sys/types.h>
|
||||||
# include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
# include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif // GTEST_OS_LINUX
|
#endif // GTEST_OS_LINUX
|
||||||
|
|
||||||
#if GTEST_HAS_EXCEPTIONS
|
#if GTEST_HAS_EXCEPTIONS
|
||||||
# include <stdexcept>
|
#include <stdexcept>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
@ -76,7 +79,7 @@
|
||||||
// the current line number. For more details, see
|
// the current line number. For more details, see
|
||||||
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
|
// 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_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
|
||||||
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
|
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo##bar
|
||||||
|
|
||||||
// Stringifies its argument.
|
// Stringifies its argument.
|
||||||
// Work around a bug in visual studio which doesn't accept code like this:
|
// Work around a bug in visual studio which doesn't accept code like this:
|
||||||
|
@ -121,6 +124,7 @@ GTEST_API_ extern const char kStackTraceMarker[];
|
||||||
// An IgnoredValue object can be implicitly constructed from ANY value.
|
// An IgnoredValue object can be implicitly constructed from ANY value.
|
||||||
class IgnoredValue {
|
class IgnoredValue {
|
||||||
struct Sink {};
|
struct Sink {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// This constructor template allows any value to be implicitly
|
// This constructor template allows any value to be implicitly
|
||||||
// converted to IgnoredValue. The object has no data member and
|
// converted to IgnoredValue. The object has no data member and
|
||||||
|
@ -136,13 +140,13 @@ class IgnoredValue {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Appends the user-supplied message to the Google-Test-generated message.
|
// Appends the user-supplied message to the Google-Test-generated message.
|
||||||
GTEST_API_ std::string AppendUserMessage(
|
GTEST_API_ std::string AppendUserMessage(const std::string& gtest_msg,
|
||||||
const std::string& gtest_msg, const Message& user_msg);
|
const Message& user_msg);
|
||||||
|
|
||||||
#if GTEST_HAS_EXCEPTIONS
|
#if GTEST_HAS_EXCEPTIONS
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4275 \
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||||
/* an exported class was derived from a class that was not exported */)
|
4275 /* an exported class was derived from a class that was not exported */)
|
||||||
|
|
||||||
// This exception is thrown by (and only by) a failed Google Test
|
// This exception is thrown by (and only by) a failed Google Test
|
||||||
// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
|
// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
|
||||||
|
@ -181,14 +185,6 @@ GTEST_API_ std::string CreateUnifiedDiff(const std::vector<std::string>& left,
|
||||||
|
|
||||||
} // namespace edit_distance
|
} // namespace edit_distance
|
||||||
|
|
||||||
// Calculate the diff between 'left' and 'right' and return it in unified diff
|
|
||||||
// format.
|
|
||||||
// If not null, stores in 'total_line_count' the total number of lines found
|
|
||||||
// in left + right.
|
|
||||||
GTEST_API_ std::string DiffStrings(const std::string& left,
|
|
||||||
const std::string& right,
|
|
||||||
size_t* total_line_count);
|
|
||||||
|
|
||||||
// Constructs and returns the message for an equality assertion
|
// Constructs and returns the message for an equality assertion
|
||||||
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
|
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
|
||||||
//
|
//
|
||||||
|
@ -212,10 +208,8 @@ GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
|
||||||
|
|
||||||
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
|
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
|
||||||
GTEST_API_ std::string GetBoolAssertionFailureMessage(
|
GTEST_API_ std::string GetBoolAssertionFailureMessage(
|
||||||
const AssertionResult& assertion_result,
|
const AssertionResult& assertion_result, const char* expression_text,
|
||||||
const char* expression_text,
|
const char* actual_predicate_value, const char* expected_predicate_value);
|
||||||
const char* actual_predicate_value,
|
|
||||||
const char* expected_predicate_value);
|
|
||||||
|
|
||||||
// This template class represents an IEEE floating-point number
|
// This template class represents an IEEE floating-point number
|
||||||
// (either single-precision or double-precision, depending on the
|
// (either single-precision or double-precision, depending on the
|
||||||
|
@ -256,7 +250,7 @@ class FloatingPoint {
|
||||||
// Constants.
|
// Constants.
|
||||||
|
|
||||||
// # of bits in a number.
|
// # of bits in a number.
|
||||||
static const size_t kBitCount = 8*sizeof(RawType);
|
static const size_t kBitCount = 8 * sizeof(RawType);
|
||||||
|
|
||||||
// # of fraction bits in a number.
|
// # of fraction bits in a number.
|
||||||
static const size_t kFractionBitCount =
|
static const size_t kFractionBitCount =
|
||||||
|
@ -269,8 +263,8 @@ class FloatingPoint {
|
||||||
static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
|
static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
|
||||||
|
|
||||||
// The mask for the fraction bits.
|
// The mask for the fraction bits.
|
||||||
static const Bits kFractionBitMask =
|
static const Bits kFractionBitMask = ~static_cast<Bits>(0) >>
|
||||||
~static_cast<Bits>(0) >> (kExponentBitCount + 1);
|
(kExponentBitCount + 1);
|
||||||
|
|
||||||
// The mask for the exponent bits.
|
// The mask for the exponent bits.
|
||||||
static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
|
static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
|
||||||
|
@ -309,9 +303,7 @@ class FloatingPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the floating-point number that represent positive infinity.
|
// Returns the floating-point number that represent positive infinity.
|
||||||
static RawType Infinity() {
|
static RawType Infinity() { return ReinterpretBits(kExponentBitMask); }
|
||||||
return ReinterpretBits(kExponentBitMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the maximum representable finite floating-point number.
|
// Returns the maximum representable finite floating-point number.
|
||||||
static RawType Max();
|
static RawType Max();
|
||||||
|
@ -319,7 +311,7 @@ class FloatingPoint {
|
||||||
// Non-static methods
|
// Non-static methods
|
||||||
|
|
||||||
// Returns the bits that represents this number.
|
// Returns the bits that represents this number.
|
||||||
const Bits &bits() const { return u_.bits_; }
|
const Bits& bits() const { return u_.bits_; }
|
||||||
|
|
||||||
// Returns the exponent bits of this number.
|
// Returns the exponent bits of this number.
|
||||||
Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
|
Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
|
||||||
|
@ -348,8 +340,8 @@ class FloatingPoint {
|
||||||
// a NAN must return false.
|
// a NAN must return false.
|
||||||
if (is_nan() || rhs.is_nan()) return false;
|
if (is_nan() || rhs.is_nan()) return false;
|
||||||
|
|
||||||
return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
|
return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <=
|
||||||
<= kMaxUlps;
|
kMaxUlps;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -374,7 +366,7 @@ class FloatingPoint {
|
||||||
//
|
//
|
||||||
// Read http://en.wikipedia.org/wiki/Signed_number_representations
|
// Read http://en.wikipedia.org/wiki/Signed_number_representations
|
||||||
// for more details on signed number representations.
|
// for more details on signed number representations.
|
||||||
static Bits SignAndMagnitudeToBiased(const Bits &sam) {
|
static Bits SignAndMagnitudeToBiased(const Bits& sam) {
|
||||||
if (kSignBitMask & sam) {
|
if (kSignBitMask & sam) {
|
||||||
// sam represents a negative number.
|
// sam represents a negative number.
|
||||||
return ~sam + 1;
|
return ~sam + 1;
|
||||||
|
@ -386,8 +378,8 @@ class FloatingPoint {
|
||||||
|
|
||||||
// Given two numbers in the sign-and-magnitude representation,
|
// Given two numbers in the sign-and-magnitude representation,
|
||||||
// returns the distance between them as an unsigned number.
|
// returns the distance between them as an unsigned number.
|
||||||
static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
|
static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits& sam1,
|
||||||
const Bits &sam2) {
|
const Bits& sam2) {
|
||||||
const Bits biased1 = SignAndMagnitudeToBiased(sam1);
|
const Bits biased1 = SignAndMagnitudeToBiased(sam1);
|
||||||
const Bits biased2 = SignAndMagnitudeToBiased(sam2);
|
const Bits biased2 = SignAndMagnitudeToBiased(sam2);
|
||||||
return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
|
return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
|
||||||
|
@ -399,9 +391,13 @@ class FloatingPoint {
|
||||||
// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
|
// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
|
||||||
// macro defined by <windows.h>.
|
// macro defined by <windows.h>.
|
||||||
template <>
|
template <>
|
||||||
inline float FloatingPoint<float>::Max() { return FLT_MAX; }
|
inline float FloatingPoint<float>::Max() {
|
||||||
|
return FLT_MAX;
|
||||||
|
}
|
||||||
template <>
|
template <>
|
||||||
inline double FloatingPoint<double>::Max() { return DBL_MAX; }
|
inline double FloatingPoint<double>::Max() {
|
||||||
|
return DBL_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
// Typedefs the instances of the FloatingPoint template class that we
|
// Typedefs the instances of the FloatingPoint template class that we
|
||||||
// care to use.
|
// care to use.
|
||||||
|
@ -461,7 +457,8 @@ class TestFactoryBase {
|
||||||
TestFactoryBase() {}
|
TestFactoryBase() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
|
TestFactoryBase(const TestFactoryBase&) = delete;
|
||||||
|
TestFactoryBase& operator=(const TestFactoryBase&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class provides implementation of TeastFactoryBase interface.
|
// This class provides implementation of TeastFactoryBase interface.
|
||||||
|
@ -510,11 +507,11 @@ inline SetUpTearDownSuiteFuncType GetNotDefaultOrNull(
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
// Note that SuiteApiResolver inherits from T because
|
// Note that SuiteApiResolver inherits from T because
|
||||||
// SetUpTestSuite()/TearDownTestSuite() could be protected. Ths way
|
// SetUpTestSuite()/TearDownTestSuite() could be protected. This way
|
||||||
// SuiteApiResolver can access them.
|
// SuiteApiResolver can access them.
|
||||||
struct SuiteApiResolver : T {
|
struct SuiteApiResolver : T {
|
||||||
// testing::Test is only forward declared at this point. So we make it a
|
// testing::Test is only forward declared at this point. So we make it a
|
||||||
// dependend class for the compiler to be OK with it.
|
// dependent class for the compiler to be OK with it.
|
||||||
using Test =
|
using Test =
|
||||||
typename std::conditional<sizeof(T) != 0, ::testing::Test, void>::type;
|
typename std::conditional<sizeof(T) != 0, ::testing::Test, void>::type;
|
||||||
|
|
||||||
|
@ -654,7 +651,8 @@ inline const char* SkipComma(const char* str) {
|
||||||
if (comma == nullptr) {
|
if (comma == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
while (IsSpace(*(++comma))) {}
|
while (IsSpace(*(++comma))) {
|
||||||
|
}
|
||||||
return comma;
|
return comma;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,7 +666,7 @@ inline std::string GetPrefixUntilComma(const char* str) {
|
||||||
// Splits a given string on a given delimiter, populating a given
|
// Splits a given string on a given delimiter, populating a given
|
||||||
// vector with the fields.
|
// vector with the fields.
|
||||||
void SplitString(const ::std::string& str, char delimiter,
|
void SplitString(const ::std::string& str, char delimiter,
|
||||||
::std::vector< ::std::string>* dest);
|
::std::vector<::std::string>* dest);
|
||||||
|
|
||||||
// The default argument to the template below for the case when the user does
|
// The default argument to the template below for the case when the user does
|
||||||
// not provide a name generator.
|
// not provide a name generator.
|
||||||
|
@ -781,13 +779,13 @@ class TypeParameterizedTestSuite {
|
||||||
const std::vector<std::string>& type_names =
|
const std::vector<std::string>& type_names =
|
||||||
GenerateNames<DefaultNameGenerator, Types>()) {
|
GenerateNames<DefaultNameGenerator, Types>()) {
|
||||||
RegisterTypeParameterizedTestSuiteInstantiation(case_name);
|
RegisterTypeParameterizedTestSuiteInstantiation(case_name);
|
||||||
std::string test_name = StripTrailingSpaces(
|
std::string test_name =
|
||||||
GetPrefixUntilComma(test_names));
|
StripTrailingSpaces(GetPrefixUntilComma(test_names));
|
||||||
if (!state->TestExists(test_name)) {
|
if (!state->TestExists(test_name)) {
|
||||||
fprintf(stderr, "Failed to get code location for test %s.%s at %s.",
|
fprintf(stderr, "Failed to get code location for test %s.%s at %s.",
|
||||||
case_name, test_name.c_str(),
|
case_name, test_name.c_str(),
|
||||||
FormatFileLocation(code_location.file.c_str(),
|
FormatFileLocation(code_location.file.c_str(), code_location.line)
|
||||||
code_location.line).c_str());
|
.c_str());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
posix::Abort();
|
posix::Abort();
|
||||||
}
|
}
|
||||||
|
@ -831,8 +829,8 @@ class TypeParameterizedTestSuite<Fixture, internal::None, Types> {
|
||||||
// For example, if Foo() calls Bar(), which in turn calls
|
// For example, if Foo() calls Bar(), which in turn calls
|
||||||
// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
|
// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
|
||||||
// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
|
// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
|
||||||
GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(
|
GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(UnitTest* unit_test,
|
||||||
UnitTest* unit_test, int skip_count);
|
int skip_count);
|
||||||
|
|
||||||
// Helpers for suppressing warnings on unreachable code or constant
|
// Helpers for suppressing warnings on unreachable code or constant
|
||||||
// condition.
|
// condition.
|
||||||
|
@ -881,7 +879,8 @@ class GTEST_API_ Random {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t state_;
|
uint32_t state_;
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
|
Random(const Random&) = delete;
|
||||||
|
Random& operator=(const Random&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Turns const U&, U&, const U, and U all into U.
|
// Turns const U&, U&, const U, and U all into U.
|
||||||
|
@ -954,7 +953,9 @@ IsContainer IsContainerTest(int /* dummy */) {
|
||||||
|
|
||||||
typedef char IsNotContainer;
|
typedef char IsNotContainer;
|
||||||
template <class C>
|
template <class C>
|
||||||
IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
|
IsNotContainer IsContainerTest(long /* dummy */) {
|
||||||
|
return '\0';
|
||||||
|
}
|
||||||
|
|
||||||
// Trait to detect whether a type T is a hash table.
|
// Trait to detect whether a type T is a hash table.
|
||||||
// The heuristic used is that the type contains an inner type `hasher` and does
|
// The heuristic used is that the type contains an inner type `hasher` and does
|
||||||
|
@ -1017,11 +1018,13 @@ bool ArrayEq(const T* lhs, size_t size, const U* rhs);
|
||||||
|
|
||||||
// This generic version is used when k is 0.
|
// This generic version is used when k is 0.
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
|
inline bool ArrayEq(const T& lhs, const U& rhs) {
|
||||||
|
return lhs == rhs;
|
||||||
|
}
|
||||||
|
|
||||||
// This overload is used when k >= 1.
|
// This overload is used when k >= 1.
|
||||||
template <typename T, typename U, size_t N>
|
template <typename T, typename U, size_t N>
|
||||||
inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
|
inline bool ArrayEq(const T (&lhs)[N], const U (&rhs)[N]) {
|
||||||
return internal::ArrayEq(lhs, N, rhs);
|
return internal::ArrayEq(lhs, N, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,8 +1034,7 @@ inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
|
bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
|
||||||
for (size_t i = 0; i != size; i++) {
|
for (size_t i = 0; i != size; i++) {
|
||||||
if (!internal::ArrayEq(lhs[i], rhs[i]))
|
if (!internal::ArrayEq(lhs[i], rhs[i])) return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1042,8 +1044,7 @@ bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
|
||||||
template <typename Iter, typename Element>
|
template <typename Iter, typename Element>
|
||||||
Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
|
Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
|
||||||
for (Iter it = begin; it != end; ++it) {
|
for (Iter it = begin; it != end; ++it) {
|
||||||
if (internal::ArrayEq(*it, elem))
|
if (internal::ArrayEq(*it, elem)) return it;
|
||||||
return it;
|
|
||||||
}
|
}
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
@ -1057,11 +1058,13 @@ void CopyArray(const T* from, size_t size, U* to);
|
||||||
|
|
||||||
// This generic version is used when k is 0.
|
// This generic version is used when k is 0.
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
inline void CopyArray(const T& from, U* to) { *to = from; }
|
inline void CopyArray(const T& from, U* to) {
|
||||||
|
*to = from;
|
||||||
|
}
|
||||||
|
|
||||||
// This overload is used when k >= 1.
|
// This overload is used when k >= 1.
|
||||||
template <typename T, typename U, size_t N>
|
template <typename T, typename U, size_t N>
|
||||||
inline void CopyArray(const T(&from)[N], U(*to)[N]) {
|
inline void CopyArray(const T (&from)[N], U (*to)[N]) {
|
||||||
internal::CopyArray(from, N, *to);
|
internal::CopyArray(from, N, *to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1114,8 +1117,7 @@ class NativeArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
~NativeArray() {
|
~NativeArray() {
|
||||||
if (clone_ != &NativeArray::InitRef)
|
if (clone_ != &NativeArray::InitRef) delete[] array_;
|
||||||
delete[] array_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// STL-style container methods.
|
// STL-style container methods.
|
||||||
|
@ -1123,8 +1125,7 @@ class NativeArray {
|
||||||
const_iterator begin() const { return array_; }
|
const_iterator begin() const { return array_; }
|
||||||
const_iterator end() const { return array_ + size_; }
|
const_iterator end() const { return array_ + size_; }
|
||||||
bool operator==(const NativeArray& rhs) const {
|
bool operator==(const NativeArray& rhs) const {
|
||||||
return size() == rhs.size() &&
|
return size() == rhs.size() && ArrayEq(begin(), size(), rhs.begin());
|
||||||
ArrayEq(begin(), size(), rhs.begin());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1336,8 +1337,8 @@ struct tuple_size<testing::internal::FlatTuple<Ts...>>
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
|
#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
|
||||||
::testing::internal::AssertHelper(result_type, file, line, message) \
|
::testing::internal::AssertHelper(result_type, file, line, message) = \
|
||||||
= ::testing::Message()
|
::testing::Message()
|
||||||
|
|
||||||
#define GTEST_MESSAGE_(message, result_type) \
|
#define GTEST_MESSAGE_(message, result_type) \
|
||||||
GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
|
GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
|
||||||
|
@ -1470,9 +1471,11 @@ class NeverThrown {
|
||||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
|
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
|
||||||
} \
|
} \
|
||||||
} else \
|
} else \
|
||||||
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
|
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__) \
|
||||||
fail(("Expected: " #statement " doesn't throw an exception.\n" \
|
: fail(("Expected: " #statement " doesn't throw an exception.\n" \
|
||||||
" Actual: " + gtest_msg.value).c_str())
|
" Actual: " + \
|
||||||
|
gtest_msg.value) \
|
||||||
|
.c_str())
|
||||||
|
|
||||||
#define GTEST_TEST_ANY_THROW_(statement, fail) \
|
#define GTEST_TEST_ANY_THROW_(statement, fail) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
@ -1480,19 +1483,18 @@ class NeverThrown {
|
||||||
bool gtest_caught_any = false; \
|
bool gtest_caught_any = false; \
|
||||||
try { \
|
try { \
|
||||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
} \
|
} catch (...) { \
|
||||||
catch (...) { \
|
|
||||||
gtest_caught_any = true; \
|
gtest_caught_any = true; \
|
||||||
} \
|
} \
|
||||||
if (!gtest_caught_any) { \
|
if (!gtest_caught_any) { \
|
||||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
|
goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
|
||||||
} \
|
} \
|
||||||
} else \
|
} else \
|
||||||
GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
|
GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__) \
|
||||||
fail("Expected: " #statement " throws an exception.\n" \
|
: fail("Expected: " #statement \
|
||||||
|
" throws an exception.\n" \
|
||||||
" Actual: it doesn't.")
|
" Actual: it doesn't.")
|
||||||
|
|
||||||
|
|
||||||
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
|
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
|
||||||
// either a boolean expression or an AssertionResult. text is a textual
|
// either a boolean expression or an AssertionResult. text is a textual
|
||||||
// representation of expression as it was passed into the EXPECT_TRUE.
|
// representation of expression as it was passed into the EXPECT_TRUE.
|
||||||
|
@ -1502,8 +1504,9 @@ class NeverThrown {
|
||||||
::testing::AssertionResult(expression)) \
|
::testing::AssertionResult(expression)) \
|
||||||
; \
|
; \
|
||||||
else \
|
else \
|
||||||
fail(::testing::internal::GetBoolAssertionFailureMessage(\
|
fail(::testing::internal::GetBoolAssertionFailureMessage( \
|
||||||
gtest_ar_, text, #actual, #expected).c_str())
|
gtest_ar_, text, #actual, #expected) \
|
||||||
|
.c_str())
|
||||||
|
|
||||||
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
|
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
|
@ -1514,8 +1517,9 @@ class NeverThrown {
|
||||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
|
goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
|
||||||
} \
|
} \
|
||||||
} else \
|
} else \
|
||||||
GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
|
GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__) \
|
||||||
fail("Expected: " #statement " doesn't generate new fatal " \
|
: fail("Expected: " #statement \
|
||||||
|
" doesn't generate new fatal " \
|
||||||
"failures in the current thread.\n" \
|
"failures in the current thread.\n" \
|
||||||
" Actual: it does.")
|
" Actual: it does.")
|
||||||
|
|
||||||
|
@ -1534,10 +1538,16 @@ class NeverThrown {
|
||||||
public: \
|
public: \
|
||||||
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default; \
|
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default; \
|
||||||
~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \
|
~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
|
||||||
test_name)); \
|
(const GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) &) = delete; \
|
||||||
GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) & operator=( \
|
||||||
test_name)); \
|
const GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||||
|
test_name) &) = delete; /* NOLINT */ \
|
||||||
|
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
|
||||||
|
(GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) &&) noexcept = delete; \
|
||||||
|
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) & operator=( \
|
||||||
|
GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||||
|
test_name) &&) noexcept = delete; /* NOLINT */ \
|
||||||
\
|
\
|
||||||
private: \
|
private: \
|
||||||
void TestBody() override; \
|
void TestBody() override; \
|
||||||
|
|
|
@ -27,10 +27,11 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// Type and function utilities for implementing parameterized tests.
|
// Type and function utilities for implementing parameterized tests.
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
|
||||||
|
@ -46,19 +47,18 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-internal.h"
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
|
||||||
#include "gtest/gtest-printers.h"
|
#include "gtest/gtest-printers.h"
|
||||||
#include "gtest/gtest-test-part.h"
|
#include "gtest/gtest-test-part.h"
|
||||||
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
// Input to a parameterized test name generator, describing a test parameter.
|
// Input to a parameterized test name generator, describing a test parameter.
|
||||||
// Consists of the parameter value and the integer parameter index.
|
// Consists of the parameter value and the integer parameter index.
|
||||||
template <class ParamType>
|
template <class ParamType>
|
||||||
struct TestParamInfo {
|
struct TestParamInfo {
|
||||||
TestParamInfo(const ParamType& a_param, size_t an_index) :
|
TestParamInfo(const ParamType& a_param, size_t an_index)
|
||||||
param(a_param),
|
: param(a_param), index(an_index) {}
|
||||||
index(an_index) {}
|
|
||||||
ParamType param;
|
ParamType param;
|
||||||
size_t index;
|
size_t index;
|
||||||
};
|
};
|
||||||
|
@ -84,8 +84,10 @@ namespace internal {
|
||||||
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
|
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
|
||||||
CodeLocation code_location);
|
CodeLocation code_location);
|
||||||
|
|
||||||
template <typename> class ParamGeneratorInterface;
|
template <typename>
|
||||||
template <typename> class ParamGenerator;
|
class ParamGeneratorInterface;
|
||||||
|
template <typename>
|
||||||
|
class ParamGenerator;
|
||||||
|
|
||||||
// Interface for iterating over elements provided by an implementation
|
// Interface for iterating over elements provided by an implementation
|
||||||
// of ParamGeneratorInterface<T>.
|
// of ParamGeneratorInterface<T>.
|
||||||
|
@ -129,8 +131,7 @@ class ParamIterator {
|
||||||
// ParamIterator assumes ownership of the impl_ pointer.
|
// ParamIterator assumes ownership of the impl_ pointer.
|
||||||
ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
|
ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
|
||||||
ParamIterator& operator=(const ParamIterator& other) {
|
ParamIterator& operator=(const ParamIterator& other) {
|
||||||
if (this != &other)
|
if (this != &other) impl_.reset(other.impl_->Clone());
|
||||||
impl_.reset(other.impl_->Clone());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +158,7 @@ class ParamIterator {
|
||||||
private:
|
private:
|
||||||
friend class ParamGenerator<T>;
|
friend class ParamGenerator<T>;
|
||||||
explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
|
explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
|
||||||
std::unique_ptr<ParamIteratorInterface<T> > impl_;
|
std::unique_ptr<ParamIteratorInterface<T>> impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ParamGeneratorInterface<T> is the binary interface to access generators
|
// ParamGeneratorInterface<T> is the binary interface to access generators
|
||||||
|
@ -179,7 +180,7 @@ class ParamGeneratorInterface {
|
||||||
// This class implements copy initialization semantics and the contained
|
// This class implements copy initialization semantics and the contained
|
||||||
// ParamGeneratorInterface<T> instance is shared among all copies
|
// ParamGeneratorInterface<T> instance is shared among all copies
|
||||||
// of the original object. This is possible because that instance is immutable.
|
// of the original object. This is possible because that instance is immutable.
|
||||||
template<typename T>
|
template <typename T>
|
||||||
class ParamGenerator {
|
class ParamGenerator {
|
||||||
public:
|
public:
|
||||||
typedef ParamIterator<T> iterator;
|
typedef ParamIterator<T> iterator;
|
||||||
|
@ -196,7 +197,7 @@ class ParamGenerator {
|
||||||
iterator end() const { return iterator(impl_->End()); }
|
iterator end() const { return iterator(impl_->End()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<const ParamGeneratorInterface<T> > impl_;
|
std::shared_ptr<const ParamGeneratorInterface<T>> impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generates values from a range of two comparable values. Can be used to
|
// Generates values from a range of two comparable values. Can be used to
|
||||||
|
@ -207,8 +208,10 @@ template <typename T, typename IncrementT>
|
||||||
class RangeGenerator : public ParamGeneratorInterface<T> {
|
class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
public:
|
public:
|
||||||
RangeGenerator(T begin, T end, IncrementT step)
|
RangeGenerator(T begin, T end, IncrementT step)
|
||||||
: begin_(begin), end_(end),
|
: begin_(begin),
|
||||||
step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
|
end_(end),
|
||||||
|
step_(step),
|
||||||
|
end_index_(CalculateEndIndex(begin, end, step)) {}
|
||||||
~RangeGenerator() override {}
|
~RangeGenerator() override {}
|
||||||
|
|
||||||
ParamIteratorInterface<T>* Begin() const override {
|
ParamIteratorInterface<T>* Begin() const override {
|
||||||
|
@ -251,7 +254,9 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
private:
|
private:
|
||||||
Iterator(const Iterator& other)
|
Iterator(const Iterator& other)
|
||||||
: ParamIteratorInterface<T>(),
|
: ParamIteratorInterface<T>(),
|
||||||
base_(other.base_), value_(other.value_), index_(other.index_),
|
base_(other.base_),
|
||||||
|
value_(other.value_),
|
||||||
|
index_(other.index_),
|
||||||
step_(other.step_) {}
|
step_(other.step_) {}
|
||||||
|
|
||||||
// No implementation - assignment is unsupported.
|
// No implementation - assignment is unsupported.
|
||||||
|
@ -263,12 +268,10 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
const IncrementT step_;
|
const IncrementT step_;
|
||||||
}; // class RangeGenerator::Iterator
|
}; // class RangeGenerator::Iterator
|
||||||
|
|
||||||
static int CalculateEndIndex(const T& begin,
|
static int CalculateEndIndex(const T& begin, const T& end,
|
||||||
const T& end,
|
|
||||||
const IncrementT& step) {
|
const IncrementT& step) {
|
||||||
int end_index = 0;
|
int end_index = 0;
|
||||||
for (T i = begin; i < end; i = static_cast<T>(i + step))
|
for (T i = begin; i < end; i = static_cast<T>(i + step)) end_index++;
|
||||||
end_index++;
|
|
||||||
return end_index;
|
return end_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +286,6 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||||
const int end_index_;
|
const int end_index_;
|
||||||
}; // class RangeGenerator
|
}; // class RangeGenerator
|
||||||
|
|
||||||
|
|
||||||
// Generates values from a pair of STL-style iterators. Used in the
|
// Generates values from a pair of STL-style iterators. Used in the
|
||||||
// ValuesIn() function. The elements are copied from the source range
|
// ValuesIn() function. The elements are copied from the source range
|
||||||
// since the source can be located on the stack, and the generator
|
// since the source can be located on the stack, and the generator
|
||||||
|
@ -394,8 +396,8 @@ template <class TestClass>
|
||||||
class ParameterizedTestFactory : public TestFactoryBase {
|
class ParameterizedTestFactory : public TestFactoryBase {
|
||||||
public:
|
public:
|
||||||
typedef typename TestClass::ParamType ParamType;
|
typedef typename TestClass::ParamType ParamType;
|
||||||
explicit ParameterizedTestFactory(ParamType parameter) :
|
explicit ParameterizedTestFactory(ParamType parameter)
|
||||||
parameter_(parameter) {}
|
: parameter_(parameter) {}
|
||||||
Test* CreateTest() override {
|
Test* CreateTest() override {
|
||||||
TestClass::SetParam(¶meter_);
|
TestClass::SetParam(¶meter_);
|
||||||
return new TestClass();
|
return new TestClass();
|
||||||
|
@ -404,7 +406,8 @@ class ParameterizedTestFactory : public TestFactoryBase {
|
||||||
private:
|
private:
|
||||||
const ParamType parameter_;
|
const ParamType parameter_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
|
ParameterizedTestFactory(const ParameterizedTestFactory&) = delete;
|
||||||
|
ParameterizedTestFactory& operator=(const ParameterizedTestFactory&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
@ -440,7 +443,8 @@ class TestMetaFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
|
TestMetaFactory(const TestMetaFactory&) = delete;
|
||||||
|
TestMetaFactory& operator=(const TestMetaFactory&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
@ -471,7 +475,10 @@ class ParameterizedTestSuiteInfoBase {
|
||||||
ParameterizedTestSuiteInfoBase() {}
|
ParameterizedTestSuiteInfoBase() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
|
ParameterizedTestSuiteInfoBase(const ParameterizedTestSuiteInfoBase&) =
|
||||||
|
delete;
|
||||||
|
ParameterizedTestSuiteInfoBase& operator=(
|
||||||
|
const ParameterizedTestSuiteInfoBase&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
|
@ -547,8 +554,8 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||||
test_it != tests_.end(); ++test_it) {
|
test_it != tests_.end(); ++test_it) {
|
||||||
std::shared_ptr<TestInfo> test_info = *test_it;
|
std::shared_ptr<TestInfo> test_info = *test_it;
|
||||||
for (typename InstantiationContainer::iterator gen_it =
|
for (typename InstantiationContainer::iterator gen_it =
|
||||||
instantiations_.begin(); gen_it != instantiations_.end();
|
instantiations_.begin();
|
||||||
++gen_it) {
|
gen_it != instantiations_.end(); ++gen_it) {
|
||||||
const std::string& instantiation_name = gen_it->name;
|
const std::string& instantiation_name = gen_it->name;
|
||||||
ParamGenerator<ParamType> generator((*gen_it->generator)());
|
ParamGenerator<ParamType> generator((*gen_it->generator)());
|
||||||
ParamNameGeneratorFunc* name_func = gen_it->name_func;
|
ParamNameGeneratorFunc* name_func = gen_it->name_func;
|
||||||
|
@ -556,7 +563,7 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||||
int line = gen_it->line;
|
int line = gen_it->line;
|
||||||
|
|
||||||
std::string test_suite_name;
|
std::string test_suite_name;
|
||||||
if ( !instantiation_name.empty() )
|
if (!instantiation_name.empty())
|
||||||
test_suite_name = instantiation_name + "/";
|
test_suite_name = instantiation_name + "/";
|
||||||
test_suite_name += test_info->test_suite_base_name;
|
test_suite_name += test_info->test_suite_base_name;
|
||||||
|
|
||||||
|
@ -569,17 +576,16 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||||
|
|
||||||
Message test_name_stream;
|
Message test_name_stream;
|
||||||
|
|
||||||
std::string param_name = name_func(
|
std::string param_name =
|
||||||
TestParamInfo<ParamType>(*param_it, i));
|
name_func(TestParamInfo<ParamType>(*param_it, i));
|
||||||
|
|
||||||
GTEST_CHECK_(IsValidParamName(param_name))
|
GTEST_CHECK_(IsValidParamName(param_name))
|
||||||
<< "Parameterized test name '" << param_name
|
<< "Parameterized test name '" << param_name
|
||||||
<< "' is invalid, in " << file
|
<< "' is invalid, in " << file << " line " << line << std::endl;
|
||||||
<< " line " << line << std::endl;
|
|
||||||
|
|
||||||
GTEST_CHECK_(test_param_names.count(param_name) == 0)
|
GTEST_CHECK_(test_param_names.count(param_name) == 0)
|
||||||
<< "Duplicate parameterized test name '" << param_name
|
<< "Duplicate parameterized test name '" << param_name << "', in "
|
||||||
<< "', in " << file << " line " << line << std::endl;
|
<< file << " line " << line << std::endl;
|
||||||
|
|
||||||
test_param_names.insert(param_name);
|
test_param_names.insert(param_name);
|
||||||
|
|
||||||
|
@ -620,18 +626,17 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||||
|
|
||||||
const std::string test_suite_base_name;
|
const std::string test_suite_base_name;
|
||||||
const std::string test_base_name;
|
const std::string test_base_name;
|
||||||
const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
|
const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory;
|
||||||
const CodeLocation code_location;
|
const CodeLocation code_location;
|
||||||
};
|
};
|
||||||
using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >;
|
using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo>>;
|
||||||
// Records data received from INSTANTIATE_TEST_SUITE_P macros:
|
// Records data received from INSTANTIATE_TEST_SUITE_P macros:
|
||||||
// <Instantiation name, Sequence generator creation function,
|
// <Instantiation name, Sequence generator creation function,
|
||||||
// Name generator function, Source file, Source line>
|
// Name generator function, Source file, Source line>
|
||||||
struct InstantiationInfo {
|
struct InstantiationInfo {
|
||||||
InstantiationInfo(const std::string &name_in,
|
InstantiationInfo(const std::string& name_in,
|
||||||
GeneratorCreationFunc* generator_in,
|
GeneratorCreationFunc* generator_in,
|
||||||
ParamNameGeneratorFunc* name_func_in,
|
ParamNameGeneratorFunc* name_func_in, const char* file_in,
|
||||||
const char* file_in,
|
|
||||||
int line_in)
|
int line_in)
|
||||||
: name(name_in),
|
: name(name_in),
|
||||||
generator(generator_in),
|
generator(generator_in),
|
||||||
|
@ -649,13 +654,11 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||||
|
|
||||||
static bool IsValidParamName(const std::string& name) {
|
static bool IsValidParamName(const std::string& name) {
|
||||||
// Check for empty string
|
// Check for empty string
|
||||||
if (name.empty())
|
if (name.empty()) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check for invalid characters
|
// Check for invalid characters
|
||||||
for (std::string::size_type index = 0; index < name.size(); ++index) {
|
for (std::string::size_type index = 0; index < name.size(); ++index) {
|
||||||
if (!IsAlNum(name[index]) && name[index] != '_')
|
if (!IsAlNum(name[index]) && name[index] != '_') return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -666,7 +669,9 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||||
TestInfoContainer tests_;
|
TestInfoContainer tests_;
|
||||||
InstantiationContainer instantiations_;
|
InstantiationContainer instantiations_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo);
|
ParameterizedTestSuiteInfo(const ParameterizedTestSuiteInfo&) = delete;
|
||||||
|
ParameterizedTestSuiteInfo& operator=(const ParameterizedTestSuiteInfo&) =
|
||||||
|
delete;
|
||||||
}; // class ParameterizedTestSuiteInfo
|
}; // class ParameterizedTestSuiteInfo
|
||||||
|
|
||||||
// Legacy API is deprecated but still available
|
// Legacy API is deprecated but still available
|
||||||
|
@ -709,7 +714,7 @@ class ParameterizedTestSuiteRegistry {
|
||||||
// type we are looking for, so we downcast it to that type
|
// type we are looking for, so we downcast it to that type
|
||||||
// without further checks.
|
// without further checks.
|
||||||
typed_test_info = CheckedDowncastToActualType<
|
typed_test_info = CheckedDowncastToActualType<
|
||||||
ParameterizedTestSuiteInfo<TestSuite> >(test_suite_info);
|
ParameterizedTestSuiteInfo<TestSuite>>(test_suite_info);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -741,7 +746,10 @@ class ParameterizedTestSuiteRegistry {
|
||||||
|
|
||||||
TestSuiteInfoContainer test_suite_infos_;
|
TestSuiteInfoContainer test_suite_infos_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry);
|
ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) =
|
||||||
|
delete;
|
||||||
|
ParameterizedTestSuiteRegistry& operator=(
|
||||||
|
const ParameterizedTestSuiteRegistry&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Keep track of what type-parameterized test suite are defined and
|
// Keep track of what type-parameterized test suite are defined and
|
||||||
|
@ -836,7 +844,8 @@ class CartesianProductGenerator
|
||||||
: public ParamIteratorInterface<ParamType> {
|
: public ParamIteratorInterface<ParamType> {
|
||||||
public:
|
public:
|
||||||
IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
|
IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
|
||||||
const std::tuple<ParamGenerator<T>...>& generators, bool is_end)
|
const std::tuple<ParamGenerator<T>...>& generators,
|
||||||
|
bool is_end)
|
||||||
: base_(base),
|
: base_(base),
|
||||||
begin_(std::get<I>(generators).begin()...),
|
begin_(std::get<I>(generators).begin()...),
|
||||||
end_(std::get<I>(generators).end()...),
|
end_(std::get<I>(generators).end()...),
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file defines the GTEST_OS_* macro.
|
// This header file defines the GTEST_OS_* macro.
|
||||||
|
@ -37,70 +37,72 @@
|
||||||
|
|
||||||
// Determines the platform on which Google Test is compiled.
|
// Determines the platform on which Google Test is compiled.
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
# define GTEST_OS_CYGWIN 1
|
#define GTEST_OS_CYGWIN 1
|
||||||
# elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
|
#elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||||
# define GTEST_OS_WINDOWS_MINGW 1
|
#define GTEST_OS_WINDOWS_MINGW 1
|
||||||
# define GTEST_OS_WINDOWS 1
|
#define GTEST_OS_WINDOWS 1
|
||||||
#elif defined _WIN32
|
#elif defined _WIN32
|
||||||
# define GTEST_OS_WINDOWS 1
|
#define GTEST_OS_WINDOWS 1
|
||||||
# ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
# define GTEST_OS_WINDOWS_MOBILE 1
|
#define GTEST_OS_WINDOWS_MOBILE 1
|
||||||
# elif defined(WINAPI_FAMILY)
|
#elif defined(WINAPI_FAMILY)
|
||||||
# include <winapifamily.h>
|
#include <winapifamily.h>
|
||||||
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
#define GTEST_OS_WINDOWS_DESKTOP 1
|
||||||
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
||||||
# define GTEST_OS_WINDOWS_PHONE 1
|
#define GTEST_OS_WINDOWS_PHONE 1
|
||||||
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||||
# define GTEST_OS_WINDOWS_RT 1
|
#define GTEST_OS_WINDOWS_RT 1
|
||||||
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
|
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
|
||||||
# define GTEST_OS_WINDOWS_PHONE 1
|
#define GTEST_OS_WINDOWS_PHONE 1
|
||||||
# define GTEST_OS_WINDOWS_TV_TITLE 1
|
#define GTEST_OS_WINDOWS_TV_TITLE 1
|
||||||
# else
|
#else
|
||||||
// WINAPI_FAMILY defined but no known partition matched.
|
// WINAPI_FAMILY defined but no known partition matched.
|
||||||
// Default to desktop.
|
// Default to desktop.
|
||||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
#define GTEST_OS_WINDOWS_DESKTOP 1
|
||||||
# endif
|
#endif
|
||||||
# else
|
#else
|
||||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
#define GTEST_OS_WINDOWS_DESKTOP 1
|
||||||
# endif // _WIN32_WCE
|
#endif // _WIN32_WCE
|
||||||
#elif defined __OS2__
|
#elif defined __OS2__
|
||||||
# define GTEST_OS_OS2 1
|
#define GTEST_OS_OS2 1
|
||||||
#elif defined __APPLE__
|
#elif defined __APPLE__
|
||||||
# define GTEST_OS_MAC 1
|
#define GTEST_OS_MAC 1
|
||||||
# include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
# if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
# define GTEST_OS_IOS 1
|
#define GTEST_OS_IOS 1
|
||||||
# endif
|
#endif
|
||||||
#elif defined __DragonFly__
|
#elif defined __DragonFly__
|
||||||
# define GTEST_OS_DRAGONFLY 1
|
#define GTEST_OS_DRAGONFLY 1
|
||||||
#elif defined __FreeBSD__
|
#elif defined __FreeBSD__
|
||||||
# define GTEST_OS_FREEBSD 1
|
#define GTEST_OS_FREEBSD 1
|
||||||
#elif defined __Fuchsia__
|
#elif defined __Fuchsia__
|
||||||
# define GTEST_OS_FUCHSIA 1
|
#define GTEST_OS_FUCHSIA 1
|
||||||
|
#elif defined(__GNU__)
|
||||||
|
#define GTEST_OS_GNU_HURD 1
|
||||||
#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__)
|
#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__)
|
||||||
# define GTEST_OS_GNU_KFREEBSD 1
|
#define GTEST_OS_GNU_KFREEBSD 1
|
||||||
#elif defined __linux__
|
#elif defined __linux__
|
||||||
# define GTEST_OS_LINUX 1
|
#define GTEST_OS_LINUX 1
|
||||||
# if defined __ANDROID__
|
#if defined __ANDROID__
|
||||||
# define GTEST_OS_LINUX_ANDROID 1
|
#define GTEST_OS_LINUX_ANDROID 1
|
||||||
# endif
|
#endif
|
||||||
#elif defined __MVS__
|
#elif defined __MVS__
|
||||||
# define GTEST_OS_ZOS 1
|
#define GTEST_OS_ZOS 1
|
||||||
#elif defined(__sun) && defined(__SVR4)
|
#elif defined(__sun) && defined(__SVR4)
|
||||||
# define GTEST_OS_SOLARIS 1
|
#define GTEST_OS_SOLARIS 1
|
||||||
#elif defined(_AIX)
|
#elif defined(_AIX)
|
||||||
# define GTEST_OS_AIX 1
|
#define GTEST_OS_AIX 1
|
||||||
#elif defined(__hpux)
|
#elif defined(__hpux)
|
||||||
# define GTEST_OS_HPUX 1
|
#define GTEST_OS_HPUX 1
|
||||||
#elif defined __native_client__
|
#elif defined __native_client__
|
||||||
# define GTEST_OS_NACL 1
|
#define GTEST_OS_NACL 1
|
||||||
#elif defined __NetBSD__
|
#elif defined __NetBSD__
|
||||||
# define GTEST_OS_NETBSD 1
|
#define GTEST_OS_NETBSD 1
|
||||||
#elif defined __OpenBSD__
|
#elif defined __OpenBSD__
|
||||||
# define GTEST_OS_OPENBSD 1
|
#define GTEST_OS_OPENBSD 1
|
||||||
#elif defined __QNX__
|
#elif defined __QNX__
|
||||||
# define GTEST_OS_QNX 1
|
#define GTEST_OS_QNX 1
|
||||||
#elif defined(__HAIKU__)
|
#elif defined(__HAIKU__)
|
||||||
#define GTEST_OS_HAIKU 1
|
#define GTEST_OS_HAIKU 1
|
||||||
#elif defined ESP8266
|
#elif defined ESP8266
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// The Google C++ Testing and Mocking Framework (Google Test)
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file declares the String class and functions used internally by
|
// This header file declares the String class and functions used internally by
|
||||||
|
@ -36,17 +36,20 @@
|
||||||
// This header file is #included by gtest-internal.h.
|
// This header file is #included by gtest-internal.h.
|
||||||
// It should not be #included by other files.
|
// It should not be #included by other files.
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||||
|
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
// string.h is not guaranteed to provide strcpy on C++ Builder.
|
// string.h is not guaranteed to provide strcpy on C++ Builder.
|
||||||
# include <mem.h>
|
#include <mem.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -123,8 +126,7 @@ class GTEST_API_ String {
|
||||||
// Unlike strcasecmp(), this function can handle NULL argument(s).
|
// Unlike strcasecmp(), this function can handle NULL argument(s).
|
||||||
// A NULL C string is considered different to any non-NULL C string,
|
// A NULL C string is considered different to any non-NULL C string,
|
||||||
// including the empty string.
|
// including the empty string.
|
||||||
static bool CaseInsensitiveCStringEquals(const char* lhs,
|
static bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs);
|
||||||
const char* rhs);
|
|
||||||
|
|
||||||
// Compares two wide C strings, ignoring case. Returns true if and only if
|
// Compares two wide C strings, ignoring case. Returns true if and only if
|
||||||
// they have the same content.
|
// they have the same content.
|
||||||
|
@ -143,8 +145,8 @@ class GTEST_API_ String {
|
||||||
|
|
||||||
// Returns true if and only if the given string ends with the given suffix,
|
// Returns true if and only if the given string ends with the given suffix,
|
||||||
// ignoring case. Any string is considered to end with an empty suffix.
|
// ignoring case. Any string is considered to end with an empty suffix.
|
||||||
static bool EndsWithCaseInsensitive(
|
static bool EndsWithCaseInsensitive(const std::string& str,
|
||||||
const std::string& str, const std::string& suffix);
|
const std::string& suffix);
|
||||||
|
|
||||||
// Formats an int value as "%02d".
|
// Formats an int value as "%02d".
|
||||||
static std::string FormatIntWidth2(int value); // "%02d" for width == 2
|
static std::string FormatIntWidth2(int value); // "%02d" for width == 2
|
||||||
|
|
|
@ -30,7 +30,9 @@
|
||||||
// Type utilities needed for implementing typed and type-parameterized
|
// Type utilities needed for implementing typed and type-parameterized
|
||||||
// tests.
|
// tests.
|
||||||
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
// IWYU pragma: private, include "gtest/gtest.h"
|
||||||
|
// IWYU pragma: friend gtest/.*
|
||||||
|
// IWYU pragma: friend gmock/.*
|
||||||
|
|
||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||||
|
@ -39,11 +41,11 @@
|
||||||
|
|
||||||
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
||||||
// libstdc++ (which is where cxxabi.h comes from).
|
// libstdc++ (which is where cxxabi.h comes from).
|
||||||
# if GTEST_HAS_CXXABI_H_
|
#if GTEST_HAS_CXXABI_H_
|
||||||
# include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
# elif defined(__HP_aCC)
|
#elif defined(__HP_aCC)
|
||||||
# include <acxx_demangle.h>
|
#include <acxx_demangle.h>
|
||||||
# endif // GTEST_HASH_CXXABI_H_
|
#endif // GTEST_HASH_CXXABI_H_
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -101,7 +103,9 @@ std::string GetTypeName() {
|
||||||
// A unique type indicating an empty node
|
// A unique type indicating an empty node
|
||||||
struct None {};
|
struct None {};
|
||||||
|
|
||||||
# define GTEST_TEMPLATE_ template <typename T> class
|
#define GTEST_TEMPLATE_ \
|
||||||
|
template <typename T> \
|
||||||
|
class
|
||||||
|
|
||||||
// The template "selector" struct TemplateSel<Tmpl> is used to
|
// The template "selector" struct TemplateSel<Tmpl> is used to
|
||||||
// represent Tmpl, which must be a class template with one type
|
// represent Tmpl, which must be a class template with one type
|
||||||
|
@ -119,8 +123,7 @@ struct TemplateSel {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# define GTEST_BIND_(TmplSel, T) \
|
#define GTEST_BIND_(TmplSel, T) TmplSel::template Bind<T>::type
|
||||||
TmplSel::template Bind<T>::type
|
|
||||||
|
|
||||||
template <GTEST_TEMPLATE_ Head_, GTEST_TEMPLATE_... Tail_>
|
template <GTEST_TEMPLATE_ Head_, GTEST_TEMPLATE_... Tail_>
|
||||||
struct Templates {
|
struct Templates {
|
||||||
|
|
|
@ -27,8 +27,6 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// This provides interface PrimeTable that determines whether a number is a
|
// This provides interface PrimeTable that determines whether a number is a
|
||||||
// prime and determines a next prime number. This interface is used
|
// prime and determines a next prime number. This interface is used
|
||||||
// in Google Test samples demonstrating use of parameterized tests.
|
// in Google Test samples demonstrating use of parameterized tests.
|
||||||
|
@ -57,7 +55,7 @@ class OnTheFlyPrimeTable : public PrimeTable {
|
||||||
bool IsPrime(int n) const override {
|
bool IsPrime(int n) const override {
|
||||||
if (n <= 1) return false;
|
if (n <= 1) return false;
|
||||||
|
|
||||||
for (int i = 2; i*i <= n; i++) {
|
for (int i = 2; i * i <= n; i++) {
|
||||||
// n is divisible by an integer other than 1 and itself.
|
// n is divisible by an integer other than 1 and itself.
|
||||||
if ((n % i) == 0) return false;
|
if ((n % i) == 0) return false;
|
||||||
}
|
}
|
||||||
|
@ -104,13 +102,13 @@ class PreCalculatedPrimeTable : public PrimeTable {
|
||||||
|
|
||||||
// Checks every candidate for prime number (we know that 2 is the only even
|
// Checks every candidate for prime number (we know that 2 is the only even
|
||||||
// prime).
|
// prime).
|
||||||
for (int i = 2; i*i <= max; i += i%2+1) {
|
for (int i = 2; i * i <= max; i += i % 2 + 1) {
|
||||||
if (!is_prime_[i]) continue;
|
if (!is_prime_[i]) continue;
|
||||||
|
|
||||||
// Marks all multiples of i (except i itself) as non-prime.
|
// Marks all multiples of i (except i itself) as non-prime.
|
||||||
// We are starting here from i-th multiplier, because all smaller
|
// We are starting here from i-th multiplier, because all smaller
|
||||||
// complex numbers were already marked.
|
// complex numbers were already marked.
|
||||||
for (int j = i*i; j <= max; j += i) {
|
for (int j = i * i; j <= max; j += i) {
|
||||||
is_prime_[j] = false;
|
is_prime_[j] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,9 +52,9 @@ bool IsPrime(int n) {
|
||||||
// Now, we have that n is odd and n >= 3.
|
// Now, we have that n is odd and n >= 3.
|
||||||
|
|
||||||
// Try to divide n by every odd number i, starting from 3
|
// Try to divide n by every odd number i, starting from 3
|
||||||
for (int i = 3; ; i += 2) {
|
for (int i = 3;; i += 2) {
|
||||||
// We only have to try i up to the square root of n
|
// We only have to try i up to the square root of n
|
||||||
if (i > n/i) break;
|
if (i > n / i) break;
|
||||||
|
|
||||||
// Now, we have i <= n/i < n.
|
// Now, we have i <= n/i < n.
|
||||||
// If n is divisible by i, n is not prime.
|
// If n is divisible by i, n is not prime.
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// This sample shows how to use Google Test listener API to implement
|
// This sample shows how to use Google Test listener API to implement
|
||||||
// a primitive leak checker.
|
// a primitive leak checker.
|
||||||
|
|
||||||
|
@ -104,14 +103,15 @@ TEST(ListenersTest, LeaksWater) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char** argv) {
|
||||||
InitGoogleTest(&argc, argv);
|
InitGoogleTest(&argc, argv);
|
||||||
|
|
||||||
bool check_for_leaks = false;
|
bool check_for_leaks = false;
|
||||||
if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0 )
|
if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0)
|
||||||
check_for_leaks = true;
|
check_for_leaks = true;
|
||||||
else
|
else
|
||||||
printf("%s\n", "Run this program with --check_for_leaks to enable "
|
printf("%s\n",
|
||||||
|
"Run this program with --check_for_leaks to enable "
|
||||||
"custom leak checking in the tests.");
|
"custom leak checking in the tests.");
|
||||||
|
|
||||||
// If we are given the --check_for_leaks command line flag, installs the
|
// If we are given the --check_for_leaks command line flag, installs the
|
||||||
|
|
|
@ -34,14 +34,15 @@
|
||||||
//
|
//
|
||||||
// Writing a unit test using Google C++ testing framework is easy as 1-2-3:
|
// Writing a unit test using Google C++ testing framework is easy as 1-2-3:
|
||||||
|
|
||||||
|
|
||||||
// Step 1. Include necessary header files such that the stuff your
|
// Step 1. Include necessary header files such that the stuff your
|
||||||
// test logic needs is declared.
|
// test logic needs is declared.
|
||||||
//
|
//
|
||||||
// Don't forget gtest.h, which declares the testing framework.
|
// Don't forget gtest.h, which declares the testing framework.
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include "sample1.h"
|
#include "sample1.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -69,7 +70,6 @@ namespace {
|
||||||
//
|
//
|
||||||
// </TechnicalDetails>
|
// </TechnicalDetails>
|
||||||
|
|
||||||
|
|
||||||
// Tests Factorial().
|
// Tests Factorial().
|
||||||
|
|
||||||
// Tests factorial of negative numbers.
|
// Tests factorial of negative numbers.
|
||||||
|
@ -97,9 +97,7 @@ TEST(FactorialTest, Negative) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests factorial of 0.
|
// Tests factorial of 0.
|
||||||
TEST(FactorialTest, Zero) {
|
TEST(FactorialTest, Zero) { EXPECT_EQ(1, Factorial(0)); }
|
||||||
EXPECT_EQ(1, Factorial(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests factorial of positive numbers.
|
// Tests factorial of positive numbers.
|
||||||
TEST(FactorialTest, Positive) {
|
TEST(FactorialTest, Positive) {
|
||||||
|
@ -109,7 +107,6 @@ TEST(FactorialTest, Positive) {
|
||||||
EXPECT_EQ(40320, Factorial(8));
|
EXPECT_EQ(40320, Factorial(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Tests IsPrime()
|
// Tests IsPrime()
|
||||||
|
|
||||||
// Tests negative input.
|
// Tests negative input.
|
||||||
|
|
|
@ -38,7 +38,7 @@ const char* MyString::CloneCString(const char* a_c_string) {
|
||||||
if (a_c_string == nullptr) return nullptr;
|
if (a_c_string == nullptr) return nullptr;
|
||||||
|
|
||||||
const size_t len = strlen(a_c_string);
|
const size_t len = strlen(a_c_string);
|
||||||
char* const clone = new char[ len + 1 ];
|
char* const clone = new char[len + 1];
|
||||||
memcpy(clone, a_c_string, len + 1);
|
memcpy(clone, a_c_string, len + 1);
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
// A simple string class.
|
// A simple string class.
|
||||||
class MyString {
|
class MyString {
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
// needed.
|
// needed.
|
||||||
|
|
||||||
#include "sample2.h"
|
#include "sample2.h"
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
namespace {
|
namespace {
|
||||||
// In this example, we test the MyString class (a simple string).
|
// In this example, we test the MyString class (a simple string).
|
||||||
|
@ -77,8 +78,7 @@ const char kHelloString[] = "Hello, world!";
|
||||||
TEST(MyString, ConstructorFromCString) {
|
TEST(MyString, ConstructorFromCString) {
|
||||||
const MyString s(kHelloString);
|
const MyString s(kHelloString);
|
||||||
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
|
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
|
||||||
EXPECT_EQ(sizeof(kHelloString)/sizeof(kHelloString[0]) - 1,
|
EXPECT_EQ(sizeof(kHelloString) / sizeof(kHelloString[0]) - 1, s.Length());
|
||||||
s.Length());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests the copy c'tor.
|
// Tests the copy c'tor.
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
// Queue is a simple queue implemented as a singled-linked list.
|
// Queue is a simple queue implemented as a singled-linked list.
|
||||||
//
|
//
|
||||||
// The element type must support copy constructor.
|
// The element type must support copy constructor.
|
||||||
|
@ -62,7 +61,7 @@ class QueueNode {
|
||||||
: element_(an_element), next_(nullptr) {}
|
: element_(an_element), next_(nullptr) {}
|
||||||
|
|
||||||
// We disable the default assignment operator and copy c'tor.
|
// We disable the default assignment operator and copy c'tor.
|
||||||
const QueueNode& operator = (const QueueNode&);
|
const QueueNode& operator=(const QueueNode&);
|
||||||
QueueNode(const QueueNode&);
|
QueueNode(const QueueNode&);
|
||||||
|
|
||||||
E element_;
|
E element_;
|
||||||
|
@ -84,7 +83,7 @@ class Queue {
|
||||||
// 1. Deletes every node.
|
// 1. Deletes every node.
|
||||||
QueueNode<E>* node = head_;
|
QueueNode<E>* node = head_;
|
||||||
QueueNode<E>* next = node->next();
|
QueueNode<E>* next = node->next();
|
||||||
for (; ;) {
|
for (;;) {
|
||||||
delete node;
|
delete node;
|
||||||
node = next;
|
node = next;
|
||||||
if (node == nullptr) break;
|
if (node == nullptr) break;
|
||||||
|
@ -166,7 +165,7 @@ class Queue {
|
||||||
|
|
||||||
// We disallow copying a queue.
|
// We disallow copying a queue.
|
||||||
Queue(const Queue&);
|
Queue(const Queue&);
|
||||||
const Queue& operator = (const Queue&);
|
const Queue& operator=(const Queue&);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GOOGLETEST_SAMPLES_SAMPLE3_INL_H_
|
#endif // GOOGLETEST_SAMPLES_SAMPLE3_INL_H_
|
||||||
|
|
|
@ -67,7 +67,6 @@ namespace {
|
||||||
class QueueTestSmpl3 : public testing::Test {
|
class QueueTestSmpl3 : public testing::Test {
|
||||||
protected: // You should make the members protected s.t. they can be
|
protected: // You should make the members protected s.t. they can be
|
||||||
// accessed from sub-classes.
|
// accessed from sub-classes.
|
||||||
|
|
||||||
// virtual void SetUp() will be called before each test is run. You
|
// virtual void SetUp() will be called before each test is run. You
|
||||||
// should define it if you need to initialize the variables.
|
// should define it if you need to initialize the variables.
|
||||||
// Otherwise, this can be skipped.
|
// Otherwise, this can be skipped.
|
||||||
|
@ -85,15 +84,13 @@ class QueueTestSmpl3 : public testing::Test {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// A helper function that some test uses.
|
// A helper function that some test uses.
|
||||||
static int Double(int n) {
|
static int Double(int n) { return 2 * n; }
|
||||||
return 2*n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A helper function for testing Queue::Map().
|
// A helper function for testing Queue::Map().
|
||||||
void MapTester(const Queue<int> * q) {
|
void MapTester(const Queue<int>* q) {
|
||||||
// Creates a new queue, where each element is twice as big as the
|
// Creates a new queue, where each element is twice as big as the
|
||||||
// corresponding one in q.
|
// corresponding one in q.
|
||||||
const Queue<int> * const new_q = q->Map(Double);
|
const Queue<int>* const new_q = q->Map(Double);
|
||||||
|
|
||||||
// Verifies that the new queue has the same size as q.
|
// Verifies that the new queue has the same size as q.
|
||||||
ASSERT_EQ(q->Size(), new_q->Size());
|
ASSERT_EQ(q->Size(), new_q->Size());
|
||||||
|
@ -124,7 +121,7 @@ TEST_F(QueueTestSmpl3, DefaultConstructor) {
|
||||||
|
|
||||||
// Tests Dequeue().
|
// Tests Dequeue().
|
||||||
TEST_F(QueueTestSmpl3, Dequeue) {
|
TEST_F(QueueTestSmpl3, Dequeue) {
|
||||||
int * n = q0_.Dequeue();
|
int* n = q0_.Dequeue();
|
||||||
EXPECT_TRUE(n == nullptr);
|
EXPECT_TRUE(n == nullptr);
|
||||||
|
|
||||||
n = q1_.Dequeue();
|
n = q1_.Dequeue();
|
||||||
|
|
|
@ -29,14 +29,12 @@
|
||||||
|
|
||||||
// A sample program demonstrating using Google C++ testing framework.
|
// A sample program demonstrating using Google C++ testing framework.
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "sample4.h"
|
#include "sample4.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
// Returns the current counter value, and increments it.
|
// Returns the current counter value, and increments it.
|
||||||
int Counter::Increment() {
|
int Counter::Increment() { return counter_++; }
|
||||||
return counter_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the current counter value, and decrements it.
|
// Returns the current counter value, and decrements it.
|
||||||
// counter can not be less than 0, return 0 in this case
|
// counter can not be less than 0, return 0 in this case
|
||||||
|
@ -49,6 +47,4 @@ int Counter::Decrement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints the current counter value to STDOUT.
|
// Prints the current counter value to STDOUT.
|
||||||
void Counter::Print() const {
|
void Counter::Print() const { printf("%d", counter_); }
|
||||||
printf("%d", counter_);
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
#include "sample4.h"
|
#include "sample4.h"
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// This sample teaches how to reuse a test fixture in multiple test
|
// This sample teaches how to reuse a test fixture in multiple test
|
||||||
// cases by deriving sub-fixtures from it.
|
// cases by deriving sub-fixtures from it.
|
||||||
//
|
//
|
||||||
|
@ -45,9 +44,10 @@
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "sample1.h"
|
#include "sample1.h"
|
||||||
#include "sample3-inl.h"
|
#include "sample3-inl.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
namespace {
|
namespace {
|
||||||
// In this sample, we want to ensure that every test finishes within
|
// In this sample, we want to ensure that every test finishes within
|
||||||
// ~5 seconds. If a test takes longer to run, we consider it a
|
// ~5 seconds. If a test takes longer to run, we consider it a
|
||||||
|
@ -81,7 +81,6 @@ class QuickTest : public testing::Test {
|
||||||
time_t start_time_;
|
time_t start_time_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// We derive a fixture named IntegerFunctionTest from the QuickTest
|
// We derive a fixture named IntegerFunctionTest from the QuickTest
|
||||||
// fixture. All tests using this fixture will be automatically
|
// fixture. All tests using this fixture will be automatically
|
||||||
// required to be quick.
|
// required to be quick.
|
||||||
|
@ -90,7 +89,6 @@ class IntegerFunctionTest : public QuickTest {
|
||||||
// Therefore the body is empty.
|
// Therefore the body is empty.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Now we can write tests in the IntegerFunctionTest test case.
|
// Now we can write tests in the IntegerFunctionTest test case.
|
||||||
|
|
||||||
// Tests Factorial()
|
// Tests Factorial()
|
||||||
|
@ -110,7 +108,6 @@ TEST_F(IntegerFunctionTest, Factorial) {
|
||||||
EXPECT_EQ(40320, Factorial(8));
|
EXPECT_EQ(40320, Factorial(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Tests IsPrime()
|
// Tests IsPrime()
|
||||||
TEST_F(IntegerFunctionTest, IsPrime) {
|
TEST_F(IntegerFunctionTest, IsPrime) {
|
||||||
// Tests negative input.
|
// Tests negative input.
|
||||||
|
@ -131,7 +128,6 @@ TEST_F(IntegerFunctionTest, IsPrime) {
|
||||||
EXPECT_TRUE(IsPrime(23));
|
EXPECT_TRUE(IsPrime(23));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The next test case (named "QueueTest") also needs to be quick, so
|
// The next test case (named "QueueTest") also needs to be quick, so
|
||||||
// we derive another fixture from QuickTest.
|
// we derive another fixture from QuickTest.
|
||||||
//
|
//
|
||||||
|
@ -163,13 +159,10 @@ class QueueTest : public QuickTest {
|
||||||
Queue<int> q2_;
|
Queue<int> q2_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Now, let's write tests using the QueueTest fixture.
|
// Now, let's write tests using the QueueTest fixture.
|
||||||
|
|
||||||
// Tests the default constructor.
|
// Tests the default constructor.
|
||||||
TEST_F(QueueTest, DefaultConstructor) {
|
TEST_F(QueueTest, DefaultConstructor) { EXPECT_EQ(0u, q0_.Size()); }
|
||||||
EXPECT_EQ(0u, q0_.Size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests Dequeue().
|
// Tests Dequeue().
|
||||||
TEST_F(QueueTest, Dequeue) {
|
TEST_F(QueueTest, Dequeue) {
|
||||||
|
|
|
@ -27,13 +27,11 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// This sample shows how to test common properties of multiple
|
// This sample shows how to test common properties of multiple
|
||||||
// implementations of the same interface (aka interface tests).
|
// implementations of the same interface (aka interface tests).
|
||||||
|
|
||||||
// The interface and its implementations are in this header.
|
// The interface and its implementations are in this header.
|
||||||
#include "prime_tables.h"
|
#include "prime_tables.h"
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
namespace {
|
namespace {
|
||||||
// First, we define some factory functions for creating instances of
|
// First, we define some factory functions for creating instances of
|
||||||
|
@ -151,8 +149,7 @@ using testing::Types;
|
||||||
// the PrimeTableTest fixture defined earlier:
|
// the PrimeTableTest fixture defined earlier:
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class PrimeTableTest2 : public PrimeTableTest<T> {
|
class PrimeTableTest2 : public PrimeTableTest<T> {};
|
||||||
};
|
|
||||||
|
|
||||||
// Then, declare the test case. The argument is the name of the test
|
// Then, declare the test case. The argument is the name of the test
|
||||||
// fixture, and also the name of the test case (as usual). The _P
|
// fixture, and also the name of the test case (as usual). The _P
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// This sample shows how to test common properties of multiple
|
// This sample shows how to test common properties of multiple
|
||||||
// implementations of an interface (aka interface tests) using
|
// implementations of an interface (aka interface tests) using
|
||||||
// value-parameterized tests. Each test in the test case has
|
// value-parameterized tests. Each test in the test case has
|
||||||
|
@ -36,7 +35,6 @@
|
||||||
|
|
||||||
// The interface and its implementations are in this header.
|
// The interface and its implementations are in this header.
|
||||||
#include "prime_tables.h"
|
#include "prime_tables.h"
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -50,9 +48,7 @@ using ::testing::Values;
|
||||||
// SetUp() method and delete them in TearDown() method.
|
// SetUp() method and delete them in TearDown() method.
|
||||||
typedef PrimeTable* CreatePrimeTableFunc();
|
typedef PrimeTable* CreatePrimeTableFunc();
|
||||||
|
|
||||||
PrimeTable* CreateOnTheFlyPrimeTable() {
|
PrimeTable* CreateOnTheFlyPrimeTable() { return new OnTheFlyPrimeTable(); }
|
||||||
return new OnTheFlyPrimeTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t max_precalculated>
|
template <size_t max_precalculated>
|
||||||
PrimeTable* CreatePreCalculatedPrimeTable() {
|
PrimeTable* CreatePreCalculatedPrimeTable() {
|
||||||
|
|
|
@ -27,14 +27,12 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// This sample shows how to test code relying on some global flag variables.
|
// This sample shows how to test code relying on some global flag variables.
|
||||||
// Combine() helps with generating all possible combinations of such flags,
|
// Combine() helps with generating all possible combinations of such flags,
|
||||||
// and each test is given one combination as a parameter.
|
// and each test is given one combination as a parameter.
|
||||||
|
|
||||||
// Use class definitions to test from this header.
|
// Use class definitions to test from this header.
|
||||||
#include "prime_tables.h"
|
#include "prime_tables.h"
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -79,10 +77,10 @@ class HybridPrimeTable : public PrimeTable {
|
||||||
int max_precalculated_;
|
int max_precalculated_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ::testing::TestWithParam;
|
|
||||||
using ::testing::Bool;
|
using ::testing::Bool;
|
||||||
using ::testing::Values;
|
|
||||||
using ::testing::Combine;
|
using ::testing::Combine;
|
||||||
|
using ::testing::TestWithParam;
|
||||||
|
using ::testing::Values;
|
||||||
|
|
||||||
// To test all code paths for HybridPrimeTable we must test it with numbers
|
// To test all code paths for HybridPrimeTable we must test it with numbers
|
||||||
// both within and outside PreCalculatedPrimeTable's capacity and also with
|
// both within and outside PreCalculatedPrimeTable's capacity and also with
|
||||||
|
|
|
@ -26,10 +26,9 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// This sample shows how to use Google Test listener API to implement
|
// This sample shows how to use Google Test listener API to implement
|
||||||
// an alternative console output and how to use the UnitTest reflection API
|
// an alternative console output and how to use the UnitTest reflection API
|
||||||
// to enumerate test cases and tests and to inspect their results.
|
// to enumerate test suites and tests and to inspect their results.
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@ -38,10 +37,10 @@
|
||||||
using ::testing::EmptyTestEventListener;
|
using ::testing::EmptyTestEventListener;
|
||||||
using ::testing::InitGoogleTest;
|
using ::testing::InitGoogleTest;
|
||||||
using ::testing::Test;
|
using ::testing::Test;
|
||||||
using ::testing::TestCase;
|
|
||||||
using ::testing::TestEventListeners;
|
using ::testing::TestEventListeners;
|
||||||
using ::testing::TestInfo;
|
using ::testing::TestInfo;
|
||||||
using ::testing::TestPartResult;
|
using ::testing::TestPartResult;
|
||||||
|
using ::testing::TestSuite;
|
||||||
using ::testing::UnitTest;
|
using ::testing::UnitTest;
|
||||||
namespace {
|
namespace {
|
||||||
// Provides alternative output mode which produces minimal amount of
|
// Provides alternative output mode which produces minimal amount of
|
||||||
|
@ -59,29 +58,23 @@ class TersePrinter : public EmptyTestEventListener {
|
||||||
|
|
||||||
// Called before a test starts.
|
// Called before a test starts.
|
||||||
void OnTestStart(const TestInfo& test_info) override {
|
void OnTestStart(const TestInfo& test_info) override {
|
||||||
fprintf(stdout,
|
fprintf(stdout, "*** Test %s.%s starting.\n", test_info.test_suite_name(),
|
||||||
"*** Test %s.%s starting.\n",
|
|
||||||
test_info.test_case_name(),
|
|
||||||
test_info.name());
|
test_info.name());
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called after a failed assertion or a SUCCEED() invocation.
|
// Called after a failed assertion or a SUCCEED() invocation.
|
||||||
void OnTestPartResult(const TestPartResult& test_part_result) override {
|
void OnTestPartResult(const TestPartResult& test_part_result) override {
|
||||||
fprintf(stdout,
|
fprintf(stdout, "%s in %s:%d\n%s\n",
|
||||||
"%s in %s:%d\n%s\n",
|
|
||||||
test_part_result.failed() ? "*** Failure" : "Success",
|
test_part_result.failed() ? "*** Failure" : "Success",
|
||||||
test_part_result.file_name(),
|
test_part_result.file_name(), test_part_result.line_number(),
|
||||||
test_part_result.line_number(),
|
|
||||||
test_part_result.summary());
|
test_part_result.summary());
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called after a test ends.
|
// Called after a test ends.
|
||||||
void OnTestEnd(const TestInfo& test_info) override {
|
void OnTestEnd(const TestInfo& test_info) override {
|
||||||
fprintf(stdout,
|
fprintf(stdout, "*** Test %s.%s ending.\n", test_info.test_suite_name(),
|
||||||
"*** Test %s.%s ending.\n",
|
|
||||||
test_info.test_case_name(),
|
|
||||||
test_info.name());
|
test_info.name());
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
@ -101,14 +94,15 @@ TEST(CustomOutputTest, Fails) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char** argv) {
|
||||||
InitGoogleTest(&argc, argv);
|
InitGoogleTest(&argc, argv);
|
||||||
|
|
||||||
bool terse_output = false;
|
bool terse_output = false;
|
||||||
if (argc > 1 && strcmp(argv[1], "--terse_output") == 0 )
|
if (argc > 1 && strcmp(argv[1], "--terse_output") == 0)
|
||||||
terse_output = true;
|
terse_output = true;
|
||||||
else
|
else
|
||||||
printf("%s\n", "Run this program with --terse_output to change the way "
|
printf("%s\n",
|
||||||
|
"Run this program with --terse_output to change the way "
|
||||||
"it prints its output.");
|
"it prints its output.");
|
||||||
|
|
||||||
UnitTest& unit_test = *UnitTest::GetInstance();
|
UnitTest& unit_test = *UnitTest::GetInstance();
|
||||||
|
@ -149,8 +143,7 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that were meant to fail should not affect the test program outcome.
|
// Test that were meant to fail should not affect the test program outcome.
|
||||||
if (unexpectedly_failed_tests == 0)
|
if (unexpectedly_failed_tests == 0) ret_val = 0;
|
||||||
ret_val = 0;
|
|
||||||
|
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
# Please Note:
|
|
||||||
|
|
||||||
Files in this directory are no longer supported by the maintainers. They
|
|
||||||
represent mosty historical artifacts and supported by the community only. There
|
|
||||||
is no guarantee whatsoever that these scripts still work.
|
|
|
@ -1,83 +0,0 @@
|
||||||
# Copyright 2013 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.
|
|
||||||
|
|
||||||
"""Shared utilities for writing scripts for Google Test/Mock."""
|
|
||||||
|
|
||||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
# Matches the line from 'svn info .' output that describes what SVN
|
|
||||||
# path the current local directory corresponds to. For example, in
|
|
||||||
# a googletest SVN workspace's trunk/test directory, the output will be:
|
|
||||||
#
|
|
||||||
# URL: https://googletest.googlecode.com/svn/trunk/test
|
|
||||||
_SVN_INFO_URL_RE = re.compile(r'^URL: https://(\w+)\.googlecode\.com/svn(.*)')
|
|
||||||
|
|
||||||
|
|
||||||
def GetCommandOutput(command):
|
|
||||||
"""Runs the shell command and returns its stdout as a list of lines."""
|
|
||||||
|
|
||||||
f = os.popen(command, 'r')
|
|
||||||
lines = [line.strip() for line in f.readlines()]
|
|
||||||
f.close()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
def GetSvnInfo():
|
|
||||||
"""Returns the project name and the current SVN workspace's root path."""
|
|
||||||
|
|
||||||
for line in GetCommandOutput('svn info .'):
|
|
||||||
m = _SVN_INFO_URL_RE.match(line)
|
|
||||||
if m:
|
|
||||||
project = m.group(1) # googletest or googlemock
|
|
||||||
rel_path = m.group(2)
|
|
||||||
root = os.path.realpath(rel_path.count('/') * '../')
|
|
||||||
return project, root
|
|
||||||
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
|
|
||||||
def GetSvnTrunk():
|
|
||||||
"""Returns the current SVN workspace's trunk root path."""
|
|
||||||
|
|
||||||
_, root = GetSvnInfo()
|
|
||||||
return root + '/trunk' if root else None
|
|
||||||
|
|
||||||
|
|
||||||
def IsInGTestSvn():
|
|
||||||
project, _ = GetSvnInfo()
|
|
||||||
return project == 'googletest'
|
|
||||||
|
|
||||||
|
|
||||||
def IsInGMockSvn():
|
|
||||||
project, _ = GetSvnInfo()
|
|
||||||
return project == 'googlemock'
|
|
|
@ -1,253 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""fuse_gtest_files.py v0.2.0
|
|
||||||
Fuses Google Test source code into a .h file and a .cc file.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
fuse_gtest_files.py [GTEST_ROOT_DIR] OUTPUT_DIR
|
|
||||||
|
|
||||||
Scans GTEST_ROOT_DIR for Google Test source code, and generates
|
|
||||||
two files: OUTPUT_DIR/gtest/gtest.h and OUTPUT_DIR/gtest/gtest-all.cc.
|
|
||||||
Then you can build your tests by adding OUTPUT_DIR to the include
|
|
||||||
search path and linking with OUTPUT_DIR/gtest/gtest-all.cc. These
|
|
||||||
two files contain everything you need to use Google Test. Hence
|
|
||||||
you can "install" Google Test by copying them to wherever you want.
|
|
||||||
|
|
||||||
GTEST_ROOT_DIR can be omitted and defaults to the parent
|
|
||||||
directory of the directory holding this script.
|
|
||||||
|
|
||||||
EXAMPLES
|
|
||||||
./fuse_gtest_files.py fused_gtest
|
|
||||||
./fuse_gtest_files.py path/to/unpacked/gtest fused_gtest
|
|
||||||
|
|
||||||
This tool is experimental. In particular, it assumes that there is no
|
|
||||||
conditional inclusion of Google Test headers. Please report any
|
|
||||||
problems to googletestframework@googlegroups.com. You can read
|
|
||||||
https://github.com/google/googletest/blob/master/googletest/docs/advanced.md for
|
|
||||||
more information.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
try:
|
|
||||||
from sets import Set as set # For Python 2.3 compatibility
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# We assume that this file is in the scripts/ directory in the Google
|
|
||||||
# Test root directory.
|
|
||||||
DEFAULT_GTEST_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..')
|
|
||||||
|
|
||||||
# Regex for matching '#include "gtest/..."'.
|
|
||||||
INCLUDE_GTEST_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(gtest/.+)"')
|
|
||||||
|
|
||||||
# Regex for matching '#include "src/..."'.
|
|
||||||
INCLUDE_SRC_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(src/.+)"')
|
|
||||||
|
|
||||||
# Where to find the source seed files.
|
|
||||||
GTEST_H_SEED = 'include/gtest/gtest.h'
|
|
||||||
GTEST_SPI_H_SEED = 'include/gtest/gtest-spi.h'
|
|
||||||
GTEST_ALL_CC_SEED = 'src/gtest-all.cc'
|
|
||||||
|
|
||||||
# Where to put the generated files.
|
|
||||||
GTEST_H_OUTPUT = 'gtest/gtest.h'
|
|
||||||
GTEST_ALL_CC_OUTPUT = 'gtest/gtest-all.cc'
|
|
||||||
|
|
||||||
|
|
||||||
def VerifyFileExists(directory, relative_path):
|
|
||||||
"""Verifies that the given file exists; aborts on failure.
|
|
||||||
|
|
||||||
relative_path is the file path relative to the given directory.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not os.path.isfile(os.path.join(directory, relative_path)):
|
|
||||||
print('ERROR: Cannot find %s in directory %s.' % (relative_path,
|
|
||||||
directory))
|
|
||||||
print('Please either specify a valid project root directory '
|
|
||||||
'or omit it on the command line.')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def ValidateGTestRootDir(gtest_root):
|
|
||||||
"""Makes sure gtest_root points to a valid gtest root directory.
|
|
||||||
|
|
||||||
The function aborts the program on failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
VerifyFileExists(gtest_root, GTEST_H_SEED)
|
|
||||||
VerifyFileExists(gtest_root, GTEST_ALL_CC_SEED)
|
|
||||||
|
|
||||||
|
|
||||||
def VerifyOutputFile(output_dir, relative_path):
|
|
||||||
"""Verifies that the given output file path is valid.
|
|
||||||
|
|
||||||
relative_path is relative to the output_dir directory.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Makes sure the output file either doesn't exist or can be overwritten.
|
|
||||||
output_file = os.path.join(output_dir, relative_path)
|
|
||||||
if os.path.exists(output_file):
|
|
||||||
# TODO(wan@google.com): The following user-interaction doesn't
|
|
||||||
# work with automated processes. We should provide a way for the
|
|
||||||
# Makefile to force overwriting the files.
|
|
||||||
print('%s already exists in directory %s - overwrite it? (y/N) ' %
|
|
||||||
(relative_path, output_dir))
|
|
||||||
answer = sys.stdin.readline().strip()
|
|
||||||
if answer not in ['y', 'Y']:
|
|
||||||
print('ABORTED.')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Makes sure the directory holding the output file exists; creates
|
|
||||||
# it and all its ancestors if necessary.
|
|
||||||
parent_directory = os.path.dirname(output_file)
|
|
||||||
if not os.path.isdir(parent_directory):
|
|
||||||
os.makedirs(parent_directory)
|
|
||||||
|
|
||||||
|
|
||||||
def ValidateOutputDir(output_dir):
|
|
||||||
"""Makes sure output_dir points to a valid output directory.
|
|
||||||
|
|
||||||
The function aborts the program on failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
VerifyOutputFile(output_dir, GTEST_H_OUTPUT)
|
|
||||||
VerifyOutputFile(output_dir, GTEST_ALL_CC_OUTPUT)
|
|
||||||
|
|
||||||
|
|
||||||
def FuseGTestH(gtest_root, output_dir):
|
|
||||||
"""Scans folder gtest_root to generate gtest/gtest.h in output_dir."""
|
|
||||||
|
|
||||||
output_file = open(os.path.join(output_dir, GTEST_H_OUTPUT), 'w')
|
|
||||||
processed_files = set() # Holds all gtest headers we've processed.
|
|
||||||
|
|
||||||
def ProcessFile(gtest_header_path):
|
|
||||||
"""Processes the given gtest header file."""
|
|
||||||
|
|
||||||
# We don't process the same header twice.
|
|
||||||
if gtest_header_path in processed_files:
|
|
||||||
return
|
|
||||||
|
|
||||||
processed_files.add(gtest_header_path)
|
|
||||||
|
|
||||||
# Reads each line in the given gtest header.
|
|
||||||
for line in open(os.path.join(gtest_root, gtest_header_path), 'r'):
|
|
||||||
m = INCLUDE_GTEST_FILE_REGEX.match(line)
|
|
||||||
if m:
|
|
||||||
# It's '#include "gtest/..."' - let's process it recursively.
|
|
||||||
ProcessFile('include/' + m.group(1))
|
|
||||||
else:
|
|
||||||
# Otherwise we copy the line unchanged to the output file.
|
|
||||||
output_file.write(line)
|
|
||||||
|
|
||||||
ProcessFile(GTEST_H_SEED)
|
|
||||||
output_file.close()
|
|
||||||
|
|
||||||
|
|
||||||
def FuseGTestAllCcToFile(gtest_root, output_file):
|
|
||||||
"""Scans folder gtest_root to generate gtest/gtest-all.cc in output_file."""
|
|
||||||
|
|
||||||
processed_files = set()
|
|
||||||
|
|
||||||
def ProcessFile(gtest_source_file):
|
|
||||||
"""Processes the given gtest source file."""
|
|
||||||
|
|
||||||
# We don't process the same #included file twice.
|
|
||||||
if gtest_source_file in processed_files:
|
|
||||||
return
|
|
||||||
|
|
||||||
processed_files.add(gtest_source_file)
|
|
||||||
|
|
||||||
# Reads each line in the given gtest source file.
|
|
||||||
for line in open(os.path.join(gtest_root, gtest_source_file), 'r'):
|
|
||||||
m = INCLUDE_GTEST_FILE_REGEX.match(line)
|
|
||||||
if m:
|
|
||||||
if 'include/' + m.group(1) == GTEST_SPI_H_SEED:
|
|
||||||
# It's '#include "gtest/gtest-spi.h"'. This file is not
|
|
||||||
# #included by "gtest/gtest.h", so we need to process it.
|
|
||||||
ProcessFile(GTEST_SPI_H_SEED)
|
|
||||||
else:
|
|
||||||
# It's '#include "gtest/foo.h"' where foo is not gtest-spi.
|
|
||||||
# We treat it as '#include "gtest/gtest.h"', as all other
|
|
||||||
# gtest headers are being fused into gtest.h and cannot be
|
|
||||||
# #included directly.
|
|
||||||
|
|
||||||
# There is no need to #include "gtest/gtest.h" more than once.
|
|
||||||
if not GTEST_H_SEED in processed_files:
|
|
||||||
processed_files.add(GTEST_H_SEED)
|
|
||||||
output_file.write('#include "%s"\n' % (GTEST_H_OUTPUT,))
|
|
||||||
else:
|
|
||||||
m = INCLUDE_SRC_FILE_REGEX.match(line)
|
|
||||||
if m:
|
|
||||||
# It's '#include "src/foo"' - let's process it recursively.
|
|
||||||
ProcessFile(m.group(1))
|
|
||||||
else:
|
|
||||||
output_file.write(line)
|
|
||||||
|
|
||||||
ProcessFile(GTEST_ALL_CC_SEED)
|
|
||||||
|
|
||||||
|
|
||||||
def FuseGTestAllCc(gtest_root, output_dir):
|
|
||||||
"""Scans folder gtest_root to generate gtest/gtest-all.cc in output_dir."""
|
|
||||||
|
|
||||||
output_file = open(os.path.join(output_dir, GTEST_ALL_CC_OUTPUT), 'w')
|
|
||||||
FuseGTestAllCcToFile(gtest_root, output_file)
|
|
||||||
output_file.close()
|
|
||||||
|
|
||||||
|
|
||||||
def FuseGTest(gtest_root, output_dir):
|
|
||||||
"""Fuses gtest.h and gtest-all.cc."""
|
|
||||||
|
|
||||||
ValidateGTestRootDir(gtest_root)
|
|
||||||
ValidateOutputDir(output_dir)
|
|
||||||
|
|
||||||
FuseGTestH(gtest_root, output_dir)
|
|
||||||
FuseGTestAllCc(gtest_root, output_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
argc = len(sys.argv)
|
|
||||||
if argc == 2:
|
|
||||||
# fuse_gtest_files.py OUTPUT_DIR
|
|
||||||
FuseGTest(DEFAULT_GTEST_ROOT_DIR, sys.argv[1])
|
|
||||||
elif argc == 3:
|
|
||||||
# fuse_gtest_files.py GTEST_ROOT_DIR OUTPUT_DIR
|
|
||||||
FuseGTest(sys.argv[1], sys.argv[2])
|
|
||||||
else:
|
|
||||||
print(__doc__)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,733 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""gen_gtest_pred_impl.py v0.1
|
|
||||||
|
|
||||||
Generates the implementation of Google Test predicate assertions and
|
|
||||||
accompanying tests.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
gen_gtest_pred_impl.py MAX_ARITY
|
|
||||||
|
|
||||||
where MAX_ARITY is a positive integer.
|
|
||||||
|
|
||||||
The command generates the implementation of up-to MAX_ARITY-ary
|
|
||||||
predicate assertions, and writes it to file gtest_pred_impl.h in the
|
|
||||||
directory where the script is. It also generates the accompanying
|
|
||||||
unit test in file gtest_pred_impl_unittest.cc.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
# Where this script is.
|
|
||||||
SCRIPT_DIR = os.path.dirname(sys.argv[0])
|
|
||||||
|
|
||||||
# Where to store the generated header.
|
|
||||||
HEADER = os.path.join(SCRIPT_DIR, '../include/gtest/gtest_pred_impl.h')
|
|
||||||
|
|
||||||
# Where to store the generated unit test.
|
|
||||||
UNIT_TEST = os.path.join(SCRIPT_DIR, '../test/gtest_pred_impl_unittest.cc')
|
|
||||||
|
|
||||||
|
|
||||||
def HeaderPreamble(n):
|
|
||||||
"""Returns the preamble for the header file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
n: the maximum arity of the predicate macros to be generated.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# A map that defines the values used in the preamble template.
|
|
||||||
DEFS = {
|
|
||||||
'today' : time.strftime('%m/%d/%Y'),
|
|
||||||
'year' : time.strftime('%Y'),
|
|
||||||
'command' : '%s %s' % (os.path.basename(sys.argv[0]), n),
|
|
||||||
'n' : n
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
"""// 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 %(today)s by command
|
|
||||||
// '%(command)s'. DO NOT EDIT BY HAND!
|
|
||||||
//
|
|
||||||
// Implements a family of generic predicate assertion macros.
|
|
||||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
|
|
||||||
// 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 %(n)s.
|
|
||||||
// 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())
|
|
||||||
""" % DEFS)
|
|
||||||
|
|
||||||
|
|
||||||
def Arity(n):
|
|
||||||
"""Returns the English name of the given arity."""
|
|
||||||
|
|
||||||
if n < 0:
|
|
||||||
return None
|
|
||||||
elif n <= 3:
|
|
||||||
return ['nullary', 'unary', 'binary', 'ternary'][n]
|
|
||||||
else:
|
|
||||||
return '%s-ary' % n
|
|
||||||
|
|
||||||
|
|
||||||
def Title(word):
|
|
||||||
"""Returns the given word in title case. The difference between
|
|
||||||
this and string's title() method is that Title('4-ary') is '4-ary'
|
|
||||||
while '4-ary'.title() is '4-Ary'."""
|
|
||||||
|
|
||||||
return word[0].upper() + word[1:]
|
|
||||||
|
|
||||||
|
|
||||||
def OneTo(n):
|
|
||||||
"""Returns the list [1, 2, 3, ..., n]."""
|
|
||||||
|
|
||||||
return range(1, n + 1)
|
|
||||||
|
|
||||||
|
|
||||||
def Iter(n, format, sep=''):
|
|
||||||
"""Given a positive integer n, a format string that contains 0 or
|
|
||||||
more '%s' format specs, and optionally a separator string, returns
|
|
||||||
the join of n strings, each formatted with the format string on an
|
|
||||||
iterator ranged from 1 to n.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
Iter(3, 'v%s', sep=', ') returns 'v1, v2, v3'.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# How many '%s' specs are in format?
|
|
||||||
spec_count = len(format.split('%s')) - 1
|
|
||||||
return sep.join([format % (spec_count * (i,)) for i in OneTo(n)])
|
|
||||||
|
|
||||||
|
|
||||||
def ImplementationForArity(n):
|
|
||||||
"""Returns the implementation of n-ary predicate assertions."""
|
|
||||||
|
|
||||||
# A map the defines the values used in the implementation template.
|
|
||||||
DEFS = {
|
|
||||||
'n' : str(n),
|
|
||||||
'vs' : Iter(n, 'v%s', sep=', '),
|
|
||||||
'vts' : Iter(n, '#v%s', sep=', '),
|
|
||||||
'arity' : Arity(n),
|
|
||||||
'Arity' : Title(Arity(n))
|
|
||||||
}
|
|
||||||
|
|
||||||
impl = """
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED%(n)s. Don't use
|
|
||||||
// this in your code.
|
|
||||||
template <typename Pred""" % DEFS
|
|
||||||
|
|
||||||
impl += Iter(n, """,
|
|
||||||
typename T%s""")
|
|
||||||
|
|
||||||
impl += """>
|
|
||||||
AssertionResult AssertPred%(n)sHelper(const char* pred_text""" % DEFS
|
|
||||||
|
|
||||||
impl += Iter(n, """,
|
|
||||||
const char* e%s""")
|
|
||||||
|
|
||||||
impl += """,
|
|
||||||
Pred pred"""
|
|
||||||
|
|
||||||
impl += Iter(n, """,
|
|
||||||
const T%s& v%s""")
|
|
||||||
|
|
||||||
impl += """) {
|
|
||||||
if (pred(%(vs)s)) return AssertionSuccess();
|
|
||||||
|
|
||||||
""" % DEFS
|
|
||||||
|
|
||||||
impl += ' return AssertionFailure() << pred_text << "("'
|
|
||||||
|
|
||||||
impl += Iter(n, """
|
|
||||||
<< e%s""", sep=' << ", "')
|
|
||||||
|
|
||||||
impl += ' << ") evaluates to false, where"'
|
|
||||||
|
|
||||||
impl += Iter(
|
|
||||||
n, """
|
|
||||||
<< "\\n" << e%s << " evaluates to " << ::testing::PrintToString(v%s)"""
|
|
||||||
)
|
|
||||||
|
|
||||||
impl += """;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
|
|
||||||
// Don't use this in your code.
|
|
||||||
#define GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, on_failure)\\
|
|
||||||
GTEST_ASSERT_(pred_format(%(vts)s, %(vs)s), \\
|
|
||||||
on_failure)
|
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED%(n)s. Don't use
|
|
||||||
// this in your code.
|
|
||||||
#define GTEST_PRED%(n)s_(pred, %(vs)s, on_failure)\\
|
|
||||||
GTEST_ASSERT_(::testing::AssertPred%(n)sHelper(#pred""" % DEFS
|
|
||||||
|
|
||||||
impl += Iter(n, """, \\
|
|
||||||
#v%s""")
|
|
||||||
|
|
||||||
impl += """, \\
|
|
||||||
pred"""
|
|
||||||
|
|
||||||
impl += Iter(n, """, \\
|
|
||||||
v%s""")
|
|
||||||
|
|
||||||
impl += """), on_failure)
|
|
||||||
|
|
||||||
// %(Arity)s predicate assertion macros.
|
|
||||||
#define EXPECT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\
|
|
||||||
GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_NONFATAL_FAILURE_)
|
|
||||||
#define EXPECT_PRED%(n)s(pred, %(vs)s) \\
|
|
||||||
GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_NONFATAL_FAILURE_)
|
|
||||||
#define ASSERT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\
|
|
||||||
GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_FATAL_FAILURE_)
|
|
||||||
#define ASSERT_PRED%(n)s(pred, %(vs)s) \\
|
|
||||||
GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_FATAL_FAILURE_)
|
|
||||||
|
|
||||||
""" % DEFS
|
|
||||||
|
|
||||||
return impl
|
|
||||||
|
|
||||||
|
|
||||||
def HeaderPostamble():
|
|
||||||
"""Returns the postamble for the header file."""
|
|
||||||
|
|
||||||
return """
|
|
||||||
|
|
||||||
} // namespace testing
|
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def GenerateFile(path, content):
|
|
||||||
"""Given a file path and a content string
|
|
||||||
overwrites it with the given content.
|
|
||||||
"""
|
|
||||||
print 'Updating file %s . . .' % path
|
|
||||||
f = file(path, 'w+')
|
|
||||||
print >>f, content,
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
print 'File %s has been updated.' % path
|
|
||||||
|
|
||||||
|
|
||||||
def GenerateHeader(n):
|
|
||||||
"""Given the maximum arity n, updates the header file that implements
|
|
||||||
the predicate assertions.
|
|
||||||
"""
|
|
||||||
GenerateFile(HEADER,
|
|
||||||
HeaderPreamble(n)
|
|
||||||
+ ''.join([ImplementationForArity(i) for i in OneTo(n)])
|
|
||||||
+ HeaderPostamble())
|
|
||||||
|
|
||||||
|
|
||||||
def UnitTestPreamble():
|
|
||||||
"""Returns the preamble for the unit test file."""
|
|
||||||
|
|
||||||
# A map that defines the values used in the preamble template.
|
|
||||||
DEFS = {
|
|
||||||
'today' : time.strftime('%m/%d/%Y'),
|
|
||||||
'year' : time.strftime('%Y'),
|
|
||||||
'command' : '%s %s' % (os.path.basename(sys.argv[0]), sys.argv[1]),
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
"""// 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 %(today)s by command
|
|
||||||
// '%(command)s'. DO NOT EDIT BY HAND!
|
|
||||||
|
|
||||||
// Regression test for gtest_pred_impl.h
|
|
||||||
//
|
|
||||||
// This file is generated by a script and quite long. If you intend to
|
|
||||||
// learn how Google Test works by reading its unit tests, read
|
|
||||||
// gtest_unittest.cc instead.
|
|
||||||
//
|
|
||||||
// This is intended as a regression test for the Google Test predicate
|
|
||||||
// assertions. We compile it as part of the gtest_unittest target
|
|
||||||
// only to keep the implementation tidy and compact, as it is quite
|
|
||||||
// involved to set up the stage for testing Google Test using Google
|
|
||||||
// Test itself.
|
|
||||||
//
|
|
||||||
// Currently, gtest_unittest takes ~11 seconds to run in the testing
|
|
||||||
// daemon. In the future, if it grows too large and needs much more
|
|
||||||
// time to finish, we should consider separating this file into a
|
|
||||||
// stand-alone regression test.
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "gtest/gtest-spi.h"
|
|
||||||
|
|
||||||
// A user-defined data type.
|
|
||||||
struct Bool {
|
|
||||||
explicit Bool(int val) : value(val != 0) {}
|
|
||||||
|
|
||||||
bool operator>(int n) const { return value > Bool(n).value; }
|
|
||||||
|
|
||||||
Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); }
|
|
||||||
|
|
||||||
bool operator==(const Bool& rhs) const { return value == rhs.value; }
|
|
||||||
|
|
||||||
bool value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Enables Bool to be used in assertions.
|
|
||||||
std::ostream& operator<<(std::ostream& os, const Bool& x) {
|
|
||||||
return os << (x.value ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
""" % DEFS)
|
|
||||||
|
|
||||||
|
|
||||||
def TestsForArity(n):
|
|
||||||
"""Returns the tests for n-ary predicate assertions."""
|
|
||||||
|
|
||||||
# A map that defines the values used in the template for the tests.
|
|
||||||
DEFS = {
|
|
||||||
'n' : n,
|
|
||||||
'es' : Iter(n, 'e%s', sep=', '),
|
|
||||||
'vs' : Iter(n, 'v%s', sep=', '),
|
|
||||||
'vts' : Iter(n, '#v%s', sep=', '),
|
|
||||||
'tvs' : Iter(n, 'T%s v%s', sep=', '),
|
|
||||||
'int_vs' : Iter(n, 'int v%s', sep=', '),
|
|
||||||
'Bool_vs' : Iter(n, 'Bool v%s', sep=', '),
|
|
||||||
'types' : Iter(n, 'typename T%s', sep=', '),
|
|
||||||
'v_sum' : Iter(n, 'v%s', sep=' + '),
|
|
||||||
'arity' : Arity(n),
|
|
||||||
'Arity' : Title(Arity(n)),
|
|
||||||
}
|
|
||||||
|
|
||||||
tests = (
|
|
||||||
"""// Sample functions/functors for testing %(arity)s predicate assertions.
|
|
||||||
|
|
||||||
// A %(arity)s predicate function.
|
|
||||||
template <%(types)s>
|
|
||||||
bool PredFunction%(n)s(%(tvs)s) {
|
|
||||||
return %(v_sum)s > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following two functions are needed because a compiler doesn't have
|
|
||||||
// a context yet to know which template function must be instantiated.
|
|
||||||
bool PredFunction%(n)sInt(%(int_vs)s) {
|
|
||||||
return %(v_sum)s > 0;
|
|
||||||
}
|
|
||||||
bool PredFunction%(n)sBool(%(Bool_vs)s) {
|
|
||||||
return %(v_sum)s > 0;
|
|
||||||
}
|
|
||||||
""" % DEFS)
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
// A %(arity)s predicate functor.
|
|
||||||
struct PredFunctor%(n)s {
|
|
||||||
template <%(types)s>
|
|
||||||
bool operator()(""" % DEFS
|
|
||||||
|
|
||||||
tests += Iter(n, 'const T%s& v%s', sep=""",
|
|
||||||
""")
|
|
||||||
|
|
||||||
tests += """) {
|
|
||||||
return %(v_sum)s > 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
""" % DEFS
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
// A %(arity)s predicate-formatter function.
|
|
||||||
template <%(types)s>
|
|
||||||
testing::AssertionResult PredFormatFunction%(n)s(""" % DEFS
|
|
||||||
|
|
||||||
tests += Iter(n, 'const char* e%s', sep=""",
|
|
||||||
""")
|
|
||||||
|
|
||||||
tests += Iter(n, """,
|
|
||||||
const T%s& v%s""")
|
|
||||||
|
|
||||||
tests += """) {
|
|
||||||
if (PredFunction%(n)s(%(vs)s))
|
|
||||||
return testing::AssertionSuccess();
|
|
||||||
|
|
||||||
return testing::AssertionFailure()
|
|
||||||
<< """ % DEFS
|
|
||||||
|
|
||||||
tests += Iter(n, 'e%s', sep=' << " + " << ')
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
<< " is expected to be positive, but evaluates to "
|
|
||||||
<< %(v_sum)s << ".";
|
|
||||||
}
|
|
||||||
""" % DEFS
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
// A %(arity)s predicate-formatter functor.
|
|
||||||
struct PredFormatFunctor%(n)s {
|
|
||||||
template <%(types)s>
|
|
||||||
testing::AssertionResult operator()(""" % DEFS
|
|
||||||
|
|
||||||
tests += Iter(n, 'const char* e%s', sep=""",
|
|
||||||
""")
|
|
||||||
|
|
||||||
tests += Iter(n, """,
|
|
||||||
const T%s& v%s""")
|
|
||||||
|
|
||||||
tests += """) const {
|
|
||||||
return PredFormatFunction%(n)s(%(es)s, %(vs)s);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
""" % DEFS
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
// Tests for {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
|
|
||||||
|
|
||||||
class Predicate%(n)sTest : public testing::Test {
|
|
||||||
protected:
|
|
||||||
void SetUp() override {
|
|
||||||
expected_to_finish_ = true;
|
|
||||||
finished_ = false;""" % DEFS
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
""" + Iter(n, 'n%s_ = ') + """0;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
void TearDown() override {
|
|
||||||
// Verifies that each of the predicate's arguments was evaluated
|
|
||||||
// exactly once."""
|
|
||||||
|
|
||||||
tests += ''.join(["""
|
|
||||||
EXPECT_EQ(1, n%s_) <<
|
|
||||||
"The predicate assertion didn't evaluate argument %s "
|
|
||||||
"exactly once.";""" % (i, i + 1) for i in OneTo(n)])
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
|
|
||||||
// Verifies that the control flow in the test function is expected.
|
|
||||||
if (expected_to_finish_ && !finished_) {
|
|
||||||
FAIL() << "The predicate assertion unexpactedly aborted the test.";
|
|
||||||
} else if (!expected_to_finish_ && finished_) {
|
|
||||||
FAIL() << "The failed predicate assertion didn't abort the test "
|
|
||||||
"as expected.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// true if and only if the test function is expected to run to finish.
|
|
||||||
static bool expected_to_finish_;
|
|
||||||
|
|
||||||
// true if and only if the test function did run to finish.
|
|
||||||
static bool finished_;
|
|
||||||
""" % DEFS
|
|
||||||
|
|
||||||
tests += Iter(n, """
|
|
||||||
static int n%s_;""")
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
};
|
|
||||||
|
|
||||||
bool Predicate%(n)sTest::expected_to_finish_;
|
|
||||||
bool Predicate%(n)sTest::finished_;
|
|
||||||
""" % DEFS
|
|
||||||
|
|
||||||
tests += Iter(n, """int Predicate%%(n)sTest::n%s_;
|
|
||||||
""") % DEFS
|
|
||||||
|
|
||||||
tests += """
|
|
||||||
typedef Predicate%(n)sTest EXPECT_PRED_FORMAT%(n)sTest;
|
|
||||||
typedef Predicate%(n)sTest ASSERT_PRED_FORMAT%(n)sTest;
|
|
||||||
typedef Predicate%(n)sTest EXPECT_PRED%(n)sTest;
|
|
||||||
typedef Predicate%(n)sTest ASSERT_PRED%(n)sTest;
|
|
||||||
""" % DEFS
|
|
||||||
|
|
||||||
def GenTest(use_format, use_assert, expect_failure,
|
|
||||||
use_functor, use_user_type):
|
|
||||||
"""Returns the test for a predicate assertion macro.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
use_format: true if and only if the assertion is a *_PRED_FORMAT*.
|
|
||||||
use_assert: true if and only if the assertion is a ASSERT_*.
|
|
||||||
expect_failure: true if and only if the assertion is expected to fail.
|
|
||||||
use_functor: true if and only if the first argument of the assertion is
|
|
||||||
a functor (as opposed to a function)
|
|
||||||
use_user_type: true if and only if the predicate functor/function takes
|
|
||||||
argument(s) of a user-defined type.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
GenTest(1, 0, 0, 1, 0) returns a test that tests the behavior
|
|
||||||
of a successful EXPECT_PRED_FORMATn() that takes a functor
|
|
||||||
whose arguments have built-in types."""
|
|
||||||
|
|
||||||
if use_assert:
|
|
||||||
assrt = 'ASSERT' # 'assert' is reserved, so we cannot use
|
|
||||||
# that identifier here.
|
|
||||||
else:
|
|
||||||
assrt = 'EXPECT'
|
|
||||||
|
|
||||||
assertion = assrt + '_PRED'
|
|
||||||
|
|
||||||
if use_format:
|
|
||||||
pred_format = 'PredFormat'
|
|
||||||
assertion += '_FORMAT'
|
|
||||||
else:
|
|
||||||
pred_format = 'Pred'
|
|
||||||
|
|
||||||
assertion += '%(n)s' % DEFS
|
|
||||||
|
|
||||||
if use_functor:
|
|
||||||
pred_format_type = 'functor'
|
|
||||||
pred_format += 'Functor%(n)s()'
|
|
||||||
else:
|
|
||||||
pred_format_type = 'function'
|
|
||||||
pred_format += 'Function%(n)s'
|
|
||||||
if not use_format:
|
|
||||||
if use_user_type:
|
|
||||||
pred_format += 'Bool'
|
|
||||||
else:
|
|
||||||
pred_format += 'Int'
|
|
||||||
|
|
||||||
test_name = pred_format_type.title()
|
|
||||||
|
|
||||||
if use_user_type:
|
|
||||||
arg_type = 'user-defined type (Bool)'
|
|
||||||
test_name += 'OnUserType'
|
|
||||||
if expect_failure:
|
|
||||||
arg = 'Bool(n%s_++)'
|
|
||||||
else:
|
|
||||||
arg = 'Bool(++n%s_)'
|
|
||||||
else:
|
|
||||||
arg_type = 'built-in type (int)'
|
|
||||||
test_name += 'OnBuiltInType'
|
|
||||||
if expect_failure:
|
|
||||||
arg = 'n%s_++'
|
|
||||||
else:
|
|
||||||
arg = '++n%s_'
|
|
||||||
|
|
||||||
if expect_failure:
|
|
||||||
successful_or_failed = 'failed'
|
|
||||||
expected_or_not = 'expected.'
|
|
||||||
test_name += 'Failure'
|
|
||||||
else:
|
|
||||||
successful_or_failed = 'successful'
|
|
||||||
expected_or_not = 'UNEXPECTED!'
|
|
||||||
test_name += 'Success'
|
|
||||||
|
|
||||||
# A map that defines the values used in the test template.
|
|
||||||
defs = DEFS.copy()
|
|
||||||
defs.update({
|
|
||||||
'assert' : assrt,
|
|
||||||
'assertion' : assertion,
|
|
||||||
'test_name' : test_name,
|
|
||||||
'pf_type' : pred_format_type,
|
|
||||||
'pf' : pred_format,
|
|
||||||
'arg_type' : arg_type,
|
|
||||||
'arg' : arg,
|
|
||||||
'successful' : successful_or_failed,
|
|
||||||
'expected' : expected_or_not,
|
|
||||||
})
|
|
||||||
|
|
||||||
test = """
|
|
||||||
// Tests a %(successful)s %(assertion)s where the
|
|
||||||
// predicate-formatter is a %(pf_type)s on a %(arg_type)s.
|
|
||||||
TEST_F(%(assertion)sTest, %(test_name)s) {""" % defs
|
|
||||||
|
|
||||||
indent = (len(assertion) + 3)*' '
|
|
||||||
extra_indent = ''
|
|
||||||
|
|
||||||
if expect_failure:
|
|
||||||
extra_indent = ' '
|
|
||||||
if use_assert:
|
|
||||||
test += """
|
|
||||||
expected_to_finish_ = false;
|
|
||||||
EXPECT_FATAL_FAILURE({ // NOLINT"""
|
|
||||||
else:
|
|
||||||
test += """
|
|
||||||
EXPECT_NONFATAL_FAILURE({ // NOLINT"""
|
|
||||||
|
|
||||||
test += '\n' + extra_indent + """ %(assertion)s(%(pf)s""" % defs
|
|
||||||
|
|
||||||
test = test % defs
|
|
||||||
test += Iter(n, ',\n' + indent + extra_indent + '%(arg)s' % defs)
|
|
||||||
test += ');\n' + extra_indent + ' finished_ = true;\n'
|
|
||||||
|
|
||||||
if expect_failure:
|
|
||||||
test += ' }, "");\n'
|
|
||||||
|
|
||||||
test += '}\n'
|
|
||||||
return test
|
|
||||||
|
|
||||||
# Generates tests for all 2**6 = 64 combinations.
|
|
||||||
tests += ''.join([GenTest(use_format, use_assert, expect_failure,
|
|
||||||
use_functor, use_user_type)
|
|
||||||
for use_format in [0, 1]
|
|
||||||
for use_assert in [0, 1]
|
|
||||||
for expect_failure in [0, 1]
|
|
||||||
for use_functor in [0, 1]
|
|
||||||
for use_user_type in [0, 1]
|
|
||||||
])
|
|
||||||
|
|
||||||
return tests
|
|
||||||
|
|
||||||
|
|
||||||
def UnitTestPostamble():
|
|
||||||
"""Returns the postamble for the tests."""
|
|
||||||
|
|
||||||
return ''
|
|
||||||
|
|
||||||
|
|
||||||
def GenerateUnitTest(n):
|
|
||||||
"""Returns the tests for up-to n-ary predicate assertions."""
|
|
||||||
|
|
||||||
GenerateFile(UNIT_TEST,
|
|
||||||
UnitTestPreamble()
|
|
||||||
+ ''.join([TestsForArity(i) for i in OneTo(n)])
|
|
||||||
+ UnitTestPostamble())
|
|
||||||
|
|
||||||
|
|
||||||
def _Main():
|
|
||||||
"""The entry point of the script. Generates the header file and its
|
|
||||||
unit test."""
|
|
||||||
|
|
||||||
if len(sys.argv) != 2:
|
|
||||||
print __doc__
|
|
||||||
print 'Author: ' + __author__
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
n = int(sys.argv[1])
|
|
||||||
GenerateHeader(n)
|
|
||||||
GenerateUnitTest(n)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
_Main()
|
|
|
@ -1,274 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# These variables are automatically filled in by the configure script.
|
|
||||||
name="@PACKAGE_TARNAME@"
|
|
||||||
version="@PACKAGE_VERSION@"
|
|
||||||
|
|
||||||
show_usage()
|
|
||||||
{
|
|
||||||
echo "Usage: gtest-config [OPTIONS...]"
|
|
||||||
}
|
|
||||||
|
|
||||||
show_help()
|
|
||||||
{
|
|
||||||
show_usage
|
|
||||||
cat <<\EOF
|
|
||||||
|
|
||||||
The `gtest-config' script provides access to the necessary compile and linking
|
|
||||||
flags to connect with Google C++ Testing Framework, both in a build prior to
|
|
||||||
installation, and on the system proper after installation. The installation
|
|
||||||
overrides may be issued in combination with any other queries, but will only
|
|
||||||
affect installation queries if called on a built but not installed gtest. The
|
|
||||||
installation queries may not be issued with any other types of queries, and
|
|
||||||
only one installation query may be made at a time. The version queries and
|
|
||||||
compiler flag queries may be combined as desired but not mixed. Different
|
|
||||||
version queries are always combined with logical "and" semantics, and only the
|
|
||||||
last of any particular query is used while all previous ones ignored. All
|
|
||||||
versions must be specified as a sequence of numbers separated by periods.
|
|
||||||
Compiler flag queries output the union of the sets of flags when combined.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
gtest-config --min-version=1.0 || echo "Insufficient Google Test version."
|
|
||||||
|
|
||||||
g++ $(gtest-config --cppflags --cxxflags) -o foo.o -c foo.cpp
|
|
||||||
g++ $(gtest-config --ldflags --libs) -o foo foo.o
|
|
||||||
|
|
||||||
# When using a built but not installed Google Test:
|
|
||||||
g++ $(../../my_gtest_build/scripts/gtest-config ...) ...
|
|
||||||
|
|
||||||
# When using an installed Google Test, but with installation overrides:
|
|
||||||
export GTEST_PREFIX="/opt"
|
|
||||||
g++ $(gtest-config --libdir="/opt/lib64" ...) ...
|
|
||||||
|
|
||||||
Help:
|
|
||||||
--usage brief usage information
|
|
||||||
--help display this help message
|
|
||||||
|
|
||||||
Installation Overrides:
|
|
||||||
--prefix=<dir> overrides the installation prefix
|
|
||||||
--exec-prefix=<dir> overrides the executable installation prefix
|
|
||||||
--libdir=<dir> overrides the library installation prefix
|
|
||||||
--includedir=<dir> overrides the header file installation prefix
|
|
||||||
|
|
||||||
Installation Queries:
|
|
||||||
--prefix installation prefix
|
|
||||||
--exec-prefix executable installation prefix
|
|
||||||
--libdir library installation directory
|
|
||||||
--includedir header file installation directory
|
|
||||||
--version the version of the Google Test installation
|
|
||||||
|
|
||||||
Version Queries:
|
|
||||||
--min-version=VERSION return 0 if the version is at least VERSION
|
|
||||||
--exact-version=VERSION return 0 if the version is exactly VERSION
|
|
||||||
--max-version=VERSION return 0 if the version is at most VERSION
|
|
||||||
|
|
||||||
Compilation Flag Queries:
|
|
||||||
--cppflags compile flags specific to the C-like preprocessors
|
|
||||||
--cxxflags compile flags appropriate for C++ programs
|
|
||||||
--ldflags linker flags
|
|
||||||
--libs libraries for linking
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function bounds our version with a min and a max. It uses some clever
|
|
||||||
# POSIX-compliant variable expansion to portably do all the work in the shell
|
|
||||||
# and avoid any dependency on a particular "sed" or "awk" implementation.
|
|
||||||
# Notable is that it will only ever compare the first 3 components of versions.
|
|
||||||
# Further components will be cleanly stripped off. All versions must be
|
|
||||||
# unadorned, so "v1.0" will *not* work. The minimum version must be in $1, and
|
|
||||||
# the max in $2. TODO(chandlerc@google.com): If this ever breaks, we should
|
|
||||||
# investigate expanding this via autom4te from AS_VERSION_COMPARE rather than
|
|
||||||
# continuing to maintain our own shell version.
|
|
||||||
check_versions()
|
|
||||||
{
|
|
||||||
major_version=${version%%.*}
|
|
||||||
minor_version="0"
|
|
||||||
point_version="0"
|
|
||||||
if test "${version#*.}" != "${version}"; then
|
|
||||||
minor_version=${version#*.}
|
|
||||||
minor_version=${minor_version%%.*}
|
|
||||||
fi
|
|
||||||
if test "${version#*.*.}" != "${version}"; then
|
|
||||||
point_version=${version#*.*.}
|
|
||||||
point_version=${point_version%%.*}
|
|
||||||
fi
|
|
||||||
|
|
||||||
min_version="$1"
|
|
||||||
min_major_version=${min_version%%.*}
|
|
||||||
min_minor_version="0"
|
|
||||||
min_point_version="0"
|
|
||||||
if test "${min_version#*.}" != "${min_version}"; then
|
|
||||||
min_minor_version=${min_version#*.}
|
|
||||||
min_minor_version=${min_minor_version%%.*}
|
|
||||||
fi
|
|
||||||
if test "${min_version#*.*.}" != "${min_version}"; then
|
|
||||||
min_point_version=${min_version#*.*.}
|
|
||||||
min_point_version=${min_point_version%%.*}
|
|
||||||
fi
|
|
||||||
|
|
||||||
max_version="$2"
|
|
||||||
max_major_version=${max_version%%.*}
|
|
||||||
max_minor_version="0"
|
|
||||||
max_point_version="0"
|
|
||||||
if test "${max_version#*.}" != "${max_version}"; then
|
|
||||||
max_minor_version=${max_version#*.}
|
|
||||||
max_minor_version=${max_minor_version%%.*}
|
|
||||||
fi
|
|
||||||
if test "${max_version#*.*.}" != "${max_version}"; then
|
|
||||||
max_point_version=${max_version#*.*.}
|
|
||||||
max_point_version=${max_point_version%%.*}
|
|
||||||
fi
|
|
||||||
|
|
||||||
test $(($major_version)) -lt $(($min_major_version)) && exit 1
|
|
||||||
if test $(($major_version)) -eq $(($min_major_version)); then
|
|
||||||
test $(($minor_version)) -lt $(($min_minor_version)) && exit 1
|
|
||||||
if test $(($minor_version)) -eq $(($min_minor_version)); then
|
|
||||||
test $(($point_version)) -lt $(($min_point_version)) && exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
test $(($major_version)) -gt $(($max_major_version)) && exit 1
|
|
||||||
if test $(($major_version)) -eq $(($max_major_version)); then
|
|
||||||
test $(($minor_version)) -gt $(($max_minor_version)) && exit 1
|
|
||||||
if test $(($minor_version)) -eq $(($max_minor_version)); then
|
|
||||||
test $(($point_version)) -gt $(($max_point_version)) && exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# Show the usage line when no arguments are specified.
|
|
||||||
if test $# -eq 0; then
|
|
||||||
show_usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
while test $# -gt 0; do
|
|
||||||
case $1 in
|
|
||||||
--usage) show_usage; exit 0;;
|
|
||||||
--help) show_help; exit 0;;
|
|
||||||
|
|
||||||
# Installation overrides
|
|
||||||
--prefix=*) GTEST_PREFIX=${1#--prefix=};;
|
|
||||||
--exec-prefix=*) GTEST_EXEC_PREFIX=${1#--exec-prefix=};;
|
|
||||||
--libdir=*) GTEST_LIBDIR=${1#--libdir=};;
|
|
||||||
--includedir=*) GTEST_INCLUDEDIR=${1#--includedir=};;
|
|
||||||
|
|
||||||
# Installation queries
|
|
||||||
--prefix|--exec-prefix|--libdir|--includedir|--version)
|
|
||||||
if test -n "${do_query}"; then
|
|
||||||
show_usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
do_query=${1#--}
|
|
||||||
;;
|
|
||||||
|
|
||||||
# Version checking
|
|
||||||
--min-version=*)
|
|
||||||
do_check_versions=yes
|
|
||||||
min_version=${1#--min-version=}
|
|
||||||
;;
|
|
||||||
--max-version=*)
|
|
||||||
do_check_versions=yes
|
|
||||||
max_version=${1#--max-version=}
|
|
||||||
;;
|
|
||||||
--exact-version=*)
|
|
||||||
do_check_versions=yes
|
|
||||||
exact_version=${1#--exact-version=}
|
|
||||||
;;
|
|
||||||
|
|
||||||
# Compiler flag output
|
|
||||||
--cppflags) echo_cppflags=yes;;
|
|
||||||
--cxxflags) echo_cxxflags=yes;;
|
|
||||||
--ldflags) echo_ldflags=yes;;
|
|
||||||
--libs) echo_libs=yes;;
|
|
||||||
|
|
||||||
# Everything else is an error
|
|
||||||
*) show_usage; exit 1;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
# These have defaults filled in by the configure script but can also be
|
|
||||||
# overridden by environment variables or command line parameters.
|
|
||||||
prefix="${GTEST_PREFIX:-@prefix@}"
|
|
||||||
exec_prefix="${GTEST_EXEC_PREFIX:-@exec_prefix@}"
|
|
||||||
libdir="${GTEST_LIBDIR:-@libdir@}"
|
|
||||||
includedir="${GTEST_INCLUDEDIR:-@includedir@}"
|
|
||||||
|
|
||||||
# We try and detect if our binary is not located at its installed location. If
|
|
||||||
# it's not, we provide variables pointing to the source and build tree rather
|
|
||||||
# than to the install tree. This allows building against a just-built gtest
|
|
||||||
# rather than an installed gtest.
|
|
||||||
bindir="@bindir@"
|
|
||||||
this_relative_bindir=`dirname $0`
|
|
||||||
this_bindir=`cd ${this_relative_bindir}; pwd -P`
|
|
||||||
if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
|
|
||||||
# The path to the script doesn't end in the bindir sequence from Autoconf,
|
|
||||||
# assume that we are in a build tree.
|
|
||||||
build_dir=`dirname ${this_bindir}`
|
|
||||||
src_dir=`cd ${this_bindir}; cd @top_srcdir@; pwd -P`
|
|
||||||
|
|
||||||
# TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
|
|
||||||
# should work to remove it, and/or remove libtool altogether, replacing it
|
|
||||||
# with direct references to the library and a link path.
|
|
||||||
gtest_libs="${build_dir}/lib/libgtest.la @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
|
|
||||||
gtest_ldflags=""
|
|
||||||
|
|
||||||
# We provide hooks to include from either the source or build dir, where the
|
|
||||||
# build dir is always preferred. This will potentially allow us to write
|
|
||||||
# build rules for generated headers and have them automatically be preferred
|
|
||||||
# over provided versions.
|
|
||||||
gtest_cppflags="-I${build_dir}/include -I${src_dir}/include"
|
|
||||||
gtest_cxxflags="@PTHREAD_CFLAGS@"
|
|
||||||
else
|
|
||||||
# We're using an installed gtest, although it may be staged under some
|
|
||||||
# prefix. Assume (as our own libraries do) that we can resolve the prefix,
|
|
||||||
# and are present in the dynamic link paths.
|
|
||||||
gtest_ldflags="-L${libdir}"
|
|
||||||
gtest_libs="-l${name} @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
|
|
||||||
gtest_cppflags="-I${includedir}"
|
|
||||||
gtest_cxxflags="@PTHREAD_CFLAGS@"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Do an installation query if requested.
|
|
||||||
if test -n "$do_query"; then
|
|
||||||
case $do_query in
|
|
||||||
prefix) echo $prefix; exit 0;;
|
|
||||||
exec-prefix) echo $exec_prefix; exit 0;;
|
|
||||||
libdir) echo $libdir; exit 0;;
|
|
||||||
includedir) echo $includedir; exit 0;;
|
|
||||||
version) echo $version; exit 0;;
|
|
||||||
*) show_usage; exit 1;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Do a version check if requested.
|
|
||||||
if test "$do_check_versions" = "yes"; then
|
|
||||||
# Make sure we didn't receive a bad combination of parameters.
|
|
||||||
test "$echo_cppflags" = "yes" && show_usage && exit 1
|
|
||||||
test "$echo_cxxflags" = "yes" && show_usage && exit 1
|
|
||||||
test "$echo_ldflags" = "yes" && show_usage && exit 1
|
|
||||||
test "$echo_libs" = "yes" && show_usage && exit 1
|
|
||||||
|
|
||||||
if test "$exact_version" != ""; then
|
|
||||||
check_versions $exact_version $exact_version
|
|
||||||
# unreachable
|
|
||||||
else
|
|
||||||
check_versions ${min_version:-0.0.0} ${max_version:-9999.9999.9999}
|
|
||||||
# unreachable
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Do the output in the correct order so that these can be used in-line of
|
|
||||||
# a compiler invocation.
|
|
||||||
output=""
|
|
||||||
test "$echo_cppflags" = "yes" && output="$output $gtest_cppflags"
|
|
||||||
test "$echo_cxxflags" = "yes" && output="$output $gtest_cxxflags"
|
|
||||||
test "$echo_ldflags" = "yes" && output="$output $gtest_ldflags"
|
|
||||||
test "$echo_libs" = "yes" && output="$output $gtest_libs"
|
|
||||||
echo $output
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -1,855 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# Copyright 2008, Google Inc.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions are
|
|
||||||
# met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above
|
|
||||||
# copyright notice, this list of conditions and the following disclaimer
|
|
||||||
# in the documentation and/or other materials provided with the
|
|
||||||
# distribution.
|
|
||||||
# * Neither the name of Google Inc. nor the names of its
|
|
||||||
# contributors may be used to endorse or promote products derived from
|
|
||||||
# this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
"""pump v0.2.0 - Pretty Useful for Meta Programming.
|
|
||||||
|
|
||||||
A tool for preprocessor meta programming. Useful for generating
|
|
||||||
repetitive boilerplate code. Especially useful for writing C++
|
|
||||||
classes, functions, macros, and templates that need to work with
|
|
||||||
various number of arguments.
|
|
||||||
|
|
||||||
USAGE:
|
|
||||||
pump.py SOURCE_FILE
|
|
||||||
|
|
||||||
EXAMPLES:
|
|
||||||
pump.py foo.cc.pump
|
|
||||||
Converts foo.cc.pump to foo.cc.
|
|
||||||
|
|
||||||
GRAMMAR:
|
|
||||||
CODE ::= ATOMIC_CODE*
|
|
||||||
ATOMIC_CODE ::= $var ID = EXPRESSION
|
|
||||||
| $var ID = [[ CODE ]]
|
|
||||||
| $range ID EXPRESSION..EXPRESSION
|
|
||||||
| $for ID SEPARATOR [[ CODE ]]
|
|
||||||
| $($)
|
|
||||||
| $ID
|
|
||||||
| $(EXPRESSION)
|
|
||||||
| $if EXPRESSION [[ CODE ]] ELSE_BRANCH
|
|
||||||
| [[ CODE ]]
|
|
||||||
| RAW_CODE
|
|
||||||
SEPARATOR ::= RAW_CODE | EMPTY
|
|
||||||
ELSE_BRANCH ::= $else [[ CODE ]]
|
|
||||||
| $elif EXPRESSION [[ CODE ]] ELSE_BRANCH
|
|
||||||
| EMPTY
|
|
||||||
EXPRESSION has Python syntax.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
TOKEN_TABLE = [
|
|
||||||
(re.compile(r'\$var\s+'), '$var'),
|
|
||||||
(re.compile(r'\$elif\s+'), '$elif'),
|
|
||||||
(re.compile(r'\$else\s+'), '$else'),
|
|
||||||
(re.compile(r'\$for\s+'), '$for'),
|
|
||||||
(re.compile(r'\$if\s+'), '$if'),
|
|
||||||
(re.compile(r'\$range\s+'), '$range'),
|
|
||||||
(re.compile(r'\$[_A-Za-z]\w*'), '$id'),
|
|
||||||
(re.compile(r'\$\(\$\)'), '$($)'),
|
|
||||||
(re.compile(r'\$'), '$'),
|
|
||||||
(re.compile(r'\[\[\n?'), '[['),
|
|
||||||
(re.compile(r'\]\]\n?'), ']]'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class Cursor:
|
|
||||||
"""Represents a position (line and column) in a text file."""
|
|
||||||
|
|
||||||
def __init__(self, line=-1, column=-1):
|
|
||||||
self.line = line
|
|
||||||
self.column = column
|
|
||||||
|
|
||||||
def __eq__(self, rhs):
|
|
||||||
return self.line == rhs.line and self.column == rhs.column
|
|
||||||
|
|
||||||
def __ne__(self, rhs):
|
|
||||||
return not self == rhs
|
|
||||||
|
|
||||||
def __lt__(self, rhs):
|
|
||||||
return self.line < rhs.line or (
|
|
||||||
self.line == rhs.line and self.column < rhs.column)
|
|
||||||
|
|
||||||
def __le__(self, rhs):
|
|
||||||
return self < rhs or self == rhs
|
|
||||||
|
|
||||||
def __gt__(self, rhs):
|
|
||||||
return rhs < self
|
|
||||||
|
|
||||||
def __ge__(self, rhs):
|
|
||||||
return rhs <= self
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self == Eof():
|
|
||||||
return 'EOF'
|
|
||||||
else:
|
|
||||||
return '%s(%s)' % (self.line + 1, self.column)
|
|
||||||
|
|
||||||
def __add__(self, offset):
|
|
||||||
return Cursor(self.line, self.column + offset)
|
|
||||||
|
|
||||||
def __sub__(self, offset):
|
|
||||||
return Cursor(self.line, self.column - offset)
|
|
||||||
|
|
||||||
def Clone(self):
|
|
||||||
"""Returns a copy of self."""
|
|
||||||
|
|
||||||
return Cursor(self.line, self.column)
|
|
||||||
|
|
||||||
|
|
||||||
# Special cursor to indicate the end-of-file.
|
|
||||||
def Eof():
|
|
||||||
"""Returns the special cursor to denote the end-of-file."""
|
|
||||||
return Cursor(-1, -1)
|
|
||||||
|
|
||||||
|
|
||||||
class Token:
|
|
||||||
"""Represents a token in a Pump source file."""
|
|
||||||
|
|
||||||
def __init__(self, start=None, end=None, value=None, token_type=None):
|
|
||||||
if start is None:
|
|
||||||
self.start = Eof()
|
|
||||||
else:
|
|
||||||
self.start = start
|
|
||||||
if end is None:
|
|
||||||
self.end = Eof()
|
|
||||||
else:
|
|
||||||
self.end = end
|
|
||||||
self.value = value
|
|
||||||
self.token_type = token_type
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return 'Token @%s: \'%s\' type=%s' % (
|
|
||||||
self.start, self.value, self.token_type)
|
|
||||||
|
|
||||||
def Clone(self):
|
|
||||||
"""Returns a copy of self."""
|
|
||||||
|
|
||||||
return Token(self.start.Clone(), self.end.Clone(), self.value,
|
|
||||||
self.token_type)
|
|
||||||
|
|
||||||
|
|
||||||
def StartsWith(lines, pos, string):
|
|
||||||
"""Returns True iff the given position in lines starts with 'string'."""
|
|
||||||
|
|
||||||
return lines[pos.line][pos.column:].startswith(string)
|
|
||||||
|
|
||||||
|
|
||||||
def FindFirstInLine(line, token_table):
|
|
||||||
best_match_start = -1
|
|
||||||
for (regex, token_type) in token_table:
|
|
||||||
m = regex.search(line)
|
|
||||||
if m:
|
|
||||||
# We found regex in lines
|
|
||||||
if best_match_start < 0 or m.start() < best_match_start:
|
|
||||||
best_match_start = m.start()
|
|
||||||
best_match_length = m.end() - m.start()
|
|
||||||
best_match_token_type = token_type
|
|
||||||
|
|
||||||
if best_match_start < 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return (best_match_start, best_match_length, best_match_token_type)
|
|
||||||
|
|
||||||
|
|
||||||
def FindFirst(lines, token_table, cursor):
|
|
||||||
"""Finds the first occurrence of any string in strings in lines."""
|
|
||||||
|
|
||||||
start = cursor.Clone()
|
|
||||||
cur_line_number = cursor.line
|
|
||||||
for line in lines[start.line:]:
|
|
||||||
if cur_line_number == start.line:
|
|
||||||
line = line[start.column:]
|
|
||||||
m = FindFirstInLine(line, token_table)
|
|
||||||
if m:
|
|
||||||
# We found a regex in line.
|
|
||||||
(start_column, length, token_type) = m
|
|
||||||
if cur_line_number == start.line:
|
|
||||||
start_column += start.column
|
|
||||||
found_start = Cursor(cur_line_number, start_column)
|
|
||||||
found_end = found_start + length
|
|
||||||
return MakeToken(lines, found_start, found_end, token_type)
|
|
||||||
cur_line_number += 1
|
|
||||||
# We failed to find str in lines
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def SubString(lines, start, end):
|
|
||||||
"""Returns a substring in lines."""
|
|
||||||
|
|
||||||
if end == Eof():
|
|
||||||
end = Cursor(len(lines) - 1, len(lines[-1]))
|
|
||||||
|
|
||||||
if start >= end:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
if start.line == end.line:
|
|
||||||
return lines[start.line][start.column:end.column]
|
|
||||||
|
|
||||||
result_lines = ([lines[start.line][start.column:]] +
|
|
||||||
lines[start.line + 1:end.line] +
|
|
||||||
[lines[end.line][:end.column]])
|
|
||||||
return ''.join(result_lines)
|
|
||||||
|
|
||||||
|
|
||||||
def StripMetaComments(str):
|
|
||||||
"""Strip meta comments from each line in the given string."""
|
|
||||||
|
|
||||||
# First, completely remove lines containing nothing but a meta
|
|
||||||
# comment, including the trailing \n.
|
|
||||||
str = re.sub(r'^\s*\$\$.*\n', '', str)
|
|
||||||
|
|
||||||
# Then, remove meta comments from contentful lines.
|
|
||||||
return re.sub(r'\s*\$\$.*', '', str)
|
|
||||||
|
|
||||||
|
|
||||||
def MakeToken(lines, start, end, token_type):
|
|
||||||
"""Creates a new instance of Token."""
|
|
||||||
|
|
||||||
return Token(start, end, SubString(lines, start, end), token_type)
|
|
||||||
|
|
||||||
|
|
||||||
def ParseToken(lines, pos, regex, token_type):
|
|
||||||
line = lines[pos.line][pos.column:]
|
|
||||||
m = regex.search(line)
|
|
||||||
if m and not m.start():
|
|
||||||
return MakeToken(lines, pos, pos + m.end(), token_type)
|
|
||||||
else:
|
|
||||||
print 'ERROR: %s expected at %s.' % (token_type, pos)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
ID_REGEX = re.compile(r'[_A-Za-z]\w*')
|
|
||||||
EQ_REGEX = re.compile(r'=')
|
|
||||||
REST_OF_LINE_REGEX = re.compile(r'.*?(?=$|\$\$)')
|
|
||||||
OPTIONAL_WHITE_SPACES_REGEX = re.compile(r'\s*')
|
|
||||||
WHITE_SPACE_REGEX = re.compile(r'\s')
|
|
||||||
DOT_DOT_REGEX = re.compile(r'\.\.')
|
|
||||||
|
|
||||||
|
|
||||||
def Skip(lines, pos, regex):
|
|
||||||
line = lines[pos.line][pos.column:]
|
|
||||||
m = re.search(regex, line)
|
|
||||||
if m and not m.start():
|
|
||||||
return pos + m.end()
|
|
||||||
else:
|
|
||||||
return pos
|
|
||||||
|
|
||||||
|
|
||||||
def SkipUntil(lines, pos, regex, token_type):
|
|
||||||
line = lines[pos.line][pos.column:]
|
|
||||||
m = re.search(regex, line)
|
|
||||||
if m:
|
|
||||||
return pos + m.start()
|
|
||||||
else:
|
|
||||||
print ('ERROR: %s expected on line %s after column %s.' %
|
|
||||||
(token_type, pos.line + 1, pos.column))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def ParseExpTokenInParens(lines, pos):
|
|
||||||
def ParseInParens(pos):
|
|
||||||
pos = Skip(lines, pos, OPTIONAL_WHITE_SPACES_REGEX)
|
|
||||||
pos = Skip(lines, pos, r'\(')
|
|
||||||
pos = Parse(pos)
|
|
||||||
pos = Skip(lines, pos, r'\)')
|
|
||||||
return pos
|
|
||||||
|
|
||||||
def Parse(pos):
|
|
||||||
pos = SkipUntil(lines, pos, r'\(|\)', ')')
|
|
||||||
if SubString(lines, pos, pos + 1) == '(':
|
|
||||||
pos = Parse(pos + 1)
|
|
||||||
pos = Skip(lines, pos, r'\)')
|
|
||||||
return Parse(pos)
|
|
||||||
else:
|
|
||||||
return pos
|
|
||||||
|
|
||||||
start = pos.Clone()
|
|
||||||
pos = ParseInParens(pos)
|
|
||||||
return MakeToken(lines, start, pos, 'exp')
|
|
||||||
|
|
||||||
|
|
||||||
def RStripNewLineFromToken(token):
|
|
||||||
if token.value.endswith('\n'):
|
|
||||||
return Token(token.start, token.end, token.value[:-1], token.token_type)
|
|
||||||
else:
|
|
||||||
return token
|
|
||||||
|
|
||||||
|
|
||||||
def TokenizeLines(lines, pos):
|
|
||||||
while True:
|
|
||||||
found = FindFirst(lines, TOKEN_TABLE, pos)
|
|
||||||
if not found:
|
|
||||||
yield MakeToken(lines, pos, Eof(), 'code')
|
|
||||||
return
|
|
||||||
|
|
||||||
if found.start == pos:
|
|
||||||
prev_token = None
|
|
||||||
prev_token_rstripped = None
|
|
||||||
else:
|
|
||||||
prev_token = MakeToken(lines, pos, found.start, 'code')
|
|
||||||
prev_token_rstripped = RStripNewLineFromToken(prev_token)
|
|
||||||
|
|
||||||
if found.token_type == '$var':
|
|
||||||
if prev_token_rstripped:
|
|
||||||
yield prev_token_rstripped
|
|
||||||
yield found
|
|
||||||
id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
|
|
||||||
yield id_token
|
|
||||||
pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
|
|
||||||
|
|
||||||
eq_token = ParseToken(lines, pos, EQ_REGEX, '=')
|
|
||||||
yield eq_token
|
|
||||||
pos = Skip(lines, eq_token.end, r'\s*')
|
|
||||||
|
|
||||||
if SubString(lines, pos, pos + 2) != '[[':
|
|
||||||
exp_token = ParseToken(lines, pos, REST_OF_LINE_REGEX, 'exp')
|
|
||||||
yield exp_token
|
|
||||||
pos = Cursor(exp_token.end.line + 1, 0)
|
|
||||||
elif found.token_type == '$for':
|
|
||||||
if prev_token_rstripped:
|
|
||||||
yield prev_token_rstripped
|
|
||||||
yield found
|
|
||||||
id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
|
|
||||||
yield id_token
|
|
||||||
pos = Skip(lines, id_token.end, WHITE_SPACE_REGEX)
|
|
||||||
elif found.token_type == '$range':
|
|
||||||
if prev_token_rstripped:
|
|
||||||
yield prev_token_rstripped
|
|
||||||
yield found
|
|
||||||
id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
|
|
||||||
yield id_token
|
|
||||||
pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
|
|
||||||
|
|
||||||
dots_pos = SkipUntil(lines, pos, DOT_DOT_REGEX, '..')
|
|
||||||
yield MakeToken(lines, pos, dots_pos, 'exp')
|
|
||||||
yield MakeToken(lines, dots_pos, dots_pos + 2, '..')
|
|
||||||
pos = dots_pos + 2
|
|
||||||
new_pos = Cursor(pos.line + 1, 0)
|
|
||||||
yield MakeToken(lines, pos, new_pos, 'exp')
|
|
||||||
pos = new_pos
|
|
||||||
elif found.token_type == '$':
|
|
||||||
if prev_token:
|
|
||||||
yield prev_token
|
|
||||||
yield found
|
|
||||||
exp_token = ParseExpTokenInParens(lines, found.end)
|
|
||||||
yield exp_token
|
|
||||||
pos = exp_token.end
|
|
||||||
elif (found.token_type == ']]' or found.token_type == '$if' or
|
|
||||||
found.token_type == '$elif' or found.token_type == '$else'):
|
|
||||||
if prev_token_rstripped:
|
|
||||||
yield prev_token_rstripped
|
|
||||||
yield found
|
|
||||||
pos = found.end
|
|
||||||
else:
|
|
||||||
if prev_token:
|
|
||||||
yield prev_token
|
|
||||||
yield found
|
|
||||||
pos = found.end
|
|
||||||
|
|
||||||
|
|
||||||
def Tokenize(s):
|
|
||||||
"""A generator that yields the tokens in the given string."""
|
|
||||||
if s != '':
|
|
||||||
lines = s.splitlines(True)
|
|
||||||
for token in TokenizeLines(lines, Cursor(0, 0)):
|
|
||||||
yield token
|
|
||||||
|
|
||||||
|
|
||||||
class CodeNode:
|
|
||||||
def __init__(self, atomic_code_list=None):
|
|
||||||
self.atomic_code = atomic_code_list
|
|
||||||
|
|
||||||
|
|
||||||
class VarNode:
|
|
||||||
def __init__(self, identifier=None, atomic_code=None):
|
|
||||||
self.identifier = identifier
|
|
||||||
self.atomic_code = atomic_code
|
|
||||||
|
|
||||||
|
|
||||||
class RangeNode:
|
|
||||||
def __init__(self, identifier=None, exp1=None, exp2=None):
|
|
||||||
self.identifier = identifier
|
|
||||||
self.exp1 = exp1
|
|
||||||
self.exp2 = exp2
|
|
||||||
|
|
||||||
|
|
||||||
class ForNode:
|
|
||||||
def __init__(self, identifier=None, sep=None, code=None):
|
|
||||||
self.identifier = identifier
|
|
||||||
self.sep = sep
|
|
||||||
self.code = code
|
|
||||||
|
|
||||||
|
|
||||||
class ElseNode:
|
|
||||||
def __init__(self, else_branch=None):
|
|
||||||
self.else_branch = else_branch
|
|
||||||
|
|
||||||
|
|
||||||
class IfNode:
|
|
||||||
def __init__(self, exp=None, then_branch=None, else_branch=None):
|
|
||||||
self.exp = exp
|
|
||||||
self.then_branch = then_branch
|
|
||||||
self.else_branch = else_branch
|
|
||||||
|
|
||||||
|
|
||||||
class RawCodeNode:
|
|
||||||
def __init__(self, token=None):
|
|
||||||
self.raw_code = token
|
|
||||||
|
|
||||||
|
|
||||||
class LiteralDollarNode:
|
|
||||||
def __init__(self, token):
|
|
||||||
self.token = token
|
|
||||||
|
|
||||||
|
|
||||||
class ExpNode:
|
|
||||||
def __init__(self, token, python_exp):
|
|
||||||
self.token = token
|
|
||||||
self.python_exp = python_exp
|
|
||||||
|
|
||||||
|
|
||||||
def PopFront(a_list):
|
|
||||||
head = a_list[0]
|
|
||||||
a_list[:1] = []
|
|
||||||
return head
|
|
||||||
|
|
||||||
|
|
||||||
def PushFront(a_list, elem):
|
|
||||||
a_list[:0] = [elem]
|
|
||||||
|
|
||||||
|
|
||||||
def PopToken(a_list, token_type=None):
|
|
||||||
token = PopFront(a_list)
|
|
||||||
if token_type is not None and token.token_type != token_type:
|
|
||||||
print 'ERROR: %s expected at %s' % (token_type, token.start)
|
|
||||||
print 'ERROR: %s found instead' % (token,)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
return token
|
|
||||||
|
|
||||||
|
|
||||||
def PeekToken(a_list):
|
|
||||||
if not a_list:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return a_list[0]
|
|
||||||
|
|
||||||
|
|
||||||
def ParseExpNode(token):
|
|
||||||
python_exp = re.sub(r'([_A-Za-z]\w*)', r'self.GetValue("\1")', token.value)
|
|
||||||
return ExpNode(token, python_exp)
|
|
||||||
|
|
||||||
|
|
||||||
def ParseElseNode(tokens):
|
|
||||||
def Pop(token_type=None):
|
|
||||||
return PopToken(tokens, token_type)
|
|
||||||
|
|
||||||
next = PeekToken(tokens)
|
|
||||||
if not next:
|
|
||||||
return None
|
|
||||||
if next.token_type == '$else':
|
|
||||||
Pop('$else')
|
|
||||||
Pop('[[')
|
|
||||||
code_node = ParseCodeNode(tokens)
|
|
||||||
Pop(']]')
|
|
||||||
return code_node
|
|
||||||
elif next.token_type == '$elif':
|
|
||||||
Pop('$elif')
|
|
||||||
exp = Pop('code')
|
|
||||||
Pop('[[')
|
|
||||||
code_node = ParseCodeNode(tokens)
|
|
||||||
Pop(']]')
|
|
||||||
inner_else_node = ParseElseNode(tokens)
|
|
||||||
return CodeNode([IfNode(ParseExpNode(exp), code_node, inner_else_node)])
|
|
||||||
elif not next.value.strip():
|
|
||||||
Pop('code')
|
|
||||||
return ParseElseNode(tokens)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def ParseAtomicCodeNode(tokens):
|
|
||||||
def Pop(token_type=None):
|
|
||||||
return PopToken(tokens, token_type)
|
|
||||||
|
|
||||||
head = PopFront(tokens)
|
|
||||||
t = head.token_type
|
|
||||||
if t == 'code':
|
|
||||||
return RawCodeNode(head)
|
|
||||||
elif t == '$var':
|
|
||||||
id_token = Pop('id')
|
|
||||||
Pop('=')
|
|
||||||
next = PeekToken(tokens)
|
|
||||||
if next.token_type == 'exp':
|
|
||||||
exp_token = Pop()
|
|
||||||
return VarNode(id_token, ParseExpNode(exp_token))
|
|
||||||
Pop('[[')
|
|
||||||
code_node = ParseCodeNode(tokens)
|
|
||||||
Pop(']]')
|
|
||||||
return VarNode(id_token, code_node)
|
|
||||||
elif t == '$for':
|
|
||||||
id_token = Pop('id')
|
|
||||||
next_token = PeekToken(tokens)
|
|
||||||
if next_token.token_type == 'code':
|
|
||||||
sep_token = next_token
|
|
||||||
Pop('code')
|
|
||||||
else:
|
|
||||||
sep_token = None
|
|
||||||
Pop('[[')
|
|
||||||
code_node = ParseCodeNode(tokens)
|
|
||||||
Pop(']]')
|
|
||||||
return ForNode(id_token, sep_token, code_node)
|
|
||||||
elif t == '$if':
|
|
||||||
exp_token = Pop('code')
|
|
||||||
Pop('[[')
|
|
||||||
code_node = ParseCodeNode(tokens)
|
|
||||||
Pop(']]')
|
|
||||||
else_node = ParseElseNode(tokens)
|
|
||||||
return IfNode(ParseExpNode(exp_token), code_node, else_node)
|
|
||||||
elif t == '$range':
|
|
||||||
id_token = Pop('id')
|
|
||||||
exp1_token = Pop('exp')
|
|
||||||
Pop('..')
|
|
||||||
exp2_token = Pop('exp')
|
|
||||||
return RangeNode(id_token, ParseExpNode(exp1_token),
|
|
||||||
ParseExpNode(exp2_token))
|
|
||||||
elif t == '$id':
|
|
||||||
return ParseExpNode(Token(head.start + 1, head.end, head.value[1:], 'id'))
|
|
||||||
elif t == '$($)':
|
|
||||||
return LiteralDollarNode(head)
|
|
||||||
elif t == '$':
|
|
||||||
exp_token = Pop('exp')
|
|
||||||
return ParseExpNode(exp_token)
|
|
||||||
elif t == '[[':
|
|
||||||
code_node = ParseCodeNode(tokens)
|
|
||||||
Pop(']]')
|
|
||||||
return code_node
|
|
||||||
else:
|
|
||||||
PushFront(tokens, head)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def ParseCodeNode(tokens):
|
|
||||||
atomic_code_list = []
|
|
||||||
while True:
|
|
||||||
if not tokens:
|
|
||||||
break
|
|
||||||
atomic_code_node = ParseAtomicCodeNode(tokens)
|
|
||||||
if atomic_code_node:
|
|
||||||
atomic_code_list.append(atomic_code_node)
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
return CodeNode(atomic_code_list)
|
|
||||||
|
|
||||||
|
|
||||||
def ParseToAST(pump_src_text):
|
|
||||||
"""Convert the given Pump source text into an AST."""
|
|
||||||
tokens = list(Tokenize(pump_src_text))
|
|
||||||
code_node = ParseCodeNode(tokens)
|
|
||||||
return code_node
|
|
||||||
|
|
||||||
|
|
||||||
class Env:
|
|
||||||
def __init__(self):
|
|
||||||
self.variables = []
|
|
||||||
self.ranges = []
|
|
||||||
|
|
||||||
def Clone(self):
|
|
||||||
clone = Env()
|
|
||||||
clone.variables = self.variables[:]
|
|
||||||
clone.ranges = self.ranges[:]
|
|
||||||
return clone
|
|
||||||
|
|
||||||
def PushVariable(self, var, value):
|
|
||||||
# If value looks like an int, store it as an int.
|
|
||||||
try:
|
|
||||||
int_value = int(value)
|
|
||||||
if ('%s' % int_value) == value:
|
|
||||||
value = int_value
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
self.variables[:0] = [(var, value)]
|
|
||||||
|
|
||||||
def PopVariable(self):
|
|
||||||
self.variables[:1] = []
|
|
||||||
|
|
||||||
def PushRange(self, var, lower, upper):
|
|
||||||
self.ranges[:0] = [(var, lower, upper)]
|
|
||||||
|
|
||||||
def PopRange(self):
|
|
||||||
self.ranges[:1] = []
|
|
||||||
|
|
||||||
def GetValue(self, identifier):
|
|
||||||
for (var, value) in self.variables:
|
|
||||||
if identifier == var:
|
|
||||||
return value
|
|
||||||
|
|
||||||
print 'ERROR: meta variable %s is undefined.' % (identifier,)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
def EvalExp(self, exp):
|
|
||||||
try:
|
|
||||||
result = eval(exp.python_exp)
|
|
||||||
except Exception, e:
|
|
||||||
print 'ERROR: caught exception %s: %s' % (e.__class__.__name__, e)
|
|
||||||
print ('ERROR: failed to evaluate meta expression %s at %s' %
|
|
||||||
(exp.python_exp, exp.token.start))
|
|
||||||
sys.exit(1)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def GetRange(self, identifier):
|
|
||||||
for (var, lower, upper) in self.ranges:
|
|
||||||
if identifier == var:
|
|
||||||
return (lower, upper)
|
|
||||||
|
|
||||||
print 'ERROR: range %s is undefined.' % (identifier,)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
class Output:
|
|
||||||
def __init__(self):
|
|
||||||
self.string = ''
|
|
||||||
|
|
||||||
def GetLastLine(self):
|
|
||||||
index = self.string.rfind('\n')
|
|
||||||
if index < 0:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
return self.string[index + 1:]
|
|
||||||
|
|
||||||
def Append(self, s):
|
|
||||||
self.string += s
|
|
||||||
|
|
||||||
|
|
||||||
def RunAtomicCode(env, node, output):
|
|
||||||
if isinstance(node, VarNode):
|
|
||||||
identifier = node.identifier.value.strip()
|
|
||||||
result = Output()
|
|
||||||
RunAtomicCode(env.Clone(), node.atomic_code, result)
|
|
||||||
value = result.string
|
|
||||||
env.PushVariable(identifier, value)
|
|
||||||
elif isinstance(node, RangeNode):
|
|
||||||
identifier = node.identifier.value.strip()
|
|
||||||
lower = int(env.EvalExp(node.exp1))
|
|
||||||
upper = int(env.EvalExp(node.exp2))
|
|
||||||
env.PushRange(identifier, lower, upper)
|
|
||||||
elif isinstance(node, ForNode):
|
|
||||||
identifier = node.identifier.value.strip()
|
|
||||||
if node.sep is None:
|
|
||||||
sep = ''
|
|
||||||
else:
|
|
||||||
sep = node.sep.value
|
|
||||||
(lower, upper) = env.GetRange(identifier)
|
|
||||||
for i in range(lower, upper + 1):
|
|
||||||
new_env = env.Clone()
|
|
||||||
new_env.PushVariable(identifier, i)
|
|
||||||
RunCode(new_env, node.code, output)
|
|
||||||
if i != upper:
|
|
||||||
output.Append(sep)
|
|
||||||
elif isinstance(node, RawCodeNode):
|
|
||||||
output.Append(node.raw_code.value)
|
|
||||||
elif isinstance(node, IfNode):
|
|
||||||
cond = env.EvalExp(node.exp)
|
|
||||||
if cond:
|
|
||||||
RunCode(env.Clone(), node.then_branch, output)
|
|
||||||
elif node.else_branch is not None:
|
|
||||||
RunCode(env.Clone(), node.else_branch, output)
|
|
||||||
elif isinstance(node, ExpNode):
|
|
||||||
value = env.EvalExp(node)
|
|
||||||
output.Append('%s' % (value,))
|
|
||||||
elif isinstance(node, LiteralDollarNode):
|
|
||||||
output.Append('$')
|
|
||||||
elif isinstance(node, CodeNode):
|
|
||||||
RunCode(env.Clone(), node, output)
|
|
||||||
else:
|
|
||||||
print 'BAD'
|
|
||||||
print node
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def RunCode(env, code_node, output):
|
|
||||||
for atomic_code in code_node.atomic_code:
|
|
||||||
RunAtomicCode(env, atomic_code, output)
|
|
||||||
|
|
||||||
|
|
||||||
def IsSingleLineComment(cur_line):
|
|
||||||
return '//' in cur_line
|
|
||||||
|
|
||||||
|
|
||||||
def IsInPreprocessorDirective(prev_lines, cur_line):
|
|
||||||
if cur_line.lstrip().startswith('#'):
|
|
||||||
return True
|
|
||||||
return prev_lines and prev_lines[-1].endswith('\\')
|
|
||||||
|
|
||||||
|
|
||||||
def WrapComment(line, output):
|
|
||||||
loc = line.find('//')
|
|
||||||
before_comment = line[:loc].rstrip()
|
|
||||||
if before_comment == '':
|
|
||||||
indent = loc
|
|
||||||
else:
|
|
||||||
output.append(before_comment)
|
|
||||||
indent = len(before_comment) - len(before_comment.lstrip())
|
|
||||||
prefix = indent*' ' + '// '
|
|
||||||
max_len = 80 - len(prefix)
|
|
||||||
comment = line[loc + 2:].strip()
|
|
||||||
segs = [seg for seg in re.split(r'(\w+\W*)', comment) if seg != '']
|
|
||||||
cur_line = ''
|
|
||||||
for seg in segs:
|
|
||||||
if len((cur_line + seg).rstrip()) < max_len:
|
|
||||||
cur_line += seg
|
|
||||||
else:
|
|
||||||
if cur_line.strip() != '':
|
|
||||||
output.append(prefix + cur_line.rstrip())
|
|
||||||
cur_line = seg.lstrip()
|
|
||||||
if cur_line.strip() != '':
|
|
||||||
output.append(prefix + cur_line.strip())
|
|
||||||
|
|
||||||
|
|
||||||
def WrapCode(line, line_concat, output):
|
|
||||||
indent = len(line) - len(line.lstrip())
|
|
||||||
prefix = indent*' ' # Prefix of the current line
|
|
||||||
max_len = 80 - indent - len(line_concat) # Maximum length of the current line
|
|
||||||
new_prefix = prefix + 4*' ' # Prefix of a continuation line
|
|
||||||
new_max_len = max_len - 4 # Maximum length of a continuation line
|
|
||||||
# Prefers to wrap a line after a ',' or ';'.
|
|
||||||
segs = [seg for seg in re.split(r'([^,;]+[,;]?)', line.strip()) if seg != '']
|
|
||||||
cur_line = '' # The current line without leading spaces.
|
|
||||||
for seg in segs:
|
|
||||||
# If the line is still too long, wrap at a space.
|
|
||||||
while cur_line == '' and len(seg.strip()) > max_len:
|
|
||||||
seg = seg.lstrip()
|
|
||||||
split_at = seg.rfind(' ', 0, max_len)
|
|
||||||
output.append(prefix + seg[:split_at].strip() + line_concat)
|
|
||||||
seg = seg[split_at + 1:]
|
|
||||||
prefix = new_prefix
|
|
||||||
max_len = new_max_len
|
|
||||||
|
|
||||||
if len((cur_line + seg).rstrip()) < max_len:
|
|
||||||
cur_line = (cur_line + seg).lstrip()
|
|
||||||
else:
|
|
||||||
output.append(prefix + cur_line.rstrip() + line_concat)
|
|
||||||
prefix = new_prefix
|
|
||||||
max_len = new_max_len
|
|
||||||
cur_line = seg.lstrip()
|
|
||||||
if cur_line.strip() != '':
|
|
||||||
output.append(prefix + cur_line.strip())
|
|
||||||
|
|
||||||
|
|
||||||
def WrapPreprocessorDirective(line, output):
|
|
||||||
WrapCode(line, ' \\', output)
|
|
||||||
|
|
||||||
|
|
||||||
def WrapPlainCode(line, output):
|
|
||||||
WrapCode(line, '', output)
|
|
||||||
|
|
||||||
|
|
||||||
def IsMultiLineIWYUPragma(line):
|
|
||||||
return re.search(r'/\* IWYU pragma: ', line)
|
|
||||||
|
|
||||||
|
|
||||||
def IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
|
|
||||||
return (re.match(r'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$', line) or
|
|
||||||
re.match(r'^#include\s', line) or
|
|
||||||
# Don't break IWYU pragmas, either; that causes iwyu.py problems.
|
|
||||||
re.search(r'// IWYU pragma: ', line))
|
|
||||||
|
|
||||||
|
|
||||||
def WrapLongLine(line, output):
|
|
||||||
line = line.rstrip()
|
|
||||||
if len(line) <= 80:
|
|
||||||
output.append(line)
|
|
||||||
elif IsSingleLineComment(line):
|
|
||||||
if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
|
|
||||||
# The style guide made an exception to allow long header guard lines,
|
|
||||||
# includes and IWYU pragmas.
|
|
||||||
output.append(line)
|
|
||||||
else:
|
|
||||||
WrapComment(line, output)
|
|
||||||
elif IsInPreprocessorDirective(output, line):
|
|
||||||
if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
|
|
||||||
# The style guide made an exception to allow long header guard lines,
|
|
||||||
# includes and IWYU pragmas.
|
|
||||||
output.append(line)
|
|
||||||
else:
|
|
||||||
WrapPreprocessorDirective(line, output)
|
|
||||||
elif IsMultiLineIWYUPragma(line):
|
|
||||||
output.append(line)
|
|
||||||
else:
|
|
||||||
WrapPlainCode(line, output)
|
|
||||||
|
|
||||||
|
|
||||||
def BeautifyCode(string):
|
|
||||||
lines = string.splitlines()
|
|
||||||
output = []
|
|
||||||
for line in lines:
|
|
||||||
WrapLongLine(line, output)
|
|
||||||
output2 = [line.rstrip() for line in output]
|
|
||||||
return '\n'.join(output2) + '\n'
|
|
||||||
|
|
||||||
|
|
||||||
def ConvertFromPumpSource(src_text):
|
|
||||||
"""Return the text generated from the given Pump source text."""
|
|
||||||
ast = ParseToAST(StripMetaComments(src_text))
|
|
||||||
output = Output()
|
|
||||||
RunCode(Env(), ast, output)
|
|
||||||
return BeautifyCode(output.string)
|
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
|
||||||
if len(argv) == 1:
|
|
||||||
print __doc__
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
file_path = argv[-1]
|
|
||||||
output_str = ConvertFromPumpSource(file(file_path, 'r').read())
|
|
||||||
if file_path.endswith('.pump'):
|
|
||||||
output_file_path = file_path[:-5]
|
|
||||||
else:
|
|
||||||
output_file_path = '-'
|
|
||||||
if output_file_path == '-':
|
|
||||||
print output_str,
|
|
||||||
else:
|
|
||||||
output_file = file(output_file_path, 'w')
|
|
||||||
output_file.write('// This file was GENERATED by command:\n')
|
|
||||||
output_file.write('// %s %s\n' %
|
|
||||||
(os.path.basename(__file__), os.path.basename(file_path)))
|
|
||||||
output_file.write('// DO NOT EDIT BY HAND!!!\n\n')
|
|
||||||
output_file.write(output_str)
|
|
||||||
output_file.close()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main(sys.argv)
|
|
|
@ -1,158 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# Copyright 2013 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.
|
|
||||||
|
|
||||||
"""Script for branching Google Test/Mock wiki pages for a new version.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
release_docs.py NEW_RELEASE_VERSION
|
|
||||||
|
|
||||||
Google Test and Google Mock's external user documentation is in
|
|
||||||
interlinked wiki files. When we release a new version of
|
|
||||||
Google Test or Google Mock, we need to branch the wiki files
|
|
||||||
such that users of a specific version of Google Test/Mock can
|
|
||||||
look up documentation relevant for that version. This script
|
|
||||||
automates that process by:
|
|
||||||
|
|
||||||
- branching the current wiki pages (which document the
|
|
||||||
behavior of the SVN trunk head) to pages for the specified
|
|
||||||
version (e.g. branching FAQ.wiki to V2_6_FAQ.wiki when
|
|
||||||
NEW_RELEASE_VERSION is 2.6);
|
|
||||||
- updating the links in the branched files to point to the branched
|
|
||||||
version (e.g. a link in V2_6_FAQ.wiki that pointed to
|
|
||||||
Primer.wiki#Anchor will now point to V2_6_Primer.wiki#Anchor).
|
|
||||||
|
|
||||||
NOTE: NEW_RELEASE_VERSION must be a NEW version number for
|
|
||||||
which the wiki pages don't yet exist; otherwise you'll get SVN
|
|
||||||
errors like "svn: Path 'V1_7_PumpManual.wiki' is not a
|
|
||||||
directory" when running the script.
|
|
||||||
|
|
||||||
EXAMPLE
|
|
||||||
$ cd PATH/TO/GTEST_SVN_WORKSPACE/trunk
|
|
||||||
$ scripts/release_docs.py 2.6 # create wiki pages for v2.6
|
|
||||||
$ svn status # verify the file list
|
|
||||||
$ svn diff # verify the file contents
|
|
||||||
$ svn commit -m "release wiki pages for v2.6"
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import common
|
|
||||||
|
|
||||||
|
|
||||||
# Wiki pages that shouldn't be branched for every gtest/gmock release.
|
|
||||||
GTEST_UNVERSIONED_WIKIS = ['DevGuide.wiki']
|
|
||||||
GMOCK_UNVERSIONED_WIKIS = [
|
|
||||||
'DesignDoc.wiki',
|
|
||||||
'DevGuide.wiki',
|
|
||||||
'KnownIssues.wiki'
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def DropWikiSuffix(wiki_filename):
|
|
||||||
"""Removes the .wiki suffix (if any) from the given filename."""
|
|
||||||
|
|
||||||
return (wiki_filename[:-len('.wiki')] if wiki_filename.endswith('.wiki')
|
|
||||||
else wiki_filename)
|
|
||||||
|
|
||||||
|
|
||||||
class WikiBrancher(object):
|
|
||||||
"""Branches ..."""
|
|
||||||
|
|
||||||
def __init__(self, dot_version):
|
|
||||||
self.project, svn_root_path = common.GetSvnInfo()
|
|
||||||
if self.project not in ('googletest', 'googlemock'):
|
|
||||||
sys.exit('This script must be run in a gtest or gmock SVN workspace.')
|
|
||||||
self.wiki_dir = svn_root_path + '/wiki'
|
|
||||||
# Turn '2.6' to 'V2_6_'.
|
|
||||||
self.version_prefix = 'V' + dot_version.replace('.', '_') + '_'
|
|
||||||
self.files_to_branch = self.GetFilesToBranch()
|
|
||||||
page_names = [DropWikiSuffix(f) for f in self.files_to_branch]
|
|
||||||
# A link to Foo.wiki is in one of the following forms:
|
|
||||||
# [Foo words]
|
|
||||||
# [Foo#Anchor words]
|
|
||||||
# [http://code.google.com/.../wiki/Foo words]
|
|
||||||
# [http://code.google.com/.../wiki/Foo#Anchor words]
|
|
||||||
# We want to replace 'Foo' with 'V2_6_Foo' in the above cases.
|
|
||||||
self.search_for_re = re.compile(
|
|
||||||
# This regex matches either
|
|
||||||
# [Foo
|
|
||||||
# or
|
|
||||||
# /wiki/Foo
|
|
||||||
# followed by a space or a #, where Foo is the name of an
|
|
||||||
# unversioned wiki page.
|
|
||||||
r'(\[|/wiki/)(%s)([ #])' % '|'.join(page_names))
|
|
||||||
self.replace_with = r'\1%s\2\3' % (self.version_prefix,)
|
|
||||||
|
|
||||||
def GetFilesToBranch(self):
|
|
||||||
"""Returns a list of .wiki file names that need to be branched."""
|
|
||||||
|
|
||||||
unversioned_wikis = (GTEST_UNVERSIONED_WIKIS if self.project == 'googletest'
|
|
||||||
else GMOCK_UNVERSIONED_WIKIS)
|
|
||||||
return [f for f in os.listdir(self.wiki_dir)
|
|
||||||
if (f.endswith('.wiki') and
|
|
||||||
not re.match(r'^V\d', f) and # Excluded versioned .wiki files.
|
|
||||||
f not in unversioned_wikis)]
|
|
||||||
|
|
||||||
def BranchFiles(self):
|
|
||||||
"""Branches the .wiki files needed to be branched."""
|
|
||||||
|
|
||||||
print 'Branching %d .wiki files:' % (len(self.files_to_branch),)
|
|
||||||
os.chdir(self.wiki_dir)
|
|
||||||
for f in self.files_to_branch:
|
|
||||||
command = 'svn cp %s %s%s' % (f, self.version_prefix, f)
|
|
||||||
print command
|
|
||||||
os.system(command)
|
|
||||||
|
|
||||||
def UpdateLinksInBranchedFiles(self):
|
|
||||||
|
|
||||||
for f in self.files_to_branch:
|
|
||||||
source_file = os.path.join(self.wiki_dir, f)
|
|
||||||
versioned_file = os.path.join(self.wiki_dir, self.version_prefix + f)
|
|
||||||
print 'Updating links in %s.' % (versioned_file,)
|
|
||||||
text = file(source_file, 'r').read()
|
|
||||||
new_text = self.search_for_re.sub(self.replace_with, text)
|
|
||||||
file(versioned_file, 'w').write(new_text)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if len(sys.argv) != 2:
|
|
||||||
sys.exit(__doc__)
|
|
||||||
|
|
||||||
brancher = WikiBrancher(sys.argv[1])
|
|
||||||
brancher.BranchFiles()
|
|
||||||
brancher.UpdateLinksInBranchedFiles()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,32 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# Copyright 2010 Google Inc. All Rights Reserved.
|
|
||||||
|
|
||||||
"""Runs program specified in the command line with the substituted PATH.
|
|
||||||
|
|
||||||
This script is needed for to support building under Pulse which is unable
|
|
||||||
to override the existing PATH variable.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
|
|
||||||
SUBST_PATH_ENV_VAR_NAME = "SUBST_PATH"
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if SUBST_PATH_ENV_VAR_NAME in os.environ:
|
|
||||||
os.environ["PATH"] = os.environ[SUBST_PATH_ENV_VAR_NAME]
|
|
||||||
|
|
||||||
exit_code = subprocess.Popen(sys.argv[1:]).wait()
|
|
||||||
|
|
||||||
# exit_code is negative (-signal) if the process has been terminated by
|
|
||||||
# a signal. Returning negative exit code is not portable and so we return
|
|
||||||
# 100 instead.
|
|
||||||
if exit_code < 0:
|
|
||||||
exit_code = 100
|
|
||||||
|
|
||||||
sys.exit(exit_code)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,59 +0,0 @@
|
||||||
# A Makefile for fusing Google Test and building a sample test against it.
|
|
||||||
#
|
|
||||||
# SYNOPSIS:
|
|
||||||
#
|
|
||||||
# make [all] - makes everything.
|
|
||||||
# make TARGET - makes the given target.
|
|
||||||
# make check - makes everything and runs the built sample test.
|
|
||||||
# make clean - removes all files generated by make.
|
|
||||||
|
|
||||||
# Points to the root of fused Google Test, relative to where this file is.
|
|
||||||
FUSED_GTEST_DIR = output
|
|
||||||
|
|
||||||
# Paths to the fused gtest files.
|
|
||||||
FUSED_GTEST_H = $(FUSED_GTEST_DIR)/gtest/gtest.h
|
|
||||||
FUSED_GTEST_ALL_CC = $(FUSED_GTEST_DIR)/gtest/gtest-all.cc
|
|
||||||
|
|
||||||
# Where to find the sample test.
|
|
||||||
SAMPLE_DIR = ../../samples
|
|
||||||
|
|
||||||
# Where to find gtest_main.cc.
|
|
||||||
GTEST_MAIN_CC = ../../src/gtest_main.cc
|
|
||||||
|
|
||||||
# Flags passed to the preprocessor.
|
|
||||||
# We have no idea here whether pthreads is available in the system, so
|
|
||||||
# disable its use.
|
|
||||||
CPPFLAGS += -I$(FUSED_GTEST_DIR) -DGTEST_HAS_PTHREAD=0
|
|
||||||
|
|
||||||
# Flags passed to the C++ compiler.
|
|
||||||
CXXFLAGS += -g
|
|
||||||
|
|
||||||
all : sample1_unittest
|
|
||||||
|
|
||||||
check : all
|
|
||||||
./sample1_unittest
|
|
||||||
|
|
||||||
clean :
|
|
||||||
rm -rf $(FUSED_GTEST_DIR) sample1_unittest *.o
|
|
||||||
|
|
||||||
$(FUSED_GTEST_H) :
|
|
||||||
../fuse_gtest_files.py $(FUSED_GTEST_DIR)
|
|
||||||
|
|
||||||
$(FUSED_GTEST_ALL_CC) :
|
|
||||||
../fuse_gtest_files.py $(FUSED_GTEST_DIR)
|
|
||||||
|
|
||||||
gtest-all.o : $(FUSED_GTEST_H) $(FUSED_GTEST_ALL_CC)
|
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(FUSED_GTEST_DIR)/gtest/gtest-all.cc
|
|
||||||
|
|
||||||
gtest_main.o : $(FUSED_GTEST_H) $(GTEST_MAIN_CC)
|
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_MAIN_CC)
|
|
||||||
|
|
||||||
sample1.o : $(SAMPLE_DIR)/sample1.cc $(SAMPLE_DIR)/sample1.h
|
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(SAMPLE_DIR)/sample1.cc
|
|
||||||
|
|
||||||
sample1_unittest.o : $(SAMPLE_DIR)/sample1_unittest.cc \
|
|
||||||
$(SAMPLE_DIR)/sample1.h $(FUSED_GTEST_H)
|
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(SAMPLE_DIR)/sample1_unittest.cc
|
|
||||||
|
|
||||||
sample1_unittest : sample1.o sample1_unittest.o gtest-all.o gtest_main.o
|
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@
|
|
|
@ -1,78 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""upload_gtest.py v0.1.0 -- uploads a Google Test patch for review.
|
|
||||||
|
|
||||||
This simple wrapper passes all command line flags and
|
|
||||||
--cc=googletestframework@googlegroups.com to upload.py.
|
|
||||||
|
|
||||||
USAGE: upload_gtest.py [options for upload.py]
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
CC_FLAG = '--cc='
|
|
||||||
GTEST_GROUP = 'googletestframework@googlegroups.com'
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# Finds the path to upload.py, assuming it is in the same directory
|
|
||||||
# as this file.
|
|
||||||
my_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
upload_py_path = os.path.join(my_dir, 'upload.py')
|
|
||||||
|
|
||||||
# Adds Google Test discussion group to the cc line if it's not there
|
|
||||||
# already.
|
|
||||||
upload_py_argv = [upload_py_path]
|
|
||||||
found_cc_flag = False
|
|
||||||
for arg in sys.argv[1:]:
|
|
||||||
if arg.startswith(CC_FLAG):
|
|
||||||
found_cc_flag = True
|
|
||||||
cc_line = arg[len(CC_FLAG):]
|
|
||||||
cc_list = [addr for addr in cc_line.split(',') if addr]
|
|
||||||
if GTEST_GROUP not in cc_list:
|
|
||||||
cc_list.append(GTEST_GROUP)
|
|
||||||
upload_py_argv.append(CC_FLAG + ','.join(cc_list))
|
|
||||||
else:
|
|
||||||
upload_py_argv.append(arg)
|
|
||||||
|
|
||||||
if not found_cc_flag:
|
|
||||||
upload_py_argv.append(CC_FLAG + GTEST_GROUP)
|
|
||||||
|
|
||||||
# Invokes upload.py with the modified command line flags.
|
|
||||||
os.execv(upload_py_path, upload_py_argv)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -38,7 +38,7 @@
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
// The following lines pull in the real gtest *.cc files.
|
// The following lines pull in the real gtest *.cc files.
|
||||||
#include "src/gtest.cc"
|
#include "src/gtest-assertion-result.cc"
|
||||||
#include "src/gtest-death-test.cc"
|
#include "src/gtest-death-test.cc"
|
||||||
#include "src/gtest-filepath.cc"
|
#include "src/gtest-filepath.cc"
|
||||||
#include "src/gtest-matchers.cc"
|
#include "src/gtest-matchers.cc"
|
||||||
|
@ -46,3 +46,4 @@
|
||||||
#include "src/gtest-printers.cc"
|
#include "src/gtest-printers.cc"
|
||||||
#include "src/gtest-test-part.cc"
|
#include "src/gtest-test-part.cc"
|
||||||
#include "src/gtest-typed-test.cc"
|
#include "src/gtest-typed-test.cc"
|
||||||
|
#include "src/gtest.cc"
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// The Google C++ Testing and Mocking Framework (Google Test)
|
||||||
|
//
|
||||||
|
// This file defines the AssertionResult type.
|
||||||
|
|
||||||
|
#include "gtest/gtest-assertion-result.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "gtest/gtest-message.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// AssertionResult constructors.
|
||||||
|
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
||||||
|
AssertionResult::AssertionResult(const AssertionResult& other)
|
||||||
|
: success_(other.success_),
|
||||||
|
message_(other.message_.get() != nullptr
|
||||||
|
? new ::std::string(*other.message_)
|
||||||
|
: static_cast< ::std::string*>(nullptr)) {}
|
||||||
|
|
||||||
|
// Swaps two AssertionResults.
|
||||||
|
void AssertionResult::swap(AssertionResult& other) {
|
||||||
|
using std::swap;
|
||||||
|
swap(success_, other.success_);
|
||||||
|
swap(message_, other.message_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
|
||||||
|
AssertionResult AssertionResult::operator!() const {
|
||||||
|
AssertionResult negation(!success_);
|
||||||
|
if (message_.get() != nullptr) negation << *message_;
|
||||||
|
return negation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Makes a successful assertion result.
|
||||||
|
AssertionResult AssertionSuccess() { return AssertionResult(true); }
|
||||||
|
|
||||||
|
// Makes a failed assertion result.
|
||||||
|
AssertionResult AssertionFailure() { return AssertionResult(false); }
|
||||||
|
|
||||||
|
// Makes a failed assertion result with the given failure message.
|
||||||
|
// Deprecated; use AssertionFailure() << message.
|
||||||
|
AssertionResult AssertionFailure(const Message& message) {
|
||||||
|
return AssertionFailure() << message;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
|
@ -35,49 +35,49 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
|
||||||
#include "gtest/internal/custom/gtest.h"
|
#include "gtest/internal/custom/gtest.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
# if GTEST_OS_MAC
|
#if GTEST_OS_MAC
|
||||||
# include <crt_externs.h>
|
#include <crt_externs.h>
|
||||||
# endif // GTEST_OS_MAC
|
#endif // GTEST_OS_MAC
|
||||||
|
|
||||||
# include <errno.h>
|
#include <errno.h>
|
||||||
# include <fcntl.h>
|
#include <fcntl.h>
|
||||||
# include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
# if GTEST_OS_LINUX
|
#if GTEST_OS_LINUX
|
||||||
# include <signal.h>
|
#include <signal.h>
|
||||||
# endif // GTEST_OS_LINUX
|
#endif // GTEST_OS_LINUX
|
||||||
|
|
||||||
# include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
# if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
# include <windows.h>
|
#include <windows.h>
|
||||||
# else
|
#else
|
||||||
# include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
# include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
# endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
# if GTEST_OS_QNX
|
#if GTEST_OS_QNX
|
||||||
# include <spawn.h>
|
#include <spawn.h>
|
||||||
# endif // GTEST_OS_QNX
|
#endif // GTEST_OS_QNX
|
||||||
|
|
||||||
# if GTEST_OS_FUCHSIA
|
#if GTEST_OS_FUCHSIA
|
||||||
# include <lib/fdio/fd.h>
|
#include <lib/fdio/fd.h>
|
||||||
# include <lib/fdio/io.h>
|
#include <lib/fdio/io.h>
|
||||||
# include <lib/fdio/spawn.h>
|
#include <lib/fdio/spawn.h>
|
||||||
# include <lib/zx/channel.h>
|
#include <lib/zx/channel.h>
|
||||||
# include <lib/zx/port.h>
|
#include <lib/zx/port.h>
|
||||||
# include <lib/zx/process.h>
|
#include <lib/zx/process.h>
|
||||||
# include <lib/zx/socket.h>
|
#include <lib/zx/socket.h>
|
||||||
# include <zircon/processargs.h>
|
#include <zircon/processargs.h>
|
||||||
# include <zircon/syscalls.h>
|
#include <zircon/syscalls.h>
|
||||||
# include <zircon/syscalls/policy.h>
|
#include <zircon/syscalls/policy.h>
|
||||||
# include <zircon/syscalls/port.h>
|
#include <zircon/syscalls/port.h>
|
||||||
# endif // GTEST_OS_FUCHSIA
|
#endif // GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
@ -96,9 +96,12 @@ namespace testing {
|
||||||
// used internally at Google, is "threadsafe".
|
// used internally at Google, is "threadsafe".
|
||||||
static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
|
static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
GTEST_DEFINE_string_(
|
GTEST_DEFINE_string_(
|
||||||
death_test_style,
|
death_test_style,
|
||||||
internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
|
testing::internal::StringFromGTestEnv("death_test_style",
|
||||||
|
testing::kDefaultDeathTestStyle),
|
||||||
"Indicates how to run a death test in a forked child process: "
|
"Indicates how to run a death test in a forked child process: "
|
||||||
"\"threadsafe\" (child process re-executes the test binary "
|
"\"threadsafe\" (child process re-executes the test binary "
|
||||||
"from the beginning, running only the specific death test) or "
|
"from the beginning, running only the specific death test) or "
|
||||||
|
@ -107,7 +110,7 @@ GTEST_DEFINE_string_(
|
||||||
|
|
||||||
GTEST_DEFINE_bool_(
|
GTEST_DEFINE_bool_(
|
||||||
death_test_use_fork,
|
death_test_use_fork,
|
||||||
internal::BoolFromGTestEnv("death_test_use_fork", false),
|
testing::internal::BoolFromGTestEnv("death_test_use_fork", false),
|
||||||
"Instructs to use fork()/_exit() instead of clone() in death tests. "
|
"Instructs to use fork()/_exit() instead of clone() in death tests. "
|
||||||
"Ignored and always uses fork() on POSIX systems where clone() is not "
|
"Ignored and always uses fork() on POSIX systems where clone() is not "
|
||||||
"implemented. Useful when running under valgrind or similar tools if "
|
"implemented. Useful when running under valgrind or similar tools if "
|
||||||
|
@ -117,7 +120,6 @@ GTEST_DEFINE_bool_(
|
||||||
"work in 99% of the cases. Once valgrind is fixed, this flag will "
|
"work in 99% of the cases. Once valgrind is fixed, this flag will "
|
||||||
"most likely be removed.");
|
"most likely be removed.");
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
GTEST_DEFINE_string_(
|
GTEST_DEFINE_string_(
|
||||||
internal_run_death_test, "",
|
internal_run_death_test, "",
|
||||||
"Indicates the file, line number, temporal index of "
|
"Indicates the file, line number, temporal index of "
|
||||||
|
@ -126,7 +128,8 @@ GTEST_DEFINE_string_(
|
||||||
"the '|' characters. This flag is specified if and only if the "
|
"the '|' characters. This flag is specified if and only if the "
|
||||||
"current process is a sub-process launched for running a thread-safe "
|
"current process is a sub-process launched for running a thread-safe "
|
||||||
"death test. FOR INTERNAL USE ONLY.");
|
"death test. FOR INTERNAL USE ONLY.");
|
||||||
} // namespace internal
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
|
@ -134,9 +137,9 @@ namespace internal {
|
||||||
|
|
||||||
// Valid only for fast death tests. Indicates the code is running in the
|
// Valid only for fast death tests. Indicates the code is running in the
|
||||||
// child process of a fast style death test.
|
// child process of a fast style death test.
|
||||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
#if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||||
static bool g_in_fast_death_test_child = false;
|
static bool g_in_fast_death_test_child = false;
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
// Returns a Boolean value indicating whether the caller is currently
|
// Returns a Boolean value indicating whether the caller is currently
|
||||||
// executing in the context of the death test child process. Tools such as
|
// executing in the context of the death test child process. Tools such as
|
||||||
|
@ -144,16 +147,16 @@ static bool g_in_fast_death_test_child = false;
|
||||||
// tests. IMPORTANT: This is an internal utility. Using it may break the
|
// tests. IMPORTANT: This is an internal utility. Using it may break the
|
||||||
// implementation of death tests. User code MUST NOT use it.
|
// implementation of death tests. User code MUST NOT use it.
|
||||||
bool InDeathTestChild() {
|
bool InDeathTestChild() {
|
||||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
#if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
// On Windows and Fuchsia, death tests are thread-safe regardless of the value
|
// On Windows and Fuchsia, death tests are thread-safe regardless of the value
|
||||||
// of the death_test_style flag.
|
// of the death_test_style flag.
|
||||||
return !GTEST_FLAG(internal_run_death_test).empty();
|
return !GTEST_FLAG_GET(internal_run_death_test).empty();
|
||||||
|
|
||||||
# else
|
#else
|
||||||
|
|
||||||
if (GTEST_FLAG(death_test_style) == "threadsafe")
|
if (GTEST_FLAG_GET(death_test_style) == "threadsafe")
|
||||||
return !GTEST_FLAG(internal_run_death_test).empty();
|
return !GTEST_FLAG_GET(internal_run_death_test).empty();
|
||||||
else
|
else
|
||||||
return g_in_fast_death_test_child;
|
return g_in_fast_death_test_child;
|
||||||
#endif
|
#endif
|
||||||
|
@ -162,40 +165,38 @@ bool InDeathTestChild() {
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// ExitedWithCode constructor.
|
// ExitedWithCode constructor.
|
||||||
ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
|
ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {}
|
||||||
}
|
|
||||||
|
|
||||||
// ExitedWithCode function-call operator.
|
// ExitedWithCode function-call operator.
|
||||||
bool ExitedWithCode::operator()(int exit_status) const {
|
bool ExitedWithCode::operator()(int exit_status) const {
|
||||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
#if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
return exit_status == exit_code_;
|
return exit_status == exit_code_;
|
||||||
|
|
||||||
# else
|
#else
|
||||||
|
|
||||||
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
|
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
|
||||||
|
|
||||||
# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
#endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||||
}
|
}
|
||||||
|
|
||||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
#if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||||
// KilledBySignal constructor.
|
// KilledBySignal constructor.
|
||||||
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
|
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {}
|
||||||
}
|
|
||||||
|
|
||||||
// KilledBySignal function-call operator.
|
// KilledBySignal function-call operator.
|
||||||
bool KilledBySignal::operator()(int exit_status) const {
|
bool KilledBySignal::operator()(int exit_status) const {
|
||||||
# if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
#if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
|
if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
#endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
|
||||||
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
|
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
|
||||||
}
|
}
|
||||||
# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
#endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
@ -206,23 +207,23 @@ namespace internal {
|
||||||
static std::string ExitSummary(int exit_code) {
|
static std::string ExitSummary(int exit_code) {
|
||||||
Message m;
|
Message m;
|
||||||
|
|
||||||
# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
#if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
m << "Exited with exit status " << exit_code;
|
m << "Exited with exit status " << exit_code;
|
||||||
|
|
||||||
# else
|
#else
|
||||||
|
|
||||||
if (WIFEXITED(exit_code)) {
|
if (WIFEXITED(exit_code)) {
|
||||||
m << "Exited with exit status " << WEXITSTATUS(exit_code);
|
m << "Exited with exit status " << WEXITSTATUS(exit_code);
|
||||||
} else if (WIFSIGNALED(exit_code)) {
|
} else if (WIFSIGNALED(exit_code)) {
|
||||||
m << "Terminated by signal " << WTERMSIG(exit_code);
|
m << "Terminated by signal " << WTERMSIG(exit_code);
|
||||||
}
|
}
|
||||||
# ifdef WCOREDUMP
|
#ifdef WCOREDUMP
|
||||||
if (WCOREDUMP(exit_code)) {
|
if (WCOREDUMP(exit_code)) {
|
||||||
m << " (core dumped)";
|
m << " (core dumped)";
|
||||||
}
|
}
|
||||||
# endif
|
#endif
|
||||||
# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
#endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
return m.GetString();
|
return m.GetString();
|
||||||
}
|
}
|
||||||
|
@ -233,7 +234,7 @@ bool ExitedUnsuccessfully(int exit_status) {
|
||||||
return !ExitedWithCode(0)(exit_status);
|
return !ExitedWithCode(0)(exit_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
#if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||||
// Generates a textual failure message when a death test finds more than
|
// Generates a textual failure message when a death test finds more than
|
||||||
// one thread running, or cannot determine the number of threads, prior
|
// one thread running, or cannot determine the number of threads, prior
|
||||||
// to executing the given statement. It is the responsibility of the
|
// to executing the given statement. It is the responsibility of the
|
||||||
|
@ -254,7 +255,7 @@ static std::string DeathTestThreadWarning(size_t thread_count) {
|
||||||
<< " this is the last message you see before your test times out.";
|
<< " this is the last message you see before your test times out.";
|
||||||
return msg.GetString();
|
return msg.GetString();
|
||||||
}
|
}
|
||||||
# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
#endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
// Flag characters for reporting a death test that did not die.
|
// Flag characters for reporting a death test that did not die.
|
||||||
static const char kDeathTestLived = 'L';
|
static const char kDeathTestLived = 'L';
|
||||||
|
@ -304,13 +305,13 @@ static void DeathTestAbort(const std::string& message) {
|
||||||
|
|
||||||
// A replacement for CHECK that calls DeathTestAbort if the assertion
|
// A replacement for CHECK that calls DeathTestAbort if the assertion
|
||||||
// fails.
|
// fails.
|
||||||
# define GTEST_DEATH_TEST_CHECK_(expression) \
|
#define GTEST_DEATH_TEST_CHECK_(expression) \
|
||||||
do { \
|
do { \
|
||||||
if (!::testing::internal::IsTrue(expression)) { \
|
if (!::testing::internal::IsTrue(expression)) { \
|
||||||
DeathTestAbort( \
|
DeathTestAbort(::std::string("CHECK failed: File ") + __FILE__ + \
|
||||||
::std::string("CHECK failed: File ") + __FILE__ + ", line " \
|
", line " + \
|
||||||
+ ::testing::internal::StreamableToString(__LINE__) + ": " \
|
::testing::internal::StreamableToString(__LINE__) + \
|
||||||
+ #expression); \
|
": " + #expression); \
|
||||||
} \
|
} \
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
|
@ -321,17 +322,17 @@ static void DeathTestAbort(const std::string& message) {
|
||||||
// evaluates the expression as long as it evaluates to -1 and sets
|
// evaluates the expression as long as it evaluates to -1 and sets
|
||||||
// errno to EINTR. If the expression evaluates to -1 but errno is
|
// errno to EINTR. If the expression evaluates to -1 but errno is
|
||||||
// something other than EINTR, DeathTestAbort is called.
|
// something other than EINTR, DeathTestAbort is called.
|
||||||
# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
|
#define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
|
||||||
do { \
|
do { \
|
||||||
int gtest_retval; \
|
int gtest_retval; \
|
||||||
do { \
|
do { \
|
||||||
gtest_retval = (expression); \
|
gtest_retval = (expression); \
|
||||||
} while (gtest_retval == -1 && errno == EINTR); \
|
} while (gtest_retval == -1 && errno == EINTR); \
|
||||||
if (gtest_retval == -1) { \
|
if (gtest_retval == -1) { \
|
||||||
DeathTestAbort( \
|
DeathTestAbort(::std::string("CHECK failed: File ") + __FILE__ + \
|
||||||
::std::string("CHECK failed: File ") + __FILE__ + ", line " \
|
", line " + \
|
||||||
+ ::testing::internal::StreamableToString(__LINE__) + ": " \
|
::testing::internal::StreamableToString(__LINE__) + \
|
||||||
+ #expression + " != -1"); \
|
": " + #expression + " != -1"); \
|
||||||
} \
|
} \
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
|
@ -370,7 +371,8 @@ static void FailFromInternalError(int fd) {
|
||||||
DeathTest::DeathTest() {
|
DeathTest::DeathTest() {
|
||||||
TestInfo* const info = GetUnitTestImpl()->current_test_info();
|
TestInfo* const info = GetUnitTestImpl()->current_test_info();
|
||||||
if (info == nullptr) {
|
if (info == nullptr) {
|
||||||
DeathTestAbort("Cannot run a death test outside of a TEST or "
|
DeathTestAbort(
|
||||||
|
"Cannot run a death test outside of a TEST or "
|
||||||
"TEST_F construct");
|
"TEST_F construct");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,9 +502,7 @@ void DeathTestImpl::ReadAndInterpretStatusByte() {
|
||||||
set_read_fd(-1);
|
set_read_fd(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DeathTestImpl::GetErrorLogs() {
|
std::string DeathTestImpl::GetErrorLogs() { return GetCapturedStderr(); }
|
||||||
return GetCapturedStderr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signals that the death test code which should have exited, didn't.
|
// Signals that the death test code which should have exited, didn't.
|
||||||
// Should be called only in a death test child process.
|
// Should be called only in a death test child process.
|
||||||
|
@ -512,9 +512,9 @@ void DeathTestImpl::Abort(AbortReason reason) {
|
||||||
// The parent process considers the death test to be a failure if
|
// The parent process considers the death test to be a failure if
|
||||||
// it finds any data in our pipe. So, here we write a single flag byte
|
// it finds any data in our pipe. So, here we write a single flag byte
|
||||||
// to the pipe, then exit.
|
// to the pipe, then exit.
|
||||||
const char status_ch =
|
const char status_ch = reason == TEST_DID_NOT_DIE ? kDeathTestLived
|
||||||
reason == TEST_DID_NOT_DIE ? kDeathTestLived :
|
: reason == TEST_THREW_EXCEPTION ? kDeathTestThrew
|
||||||
reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
|
: kDeathTestReturned;
|
||||||
|
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
|
||||||
// We are leaking the descriptor here because on some platforms (i.e.,
|
// We are leaking the descriptor here because on some platforms (i.e.,
|
||||||
|
@ -533,7 +533,7 @@ void DeathTestImpl::Abort(AbortReason reason) {
|
||||||
// much easier.
|
// much easier.
|
||||||
static ::std::string FormatDeathTestOutput(const ::std::string& output) {
|
static ::std::string FormatDeathTestOutput(const ::std::string& output) {
|
||||||
::std::string ret;
|
::std::string ret;
|
||||||
for (size_t at = 0; ; ) {
|
for (size_t at = 0;;) {
|
||||||
const size_t line_end = output.find('\n', at);
|
const size_t line_end = output.find('\n', at);
|
||||||
ret += "[ DEATH ] ";
|
ret += "[ DEATH ] ";
|
||||||
if (line_end == ::std::string::npos) {
|
if (line_end == ::std::string::npos) {
|
||||||
|
@ -568,8 +568,7 @@ static ::std::string FormatDeathTestOutput(const ::std::string& output) {
|
||||||
// the first failing condition, in the order given above, is the one that is
|
// the first failing condition, in the order given above, is the one that is
|
||||||
// reported. Also sets the last death test message string.
|
// reported. Also sets the last death test message string.
|
||||||
bool DeathTestImpl::Passed(bool status_ok) {
|
bool DeathTestImpl::Passed(bool status_ok) {
|
||||||
if (!spawned())
|
if (!spawned()) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
const std::string error_message = GetErrorLogs();
|
const std::string error_message = GetErrorLogs();
|
||||||
|
|
||||||
|
@ -580,15 +579,18 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
||||||
switch (outcome()) {
|
switch (outcome()) {
|
||||||
case LIVED:
|
case LIVED:
|
||||||
buffer << " Result: failed to die.\n"
|
buffer << " Result: failed to die.\n"
|
||||||
<< " Error msg:\n" << FormatDeathTestOutput(error_message);
|
<< " Error msg:\n"
|
||||||
|
<< FormatDeathTestOutput(error_message);
|
||||||
break;
|
break;
|
||||||
case THREW:
|
case THREW:
|
||||||
buffer << " Result: threw an exception.\n"
|
buffer << " Result: threw an exception.\n"
|
||||||
<< " Error msg:\n" << FormatDeathTestOutput(error_message);
|
<< " Error msg:\n"
|
||||||
|
<< FormatDeathTestOutput(error_message);
|
||||||
break;
|
break;
|
||||||
case RETURNED:
|
case RETURNED:
|
||||||
buffer << " Result: illegal return in test statement.\n"
|
buffer << " Result: illegal return in test statement.\n"
|
||||||
<< " Error msg:\n" << FormatDeathTestOutput(error_message);
|
<< " Error msg:\n"
|
||||||
|
<< FormatDeathTestOutput(error_message);
|
||||||
break;
|
break;
|
||||||
case DIED:
|
case DIED:
|
||||||
if (status_ok) {
|
if (status_ok) {
|
||||||
|
@ -605,7 +607,8 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
||||||
} else {
|
} else {
|
||||||
buffer << " Result: died but not with expected exit code:\n"
|
buffer << " Result: died but not with expected exit code:\n"
|
||||||
<< " " << ExitSummary(status()) << "\n"
|
<< " " << ExitSummary(status()) << "\n"
|
||||||
<< "Actual msg:\n" << FormatDeathTestOutput(error_message);
|
<< "Actual msg:\n"
|
||||||
|
<< FormatDeathTestOutput(error_message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IN_PROGRESS:
|
case IN_PROGRESS:
|
||||||
|
@ -618,7 +621,7 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
# if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
// WindowsDeathTest implements death tests on Windows. Due to the
|
// WindowsDeathTest implements death tests on Windows. Due to the
|
||||||
// specifics of starting new processes on Windows, death tests there are
|
// specifics of starting new processes on Windows, death tests there are
|
||||||
// always threadsafe, and Google Test considers the
|
// always threadsafe, and Google Test considers the
|
||||||
|
@ -679,14 +682,12 @@ class WindowsDeathTest : public DeathTestImpl {
|
||||||
// status, or 0 if no child process exists. As a side effect, sets the
|
// status, or 0 if no child process exists. As a side effect, sets the
|
||||||
// outcome data member.
|
// outcome data member.
|
||||||
int WindowsDeathTest::Wait() {
|
int WindowsDeathTest::Wait() {
|
||||||
if (!spawned())
|
if (!spawned()) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Wait until the child either signals that it has acquired the write end
|
// Wait until the child either signals that it has acquired the write end
|
||||||
// of the pipe or it dies.
|
// of the pipe or it dies.
|
||||||
const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
|
const HANDLE wait_handles[2] = {child_handle_.Get(), event_handle_.Get()};
|
||||||
switch (::WaitForMultipleObjects(2,
|
switch (::WaitForMultipleObjects(2, wait_handles,
|
||||||
wait_handles,
|
|
||||||
FALSE, // Waits for any of the handles.
|
FALSE, // Waits for any of the handles.
|
||||||
INFINITE)) {
|
INFINITE)) {
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
|
@ -707,9 +708,8 @@ int WindowsDeathTest::Wait() {
|
||||||
// returns immediately if the child has already exited, regardless of
|
// returns immediately if the child has already exited, regardless of
|
||||||
// whether previous calls to WaitForMultipleObjects synchronized on this
|
// whether previous calls to WaitForMultipleObjects synchronized on this
|
||||||
// handle or not.
|
// handle or not.
|
||||||
GTEST_DEATH_TEST_CHECK_(
|
GTEST_DEATH_TEST_CHECK_(WAIT_OBJECT_0 ==
|
||||||
WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
|
::WaitForSingleObject(child_handle_.Get(), INFINITE));
|
||||||
INFINITE));
|
|
||||||
DWORD status_code;
|
DWORD status_code;
|
||||||
GTEST_DEATH_TEST_CHECK_(
|
GTEST_DEATH_TEST_CHECK_(
|
||||||
::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
|
::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
|
||||||
|
@ -742,12 +742,12 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
|
SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
|
||||||
nullptr, TRUE};
|
nullptr, TRUE};
|
||||||
HANDLE read_handle, write_handle;
|
HANDLE read_handle, write_handle;
|
||||||
GTEST_DEATH_TEST_CHECK_(
|
GTEST_DEATH_TEST_CHECK_(::CreatePipe(&read_handle, &write_handle,
|
||||||
::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
|
&handles_are_inheritable,
|
||||||
0) // Default buffer size.
|
0) // Default buffer size.
|
||||||
!= FALSE);
|
!= FALSE);
|
||||||
set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
|
set_read_fd(
|
||||||
O_RDONLY));
|
::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle), O_RDONLY));
|
||||||
write_handle_.Reset(write_handle);
|
write_handle_.Reset(write_handle);
|
||||||
event_handle_.Reset(::CreateEvent(
|
event_handle_.Reset(::CreateEvent(
|
||||||
&handles_are_inheritable,
|
&handles_are_inheritable,
|
||||||
|
@ -756,27 +756,26 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
nullptr)); // The even is unnamed.
|
nullptr)); // The even is unnamed.
|
||||||
GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr);
|
GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr);
|
||||||
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||||
kFilterFlag + "=" + info->test_suite_name() +
|
"filter=" + info->test_suite_name() + "." +
|
||||||
"." + info->name();
|
info->name();
|
||||||
const std::string internal_flag =
|
const std::string internal_flag =
|
||||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
|
std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||||
"=" + file_ + "|" + StreamableToString(line_) + "|" +
|
"internal_run_death_test=" + file_ + "|" + StreamableToString(line_) +
|
||||||
StreamableToString(death_test_index) + "|" +
|
"|" + StreamableToString(death_test_index) + "|" +
|
||||||
StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
|
StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
|
||||||
// size_t has the same width as pointers on both 32-bit and 64-bit
|
// size_t has the same width as pointers on both 32-bit and 64-bit
|
||||||
// Windows platforms.
|
// Windows platforms.
|
||||||
// See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
|
// See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
|
||||||
"|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) +
|
"|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) + "|" +
|
||||||
"|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
|
StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
|
||||||
|
|
||||||
char executable_path[_MAX_PATH + 1]; // NOLINT
|
char executable_path[_MAX_PATH + 1]; // NOLINT
|
||||||
GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
|
GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
|
||||||
executable_path,
|
executable_path,
|
||||||
_MAX_PATH));
|
_MAX_PATH));
|
||||||
|
|
||||||
std::string command_line =
|
std::string command_line = std::string(::GetCommandLineA()) + " " +
|
||||||
std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
|
filter_flag + " \"" + internal_flag + "\"";
|
||||||
internal_flag + "\"";
|
|
||||||
|
|
||||||
DeathTest::set_last_death_test_message("");
|
DeathTest::set_last_death_test_message("");
|
||||||
|
|
||||||
|
@ -796,8 +795,8 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
GTEST_DEATH_TEST_CHECK_(
|
GTEST_DEATH_TEST_CHECK_(
|
||||||
::CreateProcessA(
|
::CreateProcessA(
|
||||||
executable_path, const_cast<char*>(command_line.c_str()),
|
executable_path, const_cast<char*>(command_line.c_str()),
|
||||||
nullptr, // Retuned process handle is not inheritable.
|
nullptr, // Returned process handle is not inheritable.
|
||||||
nullptr, // Retuned thread handle is not inheritable.
|
nullptr, // Returned thread handle is not inheritable.
|
||||||
TRUE, // Child inherits all inheritable handles (for write_handle_).
|
TRUE, // Child inherits all inheritable handles (for write_handle_).
|
||||||
0x0, // Default creation flags.
|
0x0, // Default creation flags.
|
||||||
nullptr, // Inherit the parent's environment.
|
nullptr, // Inherit the parent's environment.
|
||||||
|
@ -809,7 +808,7 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
|
||||||
return OVERSEE_TEST;
|
return OVERSEE_TEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
# elif GTEST_OS_FUCHSIA
|
#elif GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
class FuchsiaDeathTest : public DeathTestImpl {
|
class FuchsiaDeathTest : public DeathTestImpl {
|
||||||
public:
|
public:
|
||||||
|
@ -855,18 +854,13 @@ class Arguments {
|
||||||
template <typename Str>
|
template <typename Str>
|
||||||
void AddArguments(const ::std::vector<Str>& arguments) {
|
void AddArguments(const ::std::vector<Str>& arguments) {
|
||||||
for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
|
for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
|
||||||
i != arguments.end();
|
i != arguments.end(); ++i) {
|
||||||
++i) {
|
|
||||||
args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
|
args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char* const* Argv() {
|
char* const* Argv() { return &args_[0]; }
|
||||||
return &args_[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
int size() {
|
int size() { return static_cast<int>(args_.size()) - 1; }
|
||||||
return static_cast<int>(args_.size()) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<char*> args_;
|
std::vector<char*> args_;
|
||||||
|
@ -880,8 +874,7 @@ int FuchsiaDeathTest::Wait() {
|
||||||
const int kSocketKey = 1;
|
const int kSocketKey = 1;
|
||||||
const int kExceptionKey = 2;
|
const int kExceptionKey = 2;
|
||||||
|
|
||||||
if (!spawned())
|
if (!spawned()) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Create a port to wait for socket/task/exception events.
|
// Create a port to wait for socket/task/exception events.
|
||||||
zx_status_t status_zx;
|
zx_status_t status_zx;
|
||||||
|
@ -890,8 +883,8 @@ int FuchsiaDeathTest::Wait() {
|
||||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
|
||||||
// Register to wait for the child process to terminate.
|
// Register to wait for the child process to terminate.
|
||||||
status_zx = child_process_.wait_async(
|
status_zx =
|
||||||
port, kProcessKey, ZX_PROCESS_TERMINATED, 0);
|
child_process_.wait_async(port, kProcessKey, ZX_PROCESS_TERMINATED, 0);
|
||||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
|
||||||
// Register to wait for the socket to be readable or closed.
|
// Register to wait for the socket to be readable or closed.
|
||||||
|
@ -900,8 +893,8 @@ int FuchsiaDeathTest::Wait() {
|
||||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
|
||||||
// Register to wait for an exception.
|
// Register to wait for an exception.
|
||||||
status_zx = exception_channel_.wait_async(
|
status_zx = exception_channel_.wait_async(port, kExceptionKey,
|
||||||
port, kExceptionKey, ZX_CHANNEL_READABLE, 0);
|
ZX_CHANNEL_READABLE, 0);
|
||||||
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
|
||||||
|
|
||||||
bool process_terminated = false;
|
bool process_terminated = false;
|
||||||
|
@ -931,9 +924,9 @@ int FuchsiaDeathTest::Wait() {
|
||||||
size_t old_length = captured_stderr_.length();
|
size_t old_length = captured_stderr_.length();
|
||||||
size_t bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
captured_stderr_.resize(old_length + kBufferSize);
|
captured_stderr_.resize(old_length + kBufferSize);
|
||||||
status_zx = stderr_socket_.read(
|
status_zx =
|
||||||
0, &captured_stderr_.front() + old_length, kBufferSize,
|
stderr_socket_.read(0, &captured_stderr_.front() + old_length,
|
||||||
&bytes_read);
|
kBufferSize, &bytes_read);
|
||||||
captured_stderr_.resize(old_length + bytes_read);
|
captured_stderr_.resize(old_length + bytes_read);
|
||||||
} while (status_zx == ZX_OK);
|
} while (status_zx == ZX_OK);
|
||||||
if (status_zx == ZX_ERR_PEER_CLOSED) {
|
if (status_zx == ZX_ERR_PEER_CLOSED) {
|
||||||
|
@ -987,13 +980,12 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
||||||
|
|
||||||
// Build the child process command line.
|
// Build the child process command line.
|
||||||
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||||
kFilterFlag + "=" + info->test_suite_name() +
|
"filter=" + info->test_suite_name() + "." +
|
||||||
"." + info->name();
|
info->name();
|
||||||
const std::string internal_flag =
|
const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
kInternalRunDeathTestFlag + "=" + file_ +
|
||||||
+ file_ + "|"
|
"|" + StreamableToString(line_) + "|" +
|
||||||
+ StreamableToString(line_) + "|"
|
StreamableToString(death_test_index);
|
||||||
+ StreamableToString(death_test_index);
|
|
||||||
Arguments args;
|
Arguments args;
|
||||||
args.AddArguments(GetInjectableArgvs());
|
args.AddArguments(GetInjectableArgvs());
|
||||||
args.AddArgument(filter_flag.c_str());
|
args.AddArgument(filter_flag.c_str());
|
||||||
|
@ -1016,8 +1008,7 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
||||||
|
|
||||||
// Create a socket pair will be used to receive the child process' stderr.
|
// Create a socket pair will be used to receive the child process' stderr.
|
||||||
zx::socket stderr_producer_socket;
|
zx::socket stderr_producer_socket;
|
||||||
status =
|
status = zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
|
||||||
zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
|
|
||||||
GTEST_DEATH_TEST_CHECK_(status >= 0);
|
GTEST_DEATH_TEST_CHECK_(status >= 0);
|
||||||
int stderr_producer_fd = -1;
|
int stderr_producer_fd = -1;
|
||||||
status =
|
status =
|
||||||
|
@ -1034,35 +1025,32 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
|
||||||
|
|
||||||
// Create a child job.
|
// Create a child job.
|
||||||
zx_handle_t child_job = ZX_HANDLE_INVALID;
|
zx_handle_t child_job = ZX_HANDLE_INVALID;
|
||||||
status = zx_job_create(zx_job_default(), 0, & child_job);
|
status = zx_job_create(zx_job_default(), 0, &child_job);
|
||||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||||
zx_policy_basic_t policy;
|
zx_policy_basic_t policy;
|
||||||
policy.condition = ZX_POL_NEW_ANY;
|
policy.condition = ZX_POL_NEW_ANY;
|
||||||
policy.policy = ZX_POL_ACTION_ALLOW;
|
policy.policy = ZX_POL_ACTION_ALLOW;
|
||||||
status = zx_job_set_policy(
|
status = zx_job_set_policy(child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC,
|
||||||
child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1);
|
&policy, 1);
|
||||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||||
|
|
||||||
// Create an exception channel attached to the |child_job|, to allow
|
// Create an exception channel attached to the |child_job|, to allow
|
||||||
// us to suppress the system default exception handler from firing.
|
// us to suppress the system default exception handler from firing.
|
||||||
status =
|
status = zx_task_create_exception_channel(
|
||||||
zx_task_create_exception_channel(
|
|
||||||
child_job, 0, exception_channel_.reset_and_get_address());
|
child_job, 0, exception_channel_.reset_and_get_address());
|
||||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||||
|
|
||||||
// Spawn the child process.
|
// Spawn the child process.
|
||||||
status = fdio_spawn_etc(
|
status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0],
|
||||||
child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr,
|
args.Argv(), nullptr, 2, spawn_actions,
|
||||||
2, spawn_actions, child_process_.reset_and_get_address(), nullptr);
|
child_process_.reset_and_get_address(), nullptr);
|
||||||
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
|
||||||
|
|
||||||
set_spawned(true);
|
set_spawned(true);
|
||||||
return OVERSEE_TEST;
|
return OVERSEE_TEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FuchsiaDeathTest::GetErrorLogs() {
|
std::string FuchsiaDeathTest::GetErrorLogs() { return captured_stderr_; }
|
||||||
return captured_stderr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // We are neither on Windows, nor on Fuchsia.
|
#else // We are neither on Windows, nor on Fuchsia.
|
||||||
|
|
||||||
|
@ -1093,8 +1081,7 @@ ForkingDeathTest::ForkingDeathTest(const char* a_statement,
|
||||||
// status, or 0 if no child process exists. As a side effect, sets the
|
// status, or 0 if no child process exists. As a side effect, sets the
|
||||||
// outcome data member.
|
// outcome data member.
|
||||||
int ForkingDeathTest::Wait() {
|
int ForkingDeathTest::Wait() {
|
||||||
if (!spawned())
|
if (!spawned()) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
ReadAndInterpretStatusByte();
|
ReadAndInterpretStatusByte();
|
||||||
|
|
||||||
|
@ -1173,11 +1160,11 @@ class ExecDeathTest : public ForkingDeathTest {
|
||||||
private:
|
private:
|
||||||
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
|
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
|
||||||
::std::vector<std::string> args = GetInjectableArgvs();
|
::std::vector<std::string> args = GetInjectableArgvs();
|
||||||
# if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
#if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
||||||
::std::vector<std::string> extra_args =
|
::std::vector<std::string> extra_args =
|
||||||
GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
|
GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
|
||||||
args.insert(args.end(), extra_args.begin(), extra_args.end());
|
args.insert(args.end(), extra_args.begin(), extra_args.end());
|
||||||
# endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
#endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
// The name of the file in which the death test is located.
|
// The name of the file in which the death test is located.
|
||||||
|
@ -1204,14 +1191,11 @@ class Arguments {
|
||||||
template <typename Str>
|
template <typename Str>
|
||||||
void AddArguments(const ::std::vector<Str>& arguments) {
|
void AddArguments(const ::std::vector<Str>& arguments) {
|
||||||
for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
|
for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
|
||||||
i != arguments.end();
|
i != arguments.end(); ++i) {
|
||||||
++i) {
|
|
||||||
args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
|
args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char* const* Argv() {
|
char* const* Argv() { return &args_[0]; }
|
||||||
return &args_[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<char*> args_;
|
std::vector<char*> args_;
|
||||||
|
@ -1224,9 +1208,9 @@ struct ExecDeathTestArgs {
|
||||||
int close_fd; // File descriptor to close; the read end of a pipe
|
int close_fd; // File descriptor to close; the read end of a pipe
|
||||||
};
|
};
|
||||||
|
|
||||||
# if GTEST_OS_QNX
|
#if GTEST_OS_QNX
|
||||||
extern "C" char** environ;
|
extern "C" char** environ;
|
||||||
# else // GTEST_OS_QNX
|
#else // GTEST_OS_QNX
|
||||||
// The main function for a threadsafe-style death test child process.
|
// The main function for a threadsafe-style death test child process.
|
||||||
// This function is called in a clone()-ed process and thus must avoid
|
// This function is called in a clone()-ed process and thus must avoid
|
||||||
// any potentially unsafe operations like malloc or libc functions.
|
// any potentially unsafe operations like malloc or libc functions.
|
||||||
|
@ -1241,8 +1225,8 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||||
UnitTest::GetInstance()->original_working_dir();
|
UnitTest::GetInstance()->original_working_dir();
|
||||||
// We can safely call chdir() as it's a direct system call.
|
// We can safely call chdir() as it's a direct system call.
|
||||||
if (chdir(original_dir) != 0) {
|
if (chdir(original_dir) != 0) {
|
||||||
DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
|
DeathTestAbort(std::string("chdir(\"") + original_dir +
|
||||||
GetLastErrnoDescription());
|
"\") failed: " + GetLastErrnoDescription());
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1253,13 +1237,12 @@ static int ExecDeathTestChildMain(void* child_arg) {
|
||||||
// one path separator.
|
// one path separator.
|
||||||
execv(args->argv[0], args->argv);
|
execv(args->argv[0], args->argv);
|
||||||
DeathTestAbort(std::string("execv(") + args->argv[0] + ", ...) in " +
|
DeathTestAbort(std::string("execv(") + args->argv[0] + ", ...) in " +
|
||||||
original_dir + " failed: " +
|
original_dir + " failed: " + GetLastErrnoDescription());
|
||||||
GetLastErrnoDescription());
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
# endif // GTEST_OS_QNX
|
#endif // GTEST_OS_QNX
|
||||||
|
|
||||||
# if GTEST_HAS_CLONE
|
#if GTEST_HAS_CLONE
|
||||||
// Two utility routines that together determine the direction the stack
|
// Two utility routines that together determine the direction the stack
|
||||||
// grows.
|
// grows.
|
||||||
// This could be accomplished more elegantly by a single recursive
|
// This could be accomplished more elegantly by a single recursive
|
||||||
|
@ -1293,7 +1276,7 @@ static bool StackGrowsDown() {
|
||||||
StackLowerThanAddress(&dummy, &result);
|
StackLowerThanAddress(&dummy, &result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
# endif // GTEST_HAS_CLONE
|
#endif // GTEST_HAS_CLONE
|
||||||
|
|
||||||
// Spawns a child process with the same executable as the current process in
|
// Spawns a child process with the same executable as the current process in
|
||||||
// a thread-safe manner and instructs it to run the death test. The
|
// a thread-safe manner and instructs it to run the death test. The
|
||||||
|
@ -1303,10 +1286,10 @@ static bool StackGrowsDown() {
|
||||||
// spawn(2) there instead. The function dies with an error message if
|
// spawn(2) there instead. The function dies with an error message if
|
||||||
// anything goes wrong.
|
// anything goes wrong.
|
||||||
static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
ExecDeathTestArgs args = { argv, close_fd };
|
ExecDeathTestArgs args = {argv, close_fd};
|
||||||
pid_t child_pid = -1;
|
pid_t child_pid = -1;
|
||||||
|
|
||||||
# if GTEST_OS_QNX
|
#if GTEST_OS_QNX
|
||||||
// Obtains the current directory and sets it to be closed in the child
|
// Obtains the current directory and sets it to be closed in the child
|
||||||
// process.
|
// process.
|
||||||
const int cwd_fd = open(".", O_RDONLY);
|
const int cwd_fd = open(".", O_RDONLY);
|
||||||
|
@ -1319,16 +1302,16 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
UnitTest::GetInstance()->original_working_dir();
|
UnitTest::GetInstance()->original_working_dir();
|
||||||
// We can safely call chdir() as it's a direct system call.
|
// We can safely call chdir() as it's a direct system call.
|
||||||
if (chdir(original_dir) != 0) {
|
if (chdir(original_dir) != 0) {
|
||||||
DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
|
DeathTestAbort(std::string("chdir(\"") + original_dir +
|
||||||
GetLastErrnoDescription());
|
"\") failed: " + GetLastErrnoDescription());
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd_flags;
|
int fd_flags;
|
||||||
// Set close_fd to be closed after spawn.
|
// Set close_fd to be closed after spawn.
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||||
fd_flags | FD_CLOEXEC));
|
fcntl(close_fd, F_SETFD, fd_flags | FD_CLOEXEC));
|
||||||
struct inheritance inherit = {0};
|
struct inheritance inherit = {0};
|
||||||
// spawn is a system call.
|
// spawn is a system call.
|
||||||
child_pid = spawn(args.argv[0], 0, nullptr, &inherit, args.argv, environ);
|
child_pid = spawn(args.argv[0], 0, nullptr, &inherit, args.argv, environ);
|
||||||
|
@ -1336,8 +1319,8 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
|
||||||
|
|
||||||
# else // GTEST_OS_QNX
|
#else // GTEST_OS_QNX
|
||||||
# if GTEST_OS_LINUX
|
#if GTEST_OS_LINUX
|
||||||
// When a SIGPROF signal is received while fork() or clone() are executing,
|
// When a SIGPROF signal is received while fork() or clone() are executing,
|
||||||
// the process may hang. To avoid this, we ignore SIGPROF here and re-enable
|
// the process may hang. To avoid this, we ignore SIGPROF here and re-enable
|
||||||
// it after the call to fork()/clone() is complete.
|
// it after the call to fork()/clone() is complete.
|
||||||
|
@ -1346,12 +1329,12 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
|
memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
|
||||||
sigemptyset(&ignore_sigprof_action.sa_mask);
|
sigemptyset(&ignore_sigprof_action.sa_mask);
|
||||||
ignore_sigprof_action.sa_handler = SIG_IGN;
|
ignore_sigprof_action.sa_handler = SIG_IGN;
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||||
SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
|
sigaction(SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
|
||||||
# endif // GTEST_OS_LINUX
|
#endif // GTEST_OS_LINUX
|
||||||
|
|
||||||
# if GTEST_HAS_CLONE
|
#if GTEST_HAS_CLONE
|
||||||
const bool use_fork = GTEST_FLAG(death_test_use_fork);
|
const bool use_fork = GTEST_FLAG_GET(death_test_use_fork);
|
||||||
|
|
||||||
if (!use_fork) {
|
if (!use_fork) {
|
||||||
static const bool stack_grows_down = StackGrowsDown();
|
static const bool stack_grows_down = StackGrowsDown();
|
||||||
|
@ -1379,19 +1362,19 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
|
||||||
|
|
||||||
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
|
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
|
||||||
}
|
}
|
||||||
# else
|
#else
|
||||||
const bool use_fork = true;
|
const bool use_fork = true;
|
||||||
# endif // GTEST_HAS_CLONE
|
#endif // GTEST_HAS_CLONE
|
||||||
|
|
||||||
if (use_fork && (child_pid = fork()) == 0) {
|
if (use_fork && (child_pid = fork()) == 0) {
|
||||||
ExecDeathTestChildMain(&args);
|
ExecDeathTestChildMain(&args);
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
# endif // GTEST_OS_QNX
|
#endif // GTEST_OS_QNX
|
||||||
# if GTEST_OS_LINUX
|
#if GTEST_OS_LINUX
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(
|
||||||
sigaction(SIGPROF, &saved_sigprof_action, nullptr));
|
sigaction(SIGPROF, &saved_sigprof_action, nullptr));
|
||||||
# endif // GTEST_OS_LINUX
|
#endif // GTEST_OS_LINUX
|
||||||
|
|
||||||
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
||||||
return child_pid;
|
return child_pid;
|
||||||
|
@ -1420,13 +1403,13 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||||
GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
|
GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
|
||||||
|
|
||||||
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||||
kFilterFlag + "=" + info->test_suite_name() +
|
"filter=" + info->test_suite_name() + "." +
|
||||||
"." + info->name();
|
info->name();
|
||||||
const std::string internal_flag =
|
const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
|
||||||
std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
|
"internal_run_death_test=" + file_ + "|" +
|
||||||
+ file_ + "|" + StreamableToString(line_) + "|"
|
StreamableToString(line_) + "|" +
|
||||||
+ StreamableToString(death_test_index) + "|"
|
StreamableToString(death_test_index) + "|" +
|
||||||
+ StreamableToString(pipe_fd[1]);
|
StreamableToString(pipe_fd[1]);
|
||||||
Arguments args;
|
Arguments args;
|
||||||
args.AddArguments(GetArgvsForDeathTestChildProcess());
|
args.AddArguments(GetArgvsForDeathTestChildProcess());
|
||||||
args.AddArgument(filter_flag.c_str());
|
args.AddArgument(filter_flag.c_str());
|
||||||
|
@ -1447,7 +1430,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
|
||||||
return OVERSEE_TEST;
|
return OVERSEE_TEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
# endif // !GTEST_OS_WINDOWS
|
#endif // !GTEST_OS_WINDOWS
|
||||||
|
|
||||||
// Creates a concrete DeathTest-derived class that depends on the
|
// Creates a concrete DeathTest-derived class that depends on the
|
||||||
// --gtest_death_test_style flag, and sets the pointer pointed to
|
// --gtest_death_test_style flag, and sets the pointer pointed to
|
||||||
|
@ -1461,15 +1444,15 @@ bool DefaultDeathTestFactory::Create(const char* statement,
|
||||||
UnitTestImpl* const impl = GetUnitTestImpl();
|
UnitTestImpl* const impl = GetUnitTestImpl();
|
||||||
const InternalRunDeathTestFlag* const flag =
|
const InternalRunDeathTestFlag* const flag =
|
||||||
impl->internal_run_death_test_flag();
|
impl->internal_run_death_test_flag();
|
||||||
const int death_test_index = impl->current_test_info()
|
const int death_test_index =
|
||||||
->increment_death_test_count();
|
impl->current_test_info()->increment_death_test_count();
|
||||||
|
|
||||||
if (flag != nullptr) {
|
if (flag != nullptr) {
|
||||||
if (death_test_index > flag->index()) {
|
if (death_test_index > flag->index()) {
|
||||||
DeathTest::set_last_death_test_message(
|
DeathTest::set_last_death_test_message(
|
||||||
"Death test count (" + StreamableToString(death_test_index)
|
"Death test count (" + StreamableToString(death_test_index) +
|
||||||
+ ") somehow exceeded expected maximum ("
|
") somehow exceeded expected maximum (" +
|
||||||
+ StreamableToString(flag->index()) + ")");
|
StreamableToString(flag->index()) + ")");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1480,41 +1463,41 @@ bool DefaultDeathTestFactory::Create(const char* statement,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
|
|
||||||
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
if (GTEST_FLAG_GET(death_test_style) == "threadsafe" ||
|
||||||
GTEST_FLAG(death_test_style) == "fast") {
|
GTEST_FLAG_GET(death_test_style) == "fast") {
|
||||||
*test = new WindowsDeathTest(statement, std::move(matcher), file, line);
|
*test = new WindowsDeathTest(statement, std::move(matcher), file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
# elif GTEST_OS_FUCHSIA
|
#elif GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
|
if (GTEST_FLAG_GET(death_test_style) == "threadsafe" ||
|
||||||
GTEST_FLAG(death_test_style) == "fast") {
|
GTEST_FLAG_GET(death_test_style) == "fast") {
|
||||||
*test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
|
*test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
# else
|
#else
|
||||||
|
|
||||||
if (GTEST_FLAG(death_test_style) == "threadsafe") {
|
if (GTEST_FLAG_GET(death_test_style) == "threadsafe") {
|
||||||
*test = new ExecDeathTest(statement, std::move(matcher), file, line);
|
*test = new ExecDeathTest(statement, std::move(matcher), file, line);
|
||||||
} else if (GTEST_FLAG(death_test_style) == "fast") {
|
} else if (GTEST_FLAG_GET(death_test_style) == "fast") {
|
||||||
*test = new NoExecDeathTest(statement, std::move(matcher));
|
*test = new NoExecDeathTest(statement, std::move(matcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
# endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
else { // NOLINT - this is more readable than unbalanced brackets inside #if.
|
else { // NOLINT - this is more readable than unbalanced brackets inside #if.
|
||||||
DeathTest::set_last_death_test_message(
|
DeathTest::set_last_death_test_message("Unknown death test style \"" +
|
||||||
"Unknown death test style \"" + GTEST_FLAG(death_test_style)
|
GTEST_FLAG_GET(death_test_style) +
|
||||||
+ "\" encountered");
|
"\" encountered");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
# if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
// Recreates the pipe and event handles from the provided parameters,
|
// Recreates the pipe and event handles from the provided parameters,
|
||||||
// signals the event, and returns a file descriptor wrapped around the pipe
|
// signals the event, and returns a file descriptor wrapped around the pipe
|
||||||
// handle. This function is called in the child process only.
|
// handle. This function is called in the child process only.
|
||||||
|
@ -1531,8 +1514,7 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
||||||
|
|
||||||
GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
|
GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
|
||||||
|
|
||||||
const HANDLE write_handle =
|
const HANDLE write_handle = reinterpret_cast<HANDLE>(write_handle_as_size_t);
|
||||||
reinterpret_cast<HANDLE>(write_handle_as_size_t);
|
|
||||||
HANDLE dup_write_handle;
|
HANDLE dup_write_handle;
|
||||||
|
|
||||||
// The newly initialized handle is accessible only in the parent
|
// The newly initialized handle is accessible only in the parent
|
||||||
|
@ -1554,9 +1536,7 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
||||||
HANDLE dup_event_handle;
|
HANDLE dup_event_handle;
|
||||||
|
|
||||||
if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
|
if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
|
||||||
::GetCurrentProcess(), &dup_event_handle,
|
::GetCurrentProcess(), &dup_event_handle, 0x0, FALSE,
|
||||||
0x0,
|
|
||||||
FALSE,
|
|
||||||
DUPLICATE_SAME_ACCESS)) {
|
DUPLICATE_SAME_ACCESS)) {
|
||||||
DeathTestAbort("Unable to duplicate the event handle " +
|
DeathTestAbort("Unable to duplicate the event handle " +
|
||||||
StreamableToString(event_handle_as_size_t) +
|
StreamableToString(event_handle_as_size_t) +
|
||||||
|
@ -1578,61 +1558,57 @@ static int GetStatusFileDescriptor(unsigned int parent_process_id,
|
||||||
|
|
||||||
return write_fd;
|
return write_fd;
|
||||||
}
|
}
|
||||||
# endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
// Returns a newly created InternalRunDeathTestFlag object with fields
|
// Returns a newly created InternalRunDeathTestFlag object with fields
|
||||||
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
||||||
// the flag is specified; otherwise returns NULL.
|
// the flag is specified; otherwise returns NULL.
|
||||||
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
|
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
|
||||||
if (GTEST_FLAG(internal_run_death_test) == "") return nullptr;
|
if (GTEST_FLAG_GET(internal_run_death_test) == "") return nullptr;
|
||||||
|
|
||||||
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
|
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
|
||||||
// can use it here.
|
// can use it here.
|
||||||
int line = -1;
|
int line = -1;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
::std::vector< ::std::string> fields;
|
::std::vector< ::std::string> fields;
|
||||||
SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
|
SplitString(GTEST_FLAG_GET(internal_run_death_test), '|', &fields);
|
||||||
int write_fd = -1;
|
int write_fd = -1;
|
||||||
|
|
||||||
# if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
|
|
||||||
unsigned int parent_process_id = 0;
|
unsigned int parent_process_id = 0;
|
||||||
size_t write_handle_as_size_t = 0;
|
size_t write_handle_as_size_t = 0;
|
||||||
size_t event_handle_as_size_t = 0;
|
size_t event_handle_as_size_t = 0;
|
||||||
|
|
||||||
if (fields.size() != 6
|
if (fields.size() != 6 || !ParseNaturalNumber(fields[1], &line) ||
|
||||||
|| !ParseNaturalNumber(fields[1], &line)
|
!ParseNaturalNumber(fields[2], &index) ||
|
||||||
|| !ParseNaturalNumber(fields[2], &index)
|
!ParseNaturalNumber(fields[3], &parent_process_id) ||
|
||||||
|| !ParseNaturalNumber(fields[3], &parent_process_id)
|
!ParseNaturalNumber(fields[4], &write_handle_as_size_t) ||
|
||||||
|| !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
|
!ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
|
||||||
|| !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
|
|
||||||
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
|
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
|
||||||
GTEST_FLAG(internal_run_death_test));
|
GTEST_FLAG_GET(internal_run_death_test));
|
||||||
}
|
}
|
||||||
write_fd = GetStatusFileDescriptor(parent_process_id,
|
write_fd = GetStatusFileDescriptor(parent_process_id, write_handle_as_size_t,
|
||||||
write_handle_as_size_t,
|
|
||||||
event_handle_as_size_t);
|
event_handle_as_size_t);
|
||||||
|
|
||||||
# elif GTEST_OS_FUCHSIA
|
#elif GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
if (fields.size() != 3
|
if (fields.size() != 3 || !ParseNaturalNumber(fields[1], &line) ||
|
||||||
|| !ParseNaturalNumber(fields[1], &line)
|
!ParseNaturalNumber(fields[2], &index)) {
|
||||||
|| !ParseNaturalNumber(fields[2], &index)) {
|
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
|
||||||
DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
|
GTEST_FLAG_GET(internal_run_death_test));
|
||||||
+ GTEST_FLAG(internal_run_death_test));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# else
|
#else
|
||||||
|
|
||||||
if (fields.size() != 4
|
if (fields.size() != 4 || !ParseNaturalNumber(fields[1], &line) ||
|
||||||
|| !ParseNaturalNumber(fields[1], &line)
|
!ParseNaturalNumber(fields[2], &index) ||
|
||||||
|| !ParseNaturalNumber(fields[2], &index)
|
!ParseNaturalNumber(fields[3], &write_fd)) {
|
||||||
|| !ParseNaturalNumber(fields[3], &write_fd)) {
|
DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
|
||||||
DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
|
GTEST_FLAG_GET(internal_run_death_test));
|
||||||
+ GTEST_FLAG(internal_run_death_test));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
|
return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,29 +30,31 @@
|
||||||
#include "gtest/internal/gtest-filepath.h"
|
#include "gtest/internal/gtest-filepath.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "gtest/internal/gtest-port.h"
|
|
||||||
#include "gtest/gtest-message.h"
|
#include "gtest/gtest-message.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
# include <windows.h>
|
#include <windows.h>
|
||||||
#elif GTEST_OS_WINDOWS
|
#elif GTEST_OS_WINDOWS
|
||||||
# include <direct.h>
|
#include <direct.h>
|
||||||
# include <io.h>
|
#include <io.h>
|
||||||
#else
|
#else
|
||||||
# include <limits.h>
|
#include <limits.h>
|
||||||
# include <climits> // Some Linux distributions define PATH_MAX here.
|
|
||||||
|
#include <climits> // Some Linux distributions define PATH_MAX here.
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
#include "gtest/internal/gtest-string.h"
|
#include "gtest/internal/gtest-string.h"
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
# define GTEST_PATH_MAX_ _MAX_PATH
|
#define GTEST_PATH_MAX_ _MAX_PATH
|
||||||
#elif defined(PATH_MAX)
|
#elif defined(PATH_MAX)
|
||||||
# define GTEST_PATH_MAX_ PATH_MAX
|
#define GTEST_PATH_MAX_ PATH_MAX
|
||||||
#elif defined(_XOPEN_PATH_MAX)
|
#elif defined(_XOPEN_PATH_MAX)
|
||||||
# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
|
#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
|
||||||
#else
|
#else
|
||||||
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
|
#define GTEST_PATH_MAX_ _POSIX_PATH_MAX
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
@ -66,16 +68,16 @@ namespace internal {
|
||||||
const char kPathSeparator = '\\';
|
const char kPathSeparator = '\\';
|
||||||
const char kAlternatePathSeparator = '/';
|
const char kAlternatePathSeparator = '/';
|
||||||
const char kAlternatePathSeparatorString[] = "/";
|
const char kAlternatePathSeparatorString[] = "/";
|
||||||
# if GTEST_OS_WINDOWS_MOBILE
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
// Windows CE doesn't have a current directory. You should not use
|
// Windows CE doesn't have a current directory. You should not use
|
||||||
// the current directory in tests on Windows CE, but this at least
|
// the current directory in tests on Windows CE, but this at least
|
||||||
// provides a reasonable fallback.
|
// provides a reasonable fallback.
|
||||||
const char kCurrentDirectoryString[] = "\\";
|
const char kCurrentDirectoryString[] = "\\";
|
||||||
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
|
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
|
||||||
const DWORD kInvalidFileAttributes = 0xffffffff;
|
const DWORD kInvalidFileAttributes = 0xffffffff;
|
||||||
# else
|
#else
|
||||||
const char kCurrentDirectoryString[] = ".\\";
|
const char kCurrentDirectoryString[] = ".\\";
|
||||||
# endif // GTEST_OS_WINDOWS_MOBILE
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
#else
|
#else
|
||||||
const char kPathSeparator = '/';
|
const char kPathSeparator = '/';
|
||||||
const char kCurrentDirectoryString[] = "./";
|
const char kCurrentDirectoryString[] = "./";
|
||||||
|
@ -99,17 +101,17 @@ FilePath FilePath::GetCurrentDir() {
|
||||||
// something reasonable.
|
// something reasonable.
|
||||||
return FilePath(kCurrentDirectoryString);
|
return FilePath(kCurrentDirectoryString);
|
||||||
#elif GTEST_OS_WINDOWS
|
#elif GTEST_OS_WINDOWS
|
||||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
char cwd[GTEST_PATH_MAX_ + 1] = {'\0'};
|
||||||
return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
|
return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
|
||||||
#else
|
#else
|
||||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
char cwd[GTEST_PATH_MAX_ + 1] = {'\0'};
|
||||||
char* result = getcwd(cwd, sizeof(cwd));
|
char* result = getcwd(cwd, sizeof(cwd));
|
||||||
# if GTEST_OS_NACL
|
#if GTEST_OS_NACL
|
||||||
// getcwd will likely fail in NaCl due to the sandbox, so return something
|
// getcwd will likely fail in NaCl due to the sandbox, so return something
|
||||||
// reasonable. The user may have provided a shim implementation for getcwd,
|
// reasonable. The user may have provided a shim implementation for getcwd,
|
||||||
// however, so fallback only when failure is detected.
|
// however, so fallback only when failure is detected.
|
||||||
return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
|
return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
|
||||||
# endif // GTEST_OS_NACL
|
#endif // GTEST_OS_NACL
|
||||||
return FilePath(result == nullptr ? "" : cwd);
|
return FilePath(result == nullptr ? "" : cwd);
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
}
|
}
|
||||||
|
@ -121,8 +123,8 @@ FilePath FilePath::GetCurrentDir() {
|
||||||
FilePath FilePath::RemoveExtension(const char* extension) const {
|
FilePath FilePath::RemoveExtension(const char* extension) const {
|
||||||
const std::string dot_extension = std::string(".") + extension;
|
const std::string dot_extension = std::string(".") + extension;
|
||||||
if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
|
if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
|
||||||
return FilePath(pathname_.substr(
|
return FilePath(
|
||||||
0, pathname_.length() - dot_extension.length()));
|
pathname_.substr(0, pathname_.length() - dot_extension.length()));
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -178,15 +180,14 @@ FilePath FilePath::RemoveFileName() const {
|
||||||
// than zero (e.g., 12), returns "dir/test_12.xml".
|
// than zero (e.g., 12), returns "dir/test_12.xml".
|
||||||
// On Windows platform, uses \ as the separator rather than /.
|
// On Windows platform, uses \ as the separator rather than /.
|
||||||
FilePath FilePath::MakeFileName(const FilePath& directory,
|
FilePath FilePath::MakeFileName(const FilePath& directory,
|
||||||
const FilePath& base_name,
|
const FilePath& base_name, int number,
|
||||||
int number,
|
|
||||||
const char* extension) {
|
const char* extension) {
|
||||||
std::string file;
|
std::string file;
|
||||||
if (number == 0) {
|
if (number == 0) {
|
||||||
file = base_name.string() + "." + extension;
|
file = base_name.string() + "." + extension;
|
||||||
} else {
|
} else {
|
||||||
file = base_name.string() + "_" + StreamableToString(number)
|
file =
|
||||||
+ "." + extension;
|
base_name.string() + "_" + StreamableToString(number) + "." + extension;
|
||||||
}
|
}
|
||||||
return ConcatPaths(directory, FilePath(file));
|
return ConcatPaths(directory, FilePath(file));
|
||||||
}
|
}
|
||||||
|
@ -195,8 +196,7 @@ FilePath FilePath::MakeFileName(const FilePath& directory,
|
||||||
// On Windows, uses \ as the separator rather than /.
|
// On Windows, uses \ as the separator rather than /.
|
||||||
FilePath FilePath::ConcatPaths(const FilePath& directory,
|
FilePath FilePath::ConcatPaths(const FilePath& directory,
|
||||||
const FilePath& relative_path) {
|
const FilePath& relative_path) {
|
||||||
if (directory.IsEmpty())
|
if (directory.IsEmpty()) return relative_path;
|
||||||
return relative_path;
|
|
||||||
const FilePath dir(directory.RemoveTrailingPathSeparator());
|
const FilePath dir(directory.RemoveTrailingPathSeparator());
|
||||||
return FilePath(dir.string() + kPathSeparator + relative_path.string());
|
return FilePath(dir.string() + kPathSeparator + relative_path.string());
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ bool FilePath::FileOrDirectoryExists() const {
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
|
LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
|
||||||
const DWORD attributes = GetFileAttributes(unicode);
|
const DWORD attributes = GetFileAttributes(unicode);
|
||||||
delete [] unicode;
|
delete[] unicode;
|
||||||
return attributes != kInvalidFileAttributes;
|
return attributes != kInvalidFileAttributes;
|
||||||
#else
|
#else
|
||||||
posix::StatStruct file_stat{};
|
posix::StatStruct file_stat{};
|
||||||
|
@ -222,8 +222,8 @@ bool FilePath::DirectoryExists() const {
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
// Don't strip off trailing separator if path is a root directory on
|
// Don't strip off trailing separator if path is a root directory on
|
||||||
// Windows (like "C:\\").
|
// Windows (like "C:\\").
|
||||||
const FilePath& path(IsRootDirectory() ? *this :
|
const FilePath& path(IsRootDirectory() ? *this
|
||||||
RemoveTrailingPathSeparator());
|
: RemoveTrailingPathSeparator());
|
||||||
#else
|
#else
|
||||||
const FilePath& path(*this);
|
const FilePath& path(*this);
|
||||||
#endif
|
#endif
|
||||||
|
@ -231,15 +231,15 @@ bool FilePath::DirectoryExists() const {
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
|
LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
|
||||||
const DWORD attributes = GetFileAttributes(unicode);
|
const DWORD attributes = GetFileAttributes(unicode);
|
||||||
delete [] unicode;
|
delete[] unicode;
|
||||||
if ((attributes != kInvalidFileAttributes) &&
|
if ((attributes != kInvalidFileAttributes) &&
|
||||||
(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
posix::StatStruct file_stat{};
|
posix::StatStruct file_stat{};
|
||||||
result = posix::Stat(path.c_str(), &file_stat) == 0 &&
|
result =
|
||||||
posix::IsDir(file_stat);
|
posix::Stat(path.c_str(), &file_stat) == 0 && posix::IsDir(file_stat);
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -262,8 +262,7 @@ bool FilePath::IsAbsolutePath() const {
|
||||||
return pathname_.length() >= 3 &&
|
return pathname_.length() >= 3 &&
|
||||||
((name[0] >= 'a' && name[0] <= 'z') ||
|
((name[0] >= 'a' && name[0] <= 'z') ||
|
||||||
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
||||||
name[1] == ':' &&
|
name[1] == ':' && IsPathSeparator(name[2]);
|
||||||
IsPathSeparator(name[2]);
|
|
||||||
#else
|
#else
|
||||||
return IsPathSeparator(name[0]);
|
return IsPathSeparator(name[0]);
|
||||||
#endif
|
#endif
|
||||||
|
@ -321,7 +320,7 @@ bool FilePath::CreateFolder() const {
|
||||||
FilePath removed_sep(this->RemoveTrailingPathSeparator());
|
FilePath removed_sep(this->RemoveTrailingPathSeparator());
|
||||||
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
|
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
|
||||||
int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
|
int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
|
||||||
delete [] unicode;
|
delete[] unicode;
|
||||||
#elif GTEST_OS_WINDOWS
|
#elif GTEST_OS_WINDOWS
|
||||||
int result = _mkdir(pathname_.c_str());
|
int result = _mkdir(pathname_.c_str());
|
||||||
#elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA
|
#elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA
|
||||||
|
@ -341,8 +340,7 @@ bool FilePath::CreateFolder() const {
|
||||||
// name, otherwise return the name string unmodified.
|
// name, otherwise return the name string unmodified.
|
||||||
// On Windows platform, uses \ as the separator, other platforms use /.
|
// On Windows platform, uses \ as the separator, other platforms use /.
|
||||||
FilePath FilePath::RemoveTrailingPathSeparator() const {
|
FilePath FilePath::RemoveTrailingPathSeparator() const {
|
||||||
return IsDirectory()
|
return IsDirectory() ? FilePath(pathname_.substr(0, pathname_.length() - 1))
|
||||||
? FilePath(pathname_.substr(0, pathname_.length() - 1))
|
|
||||||
: *this;
|
: *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#define GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
|
#define GOOGLETEST_SRC_GTEST_INTERNAL_INL_H_
|
||||||
|
|
||||||
#ifndef _WIN32_WCE
|
#ifndef _WIN32_WCE
|
||||||
# include <errno.h>
|
#include <errno.h>
|
||||||
#endif // !_WIN32_WCE
|
#endif // !_WIN32_WCE
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
|
#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
|
||||||
|
@ -50,22 +50,20 @@
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
#if GTEST_CAN_STREAM_RESULTS_
|
#if GTEST_CAN_STREAM_RESULTS_
|
||||||
# include <arpa/inet.h> // NOLINT
|
#include <arpa/inet.h> // NOLINT
|
||||||
# include <netdb.h> // NOLINT
|
#include <netdb.h> // NOLINT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
# include <windows.h> // NOLINT
|
#include <windows.h> // NOLINT
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "gtest/gtest-spi.h"
|
#include "gtest/gtest-spi.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
|
|
||||||
// Declares the flags.
|
// Declares the flags.
|
||||||
//
|
//
|
||||||
// We don't want the users to modify this flag in the code, but want
|
// We don't want the users to modify this flag in the code, but want
|
||||||
|
@ -73,32 +71,13 @@ namespace testing {
|
||||||
// declare it here as opposed to in gtest.h.
|
// declare it here as opposed to in gtest.h.
|
||||||
GTEST_DECLARE_bool_(death_test_use_fork);
|
GTEST_DECLARE_bool_(death_test_use_fork);
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// The value of GetTestTypeId() as seen from within the Google Test
|
// The value of GetTestTypeId() as seen from within the Google Test
|
||||||
// library. This is solely for testing GetTestTypeId().
|
// library. This is solely for testing GetTestTypeId().
|
||||||
GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
|
GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
|
||||||
|
|
||||||
// Names of the flags (needed for parsing Google Test flags).
|
|
||||||
const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
|
|
||||||
const char kBreakOnFailureFlag[] = "break_on_failure";
|
|
||||||
const char kCatchExceptionsFlag[] = "catch_exceptions";
|
|
||||||
const char kColorFlag[] = "color";
|
|
||||||
const char kFailFast[] = "fail_fast";
|
|
||||||
const char kFilterFlag[] = "filter";
|
|
||||||
const char kListTestsFlag[] = "list_tests";
|
|
||||||
const char kOutputFlag[] = "output";
|
|
||||||
const char kBriefFlag[] = "brief";
|
|
||||||
const char kPrintTimeFlag[] = "print_time";
|
|
||||||
const char kPrintUTF8Flag[] = "print_utf8";
|
|
||||||
const char kRandomSeedFlag[] = "random_seed";
|
|
||||||
const char kRepeatFlag[] = "repeat";
|
|
||||||
const char kShuffleFlag[] = "shuffle";
|
|
||||||
const char kStackTraceDepthFlag[] = "stack_trace_depth";
|
|
||||||
const char kStreamResultToFlag[] = "stream_result_to";
|
|
||||||
const char kThrowOnFailureFlag[] = "throw_on_failure";
|
|
||||||
const char kFlagfileFlag[] = "flagfile";
|
|
||||||
|
|
||||||
// A valid random seed must be in [1, kMaxRandomSeed].
|
// A valid random seed must be in [1, kMaxRandomSeed].
|
||||||
const int kMaxRandomSeed = 99999;
|
const int kMaxRandomSeed = 99999;
|
||||||
|
|
||||||
|
@ -125,21 +104,21 @@ GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
|
||||||
//
|
//
|
||||||
// On success, stores the value of the flag in *value, and returns
|
// On success, stores the value of the flag in *value, and returns
|
||||||
// true. On failure, returns false without changing *value.
|
// true. On failure, returns false without changing *value.
|
||||||
GTEST_API_ bool ParseInt32Flag(
|
GTEST_API_ bool ParseFlag(const char* str, const char* flag, int32_t* value);
|
||||||
const char* str, const char* flag, int32_t* value);
|
|
||||||
|
|
||||||
// Returns a random seed in range [1, kMaxRandomSeed] based on the
|
// Returns a random seed in range [1, kMaxRandomSeed] based on the
|
||||||
// given --gtest_random_seed flag value.
|
// given --gtest_random_seed flag value.
|
||||||
inline int GetRandomSeedFromFlag(int32_t random_seed_flag) {
|
inline int GetRandomSeedFromFlag(int32_t random_seed_flag) {
|
||||||
const unsigned int raw_seed = (random_seed_flag == 0) ?
|
const unsigned int raw_seed =
|
||||||
static_cast<unsigned int>(GetTimeInMillis()) :
|
(random_seed_flag == 0) ? static_cast<unsigned int>(GetTimeInMillis())
|
||||||
static_cast<unsigned int>(random_seed_flag);
|
: static_cast<unsigned int>(random_seed_flag);
|
||||||
|
|
||||||
// Normalizes the actual seed to range [1, kMaxRandomSeed] such that
|
// Normalizes the actual seed to range [1, kMaxRandomSeed] such that
|
||||||
// it's easy to type.
|
// it's easy to type.
|
||||||
const int normalized_seed =
|
const int normalized_seed =
|
||||||
static_cast<int>((raw_seed - 1U) %
|
static_cast<int>((raw_seed - 1U) %
|
||||||
static_cast<unsigned int>(kMaxRandomSeed)) + 1;
|
static_cast<unsigned int>(kMaxRandomSeed)) +
|
||||||
|
1;
|
||||||
return normalized_seed;
|
return normalized_seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,50 +139,54 @@ class GTestFlagSaver {
|
||||||
public:
|
public:
|
||||||
// The c'tor.
|
// The c'tor.
|
||||||
GTestFlagSaver() {
|
GTestFlagSaver() {
|
||||||
also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
|
also_run_disabled_tests_ = GTEST_FLAG_GET(also_run_disabled_tests);
|
||||||
break_on_failure_ = GTEST_FLAG(break_on_failure);
|
break_on_failure_ = GTEST_FLAG_GET(break_on_failure);
|
||||||
catch_exceptions_ = GTEST_FLAG(catch_exceptions);
|
catch_exceptions_ = GTEST_FLAG_GET(catch_exceptions);
|
||||||
color_ = GTEST_FLAG(color);
|
color_ = GTEST_FLAG_GET(color);
|
||||||
death_test_style_ = GTEST_FLAG(death_test_style);
|
death_test_style_ = GTEST_FLAG_GET(death_test_style);
|
||||||
death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
|
death_test_use_fork_ = GTEST_FLAG_GET(death_test_use_fork);
|
||||||
fail_fast_ = GTEST_FLAG(fail_fast);
|
fail_fast_ = GTEST_FLAG_GET(fail_fast);
|
||||||
filter_ = GTEST_FLAG(filter);
|
filter_ = GTEST_FLAG_GET(filter);
|
||||||
internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
|
internal_run_death_test_ = GTEST_FLAG_GET(internal_run_death_test);
|
||||||
list_tests_ = GTEST_FLAG(list_tests);
|
list_tests_ = GTEST_FLAG_GET(list_tests);
|
||||||
output_ = GTEST_FLAG(output);
|
output_ = GTEST_FLAG_GET(output);
|
||||||
brief_ = GTEST_FLAG(brief);
|
brief_ = GTEST_FLAG_GET(brief);
|
||||||
print_time_ = GTEST_FLAG(print_time);
|
print_time_ = GTEST_FLAG_GET(print_time);
|
||||||
print_utf8_ = GTEST_FLAG(print_utf8);
|
print_utf8_ = GTEST_FLAG_GET(print_utf8);
|
||||||
random_seed_ = GTEST_FLAG(random_seed);
|
random_seed_ = GTEST_FLAG_GET(random_seed);
|
||||||
repeat_ = GTEST_FLAG(repeat);
|
repeat_ = GTEST_FLAG_GET(repeat);
|
||||||
shuffle_ = GTEST_FLAG(shuffle);
|
recreate_environments_when_repeating_ =
|
||||||
stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
|
GTEST_FLAG_GET(recreate_environments_when_repeating);
|
||||||
stream_result_to_ = GTEST_FLAG(stream_result_to);
|
shuffle_ = GTEST_FLAG_GET(shuffle);
|
||||||
throw_on_failure_ = GTEST_FLAG(throw_on_failure);
|
stack_trace_depth_ = GTEST_FLAG_GET(stack_trace_depth);
|
||||||
|
stream_result_to_ = GTEST_FLAG_GET(stream_result_to);
|
||||||
|
throw_on_failure_ = GTEST_FLAG_GET(throw_on_failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS.
|
// The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS.
|
||||||
~GTestFlagSaver() {
|
~GTestFlagSaver() {
|
||||||
GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
|
GTEST_FLAG_SET(also_run_disabled_tests, also_run_disabled_tests_);
|
||||||
GTEST_FLAG(break_on_failure) = break_on_failure_;
|
GTEST_FLAG_SET(break_on_failure, break_on_failure_);
|
||||||
GTEST_FLAG(catch_exceptions) = catch_exceptions_;
|
GTEST_FLAG_SET(catch_exceptions, catch_exceptions_);
|
||||||
GTEST_FLAG(color) = color_;
|
GTEST_FLAG_SET(color, color_);
|
||||||
GTEST_FLAG(death_test_style) = death_test_style_;
|
GTEST_FLAG_SET(death_test_style, death_test_style_);
|
||||||
GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
|
GTEST_FLAG_SET(death_test_use_fork, death_test_use_fork_);
|
||||||
GTEST_FLAG(filter) = filter_;
|
GTEST_FLAG_SET(filter, filter_);
|
||||||
GTEST_FLAG(fail_fast) = fail_fast_;
|
GTEST_FLAG_SET(fail_fast, fail_fast_);
|
||||||
GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
|
GTEST_FLAG_SET(internal_run_death_test, internal_run_death_test_);
|
||||||
GTEST_FLAG(list_tests) = list_tests_;
|
GTEST_FLAG_SET(list_tests, list_tests_);
|
||||||
GTEST_FLAG(output) = output_;
|
GTEST_FLAG_SET(output, output_);
|
||||||
GTEST_FLAG(brief) = brief_;
|
GTEST_FLAG_SET(brief, brief_);
|
||||||
GTEST_FLAG(print_time) = print_time_;
|
GTEST_FLAG_SET(print_time, print_time_);
|
||||||
GTEST_FLAG(print_utf8) = print_utf8_;
|
GTEST_FLAG_SET(print_utf8, print_utf8_);
|
||||||
GTEST_FLAG(random_seed) = random_seed_;
|
GTEST_FLAG_SET(random_seed, random_seed_);
|
||||||
GTEST_FLAG(repeat) = repeat_;
|
GTEST_FLAG_SET(repeat, repeat_);
|
||||||
GTEST_FLAG(shuffle) = shuffle_;
|
GTEST_FLAG_SET(recreate_environments_when_repeating,
|
||||||
GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
|
recreate_environments_when_repeating_);
|
||||||
GTEST_FLAG(stream_result_to) = stream_result_to_;
|
GTEST_FLAG_SET(shuffle, shuffle_);
|
||||||
GTEST_FLAG(throw_on_failure) = throw_on_failure_;
|
GTEST_FLAG_SET(stack_trace_depth, stack_trace_depth_);
|
||||||
|
GTEST_FLAG_SET(stream_result_to, stream_result_to_);
|
||||||
|
GTEST_FLAG_SET(throw_on_failure, throw_on_failure_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -224,6 +207,7 @@ class GTestFlagSaver {
|
||||||
bool print_utf8_;
|
bool print_utf8_;
|
||||||
int32_t random_seed_;
|
int32_t random_seed_;
|
||||||
int32_t repeat_;
|
int32_t repeat_;
|
||||||
|
bool recreate_environments_when_repeating_;
|
||||||
bool shuffle_;
|
bool shuffle_;
|
||||||
int32_t stack_trace_depth_;
|
int32_t stack_trace_depth_;
|
||||||
std::string stream_result_to_;
|
std::string stream_result_to_;
|
||||||
|
@ -278,8 +262,8 @@ GTEST_API_ int32_t Int32FromEnvOrDie(const char* env_var, int32_t default_val);
|
||||||
// returns true if and only if the test should be run on this shard. The test id
|
// returns true if and only if the test should be run on this shard. The test id
|
||||||
// is some arbitrary but unique non-negative integer assigned to each test
|
// is some arbitrary but unique non-negative integer assigned to each test
|
||||||
// method. Assumes that 0 <= shard_index < total_shards.
|
// method. Assumes that 0 <= shard_index < total_shards.
|
||||||
GTEST_API_ bool ShouldRunTestOnShard(
|
GTEST_API_ bool ShouldRunTestOnShard(int total_shards, int shard_index,
|
||||||
int total_shards, int shard_index, int test_id);
|
int test_id);
|
||||||
|
|
||||||
// STL container utilities.
|
// STL container utilities.
|
||||||
|
|
||||||
|
@ -290,9 +274,8 @@ inline int CountIf(const Container& c, Predicate predicate) {
|
||||||
// Implemented as an explicit loop since std::count_if() in libCstd on
|
// Implemented as an explicit loop since std::count_if() in libCstd on
|
||||||
// Solaris has a non-standard signature.
|
// Solaris has a non-standard signature.
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
|
for (auto it = c.begin(); it != c.end(); ++it) {
|
||||||
if (predicate(*it))
|
if (predicate(*it)) ++count;
|
||||||
++count;
|
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -441,7 +424,9 @@ class OsStackTraceGetterInterface {
|
||||||
static const char* const kElidedFramesMarker;
|
static const char* const kElidedFramesMarker;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
|
OsStackTraceGetterInterface(const OsStackTraceGetterInterface&) = delete;
|
||||||
|
OsStackTraceGetterInterface& operator=(const OsStackTraceGetterInterface&) =
|
||||||
|
delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A working implementation of the OsStackTraceGetterInterface interface.
|
// A working implementation of the OsStackTraceGetterInterface interface.
|
||||||
|
@ -463,7 +448,8 @@ class OsStackTraceGetter : public OsStackTraceGetterInterface {
|
||||||
void* caller_frame_ = nullptr;
|
void* caller_frame_ = nullptr;
|
||||||
#endif // GTEST_HAS_ABSL
|
#endif // GTEST_HAS_ABSL
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
|
OsStackTraceGetter(const OsStackTraceGetter&) = delete;
|
||||||
|
OsStackTraceGetter& operator=(const OsStackTraceGetter&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Information about a Google Test trace point.
|
// Information about a Google Test trace point.
|
||||||
|
@ -486,7 +472,10 @@ class DefaultGlobalTestPartResultReporter
|
||||||
private:
|
private:
|
||||||
UnitTestImpl* const unit_test_;
|
UnitTestImpl* const unit_test_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
|
DefaultGlobalTestPartResultReporter(
|
||||||
|
const DefaultGlobalTestPartResultReporter&) = delete;
|
||||||
|
DefaultGlobalTestPartResultReporter& operator=(
|
||||||
|
const DefaultGlobalTestPartResultReporter&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is the default per thread test part result reporter used in
|
// This is the default per thread test part result reporter used in
|
||||||
|
@ -502,7 +491,10 @@ class DefaultPerThreadTestPartResultReporter
|
||||||
private:
|
private:
|
||||||
UnitTestImpl* const unit_test_;
|
UnitTestImpl* const unit_test_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
|
DefaultPerThreadTestPartResultReporter(
|
||||||
|
const DefaultPerThreadTestPartResultReporter&) = delete;
|
||||||
|
DefaultPerThreadTestPartResultReporter& operator=(
|
||||||
|
const DefaultPerThreadTestPartResultReporter&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The private implementation of the UnitTest class. We don't protect
|
// The private implementation of the UnitTest class. We don't protect
|
||||||
|
@ -640,7 +632,8 @@ class GTEST_API_ UnitTestImpl {
|
||||||
// For example, if Foo() calls Bar(), which in turn calls
|
// For example, if Foo() calls Bar(), which in turn calls
|
||||||
// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
|
// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
|
||||||
// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
|
// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
|
||||||
std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
|
std::string CurrentOsStackTraceExceptTop(int skip_count)
|
||||||
|
GTEST_NO_INLINE_ GTEST_NO_TAIL_CALL_;
|
||||||
|
|
||||||
// Finds and returns a TestSuite with the given name. If one doesn't
|
// Finds and returns a TestSuite with the given name. If one doesn't
|
||||||
// exist, creates one and returns it.
|
// exist, creates one and returns it.
|
||||||
|
@ -744,9 +737,7 @@ class GTEST_API_ UnitTestImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears the results of ad-hoc test assertions.
|
// Clears the results of ad-hoc test assertions.
|
||||||
void ClearAdHocTestResult() {
|
void ClearAdHocTestResult() { ad_hoc_test_result_.Clear(); }
|
||||||
ad_hoc_test_result_.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a TestProperty to the current TestResult object when invoked in a
|
// Adds a TestProperty to the current TestResult object when invoked in a
|
||||||
// context of a test or a test suite, or to the global property set. If the
|
// context of a test or a test suite, or to the global property set. If the
|
||||||
|
@ -754,10 +745,7 @@ class GTEST_API_ UnitTestImpl {
|
||||||
// updated.
|
// updated.
|
||||||
void RecordProperty(const TestProperty& test_property);
|
void RecordProperty(const TestProperty& test_property);
|
||||||
|
|
||||||
enum ReactionToSharding {
|
enum ReactionToSharding { HONOR_SHARDING_PROTOCOL, IGNORE_SHARDING_PROTOCOL };
|
||||||
HONOR_SHARDING_PROTOCOL,
|
|
||||||
IGNORE_SHARDING_PROTOCOL
|
|
||||||
};
|
|
||||||
|
|
||||||
// Matches the full name of each test against the user-specified
|
// Matches the full name of each test against the user-specified
|
||||||
// filter to decide whether the test should run, then records the
|
// filter to decide whether the test should run, then records the
|
||||||
|
@ -963,7 +951,8 @@ class GTEST_API_ UnitTestImpl {
|
||||||
// starts.
|
// starts.
|
||||||
bool catch_exceptions_;
|
bool catch_exceptions_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
|
UnitTestImpl(const UnitTestImpl&) = delete;
|
||||||
|
UnitTestImpl& operator=(const UnitTestImpl&) = delete;
|
||||||
}; // class UnitTestImpl
|
}; // class UnitTestImpl
|
||||||
|
|
||||||
// Convenience function for accessing the global UnitTest
|
// Convenience function for accessing the global UnitTest
|
||||||
|
@ -986,8 +975,9 @@ GTEST_API_ bool IsValidEscape(char ch);
|
||||||
GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
|
GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
|
||||||
GTEST_API_ bool ValidateRegex(const char* regex);
|
GTEST_API_ bool ValidateRegex(const char* regex);
|
||||||
GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
|
GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
|
||||||
GTEST_API_ bool MatchRepetitionAndRegexAtHead(
|
GTEST_API_ bool MatchRepetitionAndRegexAtHead(bool escaped, char ch,
|
||||||
bool escaped, char ch, char repeat, const char* regex, const char* str);
|
char repeat, const char* regex,
|
||||||
|
const char* str);
|
||||||
GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
|
GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
|
||||||
|
|
||||||
#endif // GTEST_USES_SIMPLE_RE
|
#endif // GTEST_USES_SIMPLE_RE
|
||||||
|
@ -1089,8 +1079,7 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
~SocketWriter() override {
|
~SocketWriter() override {
|
||||||
if (sockfd_ != -1)
|
if (sockfd_ != -1) CloseConnection();
|
||||||
CloseConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends a string to the socket.
|
// Sends a string to the socket.
|
||||||
|
@ -1100,8 +1089,7 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
|
|
||||||
const auto len = static_cast<size_t>(message.length());
|
const auto len = static_cast<size_t>(message.length());
|
||||||
if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
|
if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
|
||||||
GTEST_LOG_(WARNING)
|
GTEST_LOG_(WARNING) << "stream_result_to: failed to stream to "
|
||||||
<< "stream_result_to: failed to stream to "
|
|
||||||
<< host_name_ << ":" << port_num_;
|
<< host_name_ << ":" << port_num_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1123,7 +1111,8 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
const std::string host_name_;
|
const std::string host_name_;
|
||||||
const std::string port_num_;
|
const std::string port_num_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
|
SocketWriter(const SocketWriter&) = delete;
|
||||||
|
SocketWriter& operator=(const SocketWriter&) = delete;
|
||||||
}; // class SocketWriter
|
}; // class SocketWriter
|
||||||
|
|
||||||
// Escapes '=', '&', '%', and '\n' characters in str as "%xx".
|
// Escapes '=', '&', '%', and '\n' characters in str as "%xx".
|
||||||
|
@ -1135,7 +1124,9 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit StreamingListener(AbstractSocketWriter* socket_writer)
|
explicit StreamingListener(AbstractSocketWriter* socket_writer)
|
||||||
: socket_writer_(socket_writer) { Start(); }
|
: socket_writer_(socket_writer) {
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
void OnTestProgramStart(const UnitTest& /* unit_test */) override {
|
void OnTestProgramStart(const UnitTest& /* unit_test */) override {
|
||||||
SendLn("event=TestProgramStart");
|
SendLn("event=TestProgramStart");
|
||||||
|
@ -1158,22 +1149,22 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
|
|
||||||
void OnTestIterationEnd(const UnitTest& unit_test,
|
void OnTestIterationEnd(const UnitTest& unit_test,
|
||||||
int /* iteration */) override {
|
int /* iteration */) override {
|
||||||
SendLn("event=TestIterationEnd&passed=" +
|
SendLn("event=TestIterationEnd&passed=" + FormatBool(unit_test.Passed()) +
|
||||||
FormatBool(unit_test.Passed()) + "&elapsed_time=" +
|
"&elapsed_time=" + StreamableToString(unit_test.elapsed_time()) +
|
||||||
StreamableToString(unit_test.elapsed_time()) + "ms");
|
"ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that "event=TestCaseStart" is a wire format and has to remain
|
// Note that "event=TestCaseStart" is a wire format and has to remain
|
||||||
// "case" for compatibility
|
// "case" for compatibility
|
||||||
void OnTestCaseStart(const TestCase& test_case) override {
|
void OnTestSuiteStart(const TestSuite& test_suite) override {
|
||||||
SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
|
SendLn(std::string("event=TestCaseStart&name=") + test_suite.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that "event=TestCaseEnd" is a wire format and has to remain
|
// Note that "event=TestCaseEnd" is a wire format and has to remain
|
||||||
// "case" for compatibility
|
// "case" for compatibility
|
||||||
void OnTestCaseEnd(const TestCase& test_case) override {
|
void OnTestSuiteEnd(const TestSuite& test_suite) override {
|
||||||
SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) +
|
SendLn("event=TestCaseEnd&passed=" + FormatBool(test_suite.Passed()) +
|
||||||
"&elapsed_time=" + StreamableToString(test_case.elapsed_time()) +
|
"&elapsed_time=" + StreamableToString(test_suite.elapsed_time()) +
|
||||||
"ms");
|
"ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1183,8 +1174,7 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
|
|
||||||
void OnTestEnd(const TestInfo& test_info) override {
|
void OnTestEnd(const TestInfo& test_info) override {
|
||||||
SendLn("event=TestEnd&passed=" +
|
SendLn("event=TestEnd&passed=" +
|
||||||
FormatBool((test_info.result())->Passed()) +
|
FormatBool((test_info.result())->Passed()) + "&elapsed_time=" +
|
||||||
"&elapsed_time=" +
|
|
||||||
StreamableToString((test_info.result())->elapsed_time()) + "ms");
|
StreamableToString((test_info.result())->elapsed_time()) + "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1208,7 +1198,8 @@ class StreamingListener : public EmptyTestEventListener {
|
||||||
|
|
||||||
const std::unique_ptr<AbstractSocketWriter> socket_writer_;
|
const std::unique_ptr<AbstractSocketWriter> socket_writer_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
|
StreamingListener(const StreamingListener&) = delete;
|
||||||
|
StreamingListener& operator=(const StreamingListener&) = delete;
|
||||||
}; // class StreamingListener
|
}; // class StreamingListener
|
||||||
|
|
||||||
#endif // GTEST_CAN_STREAM_RESULTS_
|
#endif // GTEST_CAN_STREAM_RESULTS_
|
||||||
|
|
|
@ -32,12 +32,13 @@
|
||||||
// This file implements just enough of the matcher interface to allow
|
// This file implements just enough of the matcher interface to allow
|
||||||
// EXPECT_DEATH and friends to accept a matcher argument.
|
// EXPECT_DEATH and friends to accept a matcher argument.
|
||||||
|
|
||||||
#include "gtest/internal/gtest-internal.h"
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
|
||||||
#include "gtest/gtest-matchers.h"
|
#include "gtest/gtest-matchers.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// Constructs a matcher that matches a const std::string& whose value is
|
// Constructs a matcher that matches a const std::string& whose value is
|
||||||
|
|
|
@ -27,61 +27,62 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
# include <windows.h>
|
#include <io.h>
|
||||||
# include <io.h>
|
#include <sys/stat.h>
|
||||||
# include <sys/stat.h>
|
#include <windows.h>
|
||||||
# include <map> // Used in ThreadLocal.
|
|
||||||
# ifdef _MSC_VER
|
#include <map> // Used in ThreadLocal.
|
||||||
# include <crtdbg.h>
|
#ifdef _MSC_VER
|
||||||
# endif // _MSC_VER
|
#include <crtdbg.h>
|
||||||
|
#endif // _MSC_VER
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
#if GTEST_OS_MAC
|
#if GTEST_OS_MAC
|
||||||
# include <mach/mach_init.h>
|
#include <mach/mach_init.h>
|
||||||
# include <mach/task.h>
|
#include <mach/task.h>
|
||||||
# include <mach/vm_map.h>
|
#include <mach/vm_map.h>
|
||||||
#endif // GTEST_OS_MAC
|
#endif // GTEST_OS_MAC
|
||||||
|
|
||||||
#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
|
#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
|
||||||
GTEST_OS_NETBSD || GTEST_OS_OPENBSD
|
GTEST_OS_NETBSD || GTEST_OS_OPENBSD
|
||||||
# include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
# if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
|
#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
|
||||||
# include <sys/user.h>
|
#include <sys/user.h>
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GTEST_OS_QNX
|
#if GTEST_OS_QNX
|
||||||
# include <devctl.h>
|
#include <devctl.h>
|
||||||
# include <fcntl.h>
|
#include <fcntl.h>
|
||||||
# include <sys/procfs.h>
|
#include <sys/procfs.h>
|
||||||
#endif // GTEST_OS_QNX
|
#endif // GTEST_OS_QNX
|
||||||
|
|
||||||
#if GTEST_OS_AIX
|
#if GTEST_OS_AIX
|
||||||
# include <procinfo.h>
|
#include <procinfo.h>
|
||||||
# include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif // GTEST_OS_AIX
|
#endif // GTEST_OS_AIX
|
||||||
|
|
||||||
#if GTEST_OS_FUCHSIA
|
#if GTEST_OS_FUCHSIA
|
||||||
# include <zircon/process.h>
|
#include <zircon/process.h>
|
||||||
# include <zircon/syscalls.h>
|
#include <zircon/syscalls.h>
|
||||||
#endif // GTEST_OS_FUCHSIA
|
#endif // GTEST_OS_FUCHSIA
|
||||||
|
|
||||||
#include "gtest/gtest-spi.h"
|
|
||||||
#include "gtest/gtest-message.h"
|
#include "gtest/gtest-message.h"
|
||||||
|
#include "gtest/gtest-spi.h"
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
#include "gtest/internal/gtest-string.h"
|
#include "gtest/internal/gtest-string.h"
|
||||||
#include "src/gtest-internal-inl.h"
|
#include "src/gtest-internal-inl.h"
|
||||||
|
@ -89,16 +90,7 @@
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
#if GTEST_OS_LINUX || GTEST_OS_GNU_HURD
|
||||||
// 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_LINUX
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -131,8 +123,7 @@ size_t GetThreadCount() {
|
||||||
if (status == KERN_SUCCESS) {
|
if (status == KERN_SUCCESS) {
|
||||||
// task_threads allocates resources in thread_list and we need to free them
|
// task_threads allocates resources in thread_list and we need to free them
|
||||||
// to avoid leaks.
|
// to avoid leaks.
|
||||||
vm_deallocate(task,
|
vm_deallocate(task, reinterpret_cast<vm_address_t>(thread_list),
|
||||||
reinterpret_cast<vm_address_t>(thread_list),
|
|
||||||
sizeof(thread_t) * thread_count);
|
sizeof(thread_t) * thread_count);
|
||||||
return static_cast<size_t>(thread_count);
|
return static_cast<size_t>(thread_count);
|
||||||
} else {
|
} else {
|
||||||
|
@ -210,8 +201,7 @@ size_t GetThreadCount() {
|
||||||
// exclude empty members
|
// exclude empty members
|
||||||
size_t nthreads = 0;
|
size_t nthreads = 0;
|
||||||
for (size_t i = 0; i < size / static_cast<size_t>(mib[4]); i++) {
|
for (size_t i = 0; i < size / static_cast<size_t>(mib[4]); i++) {
|
||||||
if (info[i].p_tid != -1)
|
if (info[i].p_tid != -1) nthreads++;
|
||||||
nthreads++;
|
|
||||||
}
|
}
|
||||||
return nthreads;
|
return nthreads;
|
||||||
}
|
}
|
||||||
|
@ -254,13 +244,9 @@ size_t GetThreadCount() {
|
||||||
size_t GetThreadCount() {
|
size_t GetThreadCount() {
|
||||||
int dummy_buffer;
|
int dummy_buffer;
|
||||||
size_t avail;
|
size_t avail;
|
||||||
zx_status_t status = zx_object_get_info(
|
zx_status_t status =
|
||||||
zx_process_self(),
|
zx_object_get_info(zx_process_self(), ZX_INFO_PROCESS_THREADS,
|
||||||
ZX_INFO_PROCESS_THREADS,
|
&dummy_buffer, 0, nullptr, &avail);
|
||||||
&dummy_buffer,
|
|
||||||
0,
|
|
||||||
nullptr,
|
|
||||||
&avail);
|
|
||||||
if (status == ZX_OK) {
|
if (status == ZX_OK) {
|
||||||
return avail;
|
return avail;
|
||||||
} else {
|
} else {
|
||||||
|
@ -280,27 +266,15 @@ size_t GetThreadCount() {
|
||||||
|
|
||||||
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
||||||
|
|
||||||
void SleepMilliseconds(int n) {
|
AutoHandle::AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
|
||||||
::Sleep(static_cast<DWORD>(n));
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoHandle::AutoHandle()
|
AutoHandle::AutoHandle(Handle handle) : handle_(handle) {}
|
||||||
: handle_(INVALID_HANDLE_VALUE) {}
|
|
||||||
|
|
||||||
AutoHandle::AutoHandle(Handle handle)
|
AutoHandle::~AutoHandle() { Reset(); }
|
||||||
: handle_(handle) {}
|
|
||||||
|
|
||||||
AutoHandle::~AutoHandle() {
|
AutoHandle::Handle AutoHandle::Get() const { return handle_; }
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoHandle::Handle AutoHandle::Get() const {
|
void AutoHandle::Reset() { Reset(INVALID_HANDLE_VALUE); }
|
||||||
return handle_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AutoHandle::Reset() {
|
|
||||||
Reset(INVALID_HANDLE_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AutoHandle::Reset(HANDLE handle) {
|
void AutoHandle::Reset(HANDLE handle) {
|
||||||
// Resetting with the same handle we already own is invalid.
|
// Resetting with the same handle we already own is invalid.
|
||||||
|
@ -322,23 +296,6 @@ bool AutoHandle::IsCloseable() const {
|
||||||
return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
|
return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Notification::Notification()
|
|
||||||
: event_(::CreateEvent(nullptr, // Default security attributes.
|
|
||||||
TRUE, // Do not reset automatically.
|
|
||||||
FALSE, // Initially unset.
|
|
||||||
nullptr)) { // Anonymous event.
|
|
||||||
GTEST_CHECK_(event_.Get() != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Notification::Notify() {
|
|
||||||
GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Notification::WaitForNotification() {
|
|
||||||
GTEST_CHECK_(
|
|
||||||
::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mutex::Mutex()
|
Mutex::Mutex()
|
||||||
: owner_thread_id_(0),
|
: owner_thread_id_(0),
|
||||||
type_(kDynamic),
|
type_(kDynamic),
|
||||||
|
@ -391,25 +348,25 @@ namespace {
|
||||||
// MemoryIsNotDeallocated memory_is_not_deallocated;
|
// MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||||
// critical_section_ = new CRITICAL_SECTION;
|
// critical_section_ = new CRITICAL_SECTION;
|
||||||
//
|
//
|
||||||
class MemoryIsNotDeallocated
|
class MemoryIsNotDeallocated {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
|
MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
|
||||||
old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
||||||
// Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
|
// Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
|
||||||
// doesn't report mem leak if there's no matching deallocation.
|
// doesn't report mem leak if there's no matching deallocation.
|
||||||
_CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
|
(void)_CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
|
||||||
}
|
}
|
||||||
|
|
||||||
~MemoryIsNotDeallocated() {
|
~MemoryIsNotDeallocated() {
|
||||||
// Restore the original _CRTDBG_ALLOC_MEM_DF flag
|
// Restore the original _CRTDBG_ALLOC_MEM_DF flag
|
||||||
_CrtSetDbgFlag(old_crtdbg_flag_);
|
(void)_CrtSetDbgFlag(old_crtdbg_flag_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int old_crtdbg_flag_;
|
int old_crtdbg_flag_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated);
|
MemoryIsNotDeallocated(const MemoryIsNotDeallocated&) = delete;
|
||||||
|
MemoryIsNotDeallocated& operator=(const MemoryIsNotDeallocated&) = delete;
|
||||||
};
|
};
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
@ -435,15 +392,13 @@ void Mutex::ThreadSafeLazyInit() {
|
||||||
::InitializeCriticalSection(critical_section_);
|
::InitializeCriticalSection(critical_section_);
|
||||||
// Updates the critical_section_init_phase_ to 2 to signal
|
// Updates the critical_section_init_phase_ to 2 to signal
|
||||||
// initialization complete.
|
// initialization complete.
|
||||||
GTEST_CHECK_(::InterlockedCompareExchange(
|
GTEST_CHECK_(::InterlockedCompareExchange(&critical_section_init_phase_,
|
||||||
&critical_section_init_phase_, 2L, 1L) ==
|
2L, 1L) == 1L);
|
||||||
1L);
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// Somebody else is already initializing the mutex; spin until they
|
// Somebody else is already initializing the mutex; spin until they
|
||||||
// are done.
|
// are done.
|
||||||
while (::InterlockedCompareExchange(&critical_section_init_phase_,
|
while (::InterlockedCompareExchange(&critical_section_init_phase_, 2L,
|
||||||
2L,
|
|
||||||
2L) != 2L) {
|
2L) != 2L) {
|
||||||
// Possibly yields the rest of the thread's time slice to other
|
// Possibly yields the rest of the thread's time slice to other
|
||||||
// threads.
|
// threads.
|
||||||
|
@ -488,9 +443,7 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
||||||
private:
|
private:
|
||||||
struct ThreadMainParam {
|
struct ThreadMainParam {
|
||||||
ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
|
ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
|
||||||
: runnable_(runnable),
|
: runnable_(runnable), thread_can_start_(thread_can_start) {}
|
||||||
thread_can_start_(thread_can_start) {
|
|
||||||
}
|
|
||||||
std::unique_ptr<Runnable> runnable_;
|
std::unique_ptr<Runnable> runnable_;
|
||||||
// Does not own.
|
// Does not own.
|
||||||
Notification* thread_can_start_;
|
Notification* thread_can_start_;
|
||||||
|
@ -508,20 +461,18 @@ class ThreadWithParamSupport : public ThreadWithParamBase {
|
||||||
// Prohibit instantiation.
|
// Prohibit instantiation.
|
||||||
ThreadWithParamSupport();
|
ThreadWithParamSupport();
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParamSupport);
|
ThreadWithParamSupport(const ThreadWithParamSupport&) = delete;
|
||||||
|
ThreadWithParamSupport& operator=(const ThreadWithParamSupport&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ThreadWithParamBase::ThreadWithParamBase(Runnable *runnable,
|
ThreadWithParamBase::ThreadWithParamBase(Runnable* runnable,
|
||||||
Notification* thread_can_start)
|
Notification* thread_can_start)
|
||||||
: thread_(ThreadWithParamSupport::CreateThread(runnable,
|
: thread_(
|
||||||
thread_can_start)) {
|
ThreadWithParamSupport::CreateThread(runnable, thread_can_start)) {}
|
||||||
}
|
|
||||||
|
|
||||||
ThreadWithParamBase::~ThreadWithParamBase() {
|
ThreadWithParamBase::~ThreadWithParamBase() { Join(); }
|
||||||
Join();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadWithParamBase::Join() {
|
void ThreadWithParamBase::Join() {
|
||||||
GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
|
GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
|
||||||
|
@ -548,8 +499,10 @@ class ThreadLocalRegistryImpl {
|
||||||
ThreadIdToThreadLocals::iterator thread_local_pos =
|
ThreadIdToThreadLocals::iterator thread_local_pos =
|
||||||
thread_to_thread_locals->find(current_thread);
|
thread_to_thread_locals->find(current_thread);
|
||||||
if (thread_local_pos == thread_to_thread_locals->end()) {
|
if (thread_local_pos == thread_to_thread_locals->end()) {
|
||||||
thread_local_pos = thread_to_thread_locals->insert(
|
thread_local_pos =
|
||||||
std::make_pair(current_thread, ThreadLocalValues())).first;
|
thread_to_thread_locals
|
||||||
|
->insert(std::make_pair(current_thread, ThreadLocalValues()))
|
||||||
|
.first;
|
||||||
StartWatcherThreadFor(current_thread);
|
StartWatcherThreadFor(current_thread);
|
||||||
}
|
}
|
||||||
ThreadLocalValues& thread_local_values = thread_local_pos->second;
|
ThreadLocalValues& thread_local_values = thread_local_pos->second;
|
||||||
|
@ -578,8 +531,7 @@ class ThreadLocalRegistryImpl {
|
||||||
GetThreadLocalsMapLocked();
|
GetThreadLocalsMapLocked();
|
||||||
for (ThreadIdToThreadLocals::iterator it =
|
for (ThreadIdToThreadLocals::iterator it =
|
||||||
thread_to_thread_locals->begin();
|
thread_to_thread_locals->begin();
|
||||||
it != thread_to_thread_locals->end();
|
it != thread_to_thread_locals->end(); ++it) {
|
||||||
++it) {
|
|
||||||
ThreadLocalValues& thread_local_values = it->second;
|
ThreadLocalValues& thread_local_values = it->second;
|
||||||
ThreadLocalValues::iterator value_pos =
|
ThreadLocalValues::iterator value_pos =
|
||||||
thread_local_values.find(thread_local_instance);
|
thread_local_values.find(thread_local_instance);
|
||||||
|
@ -610,8 +562,7 @@ class ThreadLocalRegistryImpl {
|
||||||
ThreadLocalValues& thread_local_values = thread_local_pos->second;
|
ThreadLocalValues& thread_local_values = thread_local_pos->second;
|
||||||
for (ThreadLocalValues::iterator value_pos =
|
for (ThreadLocalValues::iterator value_pos =
|
||||||
thread_local_values.begin();
|
thread_local_values.begin();
|
||||||
value_pos != thread_local_values.end();
|
value_pos != thread_local_values.end(); ++value_pos) {
|
||||||
++value_pos) {
|
|
||||||
value_holders.push_back(value_pos->second);
|
value_holders.push_back(value_pos->second);
|
||||||
}
|
}
|
||||||
thread_to_thread_locals->erase(thread_local_pos);
|
thread_to_thread_locals->erase(thread_local_pos);
|
||||||
|
@ -637,9 +588,8 @@ class ThreadLocalRegistryImpl {
|
||||||
static void StartWatcherThreadFor(DWORD thread_id) {
|
static void StartWatcherThreadFor(DWORD thread_id) {
|
||||||
// The returned handle will be kept in thread_map and closed by
|
// The returned handle will be kept in thread_map and closed by
|
||||||
// watcher_thread in WatcherThreadFunc.
|
// watcher_thread in WatcherThreadFunc.
|
||||||
HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
|
HANDLE thread =
|
||||||
FALSE,
|
::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, thread_id);
|
||||||
thread_id);
|
|
||||||
GTEST_CHECK_(thread != nullptr);
|
GTEST_CHECK_(thread != nullptr);
|
||||||
// We need to pass a valid thread ID pointer into CreateThread for it
|
// We need to pass a valid thread ID pointer into CreateThread for it
|
||||||
// to work correctly under Win98.
|
// to work correctly under Win98.
|
||||||
|
@ -650,7 +600,8 @@ class ThreadLocalRegistryImpl {
|
||||||
&ThreadLocalRegistryImpl::WatcherThreadFunc,
|
&ThreadLocalRegistryImpl::WatcherThreadFunc,
|
||||||
reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
|
reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
|
||||||
CREATE_SUSPENDED, &watcher_thread_id);
|
CREATE_SUSPENDED, &watcher_thread_id);
|
||||||
GTEST_CHECK_(watcher_thread != nullptr);
|
GTEST_CHECK_(watcher_thread != nullptr)
|
||||||
|
<< "CreateThread failed with error " << ::GetLastError() << ".";
|
||||||
// Give the watcher thread the same priority as ours to avoid being
|
// Give the watcher thread the same priority as ours to avoid being
|
||||||
// blocked by it.
|
// blocked by it.
|
||||||
::SetThreadPriority(watcher_thread,
|
::SetThreadPriority(watcher_thread,
|
||||||
|
@ -664,8 +615,7 @@ class ThreadLocalRegistryImpl {
|
||||||
static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
|
static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
|
||||||
const ThreadIdAndHandle* tah =
|
const ThreadIdAndHandle* tah =
|
||||||
reinterpret_cast<const ThreadIdAndHandle*>(param);
|
reinterpret_cast<const ThreadIdAndHandle*>(param);
|
||||||
GTEST_CHECK_(
|
GTEST_CHECK_(::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
|
||||||
::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
|
|
||||||
OnThreadExit(tah->first);
|
OnThreadExit(tah->first);
|
||||||
::CloseHandle(tah->second);
|
::CloseHandle(tah->second);
|
||||||
delete tah;
|
delete tah;
|
||||||
|
@ -689,7 +639,8 @@ class ThreadLocalRegistryImpl {
|
||||||
};
|
};
|
||||||
|
|
||||||
Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex); // NOLINT
|
Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex); // NOLINT
|
||||||
Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex); // NOLINT
|
Mutex ThreadLocalRegistryImpl::thread_map_mutex_(
|
||||||
|
Mutex::kStaticMutex); // NOLINT
|
||||||
|
|
||||||
ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
|
ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
|
||||||
const ThreadLocalBase* thread_local_instance) {
|
const ThreadLocalBase* thread_local_instance) {
|
||||||
|
@ -799,17 +750,28 @@ bool IsValidEscape(char c) {
|
||||||
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
||||||
if (escaped) { // "\\p" where p is pattern_char.
|
if (escaped) { // "\\p" where p is pattern_char.
|
||||||
switch (pattern_char) {
|
switch (pattern_char) {
|
||||||
case 'd': return IsAsciiDigit(ch);
|
case 'd':
|
||||||
case 'D': return !IsAsciiDigit(ch);
|
return IsAsciiDigit(ch);
|
||||||
case 'f': return ch == '\f';
|
case 'D':
|
||||||
case 'n': return ch == '\n';
|
return !IsAsciiDigit(ch);
|
||||||
case 'r': return ch == '\r';
|
case 'f':
|
||||||
case 's': return IsAsciiWhiteSpace(ch);
|
return ch == '\f';
|
||||||
case 'S': return !IsAsciiWhiteSpace(ch);
|
case 'n':
|
||||||
case 't': return ch == '\t';
|
return ch == '\n';
|
||||||
case 'v': return ch == '\v';
|
case 'r':
|
||||||
case 'w': return IsAsciiWordChar(ch);
|
return ch == '\r';
|
||||||
case 'W': return !IsAsciiWordChar(ch);
|
case 's':
|
||||||
|
return IsAsciiWhiteSpace(ch);
|
||||||
|
case 'S':
|
||||||
|
return !IsAsciiWhiteSpace(ch);
|
||||||
|
case 't':
|
||||||
|
return ch == '\t';
|
||||||
|
case 'v':
|
||||||
|
return ch == '\v';
|
||||||
|
case 'w':
|
||||||
|
return IsAsciiWordChar(ch);
|
||||||
|
case 'W':
|
||||||
|
return !IsAsciiWordChar(ch);
|
||||||
}
|
}
|
||||||
return IsAsciiPunct(pattern_char) && pattern_char == ch;
|
return IsAsciiPunct(pattern_char) && pattern_char == ch;
|
||||||
}
|
}
|
||||||
|
@ -820,7 +782,8 @@ bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
|
||||||
// Helper function used by ValidateRegex() to format error messages.
|
// Helper function used by ValidateRegex() to format error messages.
|
||||||
static std::string FormatRegexSyntaxError(const char* regex, int index) {
|
static std::string FormatRegexSyntaxError(const char* regex, int index) {
|
||||||
return (Message() << "Syntax error at index " << index
|
return (Message() << "Syntax error at index " << index
|
||||||
<< " in simple regular expression \"" << regex << "\": ").GetString();
|
<< " in simple regular expression \"" << regex << "\": ")
|
||||||
|
.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates non-fatal failures and returns false if regex is invalid;
|
// Generates non-fatal failures and returns false if regex is invalid;
|
||||||
|
@ -862,12 +825,12 @@ bool ValidateRegex(const char* regex) {
|
||||||
<< "'$' can only appear at the end.";
|
<< "'$' can only appear at the end.";
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
} else if (IsInSet(ch, "()[]{}|")) {
|
} else if (IsInSet(ch, "()[]{}|")) {
|
||||||
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
|
ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'" << ch
|
||||||
<< "'" << ch << "' is unsupported.";
|
<< "' is unsupported.";
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
} else if (IsRepeat(ch) && !prev_repeatable) {
|
} else if (IsRepeat(ch) && !prev_repeatable) {
|
||||||
ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
|
ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'" << ch
|
||||||
<< "'" << ch << "' can only follow a repeatable token.";
|
<< "' can only follow a repeatable token.";
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,12 +848,10 @@ bool ValidateRegex(const char* regex) {
|
||||||
// characters to be indexable by size_t, in which case the test will
|
// characters to be indexable by size_t, in which case the test will
|
||||||
// probably time out anyway. We are fine with this limitation as
|
// probably time out anyway. We are fine with this limitation as
|
||||||
// std::string has it too.
|
// std::string has it too.
|
||||||
bool MatchRepetitionAndRegexAtHead(
|
bool MatchRepetitionAndRegexAtHead(bool escaped, char c, char repeat,
|
||||||
bool escaped, char c, char repeat, const char* regex,
|
const char* regex, const char* str) {
|
||||||
const char* str) {
|
|
||||||
const size_t min_count = (repeat == '+') ? 1 : 0;
|
const size_t min_count = (repeat == '+') ? 1 : 0;
|
||||||
const size_t max_count = (repeat == '?') ? 1 :
|
const size_t max_count = (repeat == '?') ? 1 : static_cast<size_t>(-1) - 1;
|
||||||
static_cast<size_t>(-1) - 1;
|
|
||||||
// We cannot call numeric_limits::max() as it conflicts with the
|
// We cannot call numeric_limits::max() as it conflicts with the
|
||||||
// max() macro on Windows.
|
// max() macro on Windows.
|
||||||
|
|
||||||
|
@ -903,8 +864,7 @@ bool MatchRepetitionAndRegexAtHead(
|
||||||
// greedy match.
|
// greedy match.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
|
if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -918,19 +878,17 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
|
||||||
|
|
||||||
// "$" only matches the end of a string. Note that regex being
|
// "$" only matches the end of a string. Note that regex being
|
||||||
// valid guarantees that there's nothing after "$" in it.
|
// valid guarantees that there's nothing after "$" in it.
|
||||||
if (*regex == '$')
|
if (*regex == '$') return *str == '\0';
|
||||||
return *str == '\0';
|
|
||||||
|
|
||||||
// Is the first thing in regex an escape sequence?
|
// Is the first thing in regex an escape sequence?
|
||||||
const bool escaped = *regex == '\\';
|
const bool escaped = *regex == '\\';
|
||||||
if (escaped)
|
if (escaped) ++regex;
|
||||||
++regex;
|
|
||||||
if (IsRepeat(regex[1])) {
|
if (IsRepeat(regex[1])) {
|
||||||
// MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
|
// MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
|
||||||
// here's an indirect recursion. It terminates as the regex gets
|
// here's an indirect recursion. It terminates as the regex gets
|
||||||
// shorter in each recursion.
|
// shorter in each recursion.
|
||||||
return MatchRepetitionAndRegexAtHead(
|
return MatchRepetitionAndRegexAtHead(escaped, regex[0], regex[1], regex + 2,
|
||||||
escaped, regex[0], regex[1], regex + 2, str);
|
str);
|
||||||
} else {
|
} else {
|
||||||
// regex isn't empty, isn't "$", and doesn't start with a
|
// regex isn't empty, isn't "$", and doesn't start with a
|
||||||
// repetition. We match the first atom of regex with the first
|
// repetition. We match the first atom of regex with the first
|
||||||
|
@ -951,13 +909,11 @@ bool MatchRegexAtHead(const char* regex, const char* str) {
|
||||||
bool MatchRegexAnywhere(const char* regex, const char* str) {
|
bool MatchRegexAnywhere(const char* regex, const char* str) {
|
||||||
if (regex == nullptr || str == nullptr) return false;
|
if (regex == nullptr || str == nullptr) return false;
|
||||||
|
|
||||||
if (*regex == '^')
|
if (*regex == '^') return MatchRegexAtHead(regex + 1, str);
|
||||||
return MatchRegexAtHead(regex + 1, str);
|
|
||||||
|
|
||||||
// A successful match can be anywhere in str.
|
// A successful match can be anywhere in str.
|
||||||
do {
|
do {
|
||||||
if (MatchRegexAtHead(regex, str))
|
if (MatchRegexAtHead(regex, str)) return true;
|
||||||
return true;
|
|
||||||
} while (*str++ != '\0');
|
} while (*str++ != '\0');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1038,8 +994,8 @@ GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
|
||||||
// FormatFileLocation in order to contrast the two functions.
|
// FormatFileLocation in order to contrast the two functions.
|
||||||
// Note that FormatCompilerIndependentFileLocation() does NOT append colon
|
// Note that FormatCompilerIndependentFileLocation() does NOT append colon
|
||||||
// to the file location it produces, unlike FormatFileLocation().
|
// to the file location it produces, unlike FormatFileLocation().
|
||||||
GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
|
GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
|
||||||
const char* file, int line) {
|
int line) {
|
||||||
const std::string file_name(file == nullptr ? kUnknownFile : file);
|
const std::string file_name(file == nullptr ? kUnknownFile : file);
|
||||||
|
|
||||||
if (line < 0)
|
if (line < 0)
|
||||||
|
@ -1050,12 +1006,13 @@ GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
|
||||||
|
|
||||||
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
|
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
|
||||||
: severity_(severity) {
|
: severity_(severity) {
|
||||||
const char* const marker =
|
const char* const marker = severity == GTEST_INFO ? "[ INFO ]"
|
||||||
severity == GTEST_INFO ? "[ INFO ]" :
|
: severity == GTEST_WARNING ? "[WARNING]"
|
||||||
severity == GTEST_WARNING ? "[WARNING]" :
|
: severity == GTEST_ERROR ? "[ ERROR ]"
|
||||||
severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
|
: "[ FATAL ]";
|
||||||
GetStream() << ::std::endl << marker << " "
|
GetStream() << ::std::endl
|
||||||
<< FormatFileLocation(file, line).c_str() << ": ";
|
<< marker << " " << FormatFileLocation(file, line).c_str()
|
||||||
|
<< ": ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
|
// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
|
||||||
|
@ -1078,27 +1035,26 @@ class CapturedStream {
|
||||||
public:
|
public:
|
||||||
// The ctor redirects the stream to a temporary file.
|
// The ctor redirects the stream to a temporary file.
|
||||||
explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
|
explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
|
||||||
# if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
char temp_dir_path[MAX_PATH + 1] = {'\0'}; // NOLINT
|
||||||
char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
|
char temp_file_path[MAX_PATH + 1] = {'\0'}; // NOLINT
|
||||||
|
|
||||||
::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
|
::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
|
||||||
const UINT success = ::GetTempFileNameA(temp_dir_path,
|
const UINT success = ::GetTempFileNameA(temp_dir_path, "gtest_redir",
|
||||||
"gtest_redir",
|
|
||||||
0, // Generate unique file name.
|
0, // Generate unique file name.
|
||||||
temp_file_path);
|
temp_file_path);
|
||||||
GTEST_CHECK_(success != 0)
|
GTEST_CHECK_(success != 0)
|
||||||
<< "Unable to create a temporary file in " << temp_dir_path;
|
<< "Unable to create a temporary file in " << temp_dir_path;
|
||||||
const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
|
const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
|
||||||
GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
|
GTEST_CHECK_(captured_fd != -1)
|
||||||
<< temp_file_path;
|
<< "Unable to open temporary file " << temp_file_path;
|
||||||
filename_ = temp_file_path;
|
filename_ = temp_file_path;
|
||||||
# else
|
#else
|
||||||
// There's no guarantee that a test has write access to the current
|
// There's no guarantee that a test has write access to the current
|
||||||
// directory, so we create the temporary file in a temporary directory.
|
// directory, so we create the temporary file in a temporary directory.
|
||||||
std::string name_template;
|
std::string name_template;
|
||||||
|
|
||||||
# if GTEST_OS_LINUX_ANDROID
|
#if GTEST_OS_LINUX_ANDROID
|
||||||
// Note: Android applications are expected to call the framework's
|
// Note: Android applications are expected to call the framework's
|
||||||
// Context.getExternalStorageDirectory() method through JNI to get
|
// Context.getExternalStorageDirectory() method through JNI to get
|
||||||
// the location of the world-writable SD Card directory. However,
|
// the location of the world-writable SD Card directory. However,
|
||||||
|
@ -1111,7 +1067,7 @@ class CapturedStream {
|
||||||
// '/sdcard' and other variants cannot be relied on, as they are not
|
// '/sdcard' and other variants cannot be relied on, as they are not
|
||||||
// guaranteed to be mounted, or may have a delay in mounting.
|
// guaranteed to be mounted, or may have a delay in mounting.
|
||||||
name_template = "/data/local/tmp/";
|
name_template = "/data/local/tmp/";
|
||||||
# elif GTEST_OS_IOS
|
#elif GTEST_OS_IOS
|
||||||
char user_temp_dir[PATH_MAX + 1];
|
char user_temp_dir[PATH_MAX + 1];
|
||||||
|
|
||||||
// Documented alternative to NSTemporaryDirectory() (for obtaining creating
|
// Documented alternative to NSTemporaryDirectory() (for obtaining creating
|
||||||
|
@ -1132,9 +1088,9 @@ class CapturedStream {
|
||||||
name_template = user_temp_dir;
|
name_template = user_temp_dir;
|
||||||
if (name_template.back() != GTEST_PATH_SEP_[0])
|
if (name_template.back() != GTEST_PATH_SEP_[0])
|
||||||
name_template.push_back(GTEST_PATH_SEP_[0]);
|
name_template.push_back(GTEST_PATH_SEP_[0]);
|
||||||
# else
|
#else
|
||||||
name_template = "/tmp/";
|
name_template = "/tmp/";
|
||||||
# endif
|
#endif
|
||||||
name_template.append("gtest_captured_stream.XXXXXX");
|
name_template.append("gtest_captured_stream.XXXXXX");
|
||||||
|
|
||||||
// mkstemp() modifies the string bytes in place, and does not go beyond the
|
// mkstemp() modifies the string bytes in place, and does not go beyond the
|
||||||
|
@ -1150,15 +1106,13 @@ class CapturedStream {
|
||||||
<< " for test; does the test have access to the /tmp directory?";
|
<< " for test; does the test have access to the /tmp directory?";
|
||||||
}
|
}
|
||||||
filename_ = std::move(name_template);
|
filename_ = std::move(name_template);
|
||||||
# endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
fflush(nullptr);
|
fflush(nullptr);
|
||||||
dup2(captured_fd, fd_);
|
dup2(captured_fd, fd_);
|
||||||
close(captured_fd);
|
close(captured_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CapturedStream() {
|
~CapturedStream() { remove(filename_.c_str()); }
|
||||||
remove(filename_.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetCapturedString() {
|
std::string GetCapturedString() {
|
||||||
if (uncaptured_fd_ != -1) {
|
if (uncaptured_fd_ != -1) {
|
||||||
|
@ -1185,7 +1139,8 @@ class CapturedStream {
|
||||||
// Name of the temporary file holding the stderr output.
|
// Name of the temporary file holding the stderr output.
|
||||||
::std::string filename_;
|
::std::string filename_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
|
CapturedStream(const CapturedStream&) = delete;
|
||||||
|
CapturedStream& operator=(const CapturedStream&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_DEPRECATED_POP_()
|
GTEST_DISABLE_MSC_DEPRECATED_POP_()
|
||||||
|
@ -1213,6 +1168,15 @@ static std::string GetCapturedStream(CapturedStream** captured_stream) {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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 // defined(_MSC_VER) || defined(__BORLANDC__)
|
||||||
|
|
||||||
// Starts capturing stdout.
|
// Starts capturing stdout.
|
||||||
void CaptureStdout() {
|
void CaptureStdout() {
|
||||||
CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
|
CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
|
||||||
|
@ -1235,10 +1199,6 @@ std::string GetCapturedStderr() {
|
||||||
|
|
||||||
#endif // GTEST_HAS_STREAM_REDIRECTION
|
#endif // GTEST_HAS_STREAM_REDIRECTION
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
size_t GetFileSize(FILE* file) {
|
size_t GetFileSize(FILE* file) {
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
return static_cast<size_t>(ftell(file));
|
return static_cast<size_t>(ftell(file));
|
||||||
|
@ -1256,7 +1216,8 @@ std::string ReadEntireFile(FILE* file) {
|
||||||
// Keeps reading the file until we cannot read further or the
|
// Keeps reading the file until we cannot read further or the
|
||||||
// pre-determined file size is reached.
|
// pre-determined file size is reached.
|
||||||
do {
|
do {
|
||||||
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
|
bytes_last_read =
|
||||||
|
fread(buffer + bytes_read, 1, file_size - bytes_read, file);
|
||||||
bytes_read += bytes_last_read;
|
bytes_read += bytes_last_read;
|
||||||
} while (bytes_last_read > 0 && bytes_read < file_size);
|
} while (bytes_last_read > 0 && bytes_read < file_size);
|
||||||
|
|
||||||
|
@ -1388,8 +1349,8 @@ int32_t Int32FromGTestEnv(const char* flag, int32_t default_value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t result = default_value;
|
int32_t result = default_value;
|
||||||
if (!ParseInt32(Message() << "Environment variable " << env_var,
|
if (!ParseInt32(Message() << "Environment variable " << env_var, string_value,
|
||||||
string_value, &result)) {
|
&result)) {
|
||||||
printf("The default value %s is used.\n",
|
printf("The default value %s is used.\n",
|
||||||
(Message() << default_value).GetString().c_str());
|
(Message() << default_value).GetString().c_str());
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -1408,7 +1369,7 @@ int32_t Int32FromGTestEnv(const char* flag, int32_t default_value) {
|
||||||
// not check that the flag is 'output'
|
// not check that the flag is 'output'
|
||||||
// In essence this checks an env variable called XML_OUTPUT_FILE
|
// In essence this checks an env variable called XML_OUTPUT_FILE
|
||||||
// and if it is set we prepend "xml:" to its value, if it not set we return ""
|
// and if it is set we prepend "xml:" to its value, if it not set we return ""
|
||||||
std::string OutputFlagAlsoCheckEnvVar(){
|
std::string OutputFlagAlsoCheckEnvVar() {
|
||||||
std::string default_value_for_output_flag = "";
|
std::string default_value_for_output_flag = "";
|
||||||
const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
|
const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
|
||||||
if (nullptr != xml_output_file_env) {
|
if (nullptr != xml_output_file_env) {
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
// Google Test - The Google C++ Testing and Mocking Framework
|
// Google Test - The Google C++ Testing and Mocking Framework
|
||||||
//
|
//
|
||||||
// This file implements a universal value printer that can print a
|
// This file implements a universal value printer that can print a
|
||||||
|
@ -101,7 +100,7 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
||||||
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
|
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
|
||||||
*os << " ... ";
|
*os << " ... ";
|
||||||
// Rounds up to 2-byte boundary.
|
// Rounds up to 2-byte boundary.
|
||||||
const size_t resume_pos = (count - kChunkSize + 1)/2*2;
|
const size_t resume_pos = (count - kChunkSize + 1) / 2 * 2;
|
||||||
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
|
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
|
||||||
}
|
}
|
||||||
*os << ">";
|
*os << ">";
|
||||||
|
@ -136,11 +135,7 @@ void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
|
||||||
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
|
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
|
||||||
// - as a hexadecimal escape sequence (e.g. '\x7F'), or
|
// - as a hexadecimal escape sequence (e.g. '\x7F'), or
|
||||||
// - as a special escape sequence (e.g. '\r', '\n').
|
// - as a special escape sequence (e.g. '\r', '\n').
|
||||||
enum CharFormat {
|
enum CharFormat { kAsIs, kHexEscape, kSpecialEscape };
|
||||||
kAsIs,
|
|
||||||
kHexEscape,
|
|
||||||
kSpecialEscape
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns true if c is a printable ASCII character. We test the
|
// Returns true if c is a printable ASCII character. We test the
|
||||||
// value of c directly instead of calling isprint(), which is buggy on
|
// value of c directly instead of calling isprint(), which is buggy on
|
||||||
|
@ -213,35 +208,21 @@ static CharFormat PrintAsStringLiteralTo(char32_t c, ostream* os) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* GetCharWidthPrefix(char) {
|
static const char* GetCharWidthPrefix(char) { return ""; }
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* GetCharWidthPrefix(signed char) {
|
static const char* GetCharWidthPrefix(signed char) { return ""; }
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* GetCharWidthPrefix(unsigned char) {
|
static const char* GetCharWidthPrefix(unsigned char) { return ""; }
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cpp_char8_t
|
#ifdef __cpp_char8_t
|
||||||
static const char* GetCharWidthPrefix(char8_t) {
|
static const char* GetCharWidthPrefix(char8_t) { return "u8"; }
|
||||||
return "u8";
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char* GetCharWidthPrefix(char16_t) {
|
static const char* GetCharWidthPrefix(char16_t) { return "u"; }
|
||||||
return "u";
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* GetCharWidthPrefix(char32_t) {
|
static const char* GetCharWidthPrefix(char32_t) { return "U"; }
|
||||||
return "U";
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* GetCharWidthPrefix(wchar_t) {
|
static const char* GetCharWidthPrefix(wchar_t) { return "L"; }
|
||||||
return "L";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints a char c as if it's part of a string literal, escaping it when
|
// Prints a char c as if it's part of a string literal, escaping it when
|
||||||
// necessary; returns how c was formatted.
|
// necessary; returns how c was formatted.
|
||||||
|
@ -276,8 +257,7 @@ void PrintCharAndCodeTo(Char c, ostream* os) {
|
||||||
// To aid user debugging, we also print c's code in decimal, unless
|
// To aid user debugging, we also print c's code in decimal, unless
|
||||||
// it's 0 (in which case c was printed as '\\0', making the code
|
// it's 0 (in which case c was printed as '\\0', making the code
|
||||||
// obvious).
|
// obvious).
|
||||||
if (c == 0)
|
if (c == 0) return;
|
||||||
return;
|
|
||||||
*os << " (" << static_cast<int>(c);
|
*os << " (" << static_cast<int>(c);
|
||||||
|
|
||||||
// For more convenience, we print c's code again in hexadecimal,
|
// For more convenience, we print c's code again in hexadecimal,
|
||||||
|
@ -304,17 +284,60 @@ void PrintTo(char32_t c, ::std::ostream* os) {
|
||||||
<< static_cast<uint32_t>(c);
|
<< static_cast<uint32_t>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gcc/clang __{u,}int128_t
|
||||||
|
#if defined(__SIZEOF_INT128__)
|
||||||
|
void PrintTo(__uint128_t v, ::std::ostream* os) {
|
||||||
|
if (v == 0) {
|
||||||
|
*os << "0";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buffer large enough for ceil(log10(2^128))==39 and the null terminator
|
||||||
|
char buf[40];
|
||||||
|
char* p = buf + sizeof(buf);
|
||||||
|
|
||||||
|
// Some configurations have a __uint128_t, but no support for built in
|
||||||
|
// division. Do manual long division instead.
|
||||||
|
|
||||||
|
uint64_t high = static_cast<uint64_t>(v >> 64);
|
||||||
|
uint64_t low = static_cast<uint64_t>(v);
|
||||||
|
|
||||||
|
*--p = 0;
|
||||||
|
while (high != 0 || low != 0) {
|
||||||
|
uint64_t high_mod = high % 10;
|
||||||
|
high = high / 10;
|
||||||
|
// This is the long division algorithm specialized for a divisor of 10 and
|
||||||
|
// only two elements.
|
||||||
|
// Notable values:
|
||||||
|
// 2^64 / 10 == 1844674407370955161
|
||||||
|
// 2^64 % 10 == 6
|
||||||
|
const uint64_t carry = 6 * high_mod + low % 10;
|
||||||
|
low = low / 10 + high_mod * 1844674407370955161 + carry / 10;
|
||||||
|
|
||||||
|
char digit = static_cast<char>(carry % 10);
|
||||||
|
*--p = '0' + digit;
|
||||||
|
}
|
||||||
|
*os << p;
|
||||||
|
}
|
||||||
|
void PrintTo(__int128_t v, ::std::ostream* os) {
|
||||||
|
__uint128_t uv = static_cast<__uint128_t>(v);
|
||||||
|
if (v < 0) {
|
||||||
|
*os << "-";
|
||||||
|
uv = -uv;
|
||||||
|
}
|
||||||
|
PrintTo(uv, os);
|
||||||
|
}
|
||||||
|
#endif // __SIZEOF_INT128__
|
||||||
|
|
||||||
// Prints the given array of characters to the ostream. CharType must be either
|
// Prints the given array of characters to the ostream. CharType must be either
|
||||||
// char, char8_t, char16_t, char32_t, or wchar_t.
|
// char, char8_t, char16_t, char32_t, or wchar_t.
|
||||||
// The array starts at begin, the length is len, it may include '\0' characters
|
// The array starts at begin, the length is len, it may include '\0' characters
|
||||||
// and may not be NUL-terminated.
|
// and may not be NUL-terminated.
|
||||||
template <typename CharType>
|
template <typename CharType>
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static CharFormat
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
PrintCharsAsStringTo(const CharType* begin, size_t len, ostream* os) {
|
||||||
static CharFormat PrintCharsAsStringTo(
|
|
||||||
const CharType* begin, size_t len, ostream* os) {
|
|
||||||
const char* const quote_prefix = GetCharWidthPrefix(*begin);
|
const char* const quote_prefix = GetCharWidthPrefix(*begin);
|
||||||
*os << quote_prefix << "\"";
|
*os << quote_prefix << "\"";
|
||||||
bool is_previous_hex = false;
|
bool is_previous_hex = false;
|
||||||
|
@ -340,12 +363,11 @@ static CharFormat PrintCharsAsStringTo(
|
||||||
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
||||||
// 'begin'. CharType must be either char or wchar_t.
|
// 'begin'. CharType must be either char or wchar_t.
|
||||||
template <typename CharType>
|
template <typename CharType>
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static void
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
UniversalPrintCharArray(const CharType* begin, size_t len,
|
||||||
static void UniversalPrintCharArray(
|
ostream* os) {
|
||||||
const CharType* begin, size_t len, ostream* os) {
|
|
||||||
// The code
|
// The code
|
||||||
// const char kFoo[] = "foo";
|
// const char kFoo[] = "foo";
|
||||||
// generates an array of 4, not 3, elements, with the last one being '\0'.
|
// generates an array of 4, not 3, elements, with the last one being '\0'.
|
||||||
|
@ -436,7 +458,7 @@ void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool ContainsUnprintableControlCodes(const char* str, size_t length) {
|
bool ContainsUnprintableControlCodes(const char* str, size_t length) {
|
||||||
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
|
const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
|
||||||
|
|
||||||
for (size_t i = 0; i < length; i++) {
|
for (size_t i = 0; i < length; i++) {
|
||||||
unsigned char ch = *s++;
|
unsigned char ch = *s++;
|
||||||
|
@ -454,10 +476,10 @@ bool ContainsUnprintableControlCodes(const char* str, size_t length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
|
bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t <= 0xbf; }
|
||||||
|
|
||||||
bool IsValidUTF8(const char* str, size_t length) {
|
bool IsValidUTF8(const char* str, size_t length) {
|
||||||
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
|
const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
|
||||||
|
|
||||||
for (size_t i = 0; i < length;) {
|
for (size_t i = 0; i < length;) {
|
||||||
unsigned char lead = s[i++];
|
unsigned char lead = s[i++];
|
||||||
|
@ -470,15 +492,13 @@ bool IsValidUTF8(const char* str, size_t length) {
|
||||||
} else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
|
} else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
|
||||||
++i; // 2-byte character
|
++i; // 2-byte character
|
||||||
} else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
|
} else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
|
||||||
IsUTF8TrailByte(s[i]) &&
|
IsUTF8TrailByte(s[i]) && IsUTF8TrailByte(s[i + 1]) &&
|
||||||
IsUTF8TrailByte(s[i + 1]) &&
|
|
||||||
// check for non-shortest form and surrogate
|
// check for non-shortest form and surrogate
|
||||||
(lead != 0xe0 || s[i] >= 0xa0) &&
|
(lead != 0xe0 || s[i] >= 0xa0) &&
|
||||||
(lead != 0xed || s[i] < 0xa0)) {
|
(lead != 0xed || s[i] < 0xa0)) {
|
||||||
i += 2; // 3-byte character
|
i += 2; // 3-byte character
|
||||||
} else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
|
} else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
|
||||||
IsUTF8TrailByte(s[i]) &&
|
IsUTF8TrailByte(s[i]) && IsUTF8TrailByte(s[i + 1]) &&
|
||||||
IsUTF8TrailByte(s[i + 1]) &&
|
|
||||||
IsUTF8TrailByte(s[i + 2]) &&
|
IsUTF8TrailByte(s[i + 2]) &&
|
||||||
// check for non-shortest form
|
// check for non-shortest form
|
||||||
(lead != 0xf0 || s[i] >= 0x90) &&
|
(lead != 0xf0 || s[i] >= 0x90) &&
|
||||||
|
@ -502,7 +522,7 @@ void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
|
||||||
|
|
||||||
void PrintStringTo(const ::std::string& s, ostream* os) {
|
void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||||
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
||||||
if (GTEST_FLAG(print_utf8)) {
|
if (GTEST_FLAG_GET(print_utf8)) {
|
||||||
ConditionalPrintAsText(s.data(), s.size(), os);
|
ConditionalPrintAsText(s.data(), s.size(), os);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,8 @@ std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
|
||||||
return os << internal::FormatFileLocation(result.file_name(),
|
return os << internal::FormatFileLocation(result.file_name(),
|
||||||
result.line_number())
|
result.line_number())
|
||||||
<< " "
|
<< " "
|
||||||
<< (result.type() == TestPartResult::kSuccess
|
<< (result.type() == TestPartResult::kSuccess ? "Success"
|
||||||
? "Success"
|
: result.type() == TestPartResult::kSkip ? "Skipped"
|
||||||
: result.type() == TestPartResult::kSkip
|
|
||||||
? "Skipped"
|
|
||||||
: result.type() == TestPartResult::kFatalFailure
|
: result.type() == TestPartResult::kFatalFailure
|
||||||
? "Fatal failure"
|
? "Fatal failure"
|
||||||
: "Non-fatal failure")
|
: "Non-fatal failure")
|
||||||
|
@ -86,8 +84,8 @@ namespace internal {
|
||||||
|
|
||||||
HasNewFatalFailureHelper::HasNewFatalFailureHelper()
|
HasNewFatalFailureHelper::HasNewFatalFailureHelper()
|
||||||
: has_new_fatal_failure_(false),
|
: has_new_fatal_failure_(false),
|
||||||
original_reporter_(GetUnitTestImpl()->
|
original_reporter_(
|
||||||
GetTestPartResultReporterForCurrentThread()) {
|
GetUnitTestImpl()->GetTestPartResultReporterForCurrentThread()) {
|
||||||
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
|
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +96,7 @@ HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
|
||||||
|
|
||||||
void HasNewFatalFailureHelper::ReportTestPartResult(
|
void HasNewFatalFailureHelper::ReportTestPartResult(
|
||||||
const TestPartResult& result) {
|
const TestPartResult& result) {
|
||||||
if (result.fatally_failed())
|
if (result.fatally_failed()) has_new_fatal_failure_ = true;
|
||||||
has_new_fatal_failure_ = true;
|
|
||||||
original_reporter_->ReportTestPartResult(result);
|
original_reporter_->ReportTestPartResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
#include "gtest/gtest-typed-test.h"
|
#include "gtest/gtest-typed-test.h"
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
@ -38,8 +37,7 @@ namespace internal {
|
||||||
// Skips to the first non-space char in str. Returns an empty string if str
|
// Skips to the first non-space char in str. Returns an empty string if str
|
||||||
// contains only whitespace characters.
|
// contains only whitespace characters.
|
||||||
static const char* SkipSpaces(const char* str) {
|
static const char* SkipSpaces(const char* str) {
|
||||||
while (IsSpace(*str))
|
while (IsSpace(*str)) str++;
|
||||||
str++;
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +83,7 @@ const char* TypedTestSuitePState::VerifyRegisteredTestNames(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RegisteredTestIter it = registered_tests_.begin();
|
for (RegisteredTestIter it = registered_tests_.begin();
|
||||||
it != registered_tests_.end();
|
it != registered_tests_.end(); ++it) {
|
||||||
++it) {
|
|
||||||
if (tests.count(it->first) == 0) {
|
if (tests.count(it->first) == 0) {
|
||||||
errors << "You forgot to list test " << it->first << ".\n";
|
errors << "You forgot to list test " << it->first << ".\n";
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,15 +28,14 @@
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
#if GTEST_OS_ESP8266 || GTEST_OS_ESP32
|
#if GTEST_OS_ESP8266 || GTEST_OS_ESP32
|
||||||
#if GTEST_OS_ESP8266
|
#if GTEST_OS_ESP8266
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
void setup() {
|
void setup() { testing::InitGoogleTest(); }
|
||||||
testing::InitGoogleTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() { RUN_ALL_TESTS(); }
|
void loop() { RUN_ALL_TESTS(); }
|
||||||
|
|
||||||
|
|
|
@ -1,57 +1,50 @@
|
||||||
CMAKE_MINIMUM_REQUIRED( VERSION 3.10 )
|
CMAKE_MINIMUM_REQUIRED( VERSION 3.8 )
|
||||||
PROJECT( OpenDDL-Parser )
|
PROJECT( OpenDDL-Parser )
|
||||||
SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
|
# read version number from cpp file of the form: static const char *Version = "0.4.0";
|
||||||
SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
|
file ( READ code/OpenDDLParser.cpp _ver )
|
||||||
SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
|
string( REGEX MATCH "static const char [*]Version[ ]*=[ ]*\"[^\"]*\"" _ver_line "${_ver}" )
|
||||||
SET ( OPENDDL_PARSER_VERSION ${OPENDDL_PARSER_VERSION_MAJOR}.${OPENDDL_PARSER_VERSION_MINOR}.${OPENDDL_PARSER_VERSION_PATCH} )
|
string( REGEX MATCH "[0-9]+\.[0-9]+\.[0-9]+" openddlparser_VERSION "${_ver_line}" )
|
||||||
SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
|
SET ( PROJECT_VERSION "${openddlparser_VERSION}" )
|
||||||
|
if ( "${PROJECT_VERSION}" STREQUAL "" )
|
||||||
|
message( FATAL_ERROR "Cannot find 'static const char *Version' in 'code/OpenDDLParser.cpp'" )
|
||||||
|
endif()
|
||||||
|
message(STATUS "openddlparser_VERSION: ${openddlparser_VERSION}")
|
||||||
|
|
||||||
option( DDL_DEBUG_OUTPUT "Set to ON to use output debug texts" OFF )
|
option( DDL_DEBUG_OUTPUT "Set to ON to use output debug texts" OFF )
|
||||||
option( DDL_STATIC_LIBRARY "Set to ON to build static libary of OpenDDL Parser." ON )
|
option( DDL_STATIC_LIBRARY "Deprecated, use BUILD_SHARED_LIBS instead." ON )
|
||||||
option( COVERALLS "Generate coveralls data" OFF )
|
# for backwards compatibility use DDL_STATIC_LIBRARY as initial value for cmake variable BUILD_SHARED_LIBS
|
||||||
|
# https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
|
|
||||||
find_package(Threads)
|
|
||||||
else()
|
|
||||||
add_definitions( -D_CRT_SECURE_NO_WARNINGS )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if ( DDL_STATIC_LIBRARY )
|
if ( DDL_STATIC_LIBRARY )
|
||||||
add_definitions( -DOPENDDL_STATIC_LIBARY )
|
set ( build_shared_libs_default OFF )
|
||||||
|
else()
|
||||||
|
set ( build_shared_libs_default ON )
|
||||||
endif()
|
endif()
|
||||||
|
option( DDL_BUILD_SHARED_LIBS "Set to ON to build shared libary of OpenDDL Parser." ${build_shared_libs_default} )
|
||||||
|
option( COVERALLS "Generate coveralls data" OFF )
|
||||||
|
option( DDL_DOCUMENTATION "Set to ON to opt in generating API documentation with Doxygen" OFF )
|
||||||
|
option( DDL_BUILD_TESTS "Set to OFF to not build tests by default" ON )
|
||||||
|
option( DDL_BUILD_PARSER_DEMO "Set to OFF to opt out building parser demo" ON )
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING")
|
add_definitions(
|
||||||
add_definitions(-DGTEST_HAS_TR1_TUPLE=0)
|
-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING
|
||||||
|
-DGTEST_HAS_TR1_TUPLE=0
|
||||||
|
-D_CRT_SECURE_NO_WARNINGS
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions( -DOPENDDLPARSER_BUILD )
|
|
||||||
add_definitions( -D_VARIADIC_MAX=10 )
|
add_definitions( -D_VARIADIC_MAX=10 )
|
||||||
add_definitions( -DGTEST_HAS_PTHREAD=0 )
|
add_definitions( -DGTEST_HAS_PTHREAD=0 )
|
||||||
if ( DDL_DEBUG_OUTPUT )
|
if ( DDL_DEBUG_OUTPUT )
|
||||||
add_definitions( -DDDL_DEBUG_HEADER_NAME)
|
add_definitions( -DDDL_DEBUG_HEADER_NAME)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(
|
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||||
./
|
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib )
|
||||||
include/
|
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib )
|
||||||
contrib/gtest-1.7.0/include
|
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin )
|
||||||
contrib/gtest-1.7.0/
|
|
||||||
)
|
|
||||||
|
|
||||||
link_directories(
|
if (MSVC)
|
||||||
${CMAKE_HOME_DIRECTORY}/lib
|
|
||||||
)
|
|
||||||
|
|
||||||
SET( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake )
|
|
||||||
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
|
|
||||||
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
|
|
||||||
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
|
|
||||||
|
|
||||||
if( WIN32 AND NOT CYGWIN )
|
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc" ) # Force to always compile with W4
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc" ) # Force to always compile with W4
|
||||||
if( CMAKE_CXX_FLAGS MATCHES "/W[0-4]" )
|
if( CMAKE_CXX_FLAGS MATCHES "/W[0-4]" )
|
||||||
string( REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" )
|
string( REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" )
|
||||||
|
@ -72,21 +65,16 @@ if (COVERALLS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Include the doc component.
|
# Include the doc component.
|
||||||
FIND_PACKAGE( doxygen )
|
if(DDL_DOCUMENTATION)
|
||||||
IF ( DOXYGEN_FOUND )
|
find_package(Doxygen REQUIRED)
|
||||||
CONFIGURE_FILE( doc/openddlparser_doc.in doc/doxygenfile @ONLY )
|
CONFIGURE_FILE( doc/openddlparser_doc.in doc/doxygenfile @ONLY )
|
||||||
ADD_CUSTOM_TARGET( doc ALL ${DOXYGEN_EXECUTABLE} doc/doxygenfile
|
add_custom_target(doc ALL
|
||||||
|
${DOXYGEN_EXECUTABLE} doc/doxygenfile
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMENT "Generating API documentation with Doxygen" VERBATIM )
|
COMMENT "Generating API documentation with Doxygen" VERBATIM )
|
||||||
ENDIF ( DOXYGEN_FOUND )
|
endif()
|
||||||
|
|
||||||
SET ( openddl_parser_src
|
SET ( openddlparser_headers
|
||||||
code/OpenDDLCommon.cpp
|
|
||||||
code/OpenDDLExport.cpp
|
|
||||||
code/OpenDDLParser.cpp
|
|
||||||
code/OpenDDLStream.cpp
|
|
||||||
code/DDLNode.cpp
|
|
||||||
code/Value.cpp
|
|
||||||
include/openddlparser/OpenDDLCommon.h
|
include/openddlparser/OpenDDLCommon.h
|
||||||
include/openddlparser/OpenDDLExport.h
|
include/openddlparser/OpenDDLExport.h
|
||||||
include/openddlparser/OpenDDLParser.h
|
include/openddlparser/OpenDDLParser.h
|
||||||
|
@ -95,36 +83,51 @@ SET ( openddl_parser_src
|
||||||
include/openddlparser/DDLNode.h
|
include/openddlparser/DDLNode.h
|
||||||
include/openddlparser/Value.h
|
include/openddlparser/Value.h
|
||||||
include/openddlparser/TPoolAllocator.h
|
include/openddlparser/TPoolAllocator.h
|
||||||
README.md
|
)
|
||||||
|
SET ( openddlparser_src
|
||||||
|
code/OpenDDLCommon.cpp
|
||||||
|
code/OpenDDLExport.cpp
|
||||||
|
code/OpenDDLParser.cpp
|
||||||
|
code/OpenDDLStream.cpp
|
||||||
|
code/DDLNode.cpp
|
||||||
|
code/Value.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
SOURCE_GROUP( code FILES ${openddl_parser_src} )
|
SOURCE_GROUP( code FILES ${openddlparser_src} )
|
||||||
|
|
||||||
if ( DDL_STATIC_LIBRARY )
|
ADD_LIBRARY( openddlparser ${openddlparser_src})
|
||||||
ADD_LIBRARY( openddl_parser STATIC
|
|
||||||
${openddl_parser_src}
|
target_include_directories(openddlparser PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
|
||||||
|
|
||||||
|
target_compile_features(openddlparser PUBLIC cxx_std_11)
|
||||||
|
|
||||||
|
if(DDL_BUILD_SHARED_LIBS)
|
||||||
|
set_target_properties(openddlparser PROPERTIES
|
||||||
|
CXX_VISIBILITY_PRESET hidden
|
||||||
|
VISIBILITY_INLINES_HIDDEN TRUE
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
ADD_LIBRARY( openddl_parser SHARED
|
target_compile_definitions(openddlparser PUBLIC OPENDDL_STATIC_LIBARY)
|
||||||
${openddl_parser_src}
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
SET ( GTEST_PATH contrib/gtest-1.7.0 )
|
set_target_properties( openddlparser PROPERTIES PUBLIC_HEADER "${openddlparser_headers}")
|
||||||
|
|
||||||
SET ( gtest_src
|
if (DDL_BUILD_TESTS)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
SET ( GTEST_PATH contrib/gtest-1.7.0 )
|
||||||
|
|
||||||
|
SET ( gtest_src
|
||||||
${GTEST_PATH}/src/gtest-death-test.cc
|
${GTEST_PATH}/src/gtest-death-test.cc
|
||||||
${GTEST_PATH}/src/gtest-filepath.cc
|
${GTEST_PATH}/src/gtest-filepath.cc
|
||||||
${GTEST_PATH}/src/gtest-internal-inl.h
|
|
||||||
${GTEST_PATH}/src/gtest-port.cc
|
${GTEST_PATH}/src/gtest-port.cc
|
||||||
${GTEST_PATH}/src/gtest-printers.cc
|
${GTEST_PATH}/src/gtest-printers.cc
|
||||||
${GTEST_PATH}/src/gtest-test-part.cc
|
${GTEST_PATH}/src/gtest-test-part.cc
|
||||||
${GTEST_PATH}/src/gtest-typed-test.cc
|
${GTEST_PATH}/src/gtest-typed-test.cc
|
||||||
${GTEST_PATH}/src/gtest.cc
|
${GTEST_PATH}/src/gtest.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
SET( openddl_parser_unittest_src
|
SET( openddlparser_unittest_src
|
||||||
test/UnitTestCommon.h
|
|
||||||
test/DDLNodeTest.cpp
|
test/DDLNodeTest.cpp
|
||||||
test/OpenDDLCommonTest.cpp
|
test/OpenDDLCommonTest.cpp
|
||||||
test/OpenDDLExportTest.cpp
|
test/OpenDDLExportTest.cpp
|
||||||
|
@ -136,35 +139,73 @@ SET( openddl_parser_unittest_src
|
||||||
test/OpenDDLDefectsTest.cpp
|
test/OpenDDLDefectsTest.cpp
|
||||||
test/OssFuzzTest.cpp
|
test/OssFuzzTest.cpp
|
||||||
test/main.cpp
|
test/main.cpp
|
||||||
)
|
)
|
||||||
add_definitions(-DOPENDDL_TEST_DATA="${CMAKE_CURRENT_LIST_DIR}/test/TestData")
|
|
||||||
|
|
||||||
SOURCE_GROUP( code FILES ${openddl_parser_unittest_src} )
|
SOURCE_GROUP( code FILES ${openddlparser_unittest_src} )
|
||||||
SOURCE_GROUP( gtest FILES ${gtest_src} )
|
SOURCE_GROUP( gtest FILES ${gtest_src} )
|
||||||
|
|
||||||
ADD_EXECUTABLE( openddl_parser_unittest
|
ADD_EXECUTABLE( openddlparser_unittest
|
||||||
${gtest_src}
|
${gtest_src}
|
||||||
${openddl_parser_unittest_src}
|
${openddlparser_unittest_src}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries( openddl_parser_unittest openddl_parser ${CMAKE_THREAD_LIBS_INIT} )
|
target_include_directories(openddlparser_unittest
|
||||||
|
PRIVATE
|
||||||
|
${GTEST_PATH}
|
||||||
|
${GTEST_PATH}/include
|
||||||
|
)
|
||||||
|
target_link_libraries(openddlparser_unittest openddlparser Threads::Threads)
|
||||||
|
target_compile_features(openddlparser_unittest PRIVATE cxx_std_11)
|
||||||
|
target_compile_definitions(openddlparser_unittest PRIVATE OPENDDL_TEST_DATA="${PROJECT_SOURCE_DIR}/test/TestData")
|
||||||
|
endif ()
|
||||||
|
|
||||||
SET( openddl_parser_demo_src
|
if (DDL_BUILD_PARSER_DEMO)
|
||||||
|
SET( openddlparser_demo_src
|
||||||
demo/main.cpp
|
demo/main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (COVERALLS)
|
if (COVERALLS)
|
||||||
set(COVERAGE_SRCS ${gtest_src} ${openddl_parser_unittest_src} )
|
set(COVERAGE_SRCS ${gtest_src} ${openddlparser_unittest_src} )
|
||||||
|
|
||||||
# Create the coveralls target.
|
# Create the coveralls target.
|
||||||
coveralls_setup(
|
coveralls_setup(
|
||||||
"${COVERAGE_SRCS}" # The source files.
|
"${COVERAGE_SRCS}" # The source files.
|
||||||
ON # If we should upload.
|
ON # If we should upload.
|
||||||
"${PROJECT_SOURCE_DIR}/cmake/") # (Optional) Alternate project cmake module path.
|
"${PROJECT_SOURCE_DIR}/cmake/") # (Optional) Alternate project cmake module path.
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
ADD_EXECUTABLE( openddl_parser_demo
|
ADD_EXECUTABLE( openddlparser_demo
|
||||||
${openddl_parser_demo_src}
|
${openddlparser_demo_src}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries( openddl_parser_demo openddl_parser )
|
target_link_libraries( openddlparser_demo openddlparser )
|
||||||
|
target_compile_features(openddlparser_demo PRIVATE cxx_std_11)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
|
||||||
|
install(TARGETS openddlparser
|
||||||
|
EXPORT openddlparser-targets
|
||||||
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||||
|
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
|
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
|
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
|
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/openddlparser")
|
||||||
|
|
||||||
|
export(EXPORT openddlparser-targets
|
||||||
|
FILE openddlparser-config.cmake
|
||||||
|
NAMESPACE openddlparser::)
|
||||||
|
|
||||||
|
install(EXPORT openddlparser-targets
|
||||||
|
FILE openddlparser-config.cmake
|
||||||
|
NAMESPACE openddlparser::
|
||||||
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/openddlparser")
|
||||||
|
|
||||||
|
write_basic_package_version_file(
|
||||||
|
"${CMAKE_BINARY_DIR}/openddlparser-config-version.cmake"
|
||||||
|
COMPATIBILITY SameMajorVersion)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES "${CMAKE_BINARY_DIR}/openddlparser-config-version.cmake"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/openddlparser")
|
||||||
|
|
|
@ -224,7 +224,7 @@ bool OpenDDLExport::writeValueType(Value::ValueType type, size_t numItems, std::
|
||||||
statement += "[";
|
statement += "[";
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
::memset(buffer, '\0', 256 * sizeof(char));
|
::memset(buffer, '\0', 256 * sizeof(char));
|
||||||
sprintf(buffer, "%d", static_cast<int>(numItems));
|
snprintf(buffer, sizeof(buffer), "%d", static_cast<int>(numItems));
|
||||||
statement += buffer;
|
statement += buffer;
|
||||||
statement += "]";
|
statement += "]";
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ bool OpenDDLExport::writeValue(Value *val, std::string &statement) {
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
::memset(buffer, '\0', 256 * sizeof(char));
|
::memset(buffer, '\0', 256 * sizeof(char));
|
||||||
sprintf(buffer, "%d", val->getInt16());
|
snprintf(buffer, sizeof(buffer), "%d", val->getInt16());
|
||||||
statement += buffer;
|
statement += buffer;
|
||||||
} break;
|
} break;
|
||||||
case Value::ValueType::ddl_int32: {
|
case Value::ValueType::ddl_int32: {
|
||||||
|
@ -263,7 +263,7 @@ bool OpenDDLExport::writeValue(Value *val, std::string &statement) {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
::memset(buffer, '\0', 256 * sizeof(char));
|
::memset(buffer, '\0', 256 * sizeof(char));
|
||||||
const int i = static_cast<int>(val->getInt32());
|
const int i = static_cast<int>(val->getInt32());
|
||||||
sprintf(buffer, "%d", i);
|
snprintf(buffer, sizeof(buffer), "%d", i);
|
||||||
statement += buffer;
|
statement += buffer;
|
||||||
} break;
|
} break;
|
||||||
case Value::ValueType::ddl_int64: {
|
case Value::ValueType::ddl_int64: {
|
||||||
|
|
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
@ -3,8 +3,7 @@
|
||||||
Open Asset Import Library (assimp)
|
Open Asset Import Library (assimp)
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006-2020, assimp team
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
@ -60,7 +59,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef AI_CONFIG_H_INC
|
#ifndef AI_CONFIG_H_INC
|
||||||
#define AI_CONFIG_H_INC
|
#define AI_CONFIG_H_INC
|
||||||
|
|
||||||
|
|
||||||
// ###########################################################################
|
// ###########################################################################
|
||||||
// LIBRARY SETTINGS
|
// LIBRARY SETTINGS
|
||||||
// General, global settings
|
// General, global settings
|
||||||
|
@ -79,7 +77,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define AI_CONFIG_GLOB_MEASURE_TIME \
|
#define AI_CONFIG_GLOB_MEASURE_TIME \
|
||||||
"GLOB_MEASURE_TIME"
|
"GLOB_MEASURE_TIME"
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** @brief Global setting to disable generation of skeleton dummy meshes
|
/** @brief Global setting to disable generation of skeleton dummy meshes
|
||||||
*
|
*
|
||||||
|
@ -91,34 +88,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define AI_CONFIG_IMPORT_NO_SKELETON_MESHES \
|
#define AI_CONFIG_IMPORT_NO_SKELETON_MESHES \
|
||||||
"IMPORT_NO_SKELETON_MESHES"
|
"IMPORT_NO_SKELETON_MESHES"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# if 0 // not implemented yet
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
/** @brief Set Assimp's multithreading policy.
|
|
||||||
*
|
|
||||||
* This setting is ignored if Assimp was built without boost.thread
|
|
||||||
* support (ASSIMP_BUILD_NO_THREADING, which is implied by ASSIMP_BUILD_BOOST_WORKAROUND).
|
|
||||||
* Possible values are: -1 to let Assimp decide what to do, 0 to disable
|
|
||||||
* multithreading entirely and any number larger than 0 to force a specific
|
|
||||||
* number of threads. Assimp is always free to ignore this settings, which is
|
|
||||||
* merely a hint. Usually, the default value (-1) will be fine. However, if
|
|
||||||
* Assimp is used concurrently from multiple user threads, it might be useful
|
|
||||||
* to limit each Importer instance to a specific number of cores.
|
|
||||||
*
|
|
||||||
* For more information, see the @link threading Threading page@endlink.
|
|
||||||
* Property type: int, default value: -1.
|
|
||||||
*/
|
|
||||||
#define AI_CONFIG_GLOB_MULTITHREADING \
|
|
||||||
"GLOB_MULTITHREADING"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ###########################################################################
|
// ###########################################################################
|
||||||
// POST PROCESSING SETTINGS
|
// POST PROCESSING SETTINGS
|
||||||
// Various stuff to fine-tune the behavior of a specific post processing step.
|
// Various stuff to fine-tune the behavior of a specific post processing step.
|
||||||
// ###########################################################################
|
// ###########################################################################
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** @brief Maximum bone count per mesh for the SplitbyBoneCount step.
|
/** @brief Maximum bone count per mesh for the SplitbyBoneCount step.
|
||||||
*
|
*
|
||||||
|
@ -131,13 +105,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define AI_CONFIG_PP_SBBC_MAX_BONES \
|
#define AI_CONFIG_PP_SBBC_MAX_BONES \
|
||||||
"PP_SBBC_MAX_BONES"
|
"PP_SBBC_MAX_BONES"
|
||||||
|
|
||||||
|
|
||||||
// default limit for bone count
|
// default limit for bone count
|
||||||
#if (!defined AI_SBBC_DEFAULT_MAX_BONES)
|
#if (!defined AI_SBBC_DEFAULT_MAX_BONES)
|
||||||
# define AI_SBBC_DEFAULT_MAX_BONES 60
|
# define AI_SBBC_DEFAULT_MAX_BONES 60
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** @brief Specifies the maximum angle that may be between two vertex tangents
|
/** @brief Specifies the maximum angle that may be between two vertex tangents
|
||||||
* that their tangents and bi-tangents are smoothed.
|
* that their tangents and bi-tangents are smoothed.
|
||||||
|
@ -174,7 +146,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE \
|
#define AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE \
|
||||||
"PP_GSN_MAX_SMOOTHING_ANGLE"
|
"PP_GSN_MAX_SMOOTHING_ANGLE"
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** @brief Sets the colormap (= palette) to be used to decode embedded
|
/** @brief Sets the colormap (= palette) to be used to decode embedded
|
||||||
* textures in MDL (Quake or 3DGS) files.
|
* textures in MDL (Quake or 3DGS) files.
|
||||||
|
@ -541,7 +512,6 @@ enum aiComponent
|
||||||
#define AI_CONFIG_FAVOUR_SPEED \
|
#define AI_CONFIG_FAVOUR_SPEED \
|
||||||
"FAVOUR_SPEED"
|
"FAVOUR_SPEED"
|
||||||
|
|
||||||
|
|
||||||
// ###########################################################################
|
// ###########################################################################
|
||||||
// IMPORTER SETTINGS
|
// IMPORTER SETTINGS
|
||||||
// Various stuff to fine-tune the behaviour of specific importer plugins.
|
// Various stuff to fine-tune the behaviour of specific importer plugins.
|
||||||
|
@ -1090,6 +1060,8 @@ enum aiComponent
|
||||||
* Point clouds are only a collection of vertices which have nor spatial organization
|
* Point clouds are only a collection of vertices which have nor spatial organization
|
||||||
* by a face and the validation process will remove them. Enabling this feature will
|
* by a face and the validation process will remove them. Enabling this feature will
|
||||||
* switch off the flag and enable the functionality to export pure point clouds.
|
* switch off the flag and enable the functionality to export pure point clouds.
|
||||||
|
*
|
||||||
|
* Property type: Bool. Default value: false.
|
||||||
*/
|
*/
|
||||||
#define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS"
|
#define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS"
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2022, assimp team
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -36,7 +35,6 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -55,21 +53,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <assimp/defs.h>
|
#include <assimp/defs.h>
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
template <typename TReal> class aiVector3t;
|
template <typename TReal> class aiVector3t;
|
||||||
template <typename TReal> class aiMatrix3x3t;
|
template <typename TReal> class aiMatrix3x3t;
|
||||||
template <typename TReal> class aiMatrix4x4t;
|
template <typename TReal> class aiMatrix4x4t;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Represents a quaternion in a 4D vector. */
|
/**
|
||||||
|
* @brief This class represents a quaternion as a 4D vector.
|
||||||
|
*/
|
||||||
template <typename TReal>
|
template <typename TReal>
|
||||||
class aiQuaterniont
|
class aiQuaterniont {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
aiQuaterniont() AI_NO_EXCEPT : w(1.0), x(), y(), z() {}
|
aiQuaterniont() AI_NO_EXCEPT : w(1.0), x(), y(), z() {}
|
||||||
aiQuaterniont(TReal pw, TReal px, TReal py, TReal pz)
|
aiQuaterniont(TReal pw, TReal px, TReal py, TReal pz)
|
||||||
: w(pw), x(px), y(py), z(pz) {}
|
: w(pw), x(px), y(py), z(pz) {}
|
||||||
|
|
||||||
/** Construct from rotation matrix. Result is undefined if the matrix is not orthonormal. */
|
/**
|
||||||
|
* @brief Construct from rotation matrix. Result is undefined if the matrix is not orthonormal.
|
||||||
|
*/
|
||||||
explicit aiQuaterniont( const aiMatrix3x3t<TReal>& pRotMatrix);
|
explicit aiQuaterniont( const aiMatrix3x3t<TReal>& pRotMatrix);
|
||||||
|
|
||||||
/** Construct from euler angles */
|
/** Construct from euler angles */
|
||||||
|
@ -84,8 +86,6 @@ public:
|
||||||
/** Returns a matrix representation of the quaternion */
|
/** Returns a matrix representation of the quaternion */
|
||||||
aiMatrix3x3t<TReal> GetMatrix() const;
|
aiMatrix3x3t<TReal> GetMatrix() const;
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool operator== (const aiQuaterniont& o) const;
|
bool operator== (const aiQuaterniont& o) const;
|
||||||
bool operator!= (const aiQuaterniont& o) const;
|
bool operator!= (const aiQuaterniont& o) const;
|
||||||
|
|
||||||
|
@ -94,23 +94,30 @@ public:
|
||||||
|
|
||||||
bool Equal(const aiQuaterniont &o, TReal epsilon = ai_epsilon) const;
|
bool Equal(const aiQuaterniont &o, TReal epsilon = ai_epsilon) const;
|
||||||
|
|
||||||
public:
|
/**
|
||||||
|
* @brief Will normalize the quaternion representation.
|
||||||
/** Normalize the quaternion */
|
*/
|
||||||
aiQuaterniont& Normalize();
|
aiQuaterniont& Normalize();
|
||||||
|
|
||||||
/** Compute quaternion conjugate */
|
/**
|
||||||
aiQuaterniont& Conjugate ();
|
* @brief Will compute the quaternion conjugate. The result will be stored in the instance.
|
||||||
|
*/
|
||||||
|
aiQuaterniont& Conjugate();
|
||||||
|
|
||||||
/** Rotate a point by this quaternion */
|
/**
|
||||||
aiVector3t<TReal> Rotate (const aiVector3t<TReal>& in) const;
|
* @brief Rotate a point by this quaternion
|
||||||
|
*/
|
||||||
|
aiVector3t<TReal> Rotate(const aiVector3t<TReal>& in) const;
|
||||||
|
|
||||||
/** Multiply two quaternions */
|
/**
|
||||||
aiQuaterniont operator* (const aiQuaterniont& two) const;
|
* @brief Multiply two quaternions
|
||||||
|
* @param two The other quaternion.
|
||||||
|
* @return The result of the multiplication.
|
||||||
|
*/
|
||||||
|
aiQuaterniont operator * (const aiQuaterniont& two) const;
|
||||||
|
|
||||||
public:
|
/**
|
||||||
|
* @brief Performs a spherical interpolation between two quaternions and writes the result into the third.
|
||||||
/** Performs a spherical interpolation between two quaternions and writes the result into the third.
|
|
||||||
* @param pOut Target object to received the interpolated rotation.
|
* @param pOut Target object to received the interpolated rotation.
|
||||||
* @param pStart Start rotation of the interpolation at factor == 0.
|
* @param pStart Start rotation of the interpolation at factor == 0.
|
||||||
* @param pEnd End rotation, factor == 1.
|
* @param pEnd End rotation, factor == 1.
|
||||||
|
@ -119,13 +126,11 @@ public:
|
||||||
static void Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart,
|
static void Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart,
|
||||||
const aiQuaterniont& pEnd, TReal pFactor);
|
const aiQuaterniont& pEnd, TReal pFactor);
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//! w,x,y,z components of the quaternion
|
//! w,x,y,z components of the quaternion
|
||||||
TReal w, x, y, z;
|
TReal w, x, y, z;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
typedef aiQuaterniont<ai_real> aiQuaternion;
|
using aiQuaternion = aiQuaterniont<ai_real>;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
|
@ -237,7 +237,8 @@ inline void aiQuaterniont<TReal>::Interpolate( aiQuaterniont& pOut, const aiQuat
|
||||||
|
|
||||||
// Calculate coefficients
|
// Calculate coefficients
|
||||||
TReal sclp, sclq;
|
TReal sclp, sclq;
|
||||||
if( (static_cast<TReal>(1.0) - cosom) > static_cast<TReal>(0.0001)) // 0.0001 -> some epsillon
|
|
||||||
|
if ((static_cast<TReal>(1.0) - cosom) > ai_epsilon) // 0.0001 -> some epsillon
|
||||||
{
|
{
|
||||||
// Standard case (slerp)
|
// Standard case (slerp)
|
||||||
TReal omega, sinom;
|
TReal omega, sinom;
|
||||||
|
|
|
@ -89,6 +89,7 @@ SET( COMMON
|
||||||
unit/utProfiler.cpp
|
unit/utProfiler.cpp
|
||||||
unit/utSharedPPData.cpp
|
unit/utSharedPPData.cpp
|
||||||
unit/utStringUtils.cpp
|
unit/utStringUtils.cpp
|
||||||
|
unit/Common/utMaybe.cpp
|
||||||
unit/Common/utMesh.cpp
|
unit/Common/utMesh.cpp
|
||||||
unit/Common/utStandardShapes.cpp
|
unit/Common/utStandardShapes.cpp
|
||||||
unit/Common/uiScene.cpp
|
unit/Common/uiScene.cpp
|
||||||
|
@ -262,6 +263,14 @@ IF(MSVC)
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
IF (ASSIMP_WARNINGS_AS_ERRORS)
|
||||||
|
IF (MSVC)
|
||||||
|
TARGET_COMPILE_OPTIONS(unit PRIVATE /W4 /WX)
|
||||||
|
ELSE()
|
||||||
|
TARGET_COMPILE_OPTIONS(unit PRIVATE -Wall -Werror)
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
target_link_libraries( unit assimp ${platform_libs} )
|
target_link_libraries( unit assimp ${platform_libs} )
|
||||||
|
|
||||||
add_subdirectory(headercheck)
|
add_subdirectory(headercheck)
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software 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 the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
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 "UnitTestPCH.h"
|
||||||
|
#include "Common/Maybe.h"
|
||||||
|
|
||||||
|
using namespace Assimp;
|
||||||
|
|
||||||
|
class utMaybe : public ::testing::Test {
|
||||||
|
// empty
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(utMaybe, creationTest) {
|
||||||
|
Maybe<int> first(1);
|
||||||
|
EXPECT_EQ(first.Get(), 1);
|
||||||
|
}
|
|
@ -205,7 +205,7 @@ private:
|
||||||
const char *key_name) {
|
const char *key_name) {
|
||||||
aiNode *global_info = get_global_info(scene);
|
aiNode *global_info = get_global_info(scene);
|
||||||
EXPECT_NE(nullptr, global_info);
|
EXPECT_NE(nullptr, global_info);
|
||||||
T temp;
|
T temp = 0;
|
||||||
EXPECT_TRUE(global_info->mMetaData->Get(key_name, temp));
|
EXPECT_TRUE(global_info->mMetaData->Get(key_name, temp));
|
||||||
EXPECT_EQ(expected_value, temp);
|
EXPECT_EQ(expected_value, temp);
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ private:
|
||||||
aiNode *global_info = get_global_info(scene);
|
aiNode *global_info = get_global_info(scene);
|
||||||
EXPECT_NE(nullptr, global_info);
|
EXPECT_NE(nullptr, global_info);
|
||||||
for (auto it = p_kv.begin(); it != p_kv.end(); ++it) {
|
for (auto it = p_kv.begin(); it != p_kv.end(); ++it) {
|
||||||
T temp;
|
T temp = 0;
|
||||||
EXPECT_TRUE(global_info->mMetaData->Get(it->second, temp));
|
EXPECT_TRUE(global_info->mMetaData->Get(it->second, temp));
|
||||||
EXPECT_EQ(it->first, temp);
|
EXPECT_EQ(it->first, temp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_NE(nullptr, scene->mMaterials);
|
EXPECT_NE(nullptr, scene->mMaterials);
|
||||||
|
|
||||||
aiShadingMode shading_mode;
|
aiShadingMode shading_mode = aiShadingMode_Flat;
|
||||||
scene->mMaterials[0]->Get(AI_MATKEY_SHADING_MODEL, shading_mode);
|
scene->mMaterials[0]->Get(AI_MATKEY_SHADING_MODEL, shading_mode);
|
||||||
EXPECT_EQ(aiShadingMode_Flat, shading_mode);
|
EXPECT_EQ(aiShadingMode_Flat, shading_mode);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ public:
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_NE(nullptr, scene->mMaterials);
|
EXPECT_NE(nullptr, scene->mMaterials);
|
||||||
|
|
||||||
aiBlendMode blend_mode;
|
aiBlendMode blend_mode = aiBlendMode_Default;
|
||||||
scene->mMaterials[0]->Get(AI_MATKEY_BLEND_FUNC, blend_mode);
|
scene->mMaterials[0]->Get(AI_MATKEY_BLEND_FUNC, blend_mode);
|
||||||
EXPECT_EQ(aiBlendMode_Additive, blend_mode);
|
EXPECT_EQ(aiBlendMode_Additive, blend_mode);
|
||||||
}
|
}
|
||||||
|
@ -104,14 +104,14 @@ public:
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_NE(nullptr, scene->mMaterials);
|
EXPECT_NE(nullptr, scene->mMaterials);
|
||||||
|
|
||||||
int texture_flags;
|
int texture_flags = 0;
|
||||||
scene->mMaterials[0]->Get(AI_MATKEY_TEXFLAGS_DIFFUSE(0), texture_flags);
|
scene->mMaterials[0]->Get(AI_MATKEY_TEXFLAGS_DIFFUSE(0), texture_flags);
|
||||||
EXPECT_EQ(aiTextureFlags_UseAlpha, texture_flags);
|
EXPECT_EQ(aiTextureFlags_UseAlpha, texture_flags);
|
||||||
|
|
||||||
// The model has only one texture, a 256 color bitmap with
|
// The model has only one texture, a 256 color bitmap with
|
||||||
// a palette. Pure blue is the last color in the palette,
|
// a palette. Pure blue is the last color in the palette,
|
||||||
// and should be the transparency color.
|
// and should be the transparency color.
|
||||||
aiColor3D transparency_color;
|
aiColor3D transparency_color = {};
|
||||||
scene->mMaterials[0]->Get(AI_MATKEY_COLOR_TRANSPARENT, transparency_color);
|
scene->mMaterials[0]->Get(AI_MATKEY_COLOR_TRANSPARENT, transparency_color);
|
||||||
EXPECT_EQ(aiColor3D(0, 0, 255), transparency_color);
|
EXPECT_EQ(aiColor3D(0, 0, 255), transparency_color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ TEST_F( utVersion, aiGetVersionMajorTest ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F( utVersion, aiGetVersionPatchTest ) {
|
TEST_F( utVersion, aiGetVersionPatchTest ) {
|
||||||
EXPECT_EQ(aiGetVersionPatch(), 4U );
|
EXPECT_EQ(aiGetVersionPatch(), 5U );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F( utVersion, aiGetCompileFlagsTest ) {
|
TEST_F( utVersion, aiGetCompileFlagsTest ) {
|
||||||
|
|