Merge branch 'master' into kimkulling/use_float_for_material_parameters_issue-4685

kimkulling/use_float_for_material_parameters_issue-4685
Kim Kulling 2022-10-18 21:22:51 +02:00 committed by GitHub
commit 5c7215b4b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
108 changed files with 3864 additions and 7466 deletions

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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()

View File

@ -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");
@ -466,41 +465,55 @@ void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
out.Key("value"); out.Key("value");
switch (prop->mType) { switch (prop->mType) {
case aiPTI_Float: case aiPTI_Float:
if (prop->mDataLength / sizeof(float) > 1) { if (prop->mDataLength / sizeof(float) > 1) {
out.StartArray(); out.StartArray();
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(float); ++ii) { for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(float); ++ii) {
out.Element(reinterpret_cast<float *>(prop->mData)[ii]); out.Element(reinterpret_cast<float *>(prop->mData)[ii]);
}
out.EndArray();
} else {
out.SimpleValue(*reinterpret_cast<float *>(prop->mData));
} }
out.EndArray(); break;
} else { case aiPTI_Double:
out.SimpleValue(*reinterpret_cast<float *>(prop->mData)); if (prop->mDataLength / sizeof(double) > 1) {
} out.StartArray();
break; for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(double); ++ii) {
out.Element(reinterpret_cast<double*>(prop->mData)[ii]);
case aiPTI_Integer: }
if (prop->mDataLength / sizeof(int) > 1) { out.EndArray();
out.StartArray(); } else {
for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(int); ++ii) { out.SimpleValue(*reinterpret_cast<double*>(prop->mData));
out.Element(reinterpret_cast<int *>(prop->mData)[ii]);
} }
out.EndArray(); break;
} else { case aiPTI_Integer:
out.SimpleValue(*reinterpret_cast<int *>(prop->mData)); if (prop->mDataLength / sizeof(int) > 1) {
} out.StartArray();
break; for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(int); ++ii) {
out.Element(reinterpret_cast<int *>(prop->mData)[ii]);
}
out.EndArray();
} else {
out.SimpleValue(*reinterpret_cast<int *>(prop->mData));
}
break;
case aiPTI_String: { case aiPTI_String:
aiString s; {
aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s); aiString s;
out.SimpleValue(s); aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
} break; out.SimpleValue(s);
case aiPTI_Buffer: { }
// binary data is written as series of hex-encoded octets break;
out.SimpleValue(prop->mData, prop->mDataLength); case aiPTI_Buffer:
} break; {
default: // binary data is written as series of hex-encoded octets
assert(false); out.SimpleValue(prop->mData, prop->mDataLength);
}
break;
default:
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__");

View File

@ -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);

View File

@ -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) {

View File

@ -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
); );

View File

@ -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,7 +451,15 @@ 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;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); 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));
std::vector<int> uvIndices; std::vector<int> uvIndices;
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
@ -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,7 +503,14 @@ 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;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); 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));
std::vector<int> uvIndices; std::vector<int> uvIndices;
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));

View File

@ -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);
} }

View File

@ -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,20 +51,19 @@ 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;
namespace Assimp { namespace Assimp {
namespace MD5 { namespace MD5 {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Represents a single element in a MD5 file /** Represents a single element in a MD5 file
* *
* 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,54 +392,63 @@ private:
*/ */
void ParseHeader(); void ParseHeader();
bool SkipLine(const char* in, const char** out);
// override these functions to make sure the line counter gets incremented bool SkipLine( );
// ------------------------------------------------------------------- bool SkipSpacesAndLineEnd( const char* in, const char** out);
bool SkipLine( const char* in, const char** out) bool SkipSpacesAndLineEnd();
{ bool SkipSpaces();
++lineNumber;
return Assimp::SkipLine(in,out);
}
// -------------------------------------------------------------------
bool SkipLine( )
{
return SkipLine(buffer,(const char**)&buffer);
}
// -------------------------------------------------------------------
bool SkipSpacesAndLineEnd( const char* in, const char** out)
{
bool bHad = false;
bool running = true;
while (running) {
if( *in == '\r' || *in == '\n') {
// we open files in binary mode, so there could be \r\n sequences ...
if (!bHad) {
bHad = true;
++lineNumber;
}
}
else if (*in == '\t' || *in == ' ')bHad = false;
else break;
in++;
}
*out = in;
return *in != '\0';
}
// -------------------------------------------------------------------
bool SkipSpacesAndLineEnd( )
{
return SkipSpacesAndLineEnd(buffer,(const char**)&buffer);
}
// -------------------------------------------------------------------
bool SkipSpaces( )
{
return Assimp::SkipSpaces((const char**)&buffer);
}
char* buffer; char* buffer;
char* bufferEnd;
unsigned int fileSize; unsigned int fileSize;
unsigned int lineNumber; unsigned int lineNumber;
}; };
}}
// -------------------------------------------------------------------
inline bool MD5Parser::SkipLine(const char* in, const char** out) {
++lineNumber;
return Assimp::SkipLine(in ,out);
}
// -------------------------------------------------------------------
inline bool MD5Parser::SkipLine( ) {
return SkipLine(buffer,(const char**)&buffer);
}
// -------------------------------------------------------------------
inline bool MD5Parser::SkipSpacesAndLineEnd( const char* in, const char** out) {
bool bHad = false;
bool running = true;
while (running) {
if( *in == '\r' || *in == '\n') {
// we open files in binary mode, so there could be \r\n sequences ...
if (!bHad) {
bHad = true;
++lineNumber;
}
}
else if (*in == '\t' || *in == ' ')bHad = false;
else break;
++in;
if (in == bufferEnd) {
break;
}
}
*out = in;
return *in != '\0';
}
// -------------------------------------------------------------------
inline bool MD5Parser::SkipSpacesAndLineEnd() {
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

View File

@ -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);

View File

@ -269,12 +269,12 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
if ( !useVc ) { if ( !useVc ) {
mOutput << "# " << vp.size() << " vertex positions" << endl; mOutput << "# " << vp.size() << " vertex positions" << endl;
for ( const vertexData& v : vp ) { for ( const vertexData& v : vp ) {
mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << endl; mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << endl;
} }
} else { } else {
mOutput << "# " << vp.size() << " vertex positions and colors" << endl; mOutput << "# " << vp.size() << " vertex positions and colors" << endl;
for ( const vertexData& v : vp ) { for ( const vertexData& v : vp ) {
mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << " " << v.vc.r << " " << v.vc.g << " " << v.vc.b << endl; mOutput << "v " << v.vp.x << " " << v.vp.y << " " << v.vp.z << " " << v.vc.r << " " << v.vc.g << " " << v.vc.b << endl;
} }
} }
mOutput << endl; mOutput << endl;

View File

@ -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)) {

View File

@ -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 {

View File

@ -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.

View 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
# define ASSIMP_NEEDS_STB_IMAGE 1 # if ASSIMP_HAS_PBRT_EXPORT
#elif ASSIMP_HAS_M3D # define ASSIMP_NEEDS_STB_IMAGE 1
# define ASSIMP_NEEDS_STB_IMAGE 1 # elif ASSIMP_HAS_M3D
# define STBI_ONLY_PNG # define ASSIMP_NEEDS_STB_IMAGE 1
# define STBI_ONLY_PNG
# endif
#endif #endif
// Ensure all symbols are linked correctly // Ensure all symbols are linked correctly

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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)
######################################################################## ########################################################################

View File

@ -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) { ... }

View File

@ -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()

View File

@ -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_

View File

@ -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,24 +170,24 @@ 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,18 +311,17 @@ 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)); \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ terminator; \
terminator; \ } else \
} else \ ::testing::Message()
::testing::Message()
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and // EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if // ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
@ -330,15 +329,15 @@ 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
} // namespace testing } // namespace testing

View File

@ -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>

View File

@ -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,8 +111,8 @@ 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.
// //
// C++'s symbol lookup rule (i.e. Koenig lookup) says that these // C++'s symbol lookup rule (i.e. Koenig lookup) says that these
@ -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();
} }

View File

@ -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_ = \
@ -453,43 +457,42 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
#define GTEST_GET_FIRST_(first, ...) first #define GTEST_GET_FIRST_(first, ...) first
#define GTEST_GET_SECOND_(first, second, ...) second #define GTEST_GET_SECOND_(first, second, ...) second
#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \ #define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \ static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
gtest_##prefix##test_suite_name##_EvalGenerator_() { \ gtest_##prefix##test_suite_name##_EvalGenerator_() { \
return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \ return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
} \ } \
static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \ static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \ const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \
if (::testing::internal::AlwaysFalse()) { \ if (::testing::internal::AlwaysFalse()) { \
::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \ ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \
__VA_ARGS__, \ __VA_ARGS__, \
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \ ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
DUMMY_PARAM_))); \ DUMMY_PARAM_))); \
auto t = std::make_tuple(__VA_ARGS__); \ auto t = std::make_tuple(__VA_ARGS__); \
static_assert(std::tuple_size<decltype(t)>::value <= 2, \ static_assert(std::tuple_size<decltype(t)>::value <= 2, \
"Too Many Args!"); \ "Too Many Args!"); \
} \ } \
return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \ return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \
__VA_ARGS__, \ __VA_ARGS__, \
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \ ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
DUMMY_PARAM_))))(info); \ DUMMY_PARAM_))))(info); \
} \ } \
static int gtest_##prefix##test_suite_name##_dummy_ \ static int gtest_##prefix##test_suite_name##_dummy_ \
GTEST_ATTRIBUTE_UNUSED_ = \ GTEST_ATTRIBUTE_UNUSED_ = \
::testing::UnitTest::GetInstance() \ ::testing::UnitTest::GetInstance() \
->parameterized_test_registry() \ ->parameterized_test_registry() \
.GetTestSuitePatternHolder<test_suite_name>( \ .GetTestSuitePatternHolder<test_suite_name>( \
GTEST_STRINGIFY_(test_suite_name), \ GTEST_STRINGIFY_(test_suite_name), \
::testing::internal::CodeLocation(__FILE__, __LINE__)) \ ::testing::internal::CodeLocation(__FILE__, __LINE__)) \
->AddTestSuiteInstantiation( \ ->AddTestSuiteInstantiation( \
GTEST_STRINGIFY_(prefix), \ GTEST_STRINGIFY_(prefix), \
&gtest_##prefix##test_suite_name##_EvalGenerator_, \ &gtest_##prefix##test_suite_name##_EvalGenerator_, \
&gtest_##prefix##test_suite_name##_EvalGenerateName_, \ &gtest_##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 {} \
static const ::testing::internal::MarkAsIgnored gtest_allow_ignore_##T( \ static const ::testing::internal::MarkAsIgnored gtest_allow_ignore_##T( \
GTEST_STRINGIFY_(T)) GTEST_STRINGIFY_(T))

View File

@ -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
@ -375,12 +374,12 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char32_t);
// to point to a NUL-terminated string, and thus can print it as a string. // to point to a NUL-terminated string, and thus can print it as a string.
#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ #define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
template <> \ template <> \
class FormatForComparison<CharType*, OtherStringType> { \ class FormatForComparison<CharType*, OtherStringType> { \
public: \ public: \
static ::std::string Format(CharType* value) { \ static ::std::string Format(CharType* value) { \
return ::testing::PrintToString(value); \ return ::testing::PrintToString(value); \
} \ } \
} }
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
@ -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*) {}

View File

@ -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.
// //
@ -141,44 +144,46 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
// helper macro, due to some peculiarity in how the preprocessor // helper macro, due to some peculiarity in how the preprocessor
// works. The AcceptsMacroThatExpandsToUnprotectedComma test in // works. The AcceptsMacroThatExpandsToUnprotectedComma test in
// 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( \
&gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr)); \
{\ { \
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
::testing::ScopedFakeTestPartResultReporter:: \ ::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\ INTERCEPT_ONLY_CURRENT_THREAD, \
GTestExpectFatalFailureHelper::Execute();\ &gtest_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( \
&gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr)); \
{\ { \
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
::testing::ScopedFakeTestPartResultReporter:: \ ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
INTERCEPT_ALL_THREADS, &gtest_failures);\ &gtest_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
@ -207,32 +212,37 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
// instead of // instead of
// 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( \
&gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \ &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
(substr));\ (substr)); \
{\ { \
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
::testing::ScopedFakeTestPartResultReporter:: \ ::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\ INTERCEPT_ONLY_CURRENT_THREAD, \
if (::testing::internal::AlwaysTrue()) { statement; }\ &gtest_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( \
&gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \ &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
(substr));\ (substr)); \
{\ { \
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter( \
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
&gtest_failures);\ &gtest_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_

View File

@ -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

View File

@ -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_
@ -190,7 +192,7 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
typedef ::testing::internal::GenerateTypeList<Types>::type \ typedef ::testing::internal::GenerateTypeList<Types>::type \
GTEST_TYPE_PARAMS_(CaseName); \ GTEST_TYPE_PARAMS_(CaseName); \
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \ typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
GTEST_NAME_GENERATOR_(CaseName) GTEST_NAME_GENERATOR_(CaseName)
#define TYPED_TEST(CaseName, TestName) \ #define TYPED_TEST(CaseName, TestName) \
static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \ static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
@ -256,7 +258,7 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
// #included in multiple translation units linked together. // #included in multiple translation units linked together.
#define TYPED_TEST_SUITE_P(SuiteName) \ #define TYPED_TEST_SUITE_P(SuiteName) \
static ::testing::internal::TypedTestSuitePState \ static ::testing::internal::TypedTestSuitePState \
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName) GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName)
// Legacy API is deprecated but still available // Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
@ -301,21 +303,21 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
REGISTER_TYPED_TEST_SUITE_P REGISTER_TYPED_TEST_SUITE_P
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \ #define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \ static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
"test-suit-prefix must not be empty"); \ "test-suit-prefix must not be empty"); \
static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \ static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTestSuite< \ ::testing::internal::TypeParameterizedTestSuite< \
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \ SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
::testing::internal::GenerateTypeList<Types>::type>:: \ ::testing::internal::GenerateTypeList<Types>::type>:: \
Register(GTEST_STRINGIFY_(Prefix), \ Register(GTEST_STRINGIFY_(Prefix), \
::testing::internal::CodeLocation(__FILE__, __LINE__), \ ::testing::internal::CodeLocation(__FILE__, __LINE__), \
&GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \ &GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
GTEST_STRINGIFY_(SuiteName), \ GTEST_STRINGIFY_(SuiteName), \
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \ GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
::testing::internal::GenerateNames< \ ::testing::internal::GenerateNames< \
::testing::internal::NameGeneratorSelector< \ ::testing::internal::NameGeneratorSelector< \
__VA_ARGS__>::type, \ __VA_ARGS__>::type, \
::testing::internal::GenerateTypeList<Types>::type>()) ::testing::internal::GenerateTypeList<Types>::type>())
// Legacy API is deprecated but still available // Legacy API is deprecated but still available

View File

@ -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:
@ -811,8 +623,8 @@ class GTEST_API_ TestInfo {
} }
// These fields are immutable properties of the test. // These fields are immutable properties of the test.
const std::string test_suite_name_; // test suite name const std::string test_suite_name_; // test suite name
const std::string name_; // Test name const std::string name_; // Test name
// Name of the parameter type, or NULL if this is not a typed or a // Name of the parameter type, or NULL if this is not a typed or a
// type-parameterized test. // type-parameterized test.
const std::unique_ptr<const ::std::string> type_param_; const std::unique_ptr<const ::std::string> type_param_;
@ -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.
@ -1910,7 +1715,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {
// Generates a nonfatal failure at the given source file location with // Generates a nonfatal failure at the given source file location with
// a generic message. // a generic message.
#define ADD_FAILURE_AT(file, line) \ #define ADD_FAILURE_AT(file, line) \
GTEST_MESSAGE_AT_(file, line, "Failed", \ GTEST_MESSAGE_AT_(file, line, "Failed", \
::testing::TestPartResult::kNonFatalFailure) ::testing::TestPartResult::kNonFatalFailure)
@ -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.
@ -1962,16 +1767,15 @@ class TestWithParam : public Test, public WithParamInterface<T> {
// Boolean assertions. Condition can be either a Boolean expression or an // Boolean assertions. Condition can be either a Boolean expression or an
// AssertionResult. For more information on how to use AssertionResult with // AssertionResult. For more information on how to use AssertionResult with
// these macros see comments on that class. // these macros see comments on that class.
#define GTEST_EXPECT_TRUE(condition) \ #define GTEST_EXPECT_TRUE(condition) \
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
GTEST_NONFATAL_FAILURE_) GTEST_NONFATAL_FAILURE_)
#define GTEST_EXPECT_FALSE(condition) \ #define GTEST_EXPECT_FALSE(condition) \
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,17 +1992,17 @@ 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
@ -2214,9 +2017,9 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; // ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
// //
#define ASSERT_NO_FATAL_FAILURE(statement) \ #define ASSERT_NO_FATAL_FAILURE(statement) \
GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
#define EXPECT_NO_FATAL_FAILURE(statement) \ #define EXPECT_NO_FATAL_FAILURE(statement) \
GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
// Causes a trace (including the given source file path and line number, // Causes a trace (including the given source file path and line number,
// and the given message) to be included in every test failure message generated // and the given message) to be included in every test failure message generated
@ -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.
@ -2278,9 +2082,9 @@ class GTEST_API_ ScopedTrace {
// Assuming that each thread maintains its own stack of traces. // Assuming that each thread maintains its own stack of traces.
// 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.
// StaticAssertTypeEq<type1, type2>() compiles if and only if type1 and type2 // StaticAssertTypeEq<type1, type2>() compiles if and only if type1 and type2
@ -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

View File

@ -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 {
@ -72,22 +74,18 @@ namespace testing {
// GTEST_ASSERT_ is the basic statement to which all of the assertions // GTEST_ASSERT_ is the basic statement to which all of the assertions
// in this file reduce. Don't use this in your code. // in this file reduce. Don't use this in your code.
#define GTEST_ASSERT_(expression, on_failure) \ #define GTEST_ASSERT_(expression, on_failure) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (const ::testing::AssertionResult gtest_ar = (expression)) \ if (const ::testing::AssertionResult gtest_ar = (expression)) \
; \ ; \
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_

View File

@ -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_

View File

@ -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)`

View File

@ -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,28 +193,28 @@ 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", \
::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
gtest_exception.what()); \ gtest_exception.what()); \
fflush(stderr); \ fflush(stderr); \
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
} catch (...) { \ } catch (...) { \
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

View File

@ -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",

View File

@ -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:
@ -98,21 +101,21 @@ namespace testing {
// Forward declarations. // Forward declarations.
class AssertionResult; // Result of an assertion. class AssertionResult; // Result of an assertion.
class Message; // Represents a failure message. class Message; // Represents a failure message.
class Test; // Represents a test. class Test; // Represents a test.
class TestInfo; // Information about a test. class TestInfo; // Information about a test.
class TestPartResult; // Result of a test part. class TestPartResult; // Result of a test part.
class UnitTest; // A collection of test suites. class UnitTest; // A collection of test suites.
template <typename T> template <typename T>
::std::string PrintToString(const T& value); ::std::string PrintToString(const T& value);
namespace internal { namespace internal {
struct TraceInfo; // Information about a trace point. struct TraceInfo; // Information about a trace point.
class TestInfoImpl; // Opaque implementation of TestInfo class TestInfoImpl; // Opaque implementation of TestInfo
class UnitTestImpl; // Opaque implementation of UnitTest class UnitTestImpl; // Opaque implementation of UnitTest
// The text used in failure messages to indicate the start of the // The text used in failure messages to indicate the start of the
// stack trace. // stack trace.
@ -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,11 +250,11 @@ 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 =
std::numeric_limits<RawType>::digits - 1; std::numeric_limits<RawType>::digits - 1;
// # of exponent bits in a number. // # of exponent bits in a number.
static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; static const size_t kExponentBitCount = kBitCount - 1 - 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:
@ -1335,9 +1336,9 @@ struct tuple_size<testing::internal::FlatTuple<Ts...>>
#endif #endif
} // 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)
@ -1458,103 +1459,112 @@ class NeverThrown {
#endif // GTEST_HAS_EXCEPTIONS #endif // GTEST_HAS_EXCEPTIONS
#define GTEST_TEST_NO_THROW_(statement, fail) \ #define GTEST_TEST_NO_THROW_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::TrueWithString gtest_msg{}) { \ if (::testing::internal::TrueWithString gtest_msg{}) { \
try { \ try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} \ } \
GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \
catch (...) { \ catch (...) { \
gtest_msg.value = "it throws."; \ gtest_msg.value = "it throws."; \
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_ \
if (::testing::internal::AlwaysTrue()) { \ if (::testing::internal::AlwaysTrue()) { \
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 \
" Actual: it doesn't.") " throws an exception.\n" \
" 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.
#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ #define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (const ::testing::AssertionResult gtest_ar_ = \ if (const ::testing::AssertionResult gtest_ar_ = \
::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_ \
if (::testing::internal::AlwaysTrue()) { \ if (::testing::internal::AlwaysTrue()) { \
::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
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 \
"failures in the current thread.\n" \ " doesn't generate new fatal " \
" Actual: it does.") "failures in the current thread.\n" \
" Actual: it does.")
// Expands to the name of the class that implements the given test. // Expands to the name of the class that implements the given test.
#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ #define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
test_suite_name##_##test_name##_Test test_suite_name##_##test_name##_Test
// Helper macro for defining tests. // Helper macro for defining tests.
#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \ #define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \
static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \ static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \
"test_suite_name must not be empty"); \ "test_suite_name must not be empty"); \
static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \ static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \
"test_name must not be empty"); \ "test_name must not be empty"); \
class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
: public parent_class { \ : public parent_class { \
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 */ \
private: \ GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
void TestBody() override; \ (GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) &&) noexcept = delete; \
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \ GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) & operator=( \
}; \ GTEST_TEST_CLASS_NAME_(test_suite_name, \
\ test_name) &&) noexcept = delete; /* NOLINT */ \
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \ \
test_name)::test_info_ = \ private: \
::testing::internal::MakeAndRegisterTestInfo( \ void TestBody() override; \
#test_suite_name, #test_name, nullptr, nullptr, \ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \
::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \ }; \
::testing::internal::SuiteApiResolver< \ \
parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \ ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
::testing::internal::SuiteApiResolver< \ test_name)::test_info_ = \
parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \ ::testing::internal::MakeAndRegisterTestInfo( \
new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \ #test_suite_name, #test_name, nullptr, nullptr, \
test_suite_name, test_name)>); \ ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \
::testing::internal::SuiteApiResolver< \
parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \
::testing::internal::SuiteApiResolver< \
parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \
new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \
test_suite_name, test_name)>); \
void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_

View File

@ -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
@ -341,13 +343,13 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
<< "The program attempted to compare iterators " << "The program attempted to compare iterators "
<< "from different generators." << std::endl; << "from different generators." << std::endl;
return iterator_ == return iterator_ ==
CheckedDowncastToActualType<const Iterator>(&other)->iterator_; CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
} }
private: private:
Iterator(const Iterator& other) Iterator(const Iterator& other)
// The explicit constructor call suppresses a false warning // The explicit constructor call suppresses a false warning
// emitted by gcc when supplied with the -Wextra option. // emitted by gcc when supplied with the -Wextra option.
: ParamIteratorInterface<T>(), : ParamIteratorInterface<T>(),
base_(other.base_), base_(other.base_),
iterator_(other.iterator_) {} iterator_(other.iterator_) {}
@ -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(&parameter_); TestClass::SetParam(&parameter_);
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);
@ -596,15 +602,15 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line), SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
test_info->test_meta_factory->CreateTestFactory(*param_it)); test_info->test_meta_factory->CreateTestFactory(*param_it));
} // for param_it } // for param_it
} // for gen_it } // for gen_it
} // for test_it } // for test_it
if (!generated_instantiations) { if (!generated_instantiations) {
// There are no generaotrs, or they all generate nothing ... // There are no generaotrs, or they all generate nothing ...
InsertSyntheticTestCase(GetTestSuiteName(), code_location_, InsertSyntheticTestCase(GetTestSuiteName(), code_location_,
!tests_.empty()); !tests_.empty());
} }
} // RegisterTests } // RegisterTests
private: private:
// LocalTestInfo structure keeps information about a single test registered // LocalTestInfo structure keeps information about a single test registered
@ -620,42 +626,39 @@ 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), name_func(name_func_in),
name_func(name_func_in), file(file_in),
file(file_in), line(line_in) {}
line(line_in) {}
std::string name; std::string name;
GeneratorCreationFunc* generator; GeneratorCreationFunc* generator;
ParamNameGeneratorFunc* name_func; ParamNameGeneratorFunc* name_func;
const char* file; const char* file;
int line; int line;
}; };
typedef ::std::vector<InstantiationInfo> InstantiationContainer; typedef ::std::vector<InstantiationInfo> InstantiationContainer;
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()...),

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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
@ -163,7 +165,7 @@ class GTEST_API_ String {
private: private:
String(); // Not meant to be instantiated. String(); // Not meant to be instantiated.
}; // class String }; // class String
// Gets the content of the stringstream's buffer as an std::string. Each '\0' // Gets the content of the stringstream's buffer as an std::string. Each '\0'
// character in the buffer is replaced with "\\0". // character in the buffer is replaced with "\\0".

View File

@ -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 {

View File

@ -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;
} }
} }

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -34,7 +34,6 @@
#include <string.h> #include <string.h>
// A simple string class. // A simple string class.
class MyString { class MyString {
private: private:

View File

@ -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.

View File

@ -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;
@ -162,11 +161,11 @@ class Queue {
private: private:
QueueNode<E>* head_; // The first node of the queue. QueueNode<E>* head_; // The first node of the queue.
QueueNode<E>* last_; // The last node of the queue. QueueNode<E>* last_; // The last node of the queue.
size_t size_; // The number of elements in the queue. size_t size_; // The number of elements in the queue.
// We disallow copying a queue. // 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_

View File

@ -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();

View File

@ -29,26 +29,22 @@
// 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
int Counter::Decrement() { int Counter::Decrement() {
if (counter_ == 0) { if (counter_ == 0) {
return counter_; return counter_;
} else { } else {
return counter_--; return counter_--;
} }
} }
// 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_);
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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

View File

@ -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() {

View File

@ -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

View File

@ -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;
} }

View File

@ -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.

View File

@ -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'

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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 $@

File diff suppressed because it is too large Load Diff

View File

@ -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()

View File

@ -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"

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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.
#endif // GTEST_OS_WINDOWS_MOBILE #include <climits> // Some Linux distributions define PATH_MAX here.
#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;
@ -260,10 +260,9 @@ bool FilePath::IsAbsolutePath() const {
const char* const name = pathname_.c_str(); const char* const name = pathname_.c_str();
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
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,9 +340,8 @@ 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;
} }
// Removes any redundant separators that might be in the pathname. // Removes any redundant separators that might be in the pathname.

View File

@ -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.
@ -476,7 +462,7 @@ struct TraceInfo {
// This is the default global test part result reporter used in UnitTestImpl. // This is the default global test part result reporter used in UnitTestImpl.
// This class should only be used by UnitTestImpl. // This class should only be used by UnitTestImpl.
class DefaultGlobalTestPartResultReporter class DefaultGlobalTestPartResultReporter
: public TestPartResultReporterInterface { : public TestPartResultReporterInterface {
public: public:
explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
// Implements the TestPartResultReporterInterface. Reports the test part // Implements the TestPartResultReporterInterface. Reports the test part
@ -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,9 +1089,8 @@ 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_

View File

@ -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

View File

@ -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 {
@ -141,7 +132,7 @@ size_t GetThreadCount() {
} }
#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ #elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
GTEST_OS_NETBSD GTEST_OS_NETBSD
#if GTEST_OS_NETBSD #if GTEST_OS_NETBSD
#undef KERN_PROC #undef KERN_PROC
@ -184,12 +175,12 @@ size_t GetThreadCount() {
// we cannot detect it. // we cannot detect it.
size_t GetThreadCount() { size_t GetThreadCount() {
int mib[] = { int mib[] = {
CTL_KERN, CTL_KERN,
KERN_PROC, KERN_PROC,
KERN_PROC_PID | KERN_PROC_SHOW_THREADS, KERN_PROC_PID | KERN_PROC_SHOW_THREADS,
getpid(), getpid(),
sizeof(struct kinfo_proc), sizeof(struct kinfo_proc),
0, 0,
}; };
u_int miblen = sizeof(mib) / sizeof(mib[0]); u_int miblen = sizeof(mib) / sizeof(mib[0]);
@ -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.
@ -312,7 +286,7 @@ void AutoHandle::Reset(HANDLE handle) {
} else { } else {
GTEST_CHECK_(!IsCloseable()) GTEST_CHECK_(!IsCloseable())
<< "Resetting a valid handle to itself is likely a programmer error " << "Resetting a valid handle to itself is likely a programmer error "
"and thus not allowed."; "and thus not allowed.";
} }
} }
@ -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;
@ -577,9 +530,8 @@ class ThreadLocalRegistryImpl {
ThreadIdToThreadLocals* const thread_to_thread_locals = ThreadIdToThreadLocals* const thread_to_thread_locals =
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);
@ -609,9 +561,8 @@ class ThreadLocalRegistryImpl {
if (thread_local_pos != thread_to_thread_locals->end()) { if (thread_local_pos != thread_to_thread_locals->end()) {
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,16 +639,17 @@ 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) {
return ThreadLocalRegistryImpl::GetValueOnCurrentThread( return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
thread_local_instance); thread_local_instance);
} }
void ThreadLocalRegistry::OnThreadLocalDestroyed( void ThreadLocalRegistry::OnThreadLocalDestroyed(
const ThreadLocalBase* thread_local_instance) { const ThreadLocalBase* thread_local_instance) {
ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance); ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
} }
@ -786,7 +737,7 @@ bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
bool IsAsciiWordChar(char ch) { bool IsAsciiWordChar(char ch) {
return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
('0' <= ch && ch <= '9') || ch == '_'; ('0' <= ch && ch <= '9') || ch == '_';
} }
// Returns true if and only if "\\c" is a supported escape sequence. // Returns true if and only if "\\c" is a supported escape sequence.
@ -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,25 +878,23 @@ 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
// character of str and recurse. // character of str and recurse.
return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
MatchRegexAtHead(regex + 1, str + 1); MatchRegexAtHead(regex + 1, str + 1);
} }
} }
@ -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);
@ -1344,7 +1305,7 @@ bool ParseInt32(const Message& src_text, const char* str, int32_t* value) {
// LONG_MAX or LONG_MIN when the input overflows.) // LONG_MAX or LONG_MIN when the input overflows.)
result != long_value result != long_value
// The parsed value overflows as an int32_t. // The parsed value overflows as an int32_t.
) { ) {
Message msg; Message msg;
msg << "WARNING: " << src_text msg << "WARNING: " << src_text
<< " is expected to be a 32-bit integer, but actually" << " is expected to be a 32-bit integer, but actually"
@ -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) {

View File

@ -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,28 +458,28 @@ 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++;
if (std::iscntrl(ch)) { if (std::iscntrl(ch)) {
switch (ch) { switch (ch) {
case '\t': case '\t':
case '\n': case '\n':
case '\r': case '\r':
break; break;
default: default:
return true; return true;
}
} }
}
} }
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);
} }
} }

View File

@ -51,13 +51,11 @@ 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 : result.type() == TestPartResult::kFatalFailure
? "Skipped" ? "Fatal failure"
: result.type() == TestPartResult::kFatalFailure : "Non-fatal failure")
? "Fatal failure"
: "Non-fatal failure")
<< ":\n" << ":\n"
<< result.message() << std::endl; << result.message() << std::endl;
} }
@ -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);
} }

View File

@ -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";
} }

File diff suppressed because it is too large Load Diff

View File

@ -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(); }

View File

@ -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,76 +83,129 @@ 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
SOURCE_GROUP( code FILES ${openddl_parser_src} ) code/OpenDDLCommon.cpp
code/OpenDDLExport.cpp
code/OpenDDLParser.cpp
code/OpenDDLStream.cpp
code/DDLNode.cpp
code/Value.cpp
)
if ( DDL_STATIC_LIBRARY ) SOURCE_GROUP( code FILES ${openddlparser_src} )
ADD_LIBRARY( openddl_parser STATIC
${openddl_parser_src} ADD_LIBRARY( openddlparser ${openddlparser_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)
${GTEST_PATH}/src/gtest-death-test.cc find_package(Threads REQUIRED)
${GTEST_PATH}/src/gtest-filepath.cc
${GTEST_PATH}/src/gtest-internal-inl.h
${GTEST_PATH}/src/gtest-port.cc
${GTEST_PATH}/src/gtest-printers.cc
${GTEST_PATH}/src/gtest-test-part.cc
${GTEST_PATH}/src/gtest-typed-test.cc
${GTEST_PATH}/src/gtest.cc
)
SET( openddl_parser_unittest_src SET ( GTEST_PATH contrib/gtest-1.7.0 )
test/UnitTestCommon.h
test/DDLNodeTest.cpp
test/OpenDDLCommonTest.cpp
test/OpenDDLExportTest.cpp
test/OpenDDLParserTest.cpp
test/OpenDDLParserUtilsTest.cpp
test/OpenDDLStreamTest.cpp
test/OpenDDLIntegrationTest.cpp
test/ValueTest.cpp
test/OpenDDLDefectsTest.cpp
test/OssFuzzTest.cpp
test/main.cpp
)
add_definitions(-DOPENDDL_TEST_DATA="${CMAKE_CURRENT_LIST_DIR}/test/TestData")
SOURCE_GROUP( code FILES ${openddl_parser_unittest_src} ) SET ( gtest_src
SOURCE_GROUP( gtest FILES ${gtest_src} ) ${GTEST_PATH}/src/gtest-death-test.cc
${GTEST_PATH}/src/gtest-filepath.cc
${GTEST_PATH}/src/gtest-port.cc
${GTEST_PATH}/src/gtest-printers.cc
${GTEST_PATH}/src/gtest-test-part.cc
${GTEST_PATH}/src/gtest-typed-test.cc
${GTEST_PATH}/src/gtest.cc
)
ADD_EXECUTABLE( openddl_parser_unittest SET( openddlparser_unittest_src
${gtest_src} test/DDLNodeTest.cpp
${openddl_parser_unittest_src} test/OpenDDLCommonTest.cpp
) test/OpenDDLExportTest.cpp
test/OpenDDLParserTest.cpp
test/OpenDDLParserUtilsTest.cpp
test/OpenDDLStreamTest.cpp
test/OpenDDLIntegrationTest.cpp
test/ValueTest.cpp
test/OpenDDLDefectsTest.cpp
test/OssFuzzTest.cpp
test/main.cpp
)
target_link_libraries( openddl_parser_unittest openddl_parser ${CMAKE_THREAD_LIBS_INIT} ) SOURCE_GROUP( code FILES ${openddlparser_unittest_src} )
SOURCE_GROUP( gtest FILES ${gtest_src} )
SET( openddl_parser_demo_src ADD_EXECUTABLE( openddlparser_unittest
demo/main.cpp ${gtest_src}
) ${openddlparser_unittest_src}
)
if (COVERALLS) target_include_directories(openddlparser_unittest
set(COVERAGE_SRCS ${gtest_src} ${openddl_parser_unittest_src} ) 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 ()
# Create the coveralls target. if (DDL_BUILD_PARSER_DEMO)
coveralls_setup( SET( openddlparser_demo_src
"${COVERAGE_SRCS}" # The source files. demo/main.cpp
ON # If we should upload. )
"${PROJECT_SOURCE_DIR}/cmake/") # (Optional) Alternate project cmake module path.
endif()
ADD_EXECUTABLE( openddl_parser_demo if (COVERALLS)
${openddl_parser_demo_src} set(COVERAGE_SRCS ${gtest_src} ${openddlparser_unittest_src} )
)
target_link_libraries( openddl_parser_demo openddl_parser ) # Create the coveralls target.
coveralls_setup(
"${COVERAGE_SRCS}" # The source files.
ON # If we should upload.
"${PROJECT_SOURCE_DIR}/cmake/") # (Optional) Alternate project cmake module path.
endif()
ADD_EXECUTABLE( openddlparser_demo
${openddlparser_demo_src}
)
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")

View File

@ -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: {

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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);
}

View File

@ -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);
} }

View File

@ -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);
} }

Some files were not shown because too many files have changed in this diff Show More