diff options
Diffstat (limited to 'utils')
56 files changed, 8950 insertions, 2952 deletions
diff --git a/utils/FileUpdate/FileUpdate.cpp b/utils/FileUpdate/FileUpdate.cpp index 26fd75e..00c2091 100644 --- a/utils/FileUpdate/FileUpdate.cpp +++ b/utils/FileUpdate/FileUpdate.cpp @@ -79,6 +79,7 @@ int main(int argc, char **argv) { if (OutStream.has_error()) { errs() << argv[0] << ": Could not open output file '" << OutputFilename << "': " << ErrorStr << '\n'; + OutStream.clear_error(); return 1; } diff --git a/utils/NewNightlyTest.pl b/utils/NewNightlyTest.pl index 4287cc1..1b48168 100755 --- a/utils/NewNightlyTest.pl +++ b/utils/NewNightlyTest.pl @@ -47,8 +47,8 @@ use Socket; # -noclean Do not run 'make clean' before building. # -nobuild Do not build llvm. If tests are enabled perform them # on the llvm build specified in the build directory -# -release Build an LLVM Release version -# -release-asserts Build an LLVM ReleaseAsserts version +# -release Build an LLVM Release+Asserts version +# -release-asserts Build an LLVM Release version # -disable-bindings Disable building LLVM bindings. # -with-clang Checkout Clang source into tools/clang. # -compileflags Next argument specifies extra options passed to make when diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index c879a54..5025691 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1575,6 +1575,15 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( if (Name == "BXr9" || Name == "BMOVPCRX" || Name == "BMOVPCRXr9") return false; + // Tail calls are other patterns that generate existing instructions. + if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" || + Name == "TCRETURNri" || Name == "TCRETURNriND" || + Name == "TAILJMPd" || Name == "TAILJMPdt" || + Name == "TAILJMPdND" || Name == "TAILJMPdNDt" || + Name == "TAILJMPr" || Name == "TAILJMPrND" || + Name == "MOVr_TC") + return false; + // VLDMQ/VSTMQ can be hanlded with the more generic VLDMD/VSTMD. if (Name == "VLDMQ" || Name == "VLDMQ_UPD" || Name == "VSTMQ" || Name == "VSTMQ_UPD") diff --git a/utils/TableGen/ARMDecoderEmitter.h b/utils/TableGen/ARMDecoderEmitter.h index 107e085..571a947 100644 --- a/utils/TableGen/ARMDecoderEmitter.h +++ b/utils/TableGen/ARMDecoderEmitter.h @@ -31,7 +31,7 @@ public: ~ARMDecoderEmitter() { shutdownBackend(); } - + // run - Output the code emitter void run(raw_ostream &o); diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 4ba3df1..e1aa2bc 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -407,9 +407,9 @@ public: default: // This class preceeds the RHS if it is a proper subset of the RHS. if (isSubsetOf(RHS)) - return true; + return true; if (RHS.isSubsetOf(*this)) - return false; + return false; // Otherwise, order by name to ensure we have a total ordering. return ValueName < RHS.ValueName; diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index 731cde9..972989b 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(tblgen AsmWriterInst.cpp CallingConvEmitter.cpp ClangASTNodesEmitter.cpp + ClangAttrEmitter.cpp ClangDiagnosticsEmitter.cpp CodeEmitterGen.cpp CodeGenDAGPatterns.cpp @@ -22,6 +23,7 @@ add_executable(tblgen InstrInfoEmitter.cpp IntrinsicEmitter.cpp LLVMCConfigurationEmitter.cpp + NeonEmitter.cpp OptParserEmitter.cpp Record.cpp RegisterInfoEmitter.cpp @@ -39,6 +41,6 @@ target_link_libraries(tblgen LLVMSupport LLVMSystem) if( MINGW ) target_link_libraries(tblgen imagehlp psapi) endif( MINGW ) -if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) +if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD AND NOT BEOS ) target_link_libraries(tblgen pthread) endif() diff --git a/utils/TableGen/ClangASTNodesEmitter.cpp b/utils/TableGen/ClangASTNodesEmitter.cpp index 5d6423d..187ab46 100644 --- a/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/utils/TableGen/ClangASTNodesEmitter.cpp @@ -12,33 +12,19 @@ //===----------------------------------------------------------------------===// #include "ClangASTNodesEmitter.h" -#include "Record.h" -#include <map> -#include <cctype> +#include <set> using namespace llvm; //===----------------------------------------------------------------------===// // Statement Node Tables (.inc file) generation. //===----------------------------------------------------------------------===// -// Create a macro-ized version of a name -static std::string macroName(std::string S) { - for (unsigned i = 0; i < S.size(); ++i) - S[i] = std::toupper(S[i]); - - return S; -} - -// A map from a node to each of its derived nodes. -typedef std::multimap<Record*, Record*> ChildMap; -typedef ChildMap::const_iterator ChildIterator; - // Returns the first and last non-abstract subrecords // Called recursively to ensure that nodes remain contiguous -static std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree, - raw_ostream &OS, - Record *Base, - bool Root = true) { +std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode( + const ChildMap &Tree, + raw_ostream &OS, + Record *Base) { std::string BaseName = macroName(Base->getName()); ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base); @@ -60,15 +46,15 @@ static std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree, OS << "#endif\n"; if (Abstract) - OS << "ABSTRACT_STMT(" << NodeName << "(" << R->getName() << ", " - << Base->getName() << "))\n"; + OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "(" + << R->getName() << ", " << baseName(*Base) << "))\n"; else OS << NodeName << "(" << R->getName() << ", " - << Base->getName() << ")\n"; + << baseName(*Base) << ")\n"; if (Tree.find(R) != Tree.end()) { const std::pair<Record *, Record *> &Result - = EmitStmtNode(Tree, OS, R, false); + = EmitNode(Tree, OS, R); if (!First && Result.first) First = Result.first; if (Result.second) @@ -87,11 +73,10 @@ static std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree, if (First) { assert (Last && "Got a first node but not a last node for a range!"); - if (Root) - OS << "LAST_STMT_RANGE("; + if (Base == &Root) + OS << "LAST_" << macroName(Root.getName()) << "_RANGE("; else - OS << "STMT_RANGE("; - + OS << macroName(Root.getName()) << "_RANGE("; OS << Base->getName() << ", " << First->getName() << ", " << Last->getName() << ")\n\n"; } @@ -99,43 +84,82 @@ static std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree, return std::make_pair(First, Last); } -void ClangStmtNodesEmitter::run(raw_ostream &OS) { +void ClangASTNodesEmitter::run(raw_ostream &OS) { // Write the preamble - OS << "#ifndef ABSTRACT_STMT\n"; - OS << "# define ABSTRACT_STMT(Stmt) Stmt\n"; + OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n"; + OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n"; OS << "#endif\n"; - OS << "#ifndef STMT_RANGE\n"; - OS << "# define STMT_RANGE(Base, First, Last)\n"; + OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n"; + OS << "# define " + << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n"; OS << "#endif\n\n"; - OS << "#ifndef LAST_STMT_RANGE\n"; - OS << "# define LAST_STMT_RANGE(Base, First, Last) " - "STMT_RANGE(Base, First, Last)\n"; + OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n"; + OS << "# define LAST_" + << macroName(Root.getName()) << "_RANGE(Base, First, Last) " + << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n"; OS << "#endif\n\n"; // Emit statements - const std::vector<Record*> Stmts = Records.getAllDerivedDefinitions("Stmt"); + const std::vector<Record*> Stmts + = Records.getAllDerivedDefinitions(Root.getName()); ChildMap Tree; - // Create a pseudo-record to serve as the Stmt node, which isn't actually - // output. - Record Stmt ("Stmt", SMLoc()); - for (unsigned i = 0, e = Stmts.size(); i != e; ++i) { Record *R = Stmts[i]; if (R->getValue("Base")) Tree.insert(std::make_pair(R->getValueAsDef("Base"), R)); else - Tree.insert(std::make_pair(&Stmt, R)); + Tree.insert(std::make_pair(&Root, R)); } - EmitStmtNode(Tree, OS, &Stmt); + EmitNode(Tree, OS, &Root); + + OS << "#undef " << macroName(Root.getName()) << "\n"; + OS << "#undef " << macroName(Root.getName()) << "_RANGE\n"; + OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n"; + OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n"; +} + +void ClangDeclContextEmitter::run(raw_ostream &OS) { + // FIXME: Find a .td file format to allow for this to be represented better. + + OS << "#ifndef DECL_CONTEXT\n"; + OS << "# define DECL_CONTEXT(DECL)\n"; + OS << "#endif\n"; + + OS << "#ifndef DECL_CONTEXT_BASE\n"; + OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n"; + OS << "#endif\n"; + + typedef std::set<Record*> RecordSet; + typedef std::vector<Record*> RecordVector; + + RecordVector DeclContextsVector + = Records.getAllDerivedDefinitions("DeclContext"); + RecordVector Decls = Records.getAllDerivedDefinitions("Decl"); + RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end()); + + for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) { + Record *R = *i; + + if (R->getValue("Base")) { + Record *B = R->getValueAsDef("Base"); + if (DeclContexts.find(B) != DeclContexts.end()) { + OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n"; + DeclContexts.erase(B); + } + } + } + + for (RecordSet::iterator i = DeclContexts.begin(), e = DeclContexts.end(); + i != e; ++i) { + OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; + } - OS << "#undef STMT\n"; - OS << "#undef STMT_RANGE\n"; - OS << "#undef LAST_STMT_RANGE\n"; - OS << "#undef ABSTRACT_STMT\n"; + OS << "#undef DECL_CONTEXT\n"; + OS << "#undef DECL_CONTEXT_BASE\n"; } diff --git a/utils/TableGen/ClangASTNodesEmitter.h b/utils/TableGen/ClangASTNodesEmitter.h index c4ce9fa..abf9c9a 100644 --- a/utils/TableGen/ClangASTNodesEmitter.h +++ b/utils/TableGen/ClangASTNodesEmitter.h @@ -15,19 +15,67 @@ #define CLANGAST_EMITTER_H #include "TableGenBackend.h" +#include "Record.h" +#include <string> +#include <cctype> +#include <map> namespace llvm { -/// ClangStmtNodesEmitter - The top-level class emits .def files containing +/// ClangASTNodesEmitter - The top-level class emits .inc files containing /// declarations of Clang statements. /// -class ClangStmtNodesEmitter : public TableGenBackend { +class ClangASTNodesEmitter : public TableGenBackend { + // A map from a node to each of its derived nodes. + typedef std::multimap<Record*, Record*> ChildMap; + typedef ChildMap::const_iterator ChildIterator; + RecordKeeper &Records; + Record Root; + const std::string &BaseSuffix; + + // Create a macro-ized version of a name + static std::string macroName(std::string S) { + for (unsigned i = 0; i < S.size(); ++i) + S[i] = std::toupper(S[i]); + + return S; + } + + // Return the name to be printed in the base field. Normally this is + // the record's name plus the base suffix, but if it is the root node and + // the suffix is non-empty, it's just the suffix. + std::string baseName(Record &R) { + if (&R == &Root && !BaseSuffix.empty()) + return BaseSuffix; + + return R.getName() + BaseSuffix; + } + + std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS, + Record *Base); +public: + explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N, + const std::string &S) + : Records(R), Root(N, SMLoc()), BaseSuffix(S) + {} + + // run - Output the .inc file contents + void run(raw_ostream &OS); +}; + +/// ClangDeclContextEmitter - Emits an addendum to a .inc file to enumerate the +/// clang declaration contexts. +/// +class ClangDeclContextEmitter : public TableGenBackend { + RecordKeeper &Records; + public: - explicit ClangStmtNodesEmitter(RecordKeeper &R) - : Records(R) {} + explicit ClangDeclContextEmitter(RecordKeeper &R) + : Records(R) + {} - // run - Output the .def file contents + // run - Output the .inc file contents void run(raw_ostream &OS); }; diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp new file mode 100644 index 0000000..fbdd2a7 --- /dev/null +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -0,0 +1,84 @@ +//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These tablegen backends emit Clang attribute processing code +// +//===----------------------------------------------------------------------===// + +#include "ClangAttrEmitter.h" +#include "Record.h" +#include <algorithm> + +using namespace llvm; + +void ClangAttrClassEmitter::run(raw_ostream &OS) { + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n"; + OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n"; + + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); + + for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); + i != e; ++i) { + Record &R = **i; + + if (R.getValueAsBit("DoNotEmit")) + continue; + + OS << "class " << R.getName() << "Attr : public Attr {\n"; + + std::vector<Record*> Args = R.getValueAsListOfDefs("Args"); + + // FIXME: Handle arguments + assert(Args.empty() && "Can't yet handle arguments"); + + OS << "\n public:\n"; + OS << " " << R.getName() << "Attr("; + + // Arguments go here + + OS << ")\n"; + OS << " : Attr(attr::" << R.getName() << ")"; + + // Arguments go here + + OS << " {}\n\n"; + + OS << " virtual Attr *clone (ASTContext &C) const;\n"; + OS << " static bool classof(const Attr *A) { return A->getKind() == " + << "attr::" << R.getName() << "; }\n"; + OS << " static bool classof(const " << R.getName() + << "Attr *) { return true; }\n"; + OS << "};\n\n"; + } + + OS << "#endif\n"; +} + +void ClangAttrListEmitter::run(raw_ostream &OS) { + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + + OS << "#ifndef LAST_ATTR\n"; + OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n"; + OS << "#endif\n\n"; + + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); + std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); + + if (i != e) { + // Move the end iterator back to emit the last attribute. + for(--e; i != e; ++i) + OS << "ATTR(" << (*i)->getName() << ")\n"; + + OS << "LAST_ATTR(" << (*i)->getName() << ")\n\n"; + } + + OS << "#undef LAST_ATTR\n"; + OS << "#undef ATTR\n"; +} diff --git a/utils/TableGen/ClangAttrEmitter.h b/utils/TableGen/ClangAttrEmitter.h new file mode 100644 index 0000000..5ce1c87 --- /dev/null +++ b/utils/TableGen/ClangAttrEmitter.h @@ -0,0 +1,49 @@ +//===- ClangAttrEmitter.h - Generate Clang attribute handling =-*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These tablegen backends emit Clang attribute processing code +// +//===----------------------------------------------------------------------===// + +#ifndef CLANGATTR_EMITTER_H +#define CLANGATTR_EMITTER_H + +#include "TableGenBackend.h" + +namespace llvm { + +/// ClangAttrClassEmitter - class emits the class defintions for attributes for +/// clang. +class ClangAttrClassEmitter : public TableGenBackend { + RecordKeeper &Records; + + public: + explicit ClangAttrClassEmitter(RecordKeeper &R) + : Records(R) + {} + + void run(raw_ostream &OS); +}; + +/// ClangAttrListEmitter - class emits the enumeration list for attributes for +/// clang. +class ClangAttrListEmitter : public TableGenBackend { + RecordKeeper &Records; + + public: + explicit ClangAttrListEmitter(RecordKeeper &R) + : Records(R) + {} + + void run(raw_ostream &OS); +}; + +} + +#endif diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 2a2a4ef..ec702c2a5 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -24,19 +24,8 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); I != E; ++I) { Record *R = *I; - if (R->getName() == "PHI" || - R->getName() == "INLINEASM" || - R->getName() == "DBG_LABEL" || - R->getName() == "EH_LABEL" || - R->getName() == "GC_LABEL" || - R->getName() == "KILL" || - R->getName() == "EXTRACT_SUBREG" || - R->getName() == "INSERT_SUBREG" || - R->getName() == "IMPLICIT_DEF" || - R->getName() == "SUBREG_TO_REG" || - R->getName() == "COPY_TO_REGCLASS" || - R->getName() == "DBG_VALUE" || - R->getName() == "REG_SEQUENCE") continue; + if (R->getValueAsString("Namespace") == "TargetOpcode") + continue; BitsInit *BI = R->getValueAsBitsInit("Inst"); @@ -103,19 +92,7 @@ void CodeEmitterGen::run(raw_ostream &o) { const CodeGenInstruction *CGI = *IN; Record *R = CGI->TheDef; - if (R->getName() == "PHI" || - R->getName() == "INLINEASM" || - R->getName() == "DBG_LABEL" || - R->getName() == "EH_LABEL" || - R->getName() == "GC_LABEL" || - R->getName() == "KILL" || - R->getName() == "EXTRACT_SUBREG" || - R->getName() == "INSERT_SUBREG" || - R->getName() == "IMPLICIT_DEF" || - R->getName() == "SUBREG_TO_REG" || - R->getName() == "COPY_TO_REGCLASS" || - R->getName() == "DBG_VALUE" || - R->getName() == "REG_SEQUENCE") { + if (R->getValueAsString("Namespace") == "TargetOpcode") { o << " 0U,\n"; continue; } @@ -140,22 +117,10 @@ void CodeEmitterGen::run(raw_ostream &o) { for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end(); IC != EC; ++IC) { Record *R = *IC; + if (R->getValueAsString("Namespace") == "TargetOpcode") + continue; const std::string &InstName = R->getName(); std::string Case(""); - - if (InstName == "PHI" || - InstName == "INLINEASM" || - InstName == "DBG_LABEL"|| - InstName == "EH_LABEL"|| - InstName == "GC_LABEL"|| - InstName == "KILL"|| - InstName == "EXTRACT_SUBREG" || - InstName == "INSERT_SUBREG" || - InstName == "IMPLICIT_DEF" || - InstName == "SUBREG_TO_REG" || - InstName == "COPY_TO_REGCLASS" || - InstName == "DBG_VALUE" || - InstName == "REG_SEQUENCE") continue; BitsInit *BI = R->getValueAsBitsInit("Inst"); const std::vector<RecordVal> &Vals = R->getValues(); diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 99d196c..35b54a5 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -107,7 +107,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); mayLoad = R->getValueAsBit("mayLoad"); mayStore = R->getValueAsBit("mayStore"); - bool isTwoAddress = R->getValueAsBit("isTwoAddress"); isPredicable = R->getValueAsBit("isPredicable"); isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); isCommutable = R->getValueAsBit("isCommutable"); @@ -212,16 +211,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) // Parse Constraints. ParseConstraints(R->getValueAsString("Constraints"), this); - // For backward compatibility: isTwoAddress means operand 1 is tied to - // operand 0. - if (isTwoAddress) { - if (!OperandList[1].Constraints[0].isNone()) - throw R->getName() + ": cannot use isTwoAddress property: instruction " - "already has constraint set!"; - OperandList[1].Constraints[0] = - CodeGenInstruction::ConstraintInfo::getTied(0); - } - // Parse the DisableEncoding field. std::string DisableEncoding = R->getValueAsString("DisableEncoding"); while (1) { diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 3797992..d8130fb 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -329,61 +329,42 @@ struct SortInstByName { /// getInstructionsByEnumValue - Return all of the instructions defined by the /// target, ordered by their enum value. void CodeGenTarget::ComputeInstrsByEnum() const { + // The ordering here must match the ordering in TargetOpcodes.h. + const char *const FixedInstrs[] = { + "PHI", + "INLINEASM", + "DBG_LABEL", + "EH_LABEL", + "GC_LABEL", + "KILL", + "EXTRACT_SUBREG", + "INSERT_SUBREG", + "IMPLICIT_DEF", + "SUBREG_TO_REG", + "COPY_TO_REGCLASS", + "DBG_VALUE", + "REG_SEQUENCE", + "COPY", + 0 + }; const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); - const CodeGenInstruction *PHI = GetInstByName("PHI", Insts); - const CodeGenInstruction *INLINEASM = GetInstByName("INLINEASM", Insts); - const CodeGenInstruction *DBG_LABEL = GetInstByName("DBG_LABEL", Insts); - const CodeGenInstruction *EH_LABEL = GetInstByName("EH_LABEL", Insts); - const CodeGenInstruction *GC_LABEL = GetInstByName("GC_LABEL", Insts); - const CodeGenInstruction *KILL = GetInstByName("KILL", Insts); - const CodeGenInstruction *EXTRACT_SUBREG = - GetInstByName("EXTRACT_SUBREG", Insts); - const CodeGenInstruction *INSERT_SUBREG = - GetInstByName("INSERT_SUBREG", Insts); - const CodeGenInstruction *IMPLICIT_DEF = GetInstByName("IMPLICIT_DEF", Insts); - const CodeGenInstruction *SUBREG_TO_REG = - GetInstByName("SUBREG_TO_REG", Insts); - const CodeGenInstruction *COPY_TO_REGCLASS = - GetInstByName("COPY_TO_REGCLASS", Insts); - const CodeGenInstruction *DBG_VALUE = GetInstByName("DBG_VALUE", Insts); - const CodeGenInstruction *REG_SEQUENCE = GetInstByName("REG_SEQUENCE", Insts); - - // Print out the rest of the instructions now. - InstrsByEnum.push_back(PHI); - InstrsByEnum.push_back(INLINEASM); - InstrsByEnum.push_back(DBG_LABEL); - InstrsByEnum.push_back(EH_LABEL); - InstrsByEnum.push_back(GC_LABEL); - InstrsByEnum.push_back(KILL); - InstrsByEnum.push_back(EXTRACT_SUBREG); - InstrsByEnum.push_back(INSERT_SUBREG); - InstrsByEnum.push_back(IMPLICIT_DEF); - InstrsByEnum.push_back(SUBREG_TO_REG); - InstrsByEnum.push_back(COPY_TO_REGCLASS); - InstrsByEnum.push_back(DBG_VALUE); - InstrsByEnum.push_back(REG_SEQUENCE); - + for (const char *const *p = FixedInstrs; *p; ++p) { + const CodeGenInstruction *Instr = GetInstByName(*p, Insts); + assert(Instr && "Missing target independent instruction"); + assert(Instr->Namespace == "TargetOpcode" && "Bad namespace"); + InstrsByEnum.push_back(Instr); + } unsigned EndOfPredefines = InstrsByEnum.size(); - + for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator I = Insts.begin(), E = Insts.end(); I != E; ++I) { const CodeGenInstruction *CGI = I->second; - if (CGI != PHI && - CGI != INLINEASM && - CGI != DBG_LABEL && - CGI != EH_LABEL && - CGI != GC_LABEL && - CGI != KILL && - CGI != EXTRACT_SUBREG && - CGI != INSERT_SUBREG && - CGI != IMPLICIT_DEF && - CGI != SUBREG_TO_REG && - CGI != COPY_TO_REGCLASS && - CGI != DBG_VALUE && - CGI != REG_SEQUENCE) + if (CGI->Namespace != "TargetOpcode") InstrsByEnum.push_back(CGI); } - + + assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr"); + // All of the instructions are now in random order based on the map iteration. // Sort them by name. std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(), diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 4473f0d..3750bd8 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -635,6 +635,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { if (!ComplexPatterns.empty()) { OS << "bool CheckComplexPattern(SDNode *Root, SDValue N,\n"; OS << " unsigned PatternNo, SmallVectorImpl<SDValue> &Result) {\n"; + OS << " unsigned NextRes = Result.size();\n"; OS << " switch (PatternNo) {\n"; OS << " default: assert(0 && \"Invalid pattern # in table?\");\n"; for (unsigned i = 0, e = ComplexPatterns.size(); i != e; ++i) { @@ -645,12 +646,12 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { ++NumOps; // Get the chained node too. OS << " case " << i << ":\n"; - OS << " Result.resize(Result.size()+" << NumOps << ");\n"; + OS << " Result.resize(NextRes+" << NumOps << ");\n"; OS << " return " << P.getSelectFunc(); OS << "(Root, N"; for (unsigned i = 0; i != NumOps; ++i) - OS << ", Result[Result.size()-" << (NumOps-i) << ']'; + OS << ", Result[NextRes+" << i << ']'; OS << ");\n"; } OS << " }\n"; diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 0d5ee40..c5ee828 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -306,6 +306,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, REG("RFP64"); REG("RFP80"); REG("VR128"); + REG("VR256"); REG("RST"); REG("SEGMENT_REG"); REG("DEBUG_REG"); @@ -339,6 +340,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, MEM("opaque80mem"); MEM("i128mem"); MEM("f128mem"); + MEM("f256mem"); MEM("opaque512mem"); // all R, I, R, I @@ -347,6 +349,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, LEA("lea64mem"); // all I + PCR("i16imm_pcrel"); PCR("i32imm_pcrel"); PCR("i64i32imm_pcrel"); PCR("brtarget8"); @@ -500,6 +503,8 @@ static void X86ExtractSemantics( // TODO add support for fixed operands } else if (name.find("F") != name.npos) { // ignore (this pushes onto the FP stack) + } else if (name.find("A") != name.npos) { + // ignore (pushes all GP registoers onto the stack) } else if (name[name.length() - 1] == 'm') { PUSH("src"); } else if (name.find("i") != name.npos) { @@ -518,6 +523,8 @@ static void X86ExtractSemantics( // TODO add support for fixed operands } else if (name.find("F") != name.npos) { // ignore (this pops from the FP stack) + } else if (name.find("A") != name.npos) { + // ignore (pushes all GP registoers onto the stack) } else if (name[name.length() - 1] == 'm') { POP("dst"); } else { @@ -570,6 +577,7 @@ static void X86ExtractSemantics( static int ARMFlagFromOpName(LiteralConstantEmitter *type, const std::string &name) { REG("GPR"); + REG("tcGPR"); REG("cc_out"); REG("s_cc_out"); REG("tGPR"); @@ -592,10 +600,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("msr_mask"); IMM("neg_zero"); IMM("imm0_31"); - IMM("h8imm"); - IMM("h16imm"); - IMM("h32imm"); - IMM("h64imm"); + IMM("nModImm"); IMM("imm0_4095"); IMM("jt2block_operand"); IMM("t_imm_s4"); diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 9ec9e08..08fc139 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -54,15 +54,15 @@ struct OperandsSignature { bool initialize(TreePatternNode *InstPatNode, const CodeGenTarget &Target, MVT::SimpleValueType VT) { - if (!InstPatNode->isLeaf() && - InstPatNode->getOperator()->getName() == "imm") { - Operands.push_back("i"); - return true; - } - if (!InstPatNode->isLeaf() && - InstPatNode->getOperator()->getName() == "fpimm") { - Operands.push_back("f"); - return true; + if (!InstPatNode->isLeaf()) { + if (InstPatNode->getOperator()->getName() == "imm") { + Operands.push_back("i"); + return true; + } + if (InstPatNode->getOperator()->getName() == "fpimm") { + Operands.push_back("f"); + return true; + } } const CodeGenRegisterClass *DstRC = 0; @@ -432,11 +432,9 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { if ((*Memo.PhysRegs)[i] != "") - OS << " TII.copyRegToReg(*MBB, MBB->end(), " - << (*Memo.PhysRegs)[i] << ", Op" << i << ", " - << "TM.getRegisterInfo()->getPhysicalRegisterRegClass(" - << (*Memo.PhysRegs)[i] << "), " - << "MRI.getRegClass(Op" << i << "), DL);\n"; + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, " + << "TII.get(TargetOpcode::COPY), " + << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; } OS << " return FastEmitInst_"; @@ -524,14 +522,12 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { HasPred = true; } - for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { - if ((*Memo.PhysRegs)[i] != "") - OS << " TII.copyRegToReg(*MBB, MBB->end(), " - << (*Memo.PhysRegs)[i] << ", Op" << i << ", " - << "TM.getRegisterInfo()->getPhysicalRegisterRegClass(" - << (*Memo.PhysRegs)[i] << "), " - << "MRI.getRegClass(Op" << i << "), DL);\n"; - } + for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { + if ((*Memo.PhysRegs)[i] != "") + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, " + << "TII.get(TargetOpcode::COPY), " + << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; + } OS << " return FastEmitInst_"; diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 006a2a1..f28af15 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -92,7 +92,8 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { else if (OpR->isSubClassOf("PointerLikeRegClass")) Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", "; else - Res += "0, "; + // -1 means the operand does not have a fixed register class. + Res += "-1, "; // Fill in applicable flags. Res += "0"; @@ -301,7 +302,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, } OS << ", 0x"; OS.write_hex(Value); - OS << ", "; + OS << "ULL, "; // Emit the implicit uses and defs lists... std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp new file mode 100644 index 0000000..3516d31 --- /dev/null +++ b/utils/TableGen/NeonEmitter.cpp @@ -0,0 +1,1202 @@ +//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting arm_neon.h, which includes +// a declaration and definition of each function specified by the ARM NEON +// compiler interface. See ARM document DUI0348B. +// +// Each NEON instruction is implemented in terms of 1 or more functions which +// are suffixed with the element type of the input vectors. Functions may be +// implemented in terms of generic vector operations such as +, *, -, etc. or +// by calling a __builtin_-prefixed function which will be handled by clang's +// CodeGen library. +// +// Additional validation code can be generated by this file when runHeader() is +// called, rather than the normal run() entry point. +// +//===----------------------------------------------------------------------===// + +#include "NeonEmitter.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include <string> + +using namespace llvm; + +/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs, +/// which each StringRef representing a single type declared in the string. +/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing +/// 2xfloat and 4xfloat respectively. +static void ParseTypes(Record *r, std::string &s, + SmallVectorImpl<StringRef> &TV) { + const char *data = s.data(); + int len = 0; + + for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) { + if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U') + continue; + + switch (data[len]) { + case 'c': + case 's': + case 'i': + case 'l': + case 'h': + case 'f': + break; + default: + throw TGError(r->getLoc(), + "Unexpected letter: " + std::string(data + len, 1)); + break; + } + TV.push_back(StringRef(data, len + 1)); + data += len + 1; + len = -1; + } +} + +/// Widen - Convert a type code into the next wider type. char -> short, +/// short -> int, etc. +static char Widen(const char t) { + switch (t) { + case 'c': + return 's'; + case 's': + return 'i'; + case 'i': + return 'l'; + default: throw "unhandled type in widen!"; + } + return '\0'; +} + +/// Narrow - Convert a type code into the next smaller type. short -> char, +/// float -> half float, etc. +static char Narrow(const char t) { + switch (t) { + case 's': + return 'c'; + case 'i': + return 's'; + case 'l': + return 'i'; + case 'f': + return 'h'; + default: throw "unhandled type in widen!"; + } + return '\0'; +} + +/// For a particular StringRef, return the base type code, and whether it has +/// the quad-vector, polynomial, or unsigned modifiers set. +static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) { + unsigned off = 0; + + // remember quad. + if (ty[off] == 'Q') { + quad = true; + ++off; + } + + // remember poly. + if (ty[off] == 'P') { + poly = true; + ++off; + } + + // remember unsigned. + if (ty[off] == 'U') { + usgn = true; + ++off; + } + + // base type to get the type string for. + return ty[off]; +} + +/// ModType - Transform a type code and its modifiers based on a mod code. The +/// mod code definitions may be found at the top of arm_neon.td. +static char ModType(const char mod, char type, bool &quad, bool &poly, + bool &usgn, bool &scal, bool &cnst, bool &pntr) { + switch (mod) { + case 't': + if (poly) { + poly = false; + usgn = true; + } + break; + case 'u': + usgn = true; + case 'x': + poly = false; + if (type == 'f') + type = 'i'; + break; + case 'f': + if (type == 'h') + quad = true; + type = 'f'; + usgn = false; + break; + case 'w': + type = Widen(type); + quad = true; + break; + case 'n': + type = Widen(type); + break; + case 'l': + type = 'l'; + scal = true; + usgn = true; + break; + case 's': + case 'a': + scal = true; + break; + case 'k': + quad = true; + break; + case 'c': + cnst = true; + case 'p': + pntr = true; + scal = true; + break; + case 'h': + type = Narrow(type); + if (type == 'h') + quad = false; + break; + case 'e': + type = Narrow(type); + usgn = true; + break; + default: + break; + } + return type; +} + +/// TypeString - for a modifier and type, generate the name of the typedef for +/// that type. If generic is true, emit the generic vector type rather than +/// the public NEON type. QUc -> uint8x8_t / __neon_uint8x8_t. +static std::string TypeString(const char mod, StringRef typestr, + bool generic = false) { + bool quad = false; + bool poly = false; + bool usgn = false; + bool scal = false; + bool cnst = false; + bool pntr = false; + + if (mod == 'v') + return "void"; + if (mod == 'i') + return "int"; + + // base type to get the type string for. + char type = ClassifyType(typestr, quad, poly, usgn); + + // Based on the modifying character, change the type and width if necessary. + type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); + + SmallString<128> s; + + if (generic) + s += "__neon_"; + + if (usgn) + s.push_back('u'); + + switch (type) { + case 'c': + s += poly ? "poly8" : "int8"; + if (scal) + break; + s += quad ? "x16" : "x8"; + break; + case 's': + s += poly ? "poly16" : "int16"; + if (scal) + break; + s += quad ? "x8" : "x4"; + break; + case 'i': + s += "int32"; + if (scal) + break; + s += quad ? "x4" : "x2"; + break; + case 'l': + s += "int64"; + if (scal) + break; + s += quad ? "x2" : "x1"; + break; + case 'h': + s += "float16"; + if (scal) + break; + s += quad ? "x8" : "x4"; + break; + case 'f': + s += "float32"; + if (scal) + break; + s += quad ? "x4" : "x2"; + break; + default: + throw "unhandled type!"; + break; + } + + if (mod == '2') + s += "x2"; + if (mod == '3') + s += "x3"; + if (mod == '4') + s += "x4"; + + // Append _t, finishing the type string typedef type. + s += "_t"; + + if (cnst) + s += " const"; + + if (pntr) + s += " *"; + + return s.str(); +} + +/// BuiltinTypeString - for a modifier and type, generate the clang +/// BuiltinsARM.def prototype code for the function. See the top of clang's +/// Builtins.def for a description of the type strings. +static std::string BuiltinTypeString(const char mod, StringRef typestr, + ClassKind ck, bool ret) { + bool quad = false; + bool poly = false; + bool usgn = false; + bool scal = false; + bool cnst = false; + bool pntr = false; + + if (mod == 'v') + return "v"; + if (mod == 'i') + return "i"; + + // base type to get the type string for. + char type = ClassifyType(typestr, quad, poly, usgn); + + // Based on the modifying character, change the type and width if necessary. + type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); + + if (pntr) { + usgn = false; + poly = false; + type = 'v'; + } + if (type == 'h') { + type = 's'; + usgn = true; + } + usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f'); + + if (scal) { + SmallString<128> s; + + if (usgn) + s.push_back('U'); + + if (type == 'l') + s += "LLi"; + else + s.push_back(type); + + if (cnst) + s.push_back('C'); + if (pntr) + s.push_back('*'); + return s.str(); + } + + // Since the return value must be one type, return a vector type of the + // appropriate width which we will bitcast. An exception is made for + // returning structs of 2, 3, or 4 vectors which are returned in a sret-like + // fashion, storing them to a pointer arg. + if (ret) { + if (mod == '2' || mod == '3' || mod == '4') + return "vv*"; + if (mod == 'f' || (ck != ClassB && type == 'f')) + return quad ? "V4f" : "V2f"; + if (ck != ClassB && type == 's') + return quad ? "V8s" : "V4s"; + if (ck != ClassB && type == 'i') + return quad ? "V4i" : "V2i"; + if (ck != ClassB && type == 'l') + return quad ? "V2LLi" : "V1LLi"; + + return quad ? "V16c" : "V8c"; + } + + // Non-return array types are passed as individual vectors. + if (mod == '2') + return quad ? "V16cV16c" : "V8cV8c"; + if (mod == '3') + return quad ? "V16cV16cV16c" : "V8cV8cV8c"; + if (mod == '4') + return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c"; + + if (mod == 'f' || (ck != ClassB && type == 'f')) + return quad ? "V4f" : "V2f"; + if (ck != ClassB && type == 's') + return quad ? "V8s" : "V4s"; + if (ck != ClassB && type == 'i') + return quad ? "V4i" : "V2i"; + if (ck != ClassB && type == 'l') + return quad ? "V2LLi" : "V1LLi"; + + return quad ? "V16c" : "V8c"; +} + +/// StructTag - generate the name of the struct tag for a type. +/// These names are mandated by ARM's ABI. +static std::string StructTag(StringRef typestr) { + bool quad = false; + bool poly = false; + bool usgn = false; + + // base type to get the type string for. + char type = ClassifyType(typestr, quad, poly, usgn); + + SmallString<128> s; + s += "__simd"; + s += quad ? "128_" : "64_"; + if (usgn) + s.push_back('u'); + + switch (type) { + case 'c': + s += poly ? "poly8" : "int8"; + break; + case 's': + s += poly ? "poly16" : "int16"; + break; + case 'i': + s += "int32"; + break; + case 'l': + s += "int64"; + break; + case 'h': + s += "float16"; + break; + case 'f': + s += "float32"; + break; + default: + throw "unhandled type!"; + break; + } + + // Append _t, finishing the struct tag name. + s += "_t"; + + return s.str(); +} + +/// MangleName - Append a type or width suffix to a base neon function name, +/// and insert a 'q' in the appropriate location if the operation works on +/// 128b rather than 64b. E.g. turn "vst2_lane" into "vst2q_lane_f32", etc. +static std::string MangleName(const std::string &name, StringRef typestr, + ClassKind ck) { + if (name == "vcvt_f32_f16") + return name; + + bool quad = false; + bool poly = false; + bool usgn = false; + char type = ClassifyType(typestr, quad, poly, usgn); + + std::string s = name; + + switch (type) { + case 'c': + switch (ck) { + case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break; + case ClassI: s += "_i8"; break; + case ClassW: s += "_8"; break; + default: break; + } + break; + case 's': + switch (ck) { + case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break; + case ClassI: s += "_i16"; break; + case ClassW: s += "_16"; break; + default: break; + } + break; + case 'i': + switch (ck) { + case ClassS: s += usgn ? "_u32" : "_s32"; break; + case ClassI: s += "_i32"; break; + case ClassW: s += "_32"; break; + default: break; + } + break; + case 'l': + switch (ck) { + case ClassS: s += usgn ? "_u64" : "_s64"; break; + case ClassI: s += "_i64"; break; + case ClassW: s += "_64"; break; + default: break; + } + break; + case 'h': + switch (ck) { + case ClassS: + case ClassI: s += "_f16"; break; + case ClassW: s += "_16"; break; + default: break; + } + break; + case 'f': + switch (ck) { + case ClassS: + case ClassI: s += "_f32"; break; + case ClassW: s += "_32"; break; + default: break; + } + break; + default: + throw "unhandled type!"; + break; + } + if (ck == ClassB) + s += "_v"; + + // Insert a 'q' before the first '_' character so that it ends up before + // _lane or _n on vector-scalar operations. + if (quad) { + size_t pos = s.find('_'); + s = s.insert(pos, "q"); + } + return s; +} + +// Generate the string "(argtype a, argtype b, ...)" +static std::string GenArgs(const std::string &proto, StringRef typestr) { + bool define = proto.find('i') != std::string::npos; + char arg = 'a'; + + std::string s; + s += "("; + + for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { + if (!define) { + s += TypeString(proto[i], typestr); + s.push_back(' '); + } + s.push_back(arg); + if ((i + 1) < e) + s += ", "; + } + + s += ")"; + return s; +} + +static std::string Duplicate(unsigned nElts, StringRef typestr, + const std::string &a) { + std::string s; + + s = "(__neon_" + TypeString('d', typestr) + "){ "; + for (unsigned i = 0; i != nElts; ++i) { + s += a; + if ((i + 1) < nElts) + s += ", "; + } + s += " }"; + + return s; +} + +// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd. +// If structTypes is true, the NEON types are structs of vector types rather +// than vector types, and the call becomes "a.val + b.val" +static std::string GenOpString(OpKind op, const std::string &proto, + StringRef typestr, bool structTypes = true) { + bool dummy, quad = false; + char type = ClassifyType(typestr, quad, dummy, dummy); + unsigned nElts = 0; + switch (type) { + case 'c': nElts = 8; break; + case 's': nElts = 4; break; + case 'i': nElts = 2; break; + case 'l': nElts = 1; break; + case 'h': nElts = 4; break; + case 'f': nElts = 2; break; + } + + std::string ts = TypeString(proto[0], typestr); + std::string s = ts + " r; r"; + + if (structTypes) + s += ".val"; + + s += " = "; + + std::string a, b, c; + if (proto.size() > 1) + a = (structTypes && proto[1] != 'l' && proto[1] != 's') ? "a.val" : "a"; + b = structTypes ? "b.val" : "b"; + c = structTypes ? "c.val" : "c"; + + switch(op) { + case OpAdd: + s += a + " + " + b; + break; + case OpSub: + s += a + " - " + b; + break; + case OpMulN: + b = Duplicate(nElts << (int)quad, typestr, "b"); + case OpMul: + s += a + " * " + b; + break; + case OpMlaN: + c = Duplicate(nElts << (int)quad, typestr, "c"); + case OpMla: + s += a + " + ( " + b + " * " + c + " )"; + break; + case OpMlsN: + c = Duplicate(nElts << (int)quad, typestr, "c"); + case OpMls: + s += a + " - ( " + b + " * " + c + " )"; + break; + case OpEq: + s += "(__neon_" + ts + ")(" + a + " == " + b + ")"; + break; + case OpGe: + s += "(__neon_" + ts + ")(" + a + " >= " + b + ")"; + break; + case OpLe: + s += "(__neon_" + ts + ")(" + a + " <= " + b + ")"; + break; + case OpGt: + s += "(__neon_" + ts + ")(" + a + " > " + b + ")"; + break; + case OpLt: + s += "(__neon_" + ts + ")(" + a + " < " + b + ")"; + break; + case OpNeg: + s += " -" + a; + break; + case OpNot: + s += " ~" + a; + break; + case OpAnd: + s += a + " & " + b; + break; + case OpOr: + s += a + " | " + b; + break; + case OpXor: + s += a + " ^ " + b; + break; + case OpAndNot: + s += a + " & ~" + b; + break; + case OpOrNot: + s += a + " | ~" + b; + break; + case OpCast: + s += "(__neon_" + ts + ")" + a; + break; + case OpConcat: + s += "__builtin_shufflevector((__neon_int64x1_t)" + a; + s += ", (__neon_int64x1_t)" + b + ", 0, 1)"; + break; + case OpHi: + s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[1])"; + break; + case OpLo: + s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[0])"; + break; + case OpDup: + s += Duplicate(nElts << (int)quad, typestr, a); + break; + case OpSelect: + // ((0 & 1) | (~0 & 2)) + ts = TypeString(proto[1], typestr); + s += "( " + a + " & (__neon_" + ts + ")" + b + ") | "; + s += "(~" + a + " & (__neon_" + ts + ")" + c + ")"; + break; + case OpRev16: + s += "__builtin_shufflevector(" + a + ", " + a; + for (unsigned i = 2; i <= nElts << (int)quad; i += 2) + for (unsigned j = 0; j != 2; ++j) + s += ", " + utostr(i - j - 1); + s += ")"; + break; + case OpRev32: + nElts >>= 1; + s += "__builtin_shufflevector(" + a + ", " + a; + for (unsigned i = nElts; i <= nElts << (1 + (int)quad); i += nElts) + for (unsigned j = 0; j != nElts; ++j) + s += ", " + utostr(i - j - 1); + s += ")"; + break; + case OpRev64: + s += "__builtin_shufflevector(" + a + ", " + a; + for (unsigned i = nElts; i <= nElts << (int)quad; i += nElts) + for (unsigned j = 0; j != nElts; ++j) + s += ", " + utostr(i - j - 1); + s += ")"; + break; + default: + throw "unknown OpKind!"; + break; + } + s += "; return r;"; + return s; +} + +static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { + unsigned mod = proto[0]; + unsigned ret = 0; + + if (mod == 'v' || mod == 'f') + mod = proto[1]; + + bool quad = false; + bool poly = false; + bool usgn = false; + bool scal = false; + bool cnst = false; + bool pntr = false; + + // base type to get the type string for. + char type = ClassifyType(typestr, quad, poly, usgn); + + // Based on the modifying character, change the type and width if necessary. + type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); + + if (usgn) + ret |= 0x08; + if (quad) + ret |= 0x10; + + switch (type) { + case 'c': + ret |= poly ? 5 : 0; + break; + case 's': + ret |= poly ? 6 : 1; + break; + case 'i': + ret |= 2; + break; + case 'l': + ret |= 3; + break; + case 'h': + ret |= 7; + break; + case 'f': + ret |= 4; + break; + default: + throw "unhandled type!"; + break; + } + return ret; +} + +// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a) +// If structTypes is true, the NEON types are structs of vector types rather +// than vector types, and the call becomes __builtin_neon_cls(a.val) +static std::string GenBuiltin(const std::string &name, const std::string &proto, + StringRef typestr, ClassKind ck, + bool structTypes = true) { + bool dummy, quad = false; + char type = ClassifyType(typestr, quad, dummy, dummy); + unsigned nElts = 0; + switch (type) { + case 'c': nElts = 8; break; + case 's': nElts = 4; break; + case 'i': nElts = 2; break; + case 'l': nElts = 1; break; + case 'h': nElts = 4; break; + case 'f': nElts = 2; break; + } + if (quad) nElts <<= 1; + + char arg = 'a'; + std::string s; + + // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit + // sret-like argument. + bool sret = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4'); + + // If this builtin takes an immediate argument, we need to #define it rather + // than use a standard declaration, so that SemaChecking can range check + // the immediate passed by the user. + bool define = proto.find('i') != std::string::npos; + + // If all types are the same size, bitcasting the args will take care + // of arg checking. The actual signedness etc. will be taken care of with + // special enums. + if (proto.find('s') == std::string::npos) + ck = ClassB; + + if (proto[0] != 'v') { + std::string ts = TypeString(proto[0], typestr); + + if (define) { + if (sret) + s += "({ " + ts + " r; "; + else if (proto[0] != 's') + s += "(" + ts + "){(__neon_" + ts + ")"; + } else if (sret) { + s += ts + " r; "; + } else { + s += ts + " r; r"; + if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l') + s += ".val"; + + s += " = "; + } + } + + bool splat = proto.find('a') != std::string::npos; + + s += "__builtin_neon_"; + if (splat) { + std::string vname(name, 0, name.size()-2); + s += MangleName(vname, typestr, ck); + } else { + s += MangleName(name, typestr, ck); + } + s += "("; + + // Pass the address of the return variable as the first argument to sret-like + // builtins. + if (sret) + s += "&r, "; + + for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { + std::string args = std::string(&arg, 1); + if (define) + args = "(" + args + ")"; + + // Handle multiple-vector values specially, emitting each subvector as an + // argument to the __builtin. + if (structTypes && (proto[i] == '2' || proto[i] == '3' || proto[i] == '4')){ + for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) { + s += args + ".val[" + utostr(vi) + "].val"; + if ((vi + 1) < ve) + s += ", "; + } + if ((i + 1) < e) + s += ", "; + + continue; + } + + if (splat && (i + 1) == e) + s += Duplicate(nElts, typestr, args); + else + s += args; + + if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' && + proto[i] != 'p' && proto[i] != 'c' && proto[i] != 'a') { + s += ".val"; + } + if ((i + 1) < e) + s += ", "; + } + + // Extra constant integer to hold type class enum for this function, e.g. s8 + if (ck == ClassB) + s += ", " + utostr(GetNeonEnum(proto, typestr)); + + if (define) + s += ")"; + else + s += ");"; + + if (proto[0] != 'v') { + if (define) { + if (sret) + s += "; r; })"; + else if (proto[0] != 's') + s += "}"; + } else { + s += " return r;"; + } + } + return s; +} + +static std::string GenBuiltinDef(const std::string &name, + const std::string &proto, + StringRef typestr, ClassKind ck) { + std::string s("BUILTIN(__builtin_neon_"); + + // If all types are the same size, bitcasting the args will take care + // of arg checking. The actual signedness etc. will be taken care of with + // special enums. + if (proto.find('s') == std::string::npos) + ck = ClassB; + + s += MangleName(name, typestr, ck); + s += ", \""; + + for (unsigned i = 0, e = proto.size(); i != e; ++i) + s += BuiltinTypeString(proto[i], typestr, ck, i == 0); + + // Extra constant integer to hold type class enum for this function, e.g. s8 + if (ck == ClassB) + s += "i"; + + s += "\", \"n\")"; + return s; +} + +/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h +/// is comprised of type definitions and function declarations. +void NeonEmitter::run(raw_ostream &OS) { + EmitSourceFileHeader("ARM NEON Header", OS); + + // FIXME: emit license into file? + + OS << "#ifndef __ARM_NEON_H\n"; + OS << "#define __ARM_NEON_H\n\n"; + + OS << "#ifndef __ARM_NEON__\n"; + OS << "#error \"NEON support not enabled\"\n"; + OS << "#endif\n\n"; + + OS << "#include <stdint.h>\n\n"; + + // Emit NEON-specific scalar typedefs. + OS << "typedef float float32_t;\n"; + OS << "typedef uint8_t poly8_t;\n"; + OS << "typedef uint16_t poly16_t;\n"; + OS << "typedef uint16_t float16_t;\n"; + + // Emit Neon vector typedefs. + std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs"); + SmallVector<StringRef, 24> TDTypeVec; + ParseTypes(0, TypedefTypes, TDTypeVec); + + // Emit vector typedefs. + for (unsigned v = 1; v != 5; ++v) { + for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) { + bool dummy, quad = false; + (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy); + OS << "typedef __attribute__(( __vector_size__("; + + OS << utostr(8*v*(quad ? 2 : 1)) << ") )) "; + if (!quad) + OS << " "; + + OS << TypeString('s', TDTypeVec[i]); + OS << " __neon_"; + + char t = (v == 1) ? 'd' : '0' + v; + OS << TypeString(t, TDTypeVec[i]) << ";\n"; + } + } + OS << "\n"; + + // Emit struct typedefs. + for (unsigned vi = 1; vi != 5; ++vi) { + for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) { + std::string ts = TypeString('d', TDTypeVec[i], vi == 1); + std::string vs = TypeString((vi > 1) ? '0' + vi : 'd', TDTypeVec[i]); + std::string tag = (vi > 1) ? vs : StructTag(TDTypeVec[i]); + OS << "typedef struct " << tag << " {\n"; + OS << " " << ts << " val"; + if (vi > 1) + OS << "[" << utostr(vi) << "]"; + OS << ";\n} " << vs << ";\n\n"; + } + } + + OS << "#define __ai static __attribute__((__always_inline__))\n\n"; + + std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst"); + + // Unique the return+pattern types, and assign them. + for (unsigned i = 0, e = RV.size(); i != e; ++i) { + Record *R = RV[i]; + std::string name = LowercaseString(R->getName()); + std::string Proto = R->getValueAsString("Prototype"); + std::string Types = R->getValueAsString("Types"); + + SmallVector<StringRef, 16> TypeVec; + ParseTypes(R, Types, TypeVec); + + OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; + + bool define = Proto.find('i') != std::string::npos; + + for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { + assert(!Proto.empty() && ""); + + // static always inline + return type + if (define) + OS << "#define"; + else + OS << "__ai " << TypeString(Proto[0], TypeVec[ti]); + + // Function name with type suffix + OS << " " << MangleName(name, TypeVec[ti], ClassS); + + // Function arguments + OS << GenArgs(Proto, TypeVec[ti]); + + // Definition. + if (define) + OS << " "; + else + OS << " { "; + + if (k != OpNone) { + OS << GenOpString(k, Proto, TypeVec[ti]); + } else { + if (R->getSuperClasses().size() < 2) + throw TGError(R->getLoc(), "Builtin has no class kind"); + + ClassKind ck = ClassMap[R->getSuperClasses()[1]]; + + if (ck == ClassNone) + throw TGError(R->getLoc(), "Builtin has no class kind"); + OS << GenBuiltin(name, Proto, TypeVec[ti], ck); + } + if (!define) + OS << " }"; + OS << "\n"; + } + OS << "\n"; + } + OS << "#undef __ai\n\n"; + OS << "#endif /* __ARM_NEON_H */\n"; +} + +static unsigned RangeFromType(StringRef typestr) { + // base type to get the type string for. + bool quad = false, dummy = false; + char type = ClassifyType(typestr, quad, dummy, dummy); + + switch (type) { + case 'c': + return (8 << (int)quad) - 1; + case 'h': + case 's': + return (4 << (int)quad) - 1; + case 'f': + case 'i': + return (2 << (int)quad) - 1; + case 'l': + return (1 << (int)quad) - 1; + default: + throw "unhandled type!"; + break; + } +} + +/// runHeader - Emit a file with sections defining: +/// 1. the NEON section of BuiltinsARM.def. +/// 2. the SemaChecking code for the type overload checking. +/// 3. the SemaChecking code for validation of intrinsic immedate arguments. +void NeonEmitter::runHeader(raw_ostream &OS) { + std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst"); + + StringMap<OpKind> EmittedMap; + + // Generate BuiltinsARM.def for NEON + OS << "#ifdef GET_NEON_BUILTINS\n"; + for (unsigned i = 0, e = RV.size(); i != e; ++i) { + Record *R = RV[i]; + OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; + if (k != OpNone) + continue; + + std::string Proto = R->getValueAsString("Prototype"); + + // Functions with 'a' (the splat code) in the type prototype should not get + // their own builtin as they use the non-splat variant. + if (Proto.find('a') != std::string::npos) + continue; + + std::string Types = R->getValueAsString("Types"); + SmallVector<StringRef, 16> TypeVec; + ParseTypes(R, Types, TypeVec); + + if (R->getSuperClasses().size() < 2) + throw TGError(R->getLoc(), "Builtin has no class kind"); + + std::string name = LowercaseString(R->getName()); + ClassKind ck = ClassMap[R->getSuperClasses()[1]]; + + for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { + // Generate the BuiltinsARM.def declaration for this builtin, ensuring + // that each unique BUILTIN() macro appears only once in the output + // stream. + std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck); + if (EmittedMap.count(bd)) + continue; + + EmittedMap[bd] = OpNone; + OS << bd << "\n"; + } + } + OS << "#endif\n\n"; + + // Generate the overloaded type checking code for SemaChecking.cpp + OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n"; + for (unsigned i = 0, e = RV.size(); i != e; ++i) { + Record *R = RV[i]; + OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; + if (k != OpNone) + continue; + + std::string Proto = R->getValueAsString("Prototype"); + std::string Types = R->getValueAsString("Types"); + std::string name = LowercaseString(R->getName()); + + // Functions with 'a' (the splat code) in the type prototype should not get + // their own builtin as they use the non-splat variant. + if (Proto.find('a') != std::string::npos) + continue; + + // Functions which have a scalar argument cannot be overloaded, no need to + // check them if we are emitting the type checking code. + if (Proto.find('s') != std::string::npos) + continue; + + SmallVector<StringRef, 16> TypeVec; + ParseTypes(R, Types, TypeVec); + + if (R->getSuperClasses().size() < 2) + throw TGError(R->getLoc(), "Builtin has no class kind"); + + int si = -1, qi = -1; + unsigned mask = 0, qmask = 0; + for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { + // Generate the switch case(s) for this builtin for the type validation. + bool quad = false, poly = false, usgn = false; + (void) ClassifyType(TypeVec[ti], quad, poly, usgn); + + if (quad) { + qi = ti; + qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]); + } else { + si = ti; + mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]); + } + } + if (mask) + OS << "case ARM::BI__builtin_neon_" + << MangleName(name, TypeVec[si], ClassB) + << ": mask = " << "0x" << utohexstr(mask) << "; break;\n"; + if (qmask) + OS << "case ARM::BI__builtin_neon_" + << MangleName(name, TypeVec[qi], ClassB) + << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n"; + } + OS << "#endif\n\n"; + + // Generate the intrinsic range checking code for shift/lane immediates. + OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n"; + for (unsigned i = 0, e = RV.size(); i != e; ++i) { + Record *R = RV[i]; + + OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; + if (k != OpNone) + continue; + + std::string name = LowercaseString(R->getName()); + std::string Proto = R->getValueAsString("Prototype"); + std::string Types = R->getValueAsString("Types"); + + // Functions with 'a' (the splat code) in the type prototype should not get + // their own builtin as they use the non-splat variant. + if (Proto.find('a') != std::string::npos) + continue; + + // Functions which do not have an immediate do not need to have range + // checking code emitted. + if (Proto.find('i') == std::string::npos) + continue; + + SmallVector<StringRef, 16> TypeVec; + ParseTypes(R, Types, TypeVec); + + if (R->getSuperClasses().size() < 2) + throw TGError(R->getLoc(), "Builtin has no class kind"); + + ClassKind ck = ClassMap[R->getSuperClasses()[1]]; + + for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { + std::string namestr, shiftstr, rangestr; + + // Builtins which are overloaded by type will need to have their upper + // bound computed at Sema time based on the type constant. + if (Proto.find('s') == std::string::npos) { + ck = ClassB; + if (R->getValueAsBit("isShift")) { + shiftstr = ", true"; + + // Right shifts have an 'r' in the name, left shifts do not. + if (name.find('r') != std::string::npos) + rangestr = "l = 1; "; + } + rangestr += "u = RFT(TV" + shiftstr + ")"; + } else { + rangestr = "u = " + utostr(RangeFromType(TypeVec[ti])); + } + // Make sure cases appear only once by uniquing them in a string map. + namestr = MangleName(name, TypeVec[ti], ck); + if (EmittedMap.count(namestr)) + continue; + EmittedMap[namestr] = OpNone; + + // Calculate the index of the immediate that should be range checked. + unsigned immidx = 0; + + // Builtins that return a struct of multiple vectors have an extra + // leading arg for the struct return. + if (Proto[0] == '2' || Proto[0] == '3' || Proto[0] == '4') + ++immidx; + + // Add one to the index for each argument until we reach the immediate + // to be checked. Structs of vectors are passed as multiple arguments. + for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) { + switch (Proto[ii]) { + default: immidx += 1; break; + case '2': immidx += 2; break; + case '3': immidx += 3; break; + case '4': immidx += 4; break; + case 'i': ie = ii + 1; break; + } + } + OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck) + << ": i = " << immidx << "; " << rangestr << "; break;\n"; + } + } + OS << "#endif\n\n"; +} diff --git a/utils/TableGen/NeonEmitter.h b/utils/TableGen/NeonEmitter.h new file mode 100644 index 0000000..6c6760d --- /dev/null +++ b/utils/TableGen/NeonEmitter.h @@ -0,0 +1,122 @@ +//===- NeonEmitter.h - Generate arm_neon.h for use with clang ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting arm_neon.h, which includes +// a declaration and definition of each function specified by the ARM NEON +// compiler interface. See ARM document DUI0348B. +// +//===----------------------------------------------------------------------===// + +#ifndef NEON_EMITTER_H +#define NEON_EMITTER_H + +#include "Record.h" +#include "TableGenBackend.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" + +enum OpKind { + OpNone, + OpAdd, + OpSub, + OpMul, + OpMla, + OpMls, + OpMulN, + OpMlaN, + OpMlsN, + OpEq, + OpGe, + OpLe, + OpGt, + OpLt, + OpNeg, + OpNot, + OpAnd, + OpOr, + OpXor, + OpAndNot, + OpOrNot, + OpCast, + OpConcat, + OpDup, + OpHi, + OpLo, + OpSelect, + OpRev16, + OpRev32, + OpRev64 +}; + +enum ClassKind { + ClassNone, + ClassI, + ClassS, + ClassW, + ClassB +}; + +namespace llvm { + + class NeonEmitter : public TableGenBackend { + RecordKeeper &Records; + StringMap<OpKind> OpMap; + DenseMap<Record*, ClassKind> ClassMap; + + public: + NeonEmitter(RecordKeeper &R) : Records(R) { + OpMap["OP_NONE"] = OpNone; + OpMap["OP_ADD"] = OpAdd; + OpMap["OP_SUB"] = OpSub; + OpMap["OP_MUL"] = OpMul; + OpMap["OP_MLA"] = OpMla; + OpMap["OP_MLS"] = OpMls; + OpMap["OP_MUL_N"] = OpMulN; + OpMap["OP_MLA_N"] = OpMlaN; + OpMap["OP_MLS_N"] = OpMlsN; + OpMap["OP_EQ"] = OpEq; + OpMap["OP_GE"] = OpGe; + OpMap["OP_LE"] = OpLe; + OpMap["OP_GT"] = OpGt; + OpMap["OP_LT"] = OpLt; + OpMap["OP_NEG"] = OpNeg; + OpMap["OP_NOT"] = OpNot; + OpMap["OP_AND"] = OpAnd; + OpMap["OP_OR"] = OpOr; + OpMap["OP_XOR"] = OpXor; + OpMap["OP_ANDN"] = OpAndNot; + OpMap["OP_ORN"] = OpOrNot; + OpMap["OP_CAST"] = OpCast; + OpMap["OP_CONC"] = OpConcat; + OpMap["OP_HI"] = OpHi; + OpMap["OP_LO"] = OpLo; + OpMap["OP_DUP"] = OpDup; + OpMap["OP_SEL"] = OpSelect; + OpMap["OP_REV16"] = OpRev16; + OpMap["OP_REV32"] = OpRev32; + OpMap["OP_REV64"] = OpRev64; + + Record *SI = R.getClass("SInst"); + Record *II = R.getClass("IInst"); + Record *WI = R.getClass("WInst"); + ClassMap[SI] = ClassS; + ClassMap[II] = ClassI; + ClassMap[WI] = ClassW; + } + + // run - Emit arm_neon.h.inc + void run(raw_ostream &o); + + // runHeader - Emit all the __builtin prototypes used in arm_neon.h + void runHeader(raw_ostream &o); + }; + +} // End llvm namespace + +#endif diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index 4f9f604..d2cf379 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -270,7 +270,15 @@ Init *RecordRecTy::convertValue(TypedInit *TI) { } bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const { - return Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec); + if (Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec)) + return true; + + const std::vector<Record*> &SC = Rec->getSuperClasses(); + for (unsigned i = 0, e = SC.size(); i != e; ++i) + if (RHS->getRecord()->isSubClassOf(SC[i])) + return true; + + return false; } @@ -721,9 +729,20 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { break; } case EQ: { - // Make sure we've resolved + // try to fold eq comparison for 'bit' and 'int', otherwise fallback + // to string objects. + IntInit* L = + dynamic_cast<IntInit*>(LHS->convertInitializerTo(new IntRecTy())); + IntInit* R = + dynamic_cast<IntInit*>(RHS->convertInitializerTo(new IntRecTy())); + + if (L && R) + return new IntInit(L->getValue() == R->getValue()); + StringInit *LHSs = dynamic_cast<StringInit*>(LHS); StringInit *RHSs = dynamic_cast<StringInit*>(RHS); + + // Make sure we've resolved if (LHSs && RHSs) return new IntInit(LHSs->getValue() == RHSs->getValue()); @@ -971,6 +990,8 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { case IF: { IntInit *LHSi = dynamic_cast<IntInit*>(LHS); + if (Init *I = LHS->convertInitializerTo(new IntRecTy())) + LHSi = dynamic_cast<IntInit*>(I); if (LHSi) { if (LHSi->getValue()) { return MHS; @@ -990,6 +1011,8 @@ Init *TernOpInit::resolveReferences(Record &R, const RecordVal *RV) { if (Opc == IF && lhs != LHS) { IntInit *Value = dynamic_cast<IntInit*>(lhs); + if (Init *I = lhs->convertInitializerTo(new IntRecTy())) + Value = dynamic_cast<IntInit*>(I); if (Value != 0) { // Short-circuit if (Value->getValue()) { @@ -1239,7 +1262,7 @@ Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) { Init *Op = Val->resolveReferences(R, RV); if (Args != NewArgs || Op != Val) - return new DagInit(Op, "", NewArgs, ArgNames); + return new DagInit(Op, ValName, NewArgs, ArgNames); return this; } diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index c99bbd9..a3ca0bc 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -82,6 +82,7 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { << " { return false; }\n" << " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n" << " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n" + << " unsigned composeSubRegIndices(unsigned, unsigned) const;\n" << "};\n\n"; const std::vector<CodeGenRegisterClass> &RegisterClasses = @@ -95,7 +96,7 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { if (i) OS << ",\n"; OS << " " << RegisterClasses[i].getName() << "RegClassID"; - OS << " = " << (i+1); + OS << " = " << i; } OS << "\n };\n\n"; @@ -171,14 +172,28 @@ static void addSubSuperReg(Record *R, Record *S, addSubSuperReg(R, *I, SubRegs, SuperRegs, Aliases); } -// Map SubRegIndex -> Register -typedef std::map<Record*, Record*, LessRecord> SubRegMap; -// Map Register -> SubRegMap -typedef std::map<Record*, SubRegMap> AllSubRegMap; +struct RegisterMaps { + // Map SubRegIndex -> Register + typedef std::map<Record*, Record*, LessRecord> SubRegMap; + // Map Register -> SubRegMap + typedef std::map<Record*, SubRegMap> SubRegMaps; + + SubRegMaps SubReg; + SubRegMap &inferSubRegIndices(Record *Reg); + + // Composite SubRegIndex instances. + // Map (SubRegIndex,SubRegIndex) -> SubRegIndex + typedef DenseMap<std::pair<Record*,Record*>,Record*> CompositeMap; + CompositeMap Composite; + + // Compute SubRegIndex compositions after inferSubRegIndices has run on all + // registers. + void computeComposites(); +}; // Calculate all subregindices for Reg. Loopy subregs cause infinite recursion. -static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) { - SubRegMap &SRM = ASRM[Reg]; +RegisterMaps::SubRegMap &RegisterMaps::inferSubRegIndices(Record *Reg) { + SubRegMap &SRM = SubReg[Reg]; if (!SRM.empty()) return SRM; std::vector<Record*> SubRegs = Reg->getValueAsListOfDefs("SubRegs"); @@ -191,7 +206,7 @@ static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) { if (!SRM.insert(std::make_pair(Indices[i], SubRegs[i])).second) throw "SubRegIndex " + Indices[i]->getName() + " appears twice in Register " + Reg->getName(); - inferSubRegIndices(SubRegs[i], ASRM); + inferSubRegIndices(SubRegs[i]); } // Keep track of inherited subregs and how they can be reached. @@ -202,7 +217,7 @@ static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) { // Clone inherited subregs. Here the order is important - earlier subregs take // precedence. for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) { - SubRegMap &M = ASRM[SubRegs[i]]; + SubRegMap &M = SubReg[SubRegs[i]]; for (SubRegMap::iterator si = M.begin(), se = M.end(); si != se; ++si) if (!SRM.insert(*si).second) Orphans[si->second] = std::make_pair(Indices[i], si->first); @@ -226,8 +241,8 @@ static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) { DefInit *IdxInit = dynamic_cast<DefInit*>(*di); if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex")) throw "Invalid SubClassIndex in " + Pat->getAsString(); - SubRegMap::const_iterator ni = ASRM[R2].find(IdxInit->getDef()); - if (ni == ASRM[R2].end()) + SubRegMap::const_iterator ni = SubReg[R2].find(IdxInit->getDef()); + if (ni == SubReg[R2].end()) throw "Composite " + Pat->getAsString() + " refers to bad index in " + R2->getName(); R2 = ni->second; @@ -255,6 +270,62 @@ static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) { return SRM; } +void RegisterMaps::computeComposites() { + for (SubRegMaps::const_iterator sri = SubReg.begin(), sre = SubReg.end(); + sri != sre; ++sri) { + Record *Reg1 = sri->first; + const SubRegMap &SRM1 = sri->second; + for (SubRegMap::const_iterator i1 = SRM1.begin(), e1 = SRM1.end(); + i1 != e1; ++i1) { + Record *Idx1 = i1->first; + Record *Reg2 = i1->second; + // Ignore identity compositions. + if (Reg1 == Reg2) + continue; + // If Reg2 has no subregs, Idx1 doesn't compose. + if (!SubReg.count(Reg2)) + continue; + const SubRegMap &SRM2 = SubReg[Reg2]; + // Try composing Idx1 with another SubRegIndex. + for (SubRegMap::const_iterator i2 = SRM2.begin(), e2 = SRM2.end(); + i2 != e2; ++i2) { + std::pair<Record*,Record*> IdxPair(Idx1, i2->first); + Record *Reg3 = i2->second; + // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3. + for (SubRegMap::const_iterator i1d = SRM1.begin(), e1d = SRM1.end(); + i1d != e1d; ++i1d) { + // Ignore identity compositions. + if (Reg2 == Reg3) + continue; + if (i1d->second == Reg3) { + std::pair<CompositeMap::iterator,bool> Ins = + Composite.insert(std::make_pair(IdxPair, i1d->first)); + // Conflicting composition? + if (!Ins.second && Ins.first->second != i1d->first) { + errs() << "Error: SubRegIndex " << getQualifiedName(Idx1) + << " and " << getQualifiedName(IdxPair.second) + << " compose ambiguously as " + << getQualifiedName(Ins.first->second) << " or " + << getQualifiedName(i1d->first) << "\n"; + abort(); + } + } + } + } + } + } + + // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid + // compositions, so remove any mappings of that form. + for (CompositeMap::iterator i = Composite.begin(), e = Composite.end(); + i != e;) { + CompositeMap::iterator j = i; + ++i; + if (j->first.second == j->second) + Composite.erase(j); + } +} + class RegisterSorter { private: std::map<Record*, std::set<Record*>, LessRecord> &RegisterSubRegs; @@ -836,7 +907,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { std::string ClassName = Target.getName() + "GenRegisterInfo"; // Calculate the mapping of subregister+index pairs to physical registers. - AllSubRegMap AllSRM; + RegisterMaps RegMaps; // Emit the subregister + index mapping function based on the information // calculated above. @@ -845,14 +916,14 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << " switch (RegNo) {\n" << " default:\n return 0;\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - SubRegMap &SRM = inferSubRegIndices(Regs[i].TheDef, AllSRM); + RegisterMaps::SubRegMap &SRM = RegMaps.inferSubRegIndices(Regs[i].TheDef); if (SRM.empty()) continue; OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n"; OS << " switch (Index) {\n"; OS << " default: return 0;\n"; - for (SubRegMap::const_iterator ii = SRM.begin(), ie = SRM.end(); ii != ie; - ++ii) + for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(), + ie = SRM.end(); ii != ie; ++ii) OS << " case " << getQualifiedName(ii->first) << ": return " << getQualifiedName(ii->second) << ";\n"; OS << " };\n" << " break;\n"; @@ -866,12 +937,12 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << " switch (RegNo) {\n" << " default:\n return 0;\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - SubRegMap &SRM = AllSRM[Regs[i].TheDef]; + RegisterMaps::SubRegMap &SRM = RegMaps.SubReg[Regs[i].TheDef]; if (SRM.empty()) continue; OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n"; - for (SubRegMap::const_iterator ii = SRM.begin(), ie = SRM.end(); ii != ie; - ++ii) + for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(), + ie = SRM.end(); ii != ie; ++ii) OS << " if (SubRegNo == " << getQualifiedName(ii->second) << ") return " << getQualifiedName(ii->first) << ";\n"; OS << " return 0;\n"; @@ -879,7 +950,32 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << " };\n"; OS << " return 0;\n"; OS << "}\n\n"; - + + // Emit composeSubRegIndices + RegMaps.computeComposites(); + OS << "unsigned " << ClassName + << "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n" + << " switch (IdxA) {\n" + << " default:\n return IdxB;\n"; + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { + bool Open = false; + for (unsigned j = 0; j != e; ++j) { + if (Record *Comp = RegMaps.Composite.lookup( + std::make_pair(SubRegIndices[i], SubRegIndices[j]))) { + if (!Open) { + OS << " case " << getQualifiedName(SubRegIndices[i]) + << ": switch(IdxB) {\n default: return IdxB;\n"; + Open = true; + } + OS << " case " << getQualifiedName(SubRegIndices[j]) + << ": return " << getQualifiedName(Comp) << ";\n"; + } + } + if (Open) + OS << " }\n"; + } + OS << " }\n}\n\n"; + // Emit the constructor of the class... OS << ClassName << "::" << ClassName << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n" diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index 8c158e0..f81aabe 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -1635,13 +1635,12 @@ bool TGParser::ParseObjectBody(Record *CurRec) { return ParseBody(CurRec); } - /// ParseDef - Parse and return a top level or multiclass def, return the record /// corresponding to it. This returns null on error. /// /// DefInst ::= DEF ObjectName ObjectBody /// -llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) { +bool TGParser::ParseDef(MultiClass *CurMultiClass) { SMLoc DefLoc = Lex.getLoc(); assert(Lex.getCode() == tgtok::Def && "Unknown tok"); Lex.Lex(); // Eat the 'def' token. @@ -1655,7 +1654,7 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) { // Ensure redefinition doesn't happen. if (Records.getDef(CurRec->getName())) { Error(DefLoc, "def '" + CurRec->getName() + "' already defined"); - return 0; + return true; } Records.addDef(CurRec); } else { @@ -1664,20 +1663,33 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) { if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) { Error(DefLoc, "def '" + CurRec->getName() + "' already defined in this multiclass!"); - return 0; + return true; } CurMultiClass->DefPrototypes.push_back(CurRec); } if (ParseObjectBody(CurRec)) - return 0; + return true; if (CurMultiClass == 0) // Def's in multiclasses aren't really defs. CurRec->resolveReferences(); // If ObjectBody has template arguments, it's an error. assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?"); - return CurRec; + + if (CurMultiClass) { + // Copy the template arguments for the multiclass into the def. + const std::vector<std::string> &TArgs = + CurMultiClass->Rec.getTemplateArgs(); + + for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]); + assert(RV && "Template arg doesn't exist?"); + CurRec->addValue(*RV); + } + } + + return false; } @@ -1758,12 +1770,12 @@ std::vector<LetRecord> TGParser::ParseLetList() { } /// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of -/// different related productions. +/// different related productions. This works inside multiclasses too. /// /// Object ::= LET LetList IN '{' ObjectList '}' /// Object ::= LET LetList IN Object /// -bool TGParser::ParseTopLevelLet() { +bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) { assert(Lex.getCode() == tgtok::Let && "Unexpected token"); Lex.Lex(); @@ -1779,7 +1791,7 @@ bool TGParser::ParseTopLevelLet() { // If this is a scalar let, just handle it now if (Lex.getCode() != tgtok::l_brace) { // LET LetList IN Object - if (ParseObject()) + if (ParseObject(CurMultiClass)) return true; } else { // Object ::= LETCommand '{' ObjectList '}' SMLoc BraceLoc = Lex.getLoc(); @@ -1787,7 +1799,7 @@ bool TGParser::ParseTopLevelLet() { Lex.Lex(); // eat the '{'. // Parse the object list. - if (ParseObjectList()) + if (ParseObjectList(CurMultiClass)) return true; if (Lex.getCode() != tgtok::r_brace) { @@ -1802,29 +1814,6 @@ bool TGParser::ParseTopLevelLet() { return false; } -/// ParseMultiClassDef - Parse a def in a multiclass context. -/// -/// MultiClassDef ::= DefInst -/// -bool TGParser::ParseMultiClassDef(MultiClass *CurMC) { - if (Lex.getCode() != tgtok::Def) - return TokError("expected 'def' in multiclass body"); - - Record *D = ParseDef(CurMC); - if (D == 0) return true; - - // Copy the template arguments for the multiclass into the def. - const std::vector<std::string> &TArgs = CurMC->Rec.getTemplateArgs(); - - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - const RecordVal *RV = CurMC->Rec.getValue(TArgs[i]); - assert(RV && "Template arg doesn't exist?"); - D->addValue(*RV); - } - - return false; -} - /// ParseMultiClass - Parse a multiclass definition. /// /// MultiClassInst ::= MULTICLASS ID TemplateArgList? @@ -1885,10 +1874,18 @@ bool TGParser::ParseMultiClass() { if (Lex.Lex() == tgtok::r_brace) // eat the '{'. return TokError("multiclass must contain at least one def"); - while (Lex.getCode() != tgtok::r_brace) - if (ParseMultiClassDef(CurMultiClass)) - return true; - + while (Lex.getCode() != tgtok::r_brace) { + switch (Lex.getCode()) { + default: + return TokError("expected 'let', 'def' or 'defm' in multiclass body"); + case tgtok::Let: + case tgtok::Def: + case tgtok::Defm: + if (ParseObject(CurMultiClass)) + return true; + break; + } + } Lex.Lex(); // eat the '}'. } @@ -1900,7 +1897,7 @@ bool TGParser::ParseMultiClass() { /// /// DefMInst ::= DEFM ID ':' DefmSubClassRef ';' /// -bool TGParser::ParseDefm() { +bool TGParser::ParseDefm(MultiClass *CurMultiClass) { assert(Lex.getCode() == tgtok::Defm && "Unexpected token!"); if (Lex.Lex() != tgtok::Id) // eat the defm. return TokError("expected identifier after defm"); @@ -1910,6 +1907,12 @@ bool TGParser::ParseDefm() { if (Lex.Lex() != tgtok::colon) return TokError("expected ':' after defm identifier"); + // Keep track of the new generated record definitions. + std::vector<Record*> NewRecDefs; + + // This record also inherits from a regular class (non-multiclass)? + bool InheritFromClass = false; + // eat the colon. Lex.Lex(); @@ -1991,17 +1994,87 @@ bool TGParser::ParseDefm() { return Error(DefmPrefixLoc, "def '" + CurRec->getName() + "' already defined, instantiating defm with subdef '" + DefProto->getName() + "'"); - Records.addDef(CurRec); - CurRec->resolveReferences(); + + // Don't create a top level definition for defm inside multiclasses, + // instead, only update the prototypes and bind the template args + // with the new created definition. + if (CurMultiClass) { + for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); + i != e; ++i) { + if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) { + Error(DefmPrefixLoc, "defm '" + CurRec->getName() + + "' already defined in this multiclass!"); + return 0; + } + } + CurMultiClass->DefPrototypes.push_back(CurRec); + + // Copy the template arguments for the multiclass into the new def. + const std::vector<std::string> &TA = + CurMultiClass->Rec.getTemplateArgs(); + + for (unsigned i = 0, e = TA.size(); i != e; ++i) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]); + assert(RV && "Template arg doesn't exist?"); + CurRec->addValue(*RV); + } + } else { + Records.addDef(CurRec); + } + + NewRecDefs.push_back(CurRec); } if (Lex.getCode() != tgtok::comma) break; Lex.Lex(); // eat ','. SubClassLoc = Lex.getLoc(); + + // A defm can inherit from regular classes (non-multiclass) as + // long as they come in the end of the inheritance list. + InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0); + + if (InheritFromClass) + break; + Ref = ParseSubClassReference(0, true); } + if (InheritFromClass) { + // Process all the classes to inherit as if they were part of a + // regular 'def' and inherit all record values. + SubClassReference SubClass = ParseSubClassReference(0, false); + while (1) { + // Check for error. + if (SubClass.Rec == 0) return true; + + // Get the expanded definition prototypes and teach them about + // the record values the current class to inherit has + for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) { + Record *CurRec = NewRecDefs[i]; + + // Add it. + if (AddSubClass(CurRec, SubClass)) + return true; + + // Process any variables on the let stack. + for (unsigned i = 0, e = LetStack.size(); i != e; ++i) + for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) + if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, + LetStack[i][j].Bits, LetStack[i][j].Value)) + return true; + } + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat ','. + SubClass = ParseSubClassReference(0, false); + } + } + + if (!CurMultiClass) + for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) + NewRecDefs[i]->resolveReferences(); + if (Lex.getCode() != tgtok::semi) return TokError("expected ';' at end of defm"); Lex.Lex(); @@ -2016,12 +2089,12 @@ bool TGParser::ParseDefm() { /// Object ::= DefMInst /// Object ::= LETCommand '{' ObjectList '}' /// Object ::= LETCommand Object -bool TGParser::ParseObject() { +bool TGParser::ParseObject(MultiClass *MC) { switch (Lex.getCode()) { default: assert(0 && "This is not an object"); - case tgtok::Let: return ParseTopLevelLet(); - case tgtok::Def: return ParseDef(0) == 0; - case tgtok::Defm: return ParseDefm(); + case tgtok::Let: return ParseTopLevelLet(MC); + case tgtok::Def: return ParseDef(MC); + case tgtok::Defm: return ParseDefm(MC); case tgtok::Class: return ParseClass(); case tgtok::MultiClass: return ParseMultiClass(); } @@ -2029,9 +2102,9 @@ bool TGParser::ParseObject() { /// ParseObjectList /// ObjectList :== Object* -bool TGParser::ParseObjectList() { +bool TGParser::ParseObjectList(MultiClass *MC) { while (isObjectStart(Lex.getCode())) { - if (ParseObject()) + if (ParseObject(MC)) return true; } return false; diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h index 9f4b634..0aee931 100644 --- a/utils/TableGen/TGParser.h +++ b/utils/TableGen/TGParser.h @@ -69,16 +69,15 @@ private: // Semantic analysis methods. SubMultiClassReference &SubMultiClass); private: // Parser methods. - bool ParseObjectList(); - bool ParseObject(); + bool ParseObjectList(MultiClass *MC = 0); + bool ParseObject(MultiClass *MC); bool ParseClass(); bool ParseMultiClass(); - bool ParseMultiClassDef(MultiClass *CurMC); - bool ParseDefm(); - bool ParseTopLevelLet(); + bool ParseDefm(MultiClass *CurMultiClass); + bool ParseDef(MultiClass *CurMultiClass); + bool ParseTopLevelLet(MultiClass *CurMultiClass); std::vector<LetRecord> ParseLetList(); - Record *ParseDef(MultiClass *CurMultiClass); bool ParseObjectBody(Record *CurRec); bool ParseBody(Record *CurRec); bool ParseBodyItem(Record *CurRec); diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 17435f6..7a4f74f 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -19,6 +19,7 @@ #include "AsmWriterEmitter.h" #include "CallingConvEmitter.h" #include "ClangASTNodesEmitter.h" +#include "ClangAttrEmitter.h" #include "ClangDiagnosticsEmitter.h" #include "CodeEmitterGen.h" #include "DAGISelEmitter.h" @@ -29,6 +30,7 @@ #include "InstrInfoEmitter.h" #include "IntrinsicEmitter.h" #include "LLVMCConfigurationEmitter.h" +#include "NeonEmitter.h" #include "OptParserEmitter.h" #include "Record.h" #include "RegisterInfoEmitter.h" @@ -52,8 +54,11 @@ enum ActionType { GenARMDecoder, GenDisassembler, GenCallingConv, + GenClangAttrClasses, + GenClangAttrList, GenClangDiagsDefs, GenClangDiagGroups, + GenClangDeclNodes, GenClangStmtNodes, GenDAGISel, GenFastISel, @@ -63,6 +68,8 @@ enum ActionType { GenTgtIntrinsic, GenLLVMCConf, GenEDHeader, GenEDInfo, + GenArmNeon, + GenArmNeonSema, PrintEnums }; @@ -107,10 +114,16 @@ namespace { "Generate intrinsic information"), clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic", "Generate target intrinsic information"), + clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes", + "Generate clang attribute clases"), + clEnumValN(GenClangAttrList, "gen-clang-attr-list", + "Generate a clang attribute list"), clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", "Generate Clang diagnostics definitions"), clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", "Generate Clang diagnostic groups"), + clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes", + "Generate Clang AST statement nodes"), clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes", "Generate Clang AST statement nodes"), clEnumValN(GenLLVMCConf, "gen-llvmc", @@ -119,6 +132,10 @@ namespace { "Generate enhanced disassembly info header"), clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info", "Generate enhanced disassembly info"), + clEnumValN(GenArmNeon, "gen-arm-neon", + "Generate arm_neon.h for clang"), + clEnumValN(GenArmNeonSema, "gen-arm-neon-sema", + "Generate ARM NEON sema support for clang"), clEnumValN(PrintEnums, "print-enums", "Print enum values for a class"), clEnumValEnd)); @@ -191,105 +208,117 @@ int main(int argc, char **argv) { if (ParseFile(InputFilename, IncludeDirs, SrcMgr)) return 1; - raw_ostream *Out = &outs(); - if (OutputFilename != "-") { - std::string Error; - Out = new raw_fd_ostream(OutputFilename.c_str(), Error); - - if (!Error.empty()) { - errs() << argv[0] << ": error opening " << OutputFilename - << ":" << Error << "\n"; - return 1; - } - - // Make sure the file gets removed if *gasp* tablegen crashes... - sys::RemoveFileOnSignal(sys::Path(OutputFilename)); + std::string Error; + raw_fd_ostream Out(OutputFilename.c_str(), Error); + if (!Error.empty()) { + errs() << argv[0] << ": error opening " << OutputFilename + << ":" << Error << "\n"; + return 1; } + // Make sure the file gets removed if *gasp* tablegen crashes... + sys::RemoveFileOnSignal(sys::Path(OutputFilename)); + try { switch (Action) { case PrintRecords: - *Out << Records; // No argument, dump all contents + Out << Records; // No argument, dump all contents break; case GenEmitter: - CodeEmitterGen(Records).run(*Out); + CodeEmitterGen(Records).run(Out); break; case GenRegisterEnums: - RegisterInfoEmitter(Records).runEnums(*Out); + RegisterInfoEmitter(Records).runEnums(Out); break; case GenRegister: - RegisterInfoEmitter(Records).run(*Out); + RegisterInfoEmitter(Records).run(Out); break; case GenRegisterHeader: - RegisterInfoEmitter(Records).runHeader(*Out); + RegisterInfoEmitter(Records).runHeader(Out); break; case GenInstrEnums: - InstrEnumEmitter(Records).run(*Out); + InstrEnumEmitter(Records).run(Out); break; case GenInstrs: - InstrInfoEmitter(Records).run(*Out); + InstrInfoEmitter(Records).run(Out); break; case GenCallingConv: - CallingConvEmitter(Records).run(*Out); + CallingConvEmitter(Records).run(Out); break; case GenAsmWriter: - AsmWriterEmitter(Records).run(*Out); + AsmWriterEmitter(Records).run(Out); break; case GenARMDecoder: - ARMDecoderEmitter(Records).run(*Out); + ARMDecoderEmitter(Records).run(Out); break; case GenAsmMatcher: - AsmMatcherEmitter(Records).run(*Out); + AsmMatcherEmitter(Records).run(Out); + break; + case GenClangAttrClasses: + ClangAttrClassEmitter(Records).run(Out); + break; + case GenClangAttrList: + ClangAttrListEmitter(Records).run(Out); break; case GenClangDiagsDefs: - ClangDiagsDefsEmitter(Records, ClangComponent).run(*Out); + ClangDiagsDefsEmitter(Records, ClangComponent).run(Out); break; case GenClangDiagGroups: - ClangDiagGroupsEmitter(Records).run(*Out); + ClangDiagGroupsEmitter(Records).run(Out); + break; + case GenClangDeclNodes: + ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out); + ClangDeclContextEmitter(Records).run(Out); break; case GenClangStmtNodes: - ClangStmtNodesEmitter(Records).run(*Out); + ClangASTNodesEmitter(Records, "Stmt", "").run(Out); break; case GenDisassembler: - DisassemblerEmitter(Records).run(*Out); + DisassemblerEmitter(Records).run(Out); break; case GenOptParserDefs: - OptParserEmitter(Records, true).run(*Out); + OptParserEmitter(Records, true).run(Out); break; case GenOptParserImpl: - OptParserEmitter(Records, false).run(*Out); + OptParserEmitter(Records, false).run(Out); break; case GenDAGISel: - DAGISelEmitter(Records).run(*Out); + DAGISelEmitter(Records).run(Out); break; case GenFastISel: - FastISelEmitter(Records).run(*Out); + FastISelEmitter(Records).run(Out); break; case GenSubtarget: - SubtargetEmitter(Records).run(*Out); + SubtargetEmitter(Records).run(Out); break; case GenIntrinsic: - IntrinsicEmitter(Records).run(*Out); + IntrinsicEmitter(Records).run(Out); break; case GenTgtIntrinsic: - IntrinsicEmitter(Records, true).run(*Out); + IntrinsicEmitter(Records, true).run(Out); break; case GenLLVMCConf: - LLVMCConfigurationEmitter(Records).run(*Out); + LLVMCConfigurationEmitter(Records).run(Out); break; case GenEDHeader: - EDEmitter(Records).runHeader(*Out); + EDEmitter(Records).runHeader(Out); break; case GenEDInfo: - EDEmitter(Records).run(*Out); + EDEmitter(Records).run(Out); + break; + case GenArmNeon: + NeonEmitter(Records).run(Out); + break; + case GenArmNeonSema: + NeonEmitter(Records).runHeader(Out); break; case PrintEnums: { std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); for (unsigned i = 0, e = Recs.size(); i != e; ++i) - *Out << Recs[i]->getName() << ", "; - *Out << "\n"; + Out << Recs[i]->getName() << ", "; + Out << "\n"; break; } default: @@ -297,8 +326,6 @@ int main(int argc, char **argv) { return 1; } - if (Out != &outs()) - delete Out; // Close the file return 0; } catch (const TGError &Error) { @@ -313,9 +340,7 @@ int main(int argc, char **argv) { errs() << argv[0] << ": Unknown unexpected exception occurred.\n"; } - if (Out != &outs()) { - delete Out; // Close the file + if (OutputFilename != "-") std::remove(OutputFilename.c_str()); // Remove the file, it's broken - } return 1; } diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index b7085ae..4dba85b 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -33,7 +33,7 @@ using namespace llvm; MAP(C9, 38) \ MAP(E8, 39) \ MAP(F0, 40) \ - MAP(F8, 41) \ + MAP(F8, 41) \ MAP(F9, 42) // A clone of X86 since we can't depend on something that is generated. @@ -212,6 +212,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); + HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix"); HasLockPrefix = Rec->getValueAsBit("hasLockPrefix"); IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly"); @@ -532,7 +533,13 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { "Unexpected number of operands for MRMSrcRegFrm"); HANDLE_OPERAND(roRegister) HANDLE_OPERAND(rmRegister) - HANDLE_OPTIONAL(immediate) + + if (HasVEX_4VPrefix) + // FIXME: In AVX, the register below becomes the one encoded + // in ModRMVEX and the one above the one in the VEX.VVVV field + HANDLE_OPTIONAL(rmRegister) + else + HANDLE_OPTIONAL(immediate) break; case X86Local::MRMSrcMem: // Operand 1 is a register operand in the Reg/Opcode field. @@ -541,6 +548,12 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && "Unexpected number of operands for MRMSrcMemFrm"); HANDLE_OPERAND(roRegister) + + if (HasVEX_4VPrefix) + // FIXME: In AVX, the register below becomes the one encoded + // in ModRMVEX and the one above the one in the VEX.VVVV field + HANDLE_OPTIONAL(rmRegister) + HANDLE_OPERAND(memory) HANDLE_OPTIONAL(immediate) break; @@ -823,6 +836,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("RST", TYPE_ST) TYPE("i128mem", TYPE_M128) TYPE("i64i32imm_pcrel", TYPE_REL64) + TYPE("i16imm_pcrel", TYPE_REL16) TYPE("i32imm_pcrel", TYPE_REL32) TYPE("SSECC", TYPE_IMM3) TYPE("brtarget", TYPE_RELv) @@ -942,6 +956,7 @@ OperandEncoding RecognizableInstr::relocationEncodingFromString ENCODING("i64i8imm", ENCODING_IB) ENCODING("i8imm", ENCODING_IB) ENCODING("i64i32imm_pcrel", ENCODING_ID) + ENCODING("i16imm_pcrel", ENCODING_IW) ENCODING("i32imm_pcrel", ENCODING_ID) ENCODING("brtarget", ENCODING_Iv) ENCODING("brtarget8", ENCODING_IB) diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 84374b0..db4d96d 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -52,6 +52,8 @@ private: bool HasOpSizePrefix; /// The hasREX_WPrefix field from the record bool HasREX_WPrefix; + /// The hasVEX_4VPrefix field from the record + bool HasVEX_4VPrefix; /// The hasLockPrefix field from the record bool HasLockPrefix; /// The isCodeGenOnly filed from the record diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm index a9a11d9..b466755 100755 --- a/utils/buildit/build_llvm +++ b/utils/buildit/build_llvm @@ -66,7 +66,6 @@ echo DARWIN_VERS = $DARWIN_VERS DEVELOPER_DIR="${DEVELOPER_DIR-Developer}" if [ "$ARM_HOSTED_BUILD" = yes ]; then DT_HOME="$DEST_DIR/usr" - HOST_SDKROOT=$SDKROOT else DT_HOME="$DEST_DIR/$DEVELOPER_DIR/usr" fi @@ -195,9 +194,10 @@ if [ "x$MAJ_VER" != "x4" -o "x$MIN_VER" != "x0" ]; then fi make $JOBS_FLAG $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \ - UNIVERSAL_SDK_PATH=$HOST_SDKROOT \ + UNIVERSAL_SDK_PATH=$SDKROOT \ NO_RUNTIME_LIBS=1 \ DISABLE_EDIS=1 \ + DEBUG_SYMBOLS=1 \ LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \ LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \ CXXFLAGS="-DLLVM_VERSION_INFO='\" Apple Build #$LLVM_VERSION\"'" \ @@ -223,6 +223,7 @@ cd $DIR/obj-llvm || exit 1 make $LOCAL_MAKEFLAGS $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \ NO_RUNTIME_LIBS=1 \ DISABLE_EDIS=1 \ + DEBUG_SYMBOLS=1 \ LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \ LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \ OPTIMIZE_OPTION='-O3' VERBOSE=1 install @@ -243,9 +244,12 @@ echo "#define LLVM_MINOR_VERSION ${RC_ProjectSourceSubversion}" >> $DEST_DIR$DES if [ "x$LLVM_DEBUG" != "x1" ]; then # Strip local symbols from llvm libraries. - strip -S $DEST_DIR$DEST_ROOT/lib/*.[oa] + # + # Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or + # PPC objects! + strip -Sl $DEST_DIR$DEST_ROOT/lib/*.[oa] for f in `ls $DEST_DIR$DEST_ROOT/lib/*.so`; do - strip -Sx $f + strip -Sxl $f done fi @@ -269,16 +273,8 @@ else -exec lipo -extract ppc7400 -extract i386 -extract x86_64 {} -output {} \; fi -cd $DEST_DIR$DEST_ROOT -if [ "$INSTALL_LIBLTO" == yes ]; then - mkdir -p $DT_HOME/lib - mv lib/libLTO.dylib $DT_HOME/lib/libLTO.dylib - strip -S $DT_HOME/lib/libLTO.dylib -fi -rm -f lib/libLTO.a lib/libLTO.la - # The Hello dylib is an example of how to build a pass. No need to install it. -rm lib/libLLVMHello.dylib +rm $DEST_DIR$DEST_ROOT/lib/libLLVMHello.dylib # Compress manpages MDIR=$DEST_DIR$DEST_ROOT/share/man/man1 @@ -324,10 +320,35 @@ find obj-* -name \*.\[chy\] -o -name \*.cpp -print \ | cpio -pdml $SYM_DIR/src || exit 1 ################################################################################ +# Install and strip libLTO.dylib + +cd $DEST_DIR$DEST_ROOT +if [ "$INSTALL_LIBLTO" = "yes" ]; then + mkdir -p $DT_HOME/lib + mv lib/libLTO.dylib $DT_HOME/lib/libLTO.dylib + + # Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or + # PPC objects! + strip -arch all -Sl $DT_HOME/lib/libLTO.dylib +fi +rm -f lib/libLTO.a lib/libLTO.la + +################################################################################ # Remove debugging information from DEST_DIR. +cd $DIR || exit 1 + find $DEST_DIR -name \*.a -print | xargs ranlib || exit 1 find $DEST_DIR -name \*.dSYM -print | xargs rm -r || exit 1 + +# Strip debugging information from files +# +# Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or +# PPC objects! +find $DEST_DIR -perm -0111 -type f \ + ! \( -name '*.la' -o -name gccas -o -name gccld -o -name llvm-config \) \ + -print | xargs -n 1 -P ${SYSCTL} strip -arch all -Sl + chgrp -h -R wheel $DEST_DIR chgrp -R wheel $DEST_DIR @@ -339,7 +360,7 @@ find $DEST_DIR -name html.tar.gz -exec rm {} \; ################################################################################ # symlinks so that B&I can find things -if [ "$INSTALL_LIBLTO" == yes ]; then +if [ "$INSTALL_LIBLTO" = "yes" ]; then mkdir -p $DEST_DIR/usr/lib/ cd $DEST_DIR/usr/lib && \ ln -s ../../$DEVELOPER_DIR/usr/lib/libLTO.dylib ./libLTO.dylib diff --git a/utils/count/count.c b/utils/count/count.c index a37e1e0..ae96791 100644 --- a/utils/count/count.c +++ b/utils/count/count.c @@ -26,13 +26,15 @@ int main(int argc, char **argv) { } NumLines = 0; - while ((NumRead = fread(Buffer, 1, sizeof(Buffer), stdin))) { + do { unsigned i; + NumRead = fread(Buffer, 1, sizeof(Buffer), stdin); + for (i = 0; i != NumRead; ++i) if (Buffer[i] == '\n') ++NumLines; - } + } while (NumRead == sizeof(Buffer)); if (!feof(stdin)) { fprintf(stderr, "%s: error reading stdin\n", argv[0]); diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py index d10e4b0..cdf1c93 100644 --- a/utils/lit/lit/TestRunner.py +++ b/utils/lit/lit/TestRunner.py @@ -13,11 +13,13 @@ class InternalShellError(Exception): self.command = command self.message = message +kIsWindows = platform.system() == 'Windows' + # Don't use close_fds on Windows. -kUseCloseFDs = platform.system() != 'Windows' +kUseCloseFDs = not kIsWindows # Use temporary files to replace /dev/null on Windows. -kAvoidDevNull = platform.system() == 'Windows' +kAvoidDevNull = kIsWindows def executeCommand(command, cwd=None, env=None): p = subprocess.Popen(command, cwd=cwd, @@ -64,6 +66,7 @@ def executeShCmd(cmd, cfg, cwd, results): input = subprocess.PIPE stderrTempFiles = [] opened_files = [] + named_temp_files = [] # To avoid deadlock, we use a single stderr stream for piped # output. This is null until we have seen some output using # stderr. @@ -146,6 +149,15 @@ def executeShCmd(cmd, cfg, cwd, results): if not args[0]: raise InternalShellError(j, '%r: command not found' % j.args[0]) + # Replace uses of /dev/null with temporary files. + if kAvoidDevNull: + for i,arg in enumerate(args): + if arg == "/dev/null": + f = tempfile.NamedTemporaryFile(delete=False) + f.close() + named_temp_files.append(f.name) + args[i] = f.name + procs.append(subprocess.Popen(args, cwd=cwd, stdin = stdin, stdout = stdout, @@ -207,6 +219,13 @@ def executeShCmd(cmd, cfg, cwd, results): for f in opened_files: f.close() + # Remove any named temporary files we created. + for f in named_temp_files: + try: + os.remove(f) + except OSError: + pass + if cmd.negate: exitCode = not exitCode @@ -364,7 +383,7 @@ def isExpectedFail(xfails, xtargets, target_triple): return True -def parseIntegratedTestScript(test): +def parseIntegratedTestScript(test, normalize_slashes=False): """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test script and extract the lines to 'RUN' as well as 'XFAIL' and 'XTARGET' information. The RUN lines also will have variable substitution performed. @@ -375,18 +394,25 @@ def parseIntegratedTestScript(test): # # FIXME: This should not be here? sourcepath = test.getSourcePath() + sourcedir = os.path.dirname(sourcepath) execpath = test.getExecPath() execdir,execbase = os.path.split(execpath) tmpBase = os.path.join(execdir, 'Output', execbase) if test.index is not None: tmpBase += '_%d' % test.index + # Normalize slashes, if requested. + if normalize_slashes: + sourcepath = sourcepath.replace('\\', '/') + sourcedir = sourcedir.replace('\\', '/') + tmpBase = tmpBase.replace('\\', '/') + # We use #_MARKER_# to hide %% while we do the other substitutions. substitutions = [('%%', '#_MARKER_#')] substitutions.extend(test.config.substitutions) substitutions.extend([('%s', sourcepath), - ('%S', os.path.dirname(sourcepath)), - ('%p', os.path.dirname(sourcepath)), + ('%S', sourcedir), + ('%p', sourcedir), ('%t', tmpBase + '.tmp'), # FIXME: Remove this once we kill DejaGNU. ('%abs_tmp', tmpBase + '.tmp'), @@ -462,7 +488,9 @@ def executeTclTest(test, litConfig): if test.config.unsupported: return (Test.UNSUPPORTED, 'Test is unsupported') - res = parseIntegratedTestScript(test) + # Parse the test script, normalizing slashes in substitutions on Windows + # (since otherwise Tcl style lexing will treat them as escapes). + res = parseIntegratedTestScript(test, normalize_slashes=kIsWindows) if len(res) == 2: return res diff --git a/utils/unittest/UnitTestMain/Makefile b/utils/unittest/UnitTestMain/Makefile index 5c10049..cec654f 100644 --- a/utils/unittest/UnitTestMain/Makefile +++ b/utils/unittest/UnitTestMain/Makefile @@ -20,7 +20,11 @@ CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS) CPP.Flags += -DGTEST_HAS_RTTI=0 # libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not # supported by Clang, so force googletest to use its own tuple implementation. -# When we import googletest >=1.4.0, we can drop this line. -CPP.Flags += -DGTEST_HAS_TR1_TUPLE=0 +CPP.Flags += -DGTEST_USE_OWN_TR1_TUPLE + +# Disable pthreads if LLVM was configured without them. +ifneq ($(HAVE_PTHREAD), 1) + CPP.Flags += -DGTEST_HAS_PTHREAD=0 +endif include $(LEVEL)/Makefile.common diff --git a/utils/unittest/googletest/Makefile b/utils/unittest/googletest/Makefile index 1ec979d..21b29ff 100644 --- a/utils/unittest/googletest/Makefile +++ b/utils/unittest/googletest/Makefile @@ -23,9 +23,12 @@ CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS) CPP.Flags += -DGTEST_HAS_RTTI=0 # libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not # supported by Clang, so force googletest to use its own tuple implementation. -# When we import googletest >=1.4.0, we can drop this line. -CPP.Flags += -DGTEST_HAS_TR1_TUPLE=0 +CPP.Flags += -DGTEST_USE_OWN_TR1_TUPLE +# Disable pthreads if LLVM was configured without them. +ifneq ($(HAVE_PTHREAD), 1) + CPP.Flags += -DGTEST_HAS_PTHREAD=0 +endif ifeq ($(HOST_OS),MingW) CPP.Flags += -DGTEST_OS_WINDOWS=1 diff --git a/utils/unittest/googletest/README.LLVM b/utils/unittest/googletest/README.LLVM index e907a5e..d6e6f98 100644 --- a/utils/unittest/googletest/README.LLVM +++ b/utils/unittest/googletest/README.LLVM @@ -1,14 +1,14 @@ LLVM notes ---------- -This directory contains Google Test 1.2.1, with all elements removed except for +This directory contains Google Test 1.5.0, with all elements removed except for the actual source code, to minimize the addition to the LLVM distribution. Cleaned up as follows: # Remove all the unnecessary files and directories -$ rm -f aclocal* configure* Makefile* CHANGES CONTRIBUTORS README -$ rm -rf build-aux m4 make msvc samples scons scripts test xcode +$ rm -f aclocal* CMakeLists.txt configure* Makefile* CHANGES CONTRIBUTORS README +$ rm -rf build-aux codegear fused-src m4 make msvc samples scripts test xcode $ rm -f `find . -name \*\.pump` # Move all the source files to the current directory @@ -21,11 +21,11 @@ $ mv *.h include/gtest/internal/ # Update paths to the included files $ perl -pi -e 's|^#include "src/|#include "gtest/internal/|' *.cc -$ rm -f gtest-all.cc gtest_main.cc - $ mv COPYING LICENSE.TXT Modified as follows: * To GTestStreamToHelper in include/gtest/internal/gtest-internal.h, added the ability to stream with raw_os_ostream. +* To refresh Haiku support in include/gtest/internal/gtest-port.h, + see http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20100621/102898.html diff --git a/utils/unittest/googletest/gtest-death-test.cc b/utils/unittest/googletest/gtest-death-test.cc index 617e301..e4199de 100644 --- a/utils/unittest/googletest/gtest-death-test.cc +++ b/utils/unittest/googletest/gtest-death-test.cc @@ -27,17 +27,31 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Author: wan@google.com (Zhanyong Wan) +// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev) // // This file implements death tests. #include <gtest/gtest-death-test.h> #include <gtest/internal/gtest-port.h> -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST + +#if GTEST_OS_MAC +#include <crt_externs.h> +#endif // GTEST_OS_MAC + #include <errno.h> +#include <fcntl.h> #include <limits.h> #include <stdarg.h> + +#if GTEST_OS_WINDOWS +#include <windows.h> +#else +#include <sys/mman.h> +#include <sys/wait.h> +#endif // GTEST_OS_WINDOWS + #endif // GTEST_HAS_DEATH_TEST #include <gtest/gtest-message.h> @@ -48,9 +62,9 @@ // included, or there will be a compiler error. This trick is to // prevent a user from accidentally including gtest-internal-inl.h in // his code. -#define GTEST_IMPLEMENTATION +#define GTEST_IMPLEMENTATION_ 1 #include "gtest/internal/gtest-internal-inl.h" -#undef GTEST_IMPLEMENTATION +#undef GTEST_IMPLEMENTATION_ namespace testing { @@ -68,6 +82,18 @@ GTEST_DEFINE_string_( "\"fast\" (child process runs the death test immediately " "after forking)."); +GTEST_DEFINE_bool_( + death_test_use_fork, + internal::BoolFromGTestEnv("death_test_use_fork", false), + "Instructs to use fork()/_exit() instead of clone() in death tests. " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " + "it sees an unsupported combination of clone() flags. " + "It is not recommended to use this flag w/o valgrind though it will " + "work in 99% of the cases. Once valgrind is fixed, this flag will " + "most likely be removed."); + namespace internal { GTEST_DEFINE_string_( internal_run_death_test, "", @@ -79,7 +105,7 @@ GTEST_DEFINE_string_( "death test. FOR INTERNAL USE ONLY."); } // namespace internal -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST // ExitedWithCode constructor. ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { @@ -87,9 +113,14 @@ ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { // ExitedWithCode function-call operator. bool ExitedWithCode::operator()(int exit_status) const { +#if GTEST_OS_WINDOWS + return exit_status == exit_code_; +#else return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; +#endif // GTEST_OS_WINDOWS } +#if !GTEST_OS_WINDOWS // KilledBySignal constructor. KilledBySignal::KilledBySignal(int signum) : signum_(signum) { } @@ -98,6 +129,7 @@ KilledBySignal::KilledBySignal(int signum) : signum_(signum) { bool KilledBySignal::operator()(int exit_status) const { return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; } +#endif // !GTEST_OS_WINDOWS namespace internal { @@ -107,6 +139,9 @@ namespace internal { // specified by wait(2). static String ExitSummary(int exit_code) { Message m; +#if GTEST_OS_WINDOWS + m << "Exited with exit status " << exit_code; +#else if (WIFEXITED(exit_code)) { m << "Exited with exit status " << WEXITSTATUS(exit_code); } else if (WIFSIGNALED(exit_code)) { @@ -117,6 +152,7 @@ static String ExitSummary(int exit_code) { m << " (core dumped)"; } #endif +#endif // GTEST_OS_WINDOWS return m.GetString(); } @@ -126,6 +162,7 @@ bool ExitedUnsuccessfully(int exit_status) { return !ExitedWithCode(0)(exit_status); } +#if !GTEST_OS_WINDOWS // Generates a textual failure message when a death test finds more than // one thread running, or cannot determine the number of threads, prior // to executing the given statement. It is the responsibility of the @@ -133,17 +170,14 @@ bool ExitedUnsuccessfully(int exit_status) { static String DeathTestThreadWarning(size_t thread_count) { Message msg; msg << "Death tests use fork(), which is unsafe particularly" - << " in a threaded context. For this test, " << GTEST_NAME << " "; + << " in a threaded context. For this test, " << GTEST_NAME_ << " "; if (thread_count == 0) msg << "couldn't detect the number of threads."; else msg << "detected " << thread_count << " threads."; return msg.GetString(); } - -// Static string containing a description of the outcome of the -// last death test. -static String last_death_test_message; +#endif // !GTEST_OS_WINDOWS // Flag characters for reporting a death test that did not die. static const char kDeathTestLived = 'L'; @@ -159,29 +193,25 @@ static const char kDeathTestInternalError = 'I'; enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED }; // Routine for aborting the program which is safe to call from an -// exec-style death test child process, in which case the the error +// exec-style death test child process, in which case the error // message is propagated back to the parent process. Otherwise, the // message is simply printed to stderr. In either case, the program // then exits with status 1. -void DeathTestAbort(const char* format, ...) { - // This function may be called from a threadsafe-style death test - // child process, which operates on a very small stack. Use the - // heap for any additional non-miniscule memory requirements. +void DeathTestAbort(const String& message) { + // On a POSIX system, this function may be called from a threadsafe-style + // death test child process, which operates on a very small stack. Use + // the heap for any additional non-minuscule memory requirements. const InternalRunDeathTestFlag* const flag = GetUnitTestImpl()->internal_run_death_test_flag(); - va_list args; - va_start(args, format); - if (flag != NULL) { - FILE* parent = fdopen(flag->status_fd, "w"); + FILE* parent = posix::FDOpen(flag->write_fd(), "w"); fputc(kDeathTestInternalError, parent); - vfprintf(parent, format, args); - fclose(parent); - va_end(args); + fprintf(parent, "%s", message.c_str()); + fflush(parent); _exit(1); } else { - vfprintf(stderr, format, args); - va_end(args); + fprintf(stderr, "%s", message.c_str()); + fflush(stderr); abort(); } } @@ -190,11 +220,12 @@ void DeathTestAbort(const char* format, ...) { // fails. #define GTEST_DEATH_TEST_CHECK_(expression) \ do { \ - if (!(expression)) { \ - DeathTestAbort("CHECK failed: File %s, line %d: %s", \ - __FILE__, __LINE__, #expression); \ + if (!::testing::internal::IsTrue(expression)) { \ + DeathTestAbort(::testing::internal::String::Format( \ + "CHECK failed: File %s, line %d: %s", \ + __FILE__, __LINE__, #expression)); \ } \ - } while (0) + } while (::testing::internal::AlwaysFalse()) // This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for // evaluating any system call that fulfills two conditions: it must return @@ -205,15 +236,46 @@ void DeathTestAbort(const char* format, ...) { // something other than EINTR, DeathTestAbort is called. #define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ do { \ - int retval; \ + int gtest_retval; \ do { \ - retval = (expression); \ - } while (retval == -1 && errno == EINTR); \ - if (retval == -1) { \ - DeathTestAbort("CHECK failed: File %s, line %d: %s != -1", \ - __FILE__, __LINE__, #expression); \ + gtest_retval = (expression); \ + } while (gtest_retval == -1 && errno == EINTR); \ + if (gtest_retval == -1) { \ + DeathTestAbort(::testing::internal::String::Format( \ + "CHECK failed: File %s, line %d: %s != -1", \ + __FILE__, __LINE__, #expression)); \ } \ - } while (0) + } while (::testing::internal::AlwaysFalse()) + +// Returns the message describing the last system error in errno. +String GetLastErrnoDescription() { + return String(errno == 0 ? "" : posix::StrError(errno)); +} + +// This is called from a death test parent process to read a failure +// message from the death test child process and log it with the FATAL +// severity. On Windows, the message is read from a pipe handle. On other +// platforms, it is read from a file descriptor. +static void FailFromInternalError(int fd) { + Message error; + char buffer[256]; + int num_read; + + do { + while ((num_read = posix::Read(fd, buffer, 255)) > 0) { + buffer[num_read] = '\0'; + error << buffer; + } + } while (num_read == -1 && errno == EINTR); + + if (num_read == 0) { + GTEST_LOG_(FATAL) << error.GetString(); + } else { + const int last_error = errno; + GTEST_LOG_(FATAL) << "Error while reading death test internal: " + << GetLastErrnoDescription() << " [" << last_error << "]"; + } +} // Death test constructor. Increments the running death test count // for the current test. @@ -234,143 +296,146 @@ bool DeathTest::Create(const char* statement, const RE* regex, } const char* DeathTest::LastMessage() { - return last_death_test_message.c_str(); + return last_death_test_message_.c_str(); } -// ForkingDeathTest provides implementations for most of the abstract -// methods of the DeathTest interface. Only the AssumeRole method is -// left undefined. -class ForkingDeathTest : public DeathTest { - public: - ForkingDeathTest(const char* statement, const RE* regex); +void DeathTest::set_last_death_test_message(const String& message) { + last_death_test_message_ = message; +} - // All of these virtual functions are inherited from DeathTest. - virtual int Wait(); - virtual bool Passed(bool status_ok); - virtual void Abort(AbortReason reason); +String DeathTest::last_death_test_message_; +// Provides cross platform implementation for some death functionality. +class DeathTestImpl : public DeathTest { protected: - void set_forked(bool forked) { forked_ = forked; } - void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + DeathTestImpl(const char* a_statement, const RE* a_regex) + : statement_(a_statement), + regex_(a_regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS), + read_fd_(-1), + write_fd_(-1) {} + + // read_fd_ is expected to be closed and cleared by a derived class. + ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + + void Abort(AbortReason reason); + virtual bool Passed(bool status_ok); + + const char* statement() const { return statement_; } + const RE* regex() const { return regex_; } + bool spawned() const { return spawned_; } + void set_spawned(bool is_spawned) { spawned_ = is_spawned; } + int status() const { return status_; } + void set_status(int a_status) { status_ = a_status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } + int read_fd() const { return read_fd_; } void set_read_fd(int fd) { read_fd_ = fd; } + int write_fd() const { return write_fd_; } void set_write_fd(int fd) { write_fd_ = fd; } + // Called in the parent process only. Reads the result code of the death + // test child process via a pipe, interprets it to set the outcome_ + // member, and closes read_fd_. Outputs diagnostics and terminates in + // case of unexpected codes. + void ReadAndInterpretStatusByte(); + private: - // The textual content of the code this object is testing. + // The textual content of the code this object is testing. This class + // doesn't own this string and should not attempt to delete it. const char* const statement_; - // The regular expression which test output must match. + // The regular expression which test output must match. DeathTestImpl + // doesn't own this object and should not attempt to delete it. const RE* const regex_; - // True if the death test successfully forked. - bool forked_; - // PID of child process during death test; 0 in the child process itself. - pid_t child_pid_; - // File descriptors for communicating the death test's status byte. - int read_fd_; // Always -1 in the child process. - int write_fd_; // Always -1 in the parent process. + // True if the death test child process has been successfully spawned. + bool spawned_; // The exit status of the child process. int status_; // How the death test concluded. DeathTestOutcome outcome_; + // Descriptor to the read end of the pipe to the child process. It is + // always -1 in the child process. The child keeps its write end of the + // pipe in write_fd_. + int read_fd_; + // Descriptor to the child's write end of the pipe to the parent process. + // It is always -1 in the parent process. The parent keeps its end of the + // pipe in read_fd_. + int write_fd_; }; -// Constructs a ForkingDeathTest. -ForkingDeathTest::ForkingDeathTest(const char* statement, const RE* regex) - : DeathTest(), - statement_(statement), - regex_(regex), - forked_(false), - child_pid_(-1), - read_fd_(-1), - write_fd_(-1), - status_(-1), - outcome_(IN_PROGRESS) { -} - -// Reads an internal failure message from a file descriptor, then calls -// LOG(FATAL) with that message. Called from a death test parent process -// to read a failure message from the death test child process. -static void FailFromInternalError(int fd) { - Message error; - char buffer[256]; - ssize_t num_read; - - do { - while ((num_read = read(fd, buffer, 255)) > 0) { - buffer[num_read] = '\0'; - error << buffer; - } - } while (num_read == -1 && errno == EINTR); - - // TODO(smcafee): Maybe just FAIL the test instead? - if (num_read == 0) { - GTEST_LOG_(FATAL, error); - } else { - GTEST_LOG_(FATAL, - Message() << "Error while reading death test internal: " - << strerror(errno) << " [" << errno << "]"); - } -} - -// Waits for the child in a death test to exit, returning its exit -// status, or 0 if no child process exists. As a side effect, sets the -// outcome data member. -int ForkingDeathTest::Wait() { - if (!forked_) - return 0; +// Called in the parent process only. Reads the result code of the death +// test child process via a pipe, interprets it to set the outcome_ +// member, and closes read_fd_. Outputs diagnostics and terminates in +// case of unexpected codes. +void DeathTestImpl::ReadAndInterpretStatusByte() { + char flag; + int bytes_read; // The read() here blocks until data is available (signifying the // failure of the death test) or until the pipe is closed (signifying // its success), so it's okay to call this in the parent before // the child process has exited. - char flag; - ssize_t bytes_read; - do { - bytes_read = read(read_fd_, &flag, 1); + bytes_read = posix::Read(read_fd(), &flag, 1); } while (bytes_read == -1 && errno == EINTR); if (bytes_read == 0) { - outcome_ = DIED; + set_outcome(DIED); } else if (bytes_read == 1) { switch (flag) { case kDeathTestReturned: - outcome_ = RETURNED; + set_outcome(RETURNED); break; case kDeathTestLived: - outcome_ = LIVED; + set_outcome(LIVED); break; case kDeathTestInternalError: - FailFromInternalError(read_fd_); // Does not return. + FailFromInternalError(read_fd()); // Does not return. break; default: - GTEST_LOG_(FATAL, - Message() << "Death test child process reported unexpected " - << "status byte (" << static_cast<unsigned int>(flag) - << ")"); + GTEST_LOG_(FATAL) << "Death test child process reported " + << "unexpected status byte (" + << static_cast<unsigned int>(flag) << ")"; } } else { - GTEST_LOG_(FATAL, - Message() << "Read from death test child process failed: " - << strerror(errno)); + GTEST_LOG_(FATAL) << "Read from death test child process failed: " + << GetLastErrnoDescription(); } + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); + set_read_fd(-1); +} - GTEST_DEATH_TEST_CHECK_SYSCALL_(close(read_fd_)); - GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_, 0)); - return status_; +// Signals that the death test code which should have exited, didn't. +// Should be called only in a death test child process. +// Writes a status byte to the child's status file descriptor, then +// calls _exit(1). +void DeathTestImpl::Abort(AbortReason reason) { + // The parent process considers the death test to be a failure if + // it finds any data in our pipe. So, here we write a single flag byte + // to the pipe, then exit. + const char status_ch = + reason == TEST_DID_NOT_DIE ? kDeathTestLived : kDeathTestReturned; + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(write_fd())); + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) } // Assesses the success or failure of a death test, using both private // members which have previously been set, and one argument: // // Private data members: -// outcome: an enumeration describing how the death test +// outcome: An enumeration describing how the death test // concluded: DIED, LIVED, or RETURNED. The death test fails -// in the latter two cases -// status: the exit status of the child process, in the format -// specified by wait(2) -// regex: a regular expression object to be applied to +// in the latter two cases. +// status: The exit status of the child process. On *nix, it is in the +// in the format specified by wait(2). On Windows, this is the +// value supplied to the ExitProcess() API or a numeric code +// of the exception that terminated the program. +// regex: A regular expression object to be applied to // the test's captured standard error output; the death test -// fails if it does not match +// fails if it does not match. // // Argument: // status_ok: true if exit_status is acceptable in the context of @@ -378,22 +443,18 @@ int ForkingDeathTest::Wait() { // // Returns true iff all of the above conditions are met. Otherwise, the // first failing condition, in the order given above, is the one that is -// reported. Also sets the static variable last_death_test_message. -bool ForkingDeathTest::Passed(bool status_ok) { - if (!forked_) +// reported. Also sets the last death test message string. +bool DeathTestImpl::Passed(bool status_ok) { + if (!spawned()) return false; -#if GTEST_HAS_GLOBAL_STRING - const ::string error_message = GetCapturedStderr(); -#else - const ::std::string error_message = GetCapturedStderr(); -#endif // GTEST_HAS_GLOBAL_STRING + const String error_message = GetCapturedStderr(); bool success = false; Message buffer; - buffer << "Death test: " << statement_ << "\n"; - switch (outcome_) { + buffer << "Death test: " << statement() << "\n"; + switch (outcome()) { case LIVED: buffer << " Result: failed to die.\n" << " Error msg: " << error_message; @@ -404,49 +465,271 @@ bool ForkingDeathTest::Passed(bool status_ok) { break; case DIED: if (status_ok) { - if (RE::PartialMatch(error_message, *regex_)) { + const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); + if (matched) { success = true; } else { buffer << " Result: died but not with expected error.\n" - << " Expected: " << regex_->pattern() << "\n" + << " Expected: " << regex()->pattern() << "\n" << "Actual msg: " << error_message; } } else { buffer << " Result: died but not with expected exit code:\n" - << " " << ExitSummary(status_) << "\n"; + << " " << ExitSummary(status()) << "\n"; } break; case IN_PROGRESS: default: - GTEST_LOG_(FATAL, - "DeathTest::Passed somehow called before conclusion of test"); + GTEST_LOG_(FATAL) + << "DeathTest::Passed somehow called before conclusion of test"; } - last_death_test_message = buffer.GetString(); + DeathTest::set_last_death_test_message(buffer.GetString()); return success; } -// Signals that the death test code which should have exited, didn't. -// Should be called only in a death test child process. -// Writes a status byte to the child's status file desriptor, then -// calls _exit(1). -void ForkingDeathTest::Abort(AbortReason reason) { - // The parent process considers the death test to be a failure if - // it finds any data in our pipe. So, here we write a single flag byte - // to the pipe, then exit. - const char flag = - reason == TEST_DID_NOT_DIE ? kDeathTestLived : kDeathTestReturned; - GTEST_DEATH_TEST_CHECK_SYSCALL_(write(write_fd_, &flag, 1)); - GTEST_DEATH_TEST_CHECK_SYSCALL_(close(write_fd_)); - _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +#if GTEST_OS_WINDOWS +// WindowsDeathTest implements death tests on Windows. Due to the +// specifics of starting new processes on Windows, death tests there are +// always threadsafe, and Google Test considers the +// --gtest_death_test_style=fast setting to be equivalent to +// --gtest_death_test_style=threadsafe there. +// +// A few implementation notes: Like the Linux version, the Windows +// implementation uses pipes for child-to-parent communication. But due to +// the specifics of pipes on Windows, some extra steps are required: +// +// 1. The parent creates a communication pipe and stores handles to both +// ends of it. +// 2. The parent starts the child and provides it with the information +// necessary to acquire the handle to the write end of the pipe. +// 3. The child acquires the write end of the pipe and signals the parent +// using a Windows event. +// 4. Now the parent can release the write end of the pipe on its side. If +// this is done before step 3, the object's reference count goes down to +// 0 and it is destroyed, preventing the child from acquiring it. The +// parent now has to release it, or read operations on the read end of +// the pipe will not return when the child terminates. +// 5. The parent reads child's output through the pipe (outcome code and +// any possible error messages) from the pipe, and its stderr and then +// determines whether to fail the test. +// +// Note: to distinguish Win32 API calls from the local method and function +// calls, the former are explicitly resolved in the global namespace. +// +class WindowsDeathTest : public DeathTestImpl { + public: + WindowsDeathTest(const char* statement, + const RE* regex, + const char* file, + int line) + : DeathTestImpl(statement, regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // Handle to the write end of the pipe to the child process. + AutoHandle write_handle_; + // Child process handle. + AutoHandle child_handle_; + // Event the child process uses to signal the parent that it has + // acquired the handle to the write end of the pipe. After seeing this + // event the parent can release its own handles to make sure its + // ReadFile() calls return when the child terminates. + AutoHandle event_handle_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int WindowsDeathTest::Wait() { + if (!spawned()) + return 0; + + // Wait until the child either signals that it has acquired the write end + // of the pipe or it dies. + const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; + switch (::WaitForMultipleObjects(2, + wait_handles, + FALSE, // Waits for any of the handles. + INFINITE)) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + break; + default: + GTEST_DEATH_TEST_CHECK_(false); // Should not get here. + } + + // The child has acquired the write end of the pipe or exited. + // We release the handle on our side and continue. + write_handle_.Reset(); + event_handle_.Reset(); + + ReadAndInterpretStatusByte(); + + // Waits for the child process to exit if it haven't already. This + // returns immediately if the child has already exited, regardless of + // whether previous calls to WaitForMultipleObjects synchronized on this + // handle or not. + GTEST_DEATH_TEST_CHECK_( + WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), + INFINITE)); + DWORD status; + GTEST_DEATH_TEST_CHECK_(::GetExitCodeProcess(child_handle_.Get(), &status) + != FALSE); + child_handle_.Reset(); + set_status(static_cast<int>(status)); + return this->status(); +} + +// The AssumeRole process for a Windows death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole WindowsDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // WindowsDeathTest uses an anonymous pipe to communicate results of + // a death test. + SECURITY_ATTRIBUTES handles_are_inheritable = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + HANDLE read_handle, write_handle; + GTEST_DEATH_TEST_CHECK_( + ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, + 0) // Default buffer size. + != FALSE); + set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle), + O_RDONLY)); + write_handle_.Reset(write_handle); + event_handle_.Reset(::CreateEvent( + &handles_are_inheritable, + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + NULL)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); + const String filter_flag = String::Format("--%s%s=%s.%s", + GTEST_FLAG_PREFIX_, kFilterFlag, + info->test_case_name(), + info->name()); + const String internal_flag = String::Format( + "--%s%s=%s|%d|%d|%u|%Iu|%Iu", + GTEST_FLAG_PREFIX_, + kInternalRunDeathTestFlag, + file_, line_, + death_test_index, + static_cast<unsigned int>(::GetCurrentProcessId()), + // size_t has the same with as pointers on both 32-bit and 64-bit + // Windows platforms. + // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. + reinterpret_cast<size_t>(write_handle), + reinterpret_cast<size_t>(event_handle_.Get())); + + char executable_path[_MAX_PATH + 1]; // NOLINT + GTEST_DEATH_TEST_CHECK_( + _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, + executable_path, + _MAX_PATH)); + + String command_line = String::Format("%s %s \"%s\"", + ::GetCommandLineA(), + filter_flag.c_str(), + internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // The child process will share the standard handles with the parent. + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFO)); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION process_info; + GTEST_DEATH_TEST_CHECK_(::CreateProcessA( + executable_path, + const_cast<char*>(command_line.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + NULL, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), + &startup_info, + &process_info) != FALSE); + child_handle_.Reset(process_info.hProcess); + ::CloseHandle(process_info.hThread); + set_spawned(true); + return OVERSEE_TEST; +} +#else // We are not on Windows. + +// ForkingDeathTest provides implementations for most of the abstract +// methods of the DeathTest interface. Only the AssumeRole method is +// left undefined. +class ForkingDeathTest : public DeathTestImpl { + public: + ForkingDeathTest(const char* statement, const RE* regex); + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + + protected: + void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + + private: + // PID of child process during death test; 0 in the child process itself. + pid_t child_pid_; +}; + +// Constructs a ForkingDeathTest. +ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) + : DeathTestImpl(a_statement, a_regex), + child_pid_(-1) {} + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int ForkingDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + int status_value; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); + set_status(status_value); + return status_value; } // A concrete death test class that forks, then immediately runs the test // in the child process. class NoExecDeathTest : public ForkingDeathTest { public: - NoExecDeathTest(const char* statement, const RE* regex) : - ForkingDeathTest(statement, regex) { } + NoExecDeathTest(const char* a_statement, const RE* a_regex) : + ForkingDeathTest(a_statement, a_regex) { } virtual TestRole AssumeRole(); }; @@ -455,13 +738,13 @@ class NoExecDeathTest : public ForkingDeathTest { DeathTest::TestRole NoExecDeathTest::AssumeRole() { const size_t thread_count = GetThreadCount(); if (thread_count != 1) { - GTEST_LOG_(WARNING, DeathTestThreadWarning(thread_count)); + GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); } int pipe_fd[2]; GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); - last_death_test_message = ""; + DeathTest::set_last_death_test_message(""); CaptureStderr(); // When we fork the process below, the log file buffers are copied, but the // file descriptors are shared. We flush all log files here so that closing @@ -482,11 +765,14 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() { // concurrent writes to the log files. We capture stderr in the parent // process and append the child process' output to a log. LogToStderr(); + // Event forwarding to the listeners of event listener API mush be shut + // down in death test subprocesses. + GetUnitTestImpl()->listeners()->SuppressEventForwarding(); return EXECUTE_TEST; } else { GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); set_read_fd(pipe_fd[0]); - set_forked(true); + set_spawned(true); return OVERSEE_TEST; } } @@ -496,9 +782,9 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() { // only this specific death test to be run. class ExecDeathTest : public ForkingDeathTest { public: - ExecDeathTest(const char* statement, const RE* regex, + ExecDeathTest(const char* a_statement, const RE* a_regex, const char* file, int line) : - ForkingDeathTest(statement, regex), file_(file), line_(line) { } + ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } virtual TestRole AssumeRole(); private: // The name of the file in which the death test is located. @@ -513,15 +799,15 @@ class Arguments { Arguments() { args_.push_back(NULL); } + ~Arguments() { - for (std::vector<char*>::iterator i = args_.begin(); - i + 1 != args_.end(); + for (std::vector<char*>::iterator i = args_.begin(); i != args_.end(); ++i) { free(*i); } } void AddArgument(const char* argument) { - args_.insert(args_.end() - 1, strdup(argument)); + args_.insert(args_.end() - 1, posix::StrDup(argument)); } template <typename Str> @@ -529,7 +815,7 @@ class Arguments { for (typename ::std::vector<Str>::const_iterator i = arguments.begin(); i != arguments.end(); ++i) { - args_.insert(args_.end() - 1, strdup(i->c_str())); + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); } } char* const* Argv() { @@ -546,6 +832,20 @@ struct ExecDeathTestArgs { int close_fd; // File descriptor to close; the read end of a pipe }; +#if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +#else +// Some POSIX platforms expect you to declare environ. extern "C" makes +// it reside in the global namespace. +extern "C" char** environ; +inline char** GetEnviron() { return environ; } +#endif // GTEST_OS_MAC + // The main function for a threadsafe-style death test child process. // This function is called in a clone()-ed process and thus must avoid // any potentially unsafe operations like malloc or libc functions. @@ -560,8 +860,9 @@ static int ExecDeathTestChildMain(void* child_arg) { UnitTest::GetInstance()->original_working_dir(); // We can safely call chdir() as it's a direct system call. if (chdir(original_dir) != 0) { - DeathTestAbort("chdir(\"%s\") failed: %s", - original_dir, strerror(errno)); + DeathTestAbort(String::Format("chdir(\"%s\") failed: %s", + original_dir, + GetLastErrnoDescription().c_str())); return EXIT_FAILURE; } @@ -570,9 +871,11 @@ static int ExecDeathTestChildMain(void* child_arg) { // unsafe. Since execve() doesn't search the PATH, the user must // invoke the test program via a valid path that contains at least // one path separator. - execve(args->argv[0], args->argv, environ); - DeathTestAbort("execve(%s, ...) in %s failed: %s", - args->argv[0], original_dir, strerror(errno)); + execve(args->argv[0], args->argv, GetEnviron()); + DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s", + args->argv[0], + original_dir, + GetLastErrnoDescription().c_str())); return EXIT_FAILURE; } @@ -581,12 +884,12 @@ static int ExecDeathTestChildMain(void* child_arg) { // This could be accomplished more elegantly by a single recursive // function, but we want to guard against the unlikely possibility of // a smart compiler optimizing the recursion away. -static bool StackLowerThanAddress(const void* ptr) { +bool StackLowerThanAddress(const void* ptr) { int dummy; return &dummy < ptr; } -static bool StackGrowsDown() { +bool StackGrowsDown() { int dummy; return StackLowerThanAddress(&dummy); } @@ -595,18 +898,36 @@ static bool StackGrowsDown() { // that uses clone(2). It dies with an error message if anything goes // wrong. static pid_t ExecDeathTestFork(char* const* argv, int close_fd) { - static const bool stack_grows_down = StackGrowsDown(); - const size_t stack_size = getpagesize(); - void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); - void* const stack_top = - static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0); ExecDeathTestArgs args = { argv, close_fd }; - const pid_t child_pid = clone(&ExecDeathTestChildMain, stack_top, - SIGCHLD, &args); + pid_t child_pid = -1; + +#if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + void* const stack_top = + static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +#else + const bool use_fork = true; +#endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { + ExecDeathTestChildMain(&args); + _exit(0); + } + GTEST_DEATH_TEST_CHECK_(child_pid != -1); - GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); return child_pid; } @@ -622,7 +943,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { const int death_test_index = info->result()->death_test_count(); if (flag != NULL) { - set_write_fd(flag->status_fd); + set_write_fd(flag->write_fd()); return EXECUTE_TEST; } @@ -634,19 +955,18 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { const String filter_flag = String::Format("--%s%s=%s.%s", - GTEST_FLAG_PREFIX, kFilterFlag, + GTEST_FLAG_PREFIX_, kFilterFlag, info->test_case_name(), info->name()); const String internal_flag = - String::Format("--%s%s=%s:%d:%d:%d", - GTEST_FLAG_PREFIX, kInternalRunDeathTestFlag, file_, line_, - death_test_index, pipe_fd[1]); + String::Format("--%s%s=%s|%d|%d|%d", + GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag, + file_, line_, death_test_index, pipe_fd[1]); Arguments args; args.AddArguments(GetArgvs()); - args.AddArgument("--logtostderr"); args.AddArgument(filter_flag.c_str()); args.AddArgument(internal_flag.c_str()); - last_death_test_message = ""; + DeathTest::set_last_death_test_message(""); CaptureStderr(); // See the comment in NoExecDeathTest::AssumeRole for why the next line @@ -657,10 +977,12 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); set_child_pid(child_pid); set_read_fd(pipe_fd[0]); - set_forked(true); + set_spawned(true); return OVERSEE_TEST; } +#endif // !GTEST_OS_WINDOWS + // Creates a concrete DeathTest-derived class that depends on the // --gtest_death_test_style flag, and sets the pointer pointed to // by the "test" argument to its address. If the test should be @@ -676,28 +998,36 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, ->increment_death_test_count(); if (flag != NULL) { - if (death_test_index > flag->index) { - last_death_test_message = String::Format( + if (death_test_index > flag->index()) { + DeathTest::set_last_death_test_message(String::Format( "Death test count (%d) somehow exceeded expected maximum (%d)", - death_test_index, flag->index); + death_test_index, flag->index())); return false; } - if (!(flag->file == file && flag->line == line && - flag->index == death_test_index)) { + if (!(flag->file() == file && flag->line() == line && + flag->index() == death_test_index)) { *test = NULL; return true; } } +#if GTEST_OS_WINDOWS + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new WindowsDeathTest(statement, regex, file, line); + } +#else if (GTEST_FLAG(death_test_style) == "threadsafe") { *test = new ExecDeathTest(statement, regex, file, line); } else if (GTEST_FLAG(death_test_style) == "fast") { *test = new NoExecDeathTest(statement, regex); - } else { - last_death_test_message = String::Format( + } +#endif // GTEST_OS_WINDOWS + else { // NOLINT - this is more readable than unbalanced brackets inside #if. + DeathTest::set_last_death_test_message(String::Format( "Unknown death test style \"%s\" encountered", - GTEST_FLAG(death_test_style).c_str()); + GTEST_FLAG(death_test_style).c_str())); return false; } @@ -711,7 +1041,7 @@ static void SplitString(const ::std::string& str, char delimiter, ::std::vector< ::std::string>* dest) { ::std::vector< ::std::string> parsed; ::std::string::size_type pos = 0; - while (true) { + while (::testing::internal::AlwaysTrue()) { const ::std::string::size_type colon = str.find(delimiter, pos); if (colon == ::std::string::npos) { parsed.push_back(str.substr(pos)); @@ -724,25 +1054,71 @@ static void SplitString(const ::std::string& str, char delimiter, dest->swap(parsed); } -// Attempts to parse a string into a positive integer. Returns true -// if that is possible. GTEST_HAS_DEATH_TEST implies that we have -// ::std::string, so we can use it here. -static bool ParsePositiveInt(const ::std::string& str, int* number) { - // Fail fast if the given string does not begin with a digit; - // this bypasses strtol's "optional leading whitespace and plus - // or minus sign" semantics, which are undesirable here. - if (str.empty() || !isdigit(str[0])) { - return false; +#if GTEST_OS_WINDOWS +// Recreates the pipe and event handles from the provided parameters, +// signals the event, and returns a file descriptor wrapped around the pipe +// handle. This function is called in the child process only. +int GetStatusFileDescriptor(unsigned int parent_process_id, + size_t write_handle_as_size_t, + size_t event_handle_as_size_t) { + AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, // Non-inheritable. + parent_process_id)); + if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { + DeathTestAbort(String::Format("Unable to open parent process %u", + parent_process_id)); } - char* endptr; - const long parsed = strtol(str.c_str(), &endptr, 10); // NOLINT - if (*endptr == '\0' && parsed <= INT_MAX) { - *number = static_cast<int>(parsed); - return true; - } else { - return false; + + // TODO(vladl@google.com): Replace the following check with a + // compile-time assertion when available. + GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); + + const HANDLE write_handle = + reinterpret_cast<HANDLE>(write_handle_as_size_t); + HANDLE dup_write_handle; + + // The newly initialized handle is accessible only in in the parent + // process. To obtain one accessible within the child, we need to use + // DuplicateHandle. + if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, + ::GetCurrentProcess(), &dup_write_handle, + 0x0, // Requested privileges ignored since + // DUPLICATE_SAME_ACCESS is used. + FALSE, // Request non-inheritable handler. + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort(String::Format( + "Unable to duplicate the pipe handle %Iu from the parent process %u", + write_handle_as_size_t, parent_process_id)); } + + const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t); + HANDLE dup_event_handle; + + if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, + ::GetCurrentProcess(), &dup_event_handle, + 0x0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort(String::Format( + "Unable to duplicate the event handle %Iu from the parent process %u", + event_handle_as_size_t, parent_process_id)); + } + + const int write_fd = + ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND); + if (write_fd == -1) { + DeathTestAbort(String::Format( + "Unable to convert pipe handle %Iu to a file descriptor", + write_handle_as_size_t)); + } + + // Signals the parent that the write end of the pipe has been acquired + // so the parent can release its own write end. + ::SetEvent(dup_event_handle); + + return write_fd; } +#endif // GTEST_OS_WINDOWS // Returns a newly created InternalRunDeathTestFlag object with fields // initialized from the GTEST_FLAG(internal_run_death_test) flag if @@ -750,22 +1126,43 @@ static bool ParsePositiveInt(const ::std::string& str, int* number) { InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { if (GTEST_FLAG(internal_run_death_test) == "") return NULL; - InternalRunDeathTestFlag* const internal_run_death_test_flag = - new InternalRunDeathTestFlag; // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we // can use it here. + int line = -1; + int index = -1; ::std::vector< ::std::string> fields; - SplitString(GTEST_FLAG(internal_run_death_test).c_str(), ':', &fields); + SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); + int write_fd = -1; + +#if GTEST_OS_WINDOWS + unsigned int parent_process_id = 0; + size_t write_handle_as_size_t = 0; + size_t event_handle_as_size_t = 0; + + if (fields.size() != 6 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &parent_process_id) + || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) + || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { + DeathTestAbort(String::Format( + "Bad --gtest_internal_run_death_test flag: %s", + GTEST_FLAG(internal_run_death_test).c_str())); + } + write_fd = GetStatusFileDescriptor(parent_process_id, + write_handle_as_size_t, + event_handle_as_size_t); +#else if (fields.size() != 4 - || !ParsePositiveInt(fields[1], &internal_run_death_test_flag->line) - || !ParsePositiveInt(fields[2], &internal_run_death_test_flag->index) - || !ParsePositiveInt(fields[3], - &internal_run_death_test_flag->status_fd)) { - DeathTestAbort("Bad --gtest_internal_run_death_test flag: %s", - GTEST_FLAG(internal_run_death_test).c_str()); + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &write_fd)) { + DeathTestAbort(String::Format( + "Bad --gtest_internal_run_death_test flag: %s", + GTEST_FLAG(internal_run_death_test).c_str())); } - internal_run_death_test_flag->file = fields[0].c_str(); - return internal_run_death_test_flag; +#endif // GTEST_OS_WINDOWS + return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); } } // namespace internal diff --git a/utils/unittest/googletest/gtest-filepath.cc b/utils/unittest/googletest/gtest-filepath.cc index 493ba0b..c1ef918 100644 --- a/utils/unittest/googletest/gtest-filepath.cc +++ b/utils/unittest/googletest/gtest-filepath.cc @@ -34,23 +34,20 @@ #include <stdlib.h> -#ifdef _WIN32_WCE +#if GTEST_OS_WINDOWS_MOBILE #include <windows.h> -#elif defined(GTEST_OS_WINDOWS) +#elif GTEST_OS_WINDOWS #include <direct.h> #include <io.h> -#include <sys/stat.h> -#elif defined(GTEST_OS_SYMBIAN) +#elif GTEST_OS_SYMBIAN // Symbian OpenC has PATH_MAX in sys/syslimits.h #include <sys/syslimits.h> -#include <unistd.h> #else #include <limits.h> -#include <sys/stat.h> -#include <unistd.h> -#endif // _WIN32_WCE or _WIN32 +#include <climits> // Some Linux distributions define PATH_MAX here. +#endif // GTEST_OS_WINDOWS_MOBILE -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS #define GTEST_PATH_MAX_ _MAX_PATH #elif defined(PATH_MAX) #define GTEST_PATH_MAX_ PATH_MAX @@ -65,10 +62,16 @@ namespace testing { namespace internal { -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS +// On Windows, '\\' is the standard path separator, but many tools and the +// Windows API also accept '/' as an alternate path separator. Unless otherwise +// noted, a file path can contain either kind of path separators, or a mixture +// of them. const char kPathSeparator = '\\'; +const char kAlternatePathSeparator = '/'; const char kPathSeparatorString[] = "\\"; -#ifdef _WIN32_WCE +const char kAlternatePathSeparatorString[] = "/"; +#if GTEST_OS_WINDOWS_MOBILE // Windows CE doesn't have a current directory. You should not use // the current directory in tests on Windows CE, but this at least // provides a reasonable fallback. @@ -77,26 +80,35 @@ const char kCurrentDirectoryString[] = "\\"; const DWORD kInvalidFileAttributes = 0xffffffff; #else const char kCurrentDirectoryString[] = ".\\"; -#endif // _WIN32_WCE +#endif // GTEST_OS_WINDOWS_MOBILE #else const char kPathSeparator = '/'; const char kPathSeparatorString[] = "/"; const char kCurrentDirectoryString[] = "./"; #endif // GTEST_OS_WINDOWS +// Returns whether the given character is a valid path separator. +static bool IsPathSeparator(char c) { +#if GTEST_HAS_ALT_PATH_SEP_ + return (c == kPathSeparator) || (c == kAlternatePathSeparator); +#else + return c == kPathSeparator; +#endif +} + // Returns the current working directory, or "" if unsuccessful. FilePath FilePath::GetCurrentDir() { -#ifdef _WIN32_WCE -// Windows CE doesn't have a current directory, so we just return -// something reasonable. +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE doesn't have a current directory, so we just return + // something reasonable. return FilePath(kCurrentDirectoryString); -#elif defined(GTEST_OS_WINDOWS) - char cwd[GTEST_PATH_MAX_ + 1] = {}; +#elif GTEST_OS_WINDOWS + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); #else - char cwd[GTEST_PATH_MAX_ + 1] = {}; + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); -#endif +#endif // GTEST_OS_WINDOWS_MOBILE } // Returns a copy of the FilePath with the case-insensitive extension removed. @@ -106,11 +118,27 @@ FilePath FilePath::GetCurrentDir() { FilePath FilePath::RemoveExtension(const char* extension) const { String dot_extension(String::Format(".%s", extension)); if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) { - return FilePath(String(pathname_.c_str(), pathname_.GetLength() - 4)); + return FilePath(String(pathname_.c_str(), pathname_.length() - 4)); } return *this; } +// Returns a pointer to the last occurence of a valid path separator in +// the FilePath. On Windows, for example, both '/' and '\' are valid path +// separators. Returns NULL if no path separator was found. +const char* FilePath::FindLastPathSeparator() const { + const char* const last_sep = strrchr(c_str(), kPathSeparator); +#if GTEST_HAS_ALT_PATH_SEP_ + const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); + // Comparing two pointers of which only one is NULL is undefined. + if (last_alt_sep != NULL && + (last_sep == NULL || last_alt_sep > last_sep)) { + return last_alt_sep; + } +#endif + return last_sep; +} + // Returns a copy of the FilePath with the directory part removed. // Example: FilePath("path/to/file").RemoveDirectoryName() returns // FilePath("file"). If there is no directory part ("just_a_file"), it returns @@ -118,7 +146,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const { // returns an empty FilePath (""). // On Windows platform, '\' is the path separator, otherwise it is '/'. FilePath FilePath::RemoveDirectoryName() const { - const char* const last_sep = strrchr(c_str(), kPathSeparator); + const char* const last_sep = FindLastPathSeparator(); return last_sep ? FilePath(String(last_sep + 1)) : *this; } @@ -129,9 +157,14 @@ FilePath FilePath::RemoveDirectoryName() const { // not have a file, like "just/a/dir/", it returns the FilePath unmodified. // On Windows platform, '\' is the path separator, otherwise it is '/'. FilePath FilePath::RemoveFileName() const { - const char* const last_sep = strrchr(c_str(), kPathSeparator); - return FilePath(last_sep ? String(c_str(), last_sep + 1 - c_str()) - : String(kCurrentDirectoryString)); + const char* const last_sep = FindLastPathSeparator(); + String dir; + if (last_sep) { + dir = String(c_str(), last_sep + 1 - c_str()); + } else { + dir = kCurrentDirectoryString; + } + return FilePath(dir); } // Helper functions for naming files in a directory for xml output. @@ -144,44 +177,54 @@ FilePath FilePath::MakeFileName(const FilePath& directory, const FilePath& base_name, int number, const char* extension) { - FilePath dir(directory.RemoveTrailingPathSeparator()); + String file; if (number == 0) { - return FilePath(String::Format("%s%c%s.%s", dir.c_str(), kPathSeparator, - base_name.c_str(), extension)); + file = String::Format("%s.%s", base_name.c_str(), extension); + } else { + file = String::Format("%s_%d.%s", base_name.c_str(), number, extension); } - return FilePath(String::Format("%s%c%s_%d.%s", dir.c_str(), kPathSeparator, - base_name.c_str(), number, extension)); + return ConcatPaths(directory, FilePath(file)); +} + +// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". +// On Windows, uses \ as the separator rather than /. +FilePath FilePath::ConcatPaths(const FilePath& directory, + const FilePath& relative_path) { + if (directory.IsEmpty()) + return relative_path; + const FilePath dir(directory.RemoveTrailingPathSeparator()); + return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator, + relative_path.c_str())); } // Returns true if pathname describes something findable in the file-system, // either a file, directory, or whatever. bool FilePath::FileOrDirectoryExists() const { -#ifdef GTEST_OS_WINDOWS -#ifdef _WIN32_WCE +#if GTEST_OS_WINDOWS_MOBILE LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); const DWORD attributes = GetFileAttributes(unicode); delete [] unicode; return attributes != kInvalidFileAttributes; #else - struct _stat file_stat = {}; - return _stat(pathname_.c_str(), &file_stat) == 0; -#endif // _WIN32_WCE -#else - struct stat file_stat; - return stat(pathname_.c_str(), &file_stat) == 0; -#endif // GTEST_OS_WINDOWS + posix::StatStruct file_stat; + return posix::Stat(pathname_.c_str(), &file_stat) == 0; +#endif // GTEST_OS_WINDOWS_MOBILE } // Returns true if pathname describes a directory in the file-system // that exists. bool FilePath::DirectoryExists() const { bool result = false; -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS // Don't strip off trailing separator if path is a root directory on // Windows (like "C:\\"). const FilePath& path(IsRootDirectory() ? *this : RemoveTrailingPathSeparator()); -#ifdef _WIN32_WCE +#else + const FilePath& path(*this); +#endif + +#if GTEST_OS_WINDOWS_MOBILE LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); const DWORD attributes = GetFileAttributes(unicode); delete [] unicode; @@ -190,30 +233,38 @@ bool FilePath::DirectoryExists() const { result = true; } #else - struct _stat file_stat = {}; - result = _stat(path.c_str(), &file_stat) == 0 && - (_S_IFDIR & file_stat.st_mode) != 0; -#endif // _WIN32_WCE -#else - struct stat file_stat; - result = stat(pathname_.c_str(), &file_stat) == 0 && - S_ISDIR(file_stat.st_mode); -#endif // GTEST_OS_WINDOWS + posix::StatStruct file_stat; + result = posix::Stat(path.c_str(), &file_stat) == 0 && + posix::IsDir(file_stat); +#endif // GTEST_OS_WINDOWS_MOBILE + return result; } // Returns true if pathname describes a root directory. (Windows has one // root directory per disk drive.) bool FilePath::IsRootDirectory() const { -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS + // TODO(wan@google.com): on Windows a network share like + // \\server\share can be a root directory, although it cannot be the + // current directory. Handle this properly. + return pathname_.length() == 3 && IsAbsolutePath(); +#else + return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); +#endif +} + +// Returns true if pathname describes an absolute path. +bool FilePath::IsAbsolutePath() const { const char* const name = pathname_.c_str(); - return pathname_.GetLength() == 3 && +#if GTEST_OS_WINDOWS + return pathname_.length() >= 3 && ((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A' && name[0] <= 'Z')) && name[1] == ':' && - name[2] == kPathSeparator; + IsPathSeparator(name[2]); #else - return pathname_ == kPathSeparatorString; + return IsPathSeparator(name[0]); #endif } @@ -240,7 +291,8 @@ FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, // it is intended to represent a directory. Returns false otherwise. // This does NOT check that a directory (or file) actually exists. bool FilePath::IsDirectory() const { - return pathname_.EndsWith(kPathSeparatorString); + return !pathname_.empty() && + IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); } // Create directories so that path exists. Returns true if successful or if @@ -251,7 +303,7 @@ bool FilePath::CreateDirectoriesRecursively() const { return false; } - if (pathname_.GetLength() == 0 || this->DirectoryExists()) { + if (pathname_.length() == 0 || this->DirectoryExists()) { return true; } @@ -264,18 +316,17 @@ bool FilePath::CreateDirectoriesRecursively() const { // directory for any reason, including if the parent directory does not // exist. Not named "CreateDirectory" because that's a macro on Windows. bool FilePath::CreateFolder() const { -#ifdef GTEST_OS_WINDOWS -#ifdef _WIN32_WCE +#if GTEST_OS_WINDOWS_MOBILE FilePath removed_sep(this->RemoveTrailingPathSeparator()); LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); int result = CreateDirectory(unicode, NULL) ? 0 : -1; delete [] unicode; -#else +#elif GTEST_OS_WINDOWS int result = _mkdir(pathname_.c_str()); -#endif // !WIN32_WCE #else int result = mkdir(pathname_.c_str(), 0777); -#endif // _WIN32 +#endif // GTEST_OS_WINDOWS_MOBILE + if (result == -1) { return this->DirectoryExists(); // An error is OK if the directory exists. } @@ -286,31 +337,39 @@ bool FilePath::CreateFolder() const { // name, otherwise return the name string unmodified. // On Windows platform, uses \ as the separator, other platforms use /. FilePath FilePath::RemoveTrailingPathSeparator() const { - return pathname_.EndsWith(kPathSeparatorString) - ? FilePath(String(pathname_.c_str(), pathname_.GetLength() - 1)) + return IsDirectory() + ? FilePath(String(pathname_.c_str(), pathname_.length() - 1)) : *this; } -// Normalize removes any redundant separators that might be in the pathname. +// Removes any redundant separators that might be in the pathname. // For example, "bar///foo" becomes "bar/foo". Does not eliminate other // redundancies that might be in a pathname involving "." or "..". +// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). void FilePath::Normalize() { if (pathname_.c_str() == NULL) { pathname_ = ""; return; } const char* src = pathname_.c_str(); - char* const dest = new char[pathname_.GetLength() + 1]; + char* const dest = new char[pathname_.length() + 1]; char* dest_ptr = dest; - memset(dest_ptr, 0, pathname_.GetLength() + 1); + memset(dest_ptr, 0, pathname_.length() + 1); while (*src != '\0') { - *dest_ptr++ = *src; - if (*src != kPathSeparator) + *dest_ptr = *src; + if (!IsPathSeparator(*src)) { src++; - else - while (*src == kPathSeparator) + } else { +#if GTEST_HAS_ALT_PATH_SEP_ + if (*dest_ptr == kAlternatePathSeparator) { + *dest_ptr = kPathSeparator; + } +#endif + while (IsPathSeparator(*src)) src++; + } + dest_ptr++; } *dest_ptr = '\0'; pathname_ = dest; diff --git a/utils/unittest/googletest/gtest-port.cc b/utils/unittest/googletest/gtest-port.cc index 9878cae..5609599 100644 --- a/utils/unittest/googletest/gtest-port.cc +++ b/utils/unittest/googletest/gtest-port.cc @@ -35,29 +35,90 @@ #include <stdlib.h> #include <stdio.h> -#ifdef GTEST_HAS_DEATH_TEST -#include <regex.h> -#endif // GTEST_HAS_DEATH_TEST - -#ifdef _WIN32_WCE +#if GTEST_OS_WINDOWS_MOBILE #include <windows.h> // For TerminateProcess() -#endif // _WIN32_WCE +#elif GTEST_OS_WINDOWS +#include <io.h> +#include <sys/stat.h> +#else +#include <unistd.h> +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_MAC +#include <mach/mach_init.h> +#include <mach/task.h> +#include <mach/vm_map.h> +#endif // GTEST_OS_MAC #include <gtest/gtest-spi.h> #include <gtest/gtest-message.h> #include <gtest/internal/gtest-string.h> +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#include "gtest/internal/gtest-internal-inl.h" +#undef GTEST_IMPLEMENTATION_ namespace testing { namespace internal { -#ifdef GTEST_HAS_DEATH_TEST +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; +const int kStdErrFileno = 2; +#else +const int kStdOutFileno = STDOUT_FILENO; +const int kStdErrFileno = STDERR_FILENO; +#endif // _MSC_VER + +#if GTEST_OS_MAC + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const task_t task = mach_task_self(); + mach_msg_type_number_t thread_count; + thread_act_array_t thread_list; + const kern_return_t status = task_threads(task, &thread_list, &thread_count); + if (status == KERN_SUCCESS) { + // task_threads allocates resources in thread_list and we need to free them + // to avoid leaks. + vm_deallocate(task, + reinterpret_cast<vm_address_t>(thread_list), + sizeof(thread_t) * thread_count); + return static_cast<size_t>(thread_count); + } else { + return 0; + } +} + +#else + +size_t GetThreadCount() { + // There's no portable way to detect the number of threads, so we just + // return 0 to indicate that we cannot detect it. + return 0; +} + +#endif // GTEST_OS_MAC + +#if GTEST_USES_POSIX_RE // Implements RE. Currently only needed for death tests. RE::~RE() { - regfree(&partial_regex_); - regfree(&full_regex_); + if (is_valid_) { + // regfree'ing an invalid regex might crash because the content + // of the regex is undefined. Since the regex's are essentially + // the same, one cannot be valid (or invalid) without the other + // being so too. + regfree(&partial_regex_); + regfree(&full_regex_); + } free(const_cast<char*>(pattern_)); } @@ -80,7 +141,7 @@ bool RE::PartialMatch(const char* str, const RE& re) { // Initializes an RE from its string representation. void RE::Init(const char* regex) { - pattern_ = strdup(regex); + pattern_ = posix::StrDup(regex); // Reserves enough bytes to hold the regular expression used for a // full match. @@ -93,7 +154,14 @@ void RE::Init(const char* regex) { // previous expression returns false. Otherwise partial_regex_ may // not be properly initialized can may cause trouble when it's // freed. - is_valid_ = (regcomp(&partial_regex_, regex, REG_EXTENDED) == 0) && is_valid_; + // + // Some implementation of POSIX regex (e.g. on at least some + // versions of Cygwin) doesn't accept the empty string as a valid + // regex. We change it to an equivalent form "()" to be safe. + if (is_valid_) { + const char* const partial_regex = (*regex == '\0') ? "()" : regex; + is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; + } EXPECT_TRUE(is_valid_) << "Regular expression \"" << regex << "\" is not a valid POSIX Extended regular expression."; @@ -101,77 +169,362 @@ void RE::Init(const char* regex) { delete[] full_pattern; } -#endif // GTEST_HAS_DEATH_TEST +#elif GTEST_USES_SIMPLE_RE + +// Returns true iff ch appears anywhere in str (excluding the +// terminating '\0' character). +bool IsInSet(char ch, const char* str) { + return ch != '\0' && strchr(str, ch) != NULL; +} + +// Returns true iff ch belongs to the given classification. Unlike +// similar functions in <ctype.h>, these aren't affected by the +// current locale. +bool IsDigit(char ch) { return '0' <= ch && ch <= '9'; } +bool IsPunct(char ch) { + return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); +} +bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } +bool IsWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } +bool IsWordChar(char ch) { + return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_'; +} + +// Returns true iff "\\c" is a supported escape sequence. +bool IsValidEscape(char c) { + return (IsPunct(c) || IsInSet(c, "dDfnrsStvwW")); +} + +// Returns true iff the given atom (specified by escaped and pattern) +// matches ch. The result is undefined if the atom is invalid. +bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { + if (escaped) { // "\\p" where p is pattern_char. + switch (pattern_char) { + case 'd': return IsDigit(ch); + case 'D': return !IsDigit(ch); + case 'f': return ch == '\f'; + case 'n': return ch == '\n'; + case 'r': return ch == '\r'; + case 's': return IsWhiteSpace(ch); + case 'S': return !IsWhiteSpace(ch); + case 't': return ch == '\t'; + case 'v': return ch == '\v'; + case 'w': return IsWordChar(ch); + case 'W': return !IsWordChar(ch); + } + return IsPunct(pattern_char) && pattern_char == ch; + } + + return (pattern_char == '.' && ch != '\n') || pattern_char == ch; +} + +// Helper function used by ValidateRegex() to format error messages. +String FormatRegexSyntaxError(const char* regex, int index) { + return (Message() << "Syntax error at index " << index + << " in simple regular expression \"" << regex << "\": ").GetString(); +} + +// Generates non-fatal failures and returns false if regex is invalid; +// otherwise returns true. +bool ValidateRegex(const char* regex) { + if (regex == NULL) { + // TODO(wan@google.com): fix the source file location in the + // assertion failures to match where the regex is used in user + // code. + ADD_FAILURE() << "NULL is not a valid simple regular expression."; + return false; + } + + bool is_valid = true; + + // True iff ?, *, or + can follow the previous atom. + bool prev_repeatable = false; + for (int i = 0; regex[i]; i++) { + if (regex[i] == '\\') { // An escape sequence + i++; + if (regex[i] == '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "'\\' cannot appear at the end."; + return false; + } + + if (!IsValidEscape(regex[i])) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "invalid escape sequence \"\\" << regex[i] << "\"."; + is_valid = false; + } + prev_repeatable = true; + } else { // Not an escape sequence. + const char ch = regex[i]; + + if (ch == '^' && i > 0) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'^' can only appear at the beginning."; + is_valid = false; + } else if (ch == '$' && regex[i + 1] != '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'$' can only appear at the end."; + is_valid = false; + } else if (IsInSet(ch, "()[]{}|")) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' is unsupported."; + is_valid = false; + } else if (IsRepeat(ch) && !prev_repeatable) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' can only follow a repeatable token."; + is_valid = false; + } + + prev_repeatable = !IsInSet(ch, "^$?*+"); + } + } + + return is_valid; +} + +// Matches a repeated regex atom followed by a valid simple regular +// expression. The regex atom is defined as c if escaped is false, +// or \c otherwise. repeat is the repetition meta character (?, *, +// or +). The behavior is undefined if str contains too many +// characters to be indexable by size_t, in which case the test will +// probably time out anyway. We are fine with this limitation as +// std::string has it too. +bool MatchRepetitionAndRegexAtHead( + bool escaped, char c, char repeat, const char* regex, + const char* str) { + const size_t min_count = (repeat == '+') ? 1 : 0; + const size_t max_count = (repeat == '?') ? 1 : + static_cast<size_t>(-1) - 1; + // We cannot call numeric_limits::max() as it conflicts with the + // max() macro on Windows. + + for (size_t i = 0; i <= max_count; ++i) { + // We know that the atom matches each of the first i characters in str. + if (i >= min_count && MatchRegexAtHead(regex, str + i)) { + // We have enough matches at the head, and the tail matches too. + // Since we only care about *whether* the pattern matches str + // (as opposed to *how* it matches), there is no need to find a + // greedy match. + return true; + } + if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) + return false; + } + return false; +} + +// Returns true iff regex matches a prefix of str. regex must be a +// valid simple regular expression and not start with "^", or the +// result is undefined. +bool MatchRegexAtHead(const char* regex, const char* str) { + if (*regex == '\0') // An empty regex matches a prefix of anything. + return true; + + // "$" only matches the end of a string. Note that regex being + // valid guarantees that there's nothing after "$" in it. + if (*regex == '$') + return *str == '\0'; + + // Is the first thing in regex an escape sequence? + const bool escaped = *regex == '\\'; + if (escaped) + ++regex; + if (IsRepeat(regex[1])) { + // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so + // here's an indirect recursion. It terminates as the regex gets + // shorter in each recursion. + return MatchRepetitionAndRegexAtHead( + escaped, regex[0], regex[1], regex + 2, str); + } else { + // regex isn't empty, isn't "$", and doesn't start with a + // repetition. We match the first atom of regex with the first + // character of str and recurse. + return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && + MatchRegexAtHead(regex + 1, str + 1); + } +} + +// Returns true iff regex matches any substring of str. regex must be +// a valid simple regular expression, or the result is undefined. +// +// The algorithm is recursive, but the recursion depth doesn't exceed +// the regex length, so we won't need to worry about running out of +// stack space normally. In rare cases the time complexity can be +// exponential with respect to the regex length + the string length, +// but usually it's must faster (often close to linear). +bool MatchRegexAnywhere(const char* regex, const char* str) { + if (regex == NULL || str == NULL) + return false; + + if (*regex == '^') + return MatchRegexAtHead(regex + 1, str); + + // A successful match can be anywhere in str. + do { + if (MatchRegexAtHead(regex, str)) + return true; + } while (*str++ != '\0'); + return false; +} + +// Implements the RE class. + +RE::~RE() { + free(const_cast<char*>(pattern_)); + free(const_cast<char*>(full_pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = full_pattern_ = NULL; + if (regex != NULL) { + pattern_ = posix::StrDup(regex); + } + + is_valid_ = ValidateRegex(regex); + if (!is_valid_) { + // No need to calculate the full pattern when the regex is invalid. + return; + } + + const size_t len = strlen(regex); + // Reserves enough bytes to hold the regular expression used for a + // full match: we need space to prepend a '^', append a '$', and + // terminate the string with '\0'. + char* buffer = static_cast<char*>(malloc(len + 3)); + full_pattern_ = buffer; + + if (*regex != '^') + *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. -// Logs a message at the given severity level. -void GTestLog(GTestLogSeverity severity, const char* file, - int line, const char* msg) { + // We don't use snprintf or strncpy, as they trigger a warning when + // compiled with VC++ 8.0. + memcpy(buffer, regex, len); + buffer += len; + + if (len == 0 || regex[len - 1] != '$') + *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. + + *buffer = '\0'; +} + +#endif // GTEST_USES_POSIX_RE + + +GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) + : severity_(severity) { const char* const marker = severity == GTEST_INFO ? "[ INFO ]" : severity == GTEST_WARNING ? "[WARNING]" : severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; - fprintf(stderr, "\n%s %s:%d: %s\n", marker, file, line, msg); - if (severity == GTEST_FATAL) { - abort(); - } + GetStream() << ::std::endl << marker << " " + << FormatFileLocation(file, line).c_str() << ": "; } -#ifdef GTEST_HAS_DEATH_TEST +// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. +GTestLog::~GTestLog() { + GetStream() << ::std::endl; + if (severity_ == GTEST_FATAL) { + fflush(stderr); + posix::Abort(); + } +} +// Disable Microsoft deprecation warnings for POSIX functions called from +// this class (creat, dup, dup2, and close) +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4996) +#endif // _MSC_VER -// Defines the stderr capturer. +#if GTEST_HAS_STREAM_REDIRECTION_ -class CapturedStderr { +// Object that captures an output stream (stdout/stderr). +class CapturedStream { public: - // The ctor redirects stderr to a temporary file. - CapturedStderr() { - uncaptured_fd_ = dup(STDERR_FILENO); - + // The ctor redirects the stream to a temporary file. + CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { +#if GTEST_OS_WINDOWS + char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT + char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT + + ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); + const UINT success = ::GetTempFileNameA(temp_dir_path, + "gtest_redir", + 0, // Generate unique file name. + temp_file_path); + GTEST_CHECK_(success != 0) + << "Unable to create a temporary file in " << temp_dir_path; + const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); + GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " + << temp_file_path; + filename_ = temp_file_path; +#else // There's no guarantee that a test has write access to the // current directory, so we create the temporary file in the /tmp // directory instead. - char name_template[] = "/tmp/captured_stderr.XXXXXX"; + char name_template[] = "/tmp/captured_stream.XXXXXX"; const int captured_fd = mkstemp(name_template); filename_ = name_template; +#endif // GTEST_OS_WINDOWS fflush(NULL); - dup2(captured_fd, STDERR_FILENO); + dup2(captured_fd, fd_); close(captured_fd); } - ~CapturedStderr() { + ~CapturedStream() { remove(filename_.c_str()); } - // Stops redirecting stderr. - void StopCapture() { - // Restores the original stream. - fflush(NULL); - dup2(uncaptured_fd_, STDERR_FILENO); - close(uncaptured_fd_); - uncaptured_fd_ = -1; + String GetCapturedString() { + if (uncaptured_fd_ != -1) { + // Restores the original stream. + fflush(NULL); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } + + FILE* const file = posix::FOpen(filename_.c_str(), "r"); + const String content = ReadEntireFile(file); + posix::FClose(file); + return content; } - // Returns the name of the temporary file holding the stderr output. - // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we - // can use it here. - ::std::string filename() const { return filename_; } - private: + // Reads the entire content of a file as a String. + static String ReadEntireFile(FILE* file); + + // Returns the size (in bytes) of a file. + static size_t GetFileSize(FILE* file); + + const int fd_; // A stream to capture. int uncaptured_fd_; + // Name of the temporary file holding the stderr output. ::std::string filename_; -}; -static CapturedStderr* g_captured_stderr = NULL; + GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); +}; // Returns the size (in bytes) of a file. -static size_t GetFileSize(FILE * file) { +size_t CapturedStream::GetFileSize(FILE* file) { fseek(file, 0, SEEK_END); return static_cast<size_t>(ftell(file)); } // Reads the entire content of a file as a string. -// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can -// use it here. -static ::std::string ReadEntireFile(FILE * file) { +String CapturedStream::ReadEntireFile(FILE* file) { const size_t file_size = GetFileSize(file); char* const buffer = new char[file_size]; @@ -187,35 +540,58 @@ static ::std::string ReadEntireFile(FILE * file) { bytes_read += bytes_last_read; } while (bytes_last_read > 0 && bytes_read < file_size); - const ::std::string content(buffer, buffer+bytes_read); + const String content(buffer, bytes_read); delete[] buffer; return content; } -// Starts capturing stderr. -void CaptureStderr() { - if (g_captured_stderr != NULL) { - GTEST_LOG_(FATAL, "Only one stderr capturer can exist at one time."); +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +static CapturedStream* g_captured_stderr = NULL; +static CapturedStream* g_captured_stdout = NULL; + +// Starts capturing an output stream (stdout/stderr). +void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { + if (*stream != NULL) { + GTEST_LOG_(FATAL) << "Only one " << stream_name + << " capturer can exist at a time."; } - g_captured_stderr = new CapturedStderr; + *stream = new CapturedStream(fd); } -// Stops capturing stderr and returns the captured string. -// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can -// use it here. -::std::string GetCapturedStderr() { - g_captured_stderr->StopCapture(); - FILE* const file = fopen(g_captured_stderr->filename().c_str(), "r"); - const ::std::string content = ReadEntireFile(file); - fclose(file); +// Stops capturing the output stream and returns the captured string. +String GetCapturedStream(CapturedStream** captured_stream) { + const String content = (*captured_stream)->GetCapturedString(); - delete g_captured_stderr; - g_captured_stderr = NULL; + delete *captured_stream; + *captured_stream = NULL; return content; } +// Starts capturing stdout. +void CaptureStdout() { + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() { + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); } + +// Stops capturing stderr and returns the captured string. +String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); } + +#endif // GTEST_HAS_STREAM_REDIRECTION_ + +#if GTEST_HAS_DEATH_TEST + // A copy of all command line arguments. Set by InitGoogleTest(). ::std::vector<String> g_argvs; @@ -224,38 +600,30 @@ const ::std::vector<String>& GetArgvs() { return g_argvs; } #endif // GTEST_HAS_DEATH_TEST -#ifdef _WIN32_WCE -void abort() { +#if GTEST_OS_WINDOWS_MOBILE +namespace posix { +void Abort() { DebugBreak(); TerminateProcess(GetCurrentProcess(), 1); } -#endif // _WIN32_WCE +} // namespace posix +#endif // GTEST_OS_WINDOWS_MOBILE // Returns the name of the environment variable corresponding to the // given flag. For example, FlagToEnvVar("foo") will return // "GTEST_FOO" in the open-source version. static String FlagToEnvVar(const char* flag) { - const String full_flag = (Message() << GTEST_FLAG_PREFIX << flag).GetString(); + const String full_flag = + (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); Message env_var; - for (int i = 0; i != full_flag.GetLength(); i++) { + for (size_t i = 0; i != full_flag.length(); i++) { env_var << static_cast<char>(toupper(full_flag.c_str()[i])); } return env_var.GetString(); } -// Reads and returns the Boolean environment variable corresponding to -// the given flag; if it's not set, returns default_value. -// -// The value is considered true iff it's not "0". -bool BoolFromGTestEnv(const char* flag, bool default_value) { - const String env_var = FlagToEnvVar(flag); - const char* const string_value = GetEnv(env_var.c_str()); - return string_value == NULL ? - default_value : strcmp(string_value, "0") != 0; -} - // Parses 'str' for a 32-bit signed integer. If successful, writes // the result to *value and returns true; otherwise leaves *value // unchanged and returns false. @@ -297,12 +665,23 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) { return true; } +// Reads and returns the Boolean environment variable corresponding to +// the given flag; if it's not set, returns default_value. +// +// The value is considered true iff it's not "0". +bool BoolFromGTestEnv(const char* flag, bool default_value) { + const String env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + return string_value == NULL ? + default_value : strcmp(string_value, "0") != 0; +} + // Reads and returns a 32-bit integer stored in the environment // variable corresponding to the given flag; if it isn't set or // doesn't represent a valid 32-bit integer, returns default_value. Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { const String env_var = FlagToEnvVar(flag); - const char* const string_value = GetEnv(env_var.c_str()); + const char* const string_value = posix::GetEnv(env_var.c_str()); if (string_value == NULL) { // The environment variable is not set. return default_value; @@ -324,7 +703,7 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { // the given flag; if it's not set, returns default_value. const char* StringFromGTestEnv(const char* flag, const char* default_value) { const String env_var = FlagToEnvVar(flag); - const char* const value = GetEnv(env_var.c_str()); + const char* const value = posix::GetEnv(env_var.c_str()); return value == NULL ? default_value : value; } diff --git a/utils/unittest/googletest/gtest-test-part.cc b/utils/unittest/googletest/gtest-test-part.cc index 2e80f21..8249afe 100644 --- a/utils/unittest/googletest/gtest-test-part.cc +++ b/utils/unittest/googletest/gtest-test-part.cc @@ -38,12 +38,14 @@ // included, or there will be a compiler error. This trick is to // prevent a user from accidentally including gtest-internal-inl.h in // his code. -#define GTEST_IMPLEMENTATION +#define GTEST_IMPLEMENTATION_ 1 #include "gtest/internal/gtest-internal-inl.h" -#undef GTEST_IMPLEMENTATION +#undef GTEST_IMPLEMENTATION_ namespace testing { +using internal::GetUnitTestImpl; + // Gets the summary of the failure message by omitting the stack trace // in it. internal::String TestPartResult::ExtractSummary(const char* message) { @@ -54,61 +56,45 @@ internal::String TestPartResult::ExtractSummary(const char* message) { // Prints a TestPartResult object. std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { - return os << result.file_name() << ":" - << result.line_number() << ": " - << (result.type() == TPRT_SUCCESS ? "Success" : - result.type() == TPRT_FATAL_FAILURE ? "Fatal failure" : - "Non-fatal failure") << ":\n" - << result.message() << std::endl; -} - -// Constructs an empty TestPartResultArray. -TestPartResultArray::TestPartResultArray() - : list_(new internal::List<TestPartResult>) { -} - -// Destructs a TestPartResultArray. -TestPartResultArray::~TestPartResultArray() { - delete list_; + return os + << result.file_name() << ":" << result.line_number() << ": " + << (result.type() == TestPartResult::kSuccess ? "Success" : + result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : + "Non-fatal failure") << ":\n" + << result.message() << std::endl; } // Appends a TestPartResult to the array. void TestPartResultArray::Append(const TestPartResult& result) { - list_->PushBack(result); + array_.push_back(result); } // Returns the TestPartResult at the given index (0-based). const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { if (index < 0 || index >= size()) { printf("\nInvalid index (%d) into TestPartResultArray.\n", index); - internal::abort(); - } - - const internal::ListNode<TestPartResult>* p = list_->Head(); - for (int i = 0; i < index; i++) { - p = p->next(); + internal::posix::Abort(); } - return p->element(); + return array_[index]; } // Returns the number of TestPartResult objects in the array. int TestPartResultArray::size() const { - return list_->size(); + return static_cast<int>(array_.size()); } namespace internal { HasNewFatalFailureHelper::HasNewFatalFailureHelper() : has_new_fatal_failure_(false), - original_reporter_(UnitTest::GetInstance()->impl()-> + original_reporter_(GetUnitTestImpl()-> GetTestPartResultReporterForCurrentThread()) { - UnitTest::GetInstance()->impl()->SetTestPartResultReporterForCurrentThread( - this); + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); } HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { - UnitTest::GetInstance()->impl()->SetTestPartResultReporterForCurrentThread( + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( original_reporter_); } diff --git a/utils/unittest/googletest/gtest-typed-test.cc b/utils/unittest/googletest/gtest-typed-test.cc index d42a159..3cc4b5d 100644 --- a/utils/unittest/googletest/gtest-typed-test.cc +++ b/utils/unittest/googletest/gtest-typed-test.cc @@ -35,7 +35,15 @@ namespace testing { namespace internal { -#ifdef GTEST_HAS_TYPED_TEST_P +#if GTEST_HAS_TYPED_TEST_P + +// Skips to the first non-space char in str. Returns an empty string if str +// contains only whitespace characters. +static const char* SkipSpaces(const char* str) { + while (isspace(*str)) + str++; + return str; +} // Verifies that registered_tests match the test names in // defined_test_names_; returns registered_tests if successful, or @@ -45,6 +53,10 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames( typedef ::std::set<const char*>::const_iterator DefinedTestIter; registered_ = true; + // Skip initial whitespace in registered_tests since some + // preprocessors prefix stringizied literals with whitespace. + registered_tests = SkipSpaces(registered_tests); + Message errors; ::std::set<String> tests; for (const char* names = registered_tests; names != NULL; @@ -85,7 +97,8 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames( if (errors_str != "") { fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), errors_str.c_str()); - abort(); + fflush(stderr); + posix::Abort(); } return registered_tests; diff --git a/utils/unittest/googletest/gtest.cc b/utils/unittest/googletest/gtest.cc index b5a654f..aa2d5bb 100644 --- a/utils/unittest/googletest/gtest.cc +++ b/utils/unittest/googletest/gtest.cc @@ -39,15 +39,19 @@ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <wchar.h> #include <wctype.h> -#ifdef GTEST_OS_LINUX +#include <algorithm> +#include <ostream> +#include <sstream> +#include <vector> + +#if GTEST_OS_LINUX // TODO(kenton@google.com): Use autoconf to detect availability of // gettimeofday(). -#define GTEST_HAS_GETTIMEOFDAY +#define GTEST_HAS_GETTIMEOFDAY_ 1 #include <fcntl.h> #include <limits.h> @@ -60,38 +64,38 @@ #include <string> #include <vector> -#elif defined(GTEST_OS_SYMBIAN) -#define GTEST_HAS_GETTIMEOFDAY +#elif GTEST_OS_SYMBIAN +#define GTEST_HAS_GETTIMEOFDAY_ 1 #include <sys/time.h> // NOLINT -#elif defined(GTEST_OS_ZOS) -#define GTEST_HAS_GETTIMEOFDAY +#elif GTEST_OS_ZOS +#define GTEST_HAS_GETTIMEOFDAY_ 1 #include <sys/time.h> // NOLINT // On z/OS we additionally need strings.h for strcasecmp. -#include <strings.h> +#include <strings.h> // NOLINT -#elif defined(_WIN32_WCE) // We are on Windows CE. +#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. #include <windows.h> // NOLINT -#elif defined(GTEST_OS_WINDOWS) // We are on Windows proper. +#elif GTEST_OS_WINDOWS // We are on Windows proper. #include <io.h> // NOLINT #include <sys/timeb.h> // NOLINT #include <sys/types.h> // NOLINT #include <sys/stat.h> // NOLINT -#if defined(__MINGW__) || defined(__MINGW32__) +#if GTEST_OS_WINDOWS_MINGW // MinGW has gettimeofday() but not _ftime64(). // TODO(kenton@google.com): Use autoconf to detect availability of // gettimeofday(). // TODO(kenton@google.com): There are other ways to get the time on // Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW // supports these. consider using them instead. -#define GTEST_HAS_GETTIMEOFDAY +#define GTEST_HAS_GETTIMEOFDAY_ 1 #include <sys/time.h> // NOLINT -#endif +#endif // GTEST_OS_WINDOWS_MINGW // cpplint thinks that the header is already included, so we want to // silence it. @@ -102,13 +106,17 @@ // Assume other platforms have gettimeofday(). // TODO(kenton@google.com): Use autoconf to detect availability of // gettimeofday(). -#define GTEST_HAS_GETTIMEOFDAY +#define GTEST_HAS_GETTIMEOFDAY_ 1 // cpplint thinks that the header is already included, so we want to // silence it. #include <sys/time.h> // NOLINT #include <unistd.h> // NOLINT +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +#include <stdexcept> #endif // Indicates that this translation unit is part of Google Test's @@ -116,18 +124,21 @@ // included, or there will be a compiler error. This trick is to // prevent a user from accidentally including gtest-internal-inl.h in // his code. -#define GTEST_IMPLEMENTATION +#define GTEST_IMPLEMENTATION_ 1 #include "gtest/internal/gtest-internal-inl.h" -#undef GTEST_IMPLEMENTATION +#undef GTEST_IMPLEMENTATION_ -#ifdef GTEST_OS_WINDOWS -#define fileno _fileno -#define isatty _isatty +#if GTEST_OS_WINDOWS #define vsnprintf _vsnprintf #endif // GTEST_OS_WINDOWS namespace testing { +using internal::CountIf; +using internal::ForEach; +using internal::GetElementOr; +using internal::Shuffle; + // Constants. // A test whose test case name or test name matches this filter is @@ -145,15 +156,31 @@ static const char kUniversalFilter[] = "*"; // The default output file for XML output. static const char kDefaultOutputFile[] = "test_detail.xml"; +// The environment variable name for the test shard index. +static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; +// The environment variable name for the total number of test shards. +static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; +// The environment variable name for the test shard status file. +static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; + namespace internal { // The text used in failure messages to indicate the start of the // stack trace. const char kStackTraceMarker[] = "\nStack trace:\n"; +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +bool g_help_flag = false; + } // namespace internal GTEST_DEFINE_bool_( + also_run_disabled_tests, + internal::BoolFromGTestEnv("also_run_disabled_tests", false), + "Run disabled tests too, in addition to the tests normally being run."); + +GTEST_DEFINE_bool_( break_on_failure, internal::BoolFromGTestEnv("break_on_failure", false), "True iff a failed assertion should be a debugger break-point."); @@ -161,7 +188,7 @@ GTEST_DEFINE_bool_( GTEST_DEFINE_bool_( catch_exceptions, internal::BoolFromGTestEnv("catch_exceptions", false), - "True iff " GTEST_NAME + "True iff " GTEST_NAME_ " should catch exceptions and treat them as test failures."); GTEST_DEFINE_string_( @@ -170,7 +197,7 @@ GTEST_DEFINE_string_( "Whether to use colors in the output. Valid values: yes, no, " "and auto. 'auto' means to use colors if the output is " "being sent to a terminal and the TERM environment variable " - "is set to xterm or xterm-color."); + "is set to xterm, xterm-color, xterm-256color, linux or cygwin."); GTEST_DEFINE_string_( filter, @@ -198,29 +225,67 @@ GTEST_DEFINE_string_( GTEST_DEFINE_bool_( print_time, - internal::BoolFromGTestEnv("print_time", false), - "True iff " GTEST_NAME + internal::BoolFromGTestEnv("print_time", true), + "True iff " GTEST_NAME_ " should display elapsed time in text output."); GTEST_DEFINE_int32_( + random_seed, + internal::Int32FromGTestEnv("random_seed", 0), + "Random number seed to use when shuffling test orders. Must be in range " + "[1, 99999], or 0 to use a seed based on the current time."); + +GTEST_DEFINE_int32_( repeat, internal::Int32FromGTestEnv("repeat", 1), "How many times to repeat each test. Specify a negative number " "for repeating forever. Useful for shaking out flaky tests."); +GTEST_DEFINE_bool_( + show_internal_stack_frames, false, + "True iff " GTEST_NAME_ " should include internal stack frames when " + "printing test failure stack traces."); + +GTEST_DEFINE_bool_( + shuffle, + internal::BoolFromGTestEnv("shuffle", false), + "True iff " GTEST_NAME_ + " should randomize tests' order on every run."); + GTEST_DEFINE_int32_( stack_trace_depth, - internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), + internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), "The maximum number of stack frames to print when an " "assertion fails. The valid range is 0 through 100, inclusive."); GTEST_DEFINE_bool_( - show_internal_stack_frames, false, - "True iff " GTEST_NAME " should include internal stack frames when " - "printing test failure stack traces."); + throw_on_failure, + internal::BoolFromGTestEnv("throw_on_failure", false), + "When this flag is specified, a failed assertion will throw an exception " + "if exceptions are enabled or exit the program with a non-zero code " + "otherwise."); namespace internal { +// Generates a random number from [0, range), using a Linear +// Congruential Generator (LCG). Crashes if 'range' is 0 or greater +// than kMaxRange. +UInt32 Random::Generate(UInt32 range) { + // These constants are the same as are used in glibc's rand(3). + state_ = (1103515245U*state_ + 12345U) % kMaxRange; + + GTEST_CHECK_(range > 0) + << "Cannot generate a number in the range [0, 0)."; + GTEST_CHECK_(range <= kMaxRange) + << "Generation of a number in [0, " << range << ") was requested, " + << "but this can only generate numbers in [0, " << kMaxRange << ")."; + + // Converting via modulus introduces a bit of downward bias, but + // it's simple, and a linear congruential generator isn't too good + // to begin with. + return state_ % range; +} + // GTestIsInitialized() returns true iff the user has initialized // Google Test. Useful for catching the user mistake of not initializing // Google Test before calling RUN_ALL_TESTS(). @@ -232,16 +297,14 @@ namespace internal { int g_init_gtest_count = 0; static bool GTestIsInitialized() { return g_init_gtest_count != 0; } -// Iterates over a list of TestCases, keeping a running sum of the +// Iterates over a vector of TestCases, keeping a running sum of the // results of calling a given int-returning method on each. // Returns the sum. -static int SumOverTestCaseList(const internal::List<TestCase*>& case_list, +static int SumOverTestCaseList(const std::vector<TestCase*>& case_list, int (TestCase::*method)() const) { int sum = 0; - for (const internal::ListNode<TestCase*>* node = case_list.Head(); - node != NULL; - node = node->next()) { - sum += (node->element()->*method)(); + for (size_t i = 0; i < case_list.size(); i++) { + sum += (case_list[i]->*method)(); } return sum; } @@ -263,16 +326,22 @@ static bool ShouldRunTestCase(const TestCase* test_case) { } // AssertHelper constructor. -AssertHelper::AssertHelper(TestPartResultType type, const char* file, - int line, const char* message) - : type_(type), file_(file), line_(line), message_(message) { +AssertHelper::AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message) + : data_(new AssertHelperData(type, file, line, message)) { +} + +AssertHelper::~AssertHelper() { + delete data_; } // Message assignment, for assertion streaming support. void AssertHelper::operator=(const Message& message) const { UnitTest::GetInstance()-> - AddTestPartResult(type_, file_, line_, - AppendUserMessage(message_, message), + AddTestPartResult(data_->type, data_->file, data_->line, + AppendUserMessage(data_->message, message), UnitTest::GetInstance()->impl() ->CurrentOsStackTraceExceptTop(1) // Skips the stack frame for this function itself. @@ -280,7 +349,7 @@ void AssertHelper::operator=(const Message& message) const { } // Mutex for linked pointers. -Mutex g_linked_ptr_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); +GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); // Application pathname gotten in InitGoogleTest. String g_executable_path; @@ -290,11 +359,11 @@ String g_executable_path; FilePath GetCurrentExecutableName() { FilePath result; -#if defined(_WIN32_WCE) || defined(GTEST_OS_WINDOWS) +#if GTEST_OS_WINDOWS result.Set(FilePath(g_executable_path).RemoveExtension("exe")); #else result.Set(FilePath(g_executable_path)); -#endif // _WIN32_WCE || GTEST_OS_WINDOWS +#endif // GTEST_OS_WINDOWS return result.RemoveDirectoryName(); } @@ -314,16 +383,28 @@ String UnitTestOptions::GetOutputFormat() { // Returns the name of the requested output file, or the default if none // was explicitly specified. -String UnitTestOptions::GetOutputFile() { +String UnitTestOptions::GetAbsolutePathToOutputFile() { const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); if (gtest_output_flag == NULL) return String(""); const char* const colon = strchr(gtest_output_flag, ':'); if (colon == NULL) - return String(kDefaultOutputFile); + return String(internal::FilePath::ConcatPaths( + internal::FilePath( + UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(kDefaultOutputFile)).ToString() ); internal::FilePath output_name(colon + 1); + if (!output_name.IsAbsolutePath()) + // TODO(wan@google.com): on Windows \some\path is not an absolute + // path (as its meaning depends on the current drive), yet the + // following logic for turning it into an absolute path is wrong. + // Fix it. + output_name = internal::FilePath::ConcatPaths( + internal::FilePath(UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(colon + 1)); + if (!output_name.IsDirectory()) return output_name.ToString(); @@ -357,7 +438,7 @@ bool UnitTestOptions::PatternMatchesString(const char *pattern, bool UnitTestOptions::MatchesFilter(const String& name, const char* filter) { const char *cur_pattern = filter; - while (true) { + for (;;) { if (PatternMatchesString(cur_pattern, name.c_str())) { return true; } @@ -395,7 +476,7 @@ bool UnitTestOptions::FilterMatchesTest(const String &test_case_name, positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter negative = String(""); } else { - positive.Set(p, dash - p); // Everything up to the dash + positive = String(p, dash - p); // Everything up to the dash negative = String(dash+1); // Everything after the dash if (positive.empty()) { // Treat '-test1' as the same as '*-test1' @@ -409,7 +490,7 @@ bool UnitTestOptions::FilterMatchesTest(const String &test_case_name, !MatchesFilter(full_name, negative.c_str())); } -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. // This function is useful as an __except condition. @@ -426,46 +507,6 @@ int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { } // namespace internal -// The interface for printing the result of a UnitTest -class UnitTestEventListenerInterface { - public: - // The d'tor is pure virtual as this is an abstract class. - virtual ~UnitTestEventListenerInterface() = 0; - - // Called before the unit test starts. - virtual void OnUnitTestStart(const UnitTest*) {} - - // Called after the unit test ends. - virtual void OnUnitTestEnd(const UnitTest*) {} - - // Called before the test case starts. - virtual void OnTestCaseStart(const TestCase*) {} - - // Called after the test case ends. - virtual void OnTestCaseEnd(const TestCase*) {} - - // Called before the global set-up starts. - virtual void OnGlobalSetUpStart(const UnitTest*) {} - - // Called after the global set-up ends. - virtual void OnGlobalSetUpEnd(const UnitTest*) {} - - // Called before the global tear-down starts. - virtual void OnGlobalTearDownStart(const UnitTest*) {} - - // Called after the global tear-down ends. - virtual void OnGlobalTearDownEnd(const UnitTest*) {} - - // Called before the test starts. - virtual void OnTestStart(const TestInfo*) {} - - // Called after the test ends. - virtual void OnTestEnd(const TestInfo*) {} - - // Called after an assertion. - virtual void OnNewTestPartResult(const TestPartResult*) {} -}; - // The c'tor sets this object as the test part result reporter used by // Google Test. The 'result' parameter specifies where to report the // results. Intercepts only failures from the current thread. @@ -487,7 +528,7 @@ ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( } void ScopedFakeTestPartResultReporter::Init() { - internal::UnitTestImpl* const impl = UnitTest::GetInstance()->impl(); + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); if (intercept_mode_ == INTERCEPT_ALL_THREADS) { old_reporter_ = impl->GetGlobalTestPartResultReporter(); impl->SetGlobalTestPartResultReporter(this); @@ -500,7 +541,7 @@ void ScopedFakeTestPartResultReporter::Init() { // The d'tor restores the test part result reporter used by Google Test // before. ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { - internal::UnitTestImpl* const impl = UnitTest::GetInstance()->impl(); + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); if (intercept_mode_ == INTERCEPT_ALL_THREADS) { impl->SetGlobalTestPartResultReporter(old_reporter_); } else { @@ -541,11 +582,11 @@ AssertionResult HasOneFailure(const char* /* results_expr */, const char* /* type_expr */, const char* /* substr_expr */, const TestPartResultArray& results, - TestPartResultType type, + TestPartResult::Type type, const char* substr) { - const String expected( - type == TPRT_FATAL_FAILURE ? "1 fatal failure" : - "1 non-fatal failure"); + const String expected(type == TestPartResult::kFatalFailure ? + "1 fatal failure" : + "1 non-fatal failure"); Message msg; if (results.size() != 1) { msg << "Expected: " << expected << "\n" @@ -580,7 +621,7 @@ AssertionResult HasOneFailure(const char* /* results_expr */, // substring the failure message should contain. SingleFailureChecker:: SingleFailureChecker( const TestPartResultArray* results, - TestPartResultType type, + TestPartResult::Type type, const char* substr) : results_(results), type_(type), @@ -600,7 +641,7 @@ DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( void DefaultGlobalTestPartResultReporter::ReportTestPartResult( const TestPartResult& result) { unit_test_->current_test_result()->AddTestPartResult(result); - unit_test_->result_printer()->OnNewTestPartResult(&result); + unit_test_->listeners()->repeater()->OnTestPartResult(result); } DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( @@ -639,23 +680,23 @@ void UnitTestImpl::SetTestPartResultReporterForCurrentThread( // Gets the number of successful test cases. int UnitTestImpl::successful_test_case_count() const { - return test_cases_.CountIf(TestCasePassed); + return CountIf(test_cases_, TestCasePassed); } // Gets the number of failed test cases. int UnitTestImpl::failed_test_case_count() const { - return test_cases_.CountIf(TestCaseFailed); + return CountIf(test_cases_, TestCaseFailed); } // Gets the number of all test cases. int UnitTestImpl::total_test_case_count() const { - return test_cases_.size(); + return static_cast<int>(test_cases_.size()); } // Gets the number of all test cases that contain at least one test // that should run. int UnitTestImpl::test_case_to_run_count() const { - return test_cases_.CountIf(ShouldRunTestCase); + return CountIf(test_cases_, ShouldRunTestCase); } // Gets the number of successful tests. @@ -698,11 +739,13 @@ String UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { return String(""); } -static TimeInMillis GetTimeInMillis() { -#ifdef _WIN32_WCE // We are on Windows CE - // Difference between 1970-01-01 and 1601-01-01 in miliseconds. +// Returns the current time in milliseconds. +TimeInMillis GetTimeInMillis() { +#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) + // Difference between 1970-01-01 and 1601-01-01 in milliseconds. // http://analogous.blogspot.com/2005/04/epoch.html - const TimeInMillis kJavaEpochToWinFileTimeDelta = 11644473600000UL; + const TimeInMillis kJavaEpochToWinFileTimeDelta = + static_cast<TimeInMillis>(116444736UL) * 100000UL; const DWORD kTenthMicrosInMilliSecond = 10000; SYSTEMTIME now_systime; @@ -719,7 +762,7 @@ static TimeInMillis GetTimeInMillis() { return now_int64.QuadPart; } return 0; -#elif defined(GTEST_OS_WINDOWS) && !defined(GTEST_HAS_GETTIMEOFDAY) +#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ __timeb64 now; #ifdef _MSC_VER // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 @@ -734,7 +777,7 @@ static TimeInMillis GetTimeInMillis() { _ftime64(&now); #endif // _MSC_VER return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm; -#elif defined(GTEST_HAS_GETTIMEOFDAY) +#elif GTEST_HAS_GETTIMEOFDAY_ struct timeval now; gettimeofday(&now, NULL); return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000; @@ -767,16 +810,7 @@ static char* CloneString(const char* str, size_t length) { return NULL; } else { char* const clone = new char[length + 1]; - // MSVC 8 deprecates strncpy(), so we want to suppress warning - // 4996 (deprecated function) there. -#ifdef GTEST_OS_WINDOWS // We are on Windows. -#pragma warning(push) // Saves the current warning state. -#pragma warning(disable:4996) // Temporarily disables warning 4996. - strncpy(clone, str, length); -#pragma warning(pop) // Restores the warning state. -#else // We are on Linux or Mac OS. - strncpy(clone, str, length); -#endif // GTEST_OS_WINDOWS + posix::StrNCpy(clone, str, length); clone[length] = '\0'; return clone; } @@ -790,7 +824,7 @@ const char * String::CloneCString(const char* c_str) { NULL : CloneString(c_str, strlen(c_str)); } -#ifdef _WIN32_WCE +#if GTEST_OS_WINDOWS_MOBILE // Creates a UTF-16 wide string from the given ANSI string, allocating // memory using new. The caller is responsible for deleting the return // value using delete[]. Returns the wide string, or NULL if the @@ -824,7 +858,7 @@ const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { return ansi; } -#endif // _WIN32_WCE +#endif // GTEST_OS_WINDOWS_MOBILE // Compares two C strings. Returns true iff they have the same content. // @@ -843,17 +877,17 @@ bool String::CStringEquals(const char * lhs, const char * rhs) { // Converts an array of wide chars to a narrow string using the UTF-8 // encoding, and streams the result to the given Message object. -static void StreamWideCharsToMessage(const wchar_t* wstr, size_t len, +static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, Message* msg) { // TODO(wan): consider allowing a testing::String object to // contain '\0'. This will make it behave more like std::string, // and will allow ToUtf8String() to return the correct encoding // for '\0' s.t. we can get rid of the conditional here (and in // several other places). - for (size_t i = 0; i != len; ) { // NOLINT + for (size_t i = 0; i != length; ) { // NOLINT if (wstr[i] != L'\0') { - *msg << WideStringToUtf8(wstr + i, static_cast<int>(len - i)); - while (i != len && wstr[i] != L'\0') + *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i)); + while (i != length && wstr[i] != L'\0') i++; } else { *msg << '\0'; @@ -926,21 +960,37 @@ String FormatForFailureMessage(wchar_t wchar) { } // namespace internal -// AssertionResult constructor. -AssertionResult::AssertionResult(const internal::String& failure_message) - : failure_message_(failure_message) { +// AssertionResult constructors. +// Used in EXPECT_TRUE/FALSE(assertion_result). +AssertionResult::AssertionResult(const AssertionResult& other) + : success_(other.success_), + message_(other.message_.get() != NULL ? + new internal::String(*other.message_) : + static_cast<internal::String*>(NULL)) { } +// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. +AssertionResult AssertionResult::operator!() const { + AssertionResult negation(!success_); + if (message_.get() != NULL) + negation << *message_; + return negation; +} // Makes a successful assertion result. AssertionResult AssertionSuccess() { - return AssertionResult(); + 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 AssertionResult(message.GetString()); + return AssertionFailure() << message; } namespace internal { @@ -982,6 +1032,20 @@ AssertionResult EqFailure(const char* expected_expression, return AssertionFailure(msg); } +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +String GetBoolAssertionFailureMessage(const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value) { + const char* actual_message = assertion_result.message(); + Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} // Helper function for implementing ASSERT_NEAR. AssertionResult DoubleNearPredFormat(const char* expr1, @@ -1260,7 +1324,6 @@ AssertionResult IsNotSubstring( return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); } -#if GTEST_HAS_STD_STRING AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const ::std::string& needle, const ::std::string& haystack) { @@ -1272,7 +1335,6 @@ AssertionResult IsNotSubstring( const ::std::string& needle, const ::std::string& haystack) { return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); } -#endif // GTEST_HAS_STD_STRING #if GTEST_HAS_STD_WSTRING AssertionResult IsSubstring( @@ -1290,7 +1352,7 @@ AssertionResult IsNotSubstring( namespace internal { -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS namespace { @@ -1298,7 +1360,7 @@ namespace { AssertionResult HRESULTFailureHelper(const char* expr, const char* expected, long hr) { // NOLINT -#ifdef _WIN32_WCE +#if GTEST_OS_WINDOWS_MOBILE // Windows CE doesn't support FormatMessage. const char error_text[] = ""; #else @@ -1322,7 +1384,7 @@ AssertionResult HRESULTFailureHelper(const char* expr, --message_length) { error_text[message_length - 1] = '\0'; } -#endif // _WIN32_WCE +#endif // GTEST_OS_WINDOWS_MOBILE const String error_hex(String::Format("0x%08X ", hr)); Message msg; @@ -1416,17 +1478,8 @@ char* CodePointToUtf8(UInt32 code_point, char* str) { // the terminating nul character). We are asking for 32 character // buffer just in case. This is also enough for strncpy to // null-terminate the destination string. - // MSVC 8 deprecates strncpy(), so we want to suppress warning - // 4996 (deprecated function) there. -#ifdef GTEST_OS_WINDOWS // We are on Windows. -#pragma warning(push) // Saves the current warning state. -#pragma warning(disable:4996) // Temporarily disables warning 4996. -#endif - strncpy(str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), - 32); -#ifdef GTEST_OS_WINDOWS // We are on Windows. -#pragma warning(pop) // Restores the warning state. -#endif + posix::StrNCpy( + str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), 32); str[31] = '\0'; // Makes sure no change in the format to strncpy leaves // the result unterminated. } @@ -1441,23 +1494,19 @@ char* CodePointToUtf8(UInt32 code_point, char* str) { // and thus should be combined into a single Unicode code point // using CreateCodePointFromUtf16SurrogatePair. inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { - if (sizeof(wchar_t) == 2) - return (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; - else - return false; + return sizeof(wchar_t) == 2 && + (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; } // Creates a Unicode code point from UTF16 surrogate pair. inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, wchar_t second) { - if (sizeof(wchar_t) == 2) { - const UInt32 mask = (1 << 10) - 1; - return (((first & mask) << 10) | (second & mask)) + 0x10000; - } else { - // This should not be called, but we provide a sensible default - // in case it is. - return static_cast<UInt32>(first); - } + const UInt32 mask = (1 << 10) - 1; + return (sizeof(wchar_t) == 2) ? + (((first & mask) << 10) | (second & mask)) + 0x10000 : + // This function should not be called when the condition is + // false, but we provide a sensible default in case it is. + static_cast<UInt32>(first); } // Converts a wide string to a narrow string in UTF-8 encoding. @@ -1568,15 +1617,11 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression, // NULL C string is considered different to any non-NULL C string, // including the empty string. bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { - if ( lhs == NULL ) return rhs == NULL; - - if ( rhs == NULL ) return false; - -#ifdef GTEST_OS_WINDOWS - return _stricmp(lhs, rhs) == 0; -#else // GTEST_OS_WINDOWS - return strcasecmp(lhs, rhs) == 0; -#endif // GTEST_OS_WINDOWS + if (lhs == NULL) + return rhs == NULL; + if (rhs == NULL) + return false; + return posix::StrCaseCmp(lhs, rhs) == 0; } // Compares two wide C strings, ignoring case. Returns true iff they @@ -1597,9 +1642,9 @@ bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, if ( rhs == NULL ) return false; -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS return _wcsicmp(lhs, rhs) == 0; -#elif defined(GTEST_OS_LINUX) +#elif GTEST_OS_LINUX return wcscasecmp(lhs, rhs) == 0; #else // Mac OS X and Cygwin don't define wcscasecmp. Other unknown OSes @@ -1610,27 +1655,33 @@ bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, right = towlower(*rhs++); } while (left && left == right); return left == right; -#endif // OS selector -} - -// Constructs a String by copying a given number of chars from a -// buffer. E.g. String("hello", 3) will create the string "hel". -String::String(const char * buffer, size_t len) { - char * const temp = new char[ len + 1 ]; - memcpy(temp, buffer, len); - temp[ len ] = '\0'; - c_str_ = temp; +#endif // OS selector } // Compares this with another String. // Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0 // if this is greater than rhs. int String::Compare(const String & rhs) const { - if ( c_str_ == NULL ) { - return rhs.c_str_ == NULL ? 0 : -1; // NULL < anything except NULL + const char* const lhs_c_str = c_str(); + const char* const rhs_c_str = rhs.c_str(); + + if (lhs_c_str == NULL) { + return rhs_c_str == NULL ? 0 : -1; // NULL < anything except NULL + } else if (rhs_c_str == NULL) { + return 1; } - return rhs.c_str_ == NULL ? 1 : strcmp(c_str_, rhs.c_str_); + const size_t shorter_str_len = + length() <= rhs.length() ? length() : rhs.length(); + for (size_t i = 0; i != shorter_str_len; i++) { + if (lhs_c_str[i] < rhs_c_str[i]) { + return -1; + } else if (lhs_c_str[i] > rhs_c_str[i]) { + return 1; + } + } + return (length() < rhs.length()) ? -1 : + (length() > rhs.length()) ? 1 : 0; } // Returns true iff this String ends with the given suffix. *Any* @@ -1638,12 +1689,12 @@ int String::Compare(const String & rhs) const { bool String::EndsWith(const char* suffix) const { if (suffix == NULL || CStringEquals(suffix, "")) return true; - if (c_str_ == NULL) return false; + if (c_str() == NULL) return false; - const size_t this_len = strlen(c_str_); + const size_t this_len = strlen(c_str()); const size_t suffix_len = strlen(suffix); return (this_len >= suffix_len) && - CStringEquals(c_str_ + this_len - suffix_len, suffix); + CStringEquals(c_str() + this_len - suffix_len, suffix); } // Returns true iff this String ends with the given suffix, ignoring case. @@ -1651,37 +1702,12 @@ bool String::EndsWith(const char* suffix) const { bool String::EndsWithCaseInsensitive(const char* suffix) const { if (suffix == NULL || CStringEquals(suffix, "")) return true; - if (c_str_ == NULL) return false; + if (c_str() == NULL) return false; - const size_t this_len = strlen(c_str_); + const size_t this_len = strlen(c_str()); const size_t suffix_len = strlen(suffix); return (this_len >= suffix_len) && - CaseInsensitiveCStringEquals(c_str_ + this_len - suffix_len, suffix); -} - -// Sets the 0-terminated C string this String object represents. The -// old string in this object is deleted, and this object will own a -// clone of the input string. This function copies only up to length -// bytes (plus a terminating null byte), or until the first null byte, -// whichever comes first. -// -// This function works even when the c_str parameter has the same -// value as that of the c_str_ field. -void String::Set(const char * c_str, size_t length) { - // Makes sure this works when c_str == c_str_ - const char* const temp = CloneString(c_str, length); - delete[] c_str_; - c_str_ = temp; -} - -// Assigns a C string to this object. Self-assignment works. -const String& String::operator=(const char* c_str) { - // Makes sure this works when c_str == c_str_ - if (c_str != c_str_) { - delete[] c_str_; - c_str_ = CloneCString(c_str); - } - return *this; + CaseInsensitiveCStringEquals(c_str() + this_len - suffix_len, suffix); } // Formats a list of arguments to a String, using the same format @@ -1691,41 +1717,46 @@ const String& String::operator=(const char* c_str) { // available. // // The result is limited to 4096 characters (including the tailing 0). -// If 4096 characters are not enough to format the input, -// "<buffer exceeded>" is returned. +// If 4096 characters are not enough to format the input, or if +// there's an error, "<formatting error or buffer exceeded>" is +// returned. String String::Format(const char * format, ...) { va_list args; va_start(args, format); char buffer[4096]; + const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]); + // MSVC 8 deprecates vsnprintf(), so we want to suppress warning // 4996 (deprecated function) there. -#ifdef GTEST_OS_WINDOWS // We are on Windows. +#ifdef _MSC_VER // We are using MSVC. #pragma warning(push) // Saves the current warning state. #pragma warning(disable:4996) // Temporarily disables warning 4996. - const int size = - vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args); + const int size = vsnprintf(buffer, kBufferSize, format, args); #pragma warning(pop) // Restores the warning state. -#else // We are on Linux or Mac OS. - const int size = - vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args); -#endif // GTEST_OS_WINDOWS +#else // We are not using MSVC. + const int size = vsnprintf(buffer, kBufferSize, format, args); +#endif // _MSC_VER va_end(args); - return String(size >= 0 ? buffer : "<buffer exceeded>"); + // vsnprintf()'s behavior is not portable. When the buffer is not + // big enough, it returns a negative value in MSVC, and returns the + // needed buffer size on Linux. When there is an output error, it + // always returns a negative value. For simplicity, we lump the two + // error cases together. + if (size < 0 || size >= kBufferSize) { + return String("<formatting error or buffer exceeded>"); + } else { + return String(buffer, size); + } } // Converts the buffer in a StrStream to a String, converting NUL // bytes to "\\0" along the way. String StrStreamToString(StrStream* ss) { -#if GTEST_HAS_STD_STRING const ::std::string& str = ss->str(); const char* const start = str.c_str(); const char* const end = start + str.length(); -#else - const char* const start = ss->str(); - const char* const end = start + ss->pcount(); -#endif // GTEST_HAS_STD_STRING // We need to use a helper StrStream to do this transformation // because String doesn't support push_back(). @@ -1738,14 +1769,7 @@ String StrStreamToString(StrStream* ss) { } } -#if GTEST_HAS_STD_STRING return String(helper.str().c_str()); -#else - const String str(helper.str(), helper.pcount()); - helper.freeze(false); - ss->freeze(false); - return str; -#endif // GTEST_HAS_STD_STRING } // Appends the user-supplied message to the Google-Test-generated message. @@ -1763,6 +1787,8 @@ String AppendUserMessage(const String& gtest_msg, return msg.GetString(); } +} // namespace internal + // class TestResult // Creates an empty TestResult. @@ -1775,9 +1801,32 @@ TestResult::TestResult() TestResult::~TestResult() { } +// Returns the i-th test part result among all the results. i can +// range from 0 to total_part_count() - 1. If i is not in that range, +// aborts the program. +const TestPartResult& TestResult::GetTestPartResult(int i) const { + if (i < 0 || i >= total_part_count()) + internal::posix::Abort(); + return test_part_results_.at(i); +} + +// Returns the i-th test property. i can range from 0 to +// test_property_count() - 1. If i is not in that range, aborts the +// program. +const TestProperty& TestResult::GetTestProperty(int i) const { + if (i < 0 || i >= test_property_count()) + internal::posix::Abort(); + return test_properties_.at(i); +} + +// Clears the test part results. +void TestResult::ClearTestPartResults() { + test_part_results_.clear(); +} + // Adds a test part result to the list. void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { - test_part_results_.PushBack(test_part_result); + test_part_results_.push_back(test_part_result); } // Adds a test property to the list. If a property with the same key as the @@ -1787,27 +1836,27 @@ void TestResult::RecordProperty(const TestProperty& test_property) { if (!ValidateTestProperty(test_property)) { return; } - MutexLock lock(&test_properites_mutex_); - ListNode<TestProperty>* const node_with_matching_key = - test_properties_.FindIf(TestPropertyKeyIs(test_property.key())); - if (node_with_matching_key == NULL) { - test_properties_.PushBack(test_property); + internal::MutexLock lock(&test_properites_mutex_); + const std::vector<TestProperty>::iterator property_with_matching_key = + std::find_if(test_properties_.begin(), test_properties_.end(), + internal::TestPropertyKeyIs(test_property.key())); + if (property_with_matching_key == test_properties_.end()) { + test_properties_.push_back(test_property); return; } - TestProperty& property_with_matching_key = node_with_matching_key->element(); - property_with_matching_key.SetValue(test_property.value()); + property_with_matching_key->SetValue(test_property.value()); } // Adds a failure if the key is a reserved attribute of Google Test // testcase tags. Returns true if the property is valid. bool TestResult::ValidateTestProperty(const TestProperty& test_property) { - String key(test_property.key()); + internal::String key(test_property.key()); if (key == "name" || key == "status" || key == "time" || key == "classname") { ADD_FAILURE() << "Reserved key used in RecordProperty(): " << key << " ('name', 'status', 'time', and 'classname' are reserved by " - << GTEST_NAME << ")"; + << GTEST_NAME_ << ")"; return false; } return true; @@ -1815,49 +1864,51 @@ bool TestResult::ValidateTestProperty(const TestProperty& test_property) { // Clears the object. void TestResult::Clear() { - test_part_results_.Clear(); - test_properties_.Clear(); + test_part_results_.clear(); + test_properties_.clear(); death_test_count_ = 0; elapsed_time_ = 0; } -// Returns true iff the test part passed. -static bool TestPartPassed(const TestPartResult & result) { - return result.passed(); -} - -// Gets the number of successful test parts. -int TestResult::successful_part_count() const { - return test_part_results_.CountIf(TestPartPassed); -} - -// Returns true iff the test part failed. -static bool TestPartFailed(const TestPartResult & result) { - return result.failed(); -} - -// Gets the number of failed test parts. -int TestResult::failed_part_count() const { - return test_part_results_.CountIf(TestPartFailed); +// Returns true iff the test failed. +bool TestResult::Failed() const { + for (int i = 0; i < total_part_count(); ++i) { + if (GetTestPartResult(i).failed()) + return true; + } + return false; } // Returns true iff the test part fatally failed. -static bool TestPartFatallyFailed(const TestPartResult & result) { +static bool TestPartFatallyFailed(const TestPartResult& result) { return result.fatally_failed(); } // Returns true iff the test fatally failed. bool TestResult::HasFatalFailure() const { - return test_part_results_.CountIf(TestPartFatallyFailed) > 0; + return CountIf(test_part_results_, TestPartFatallyFailed) > 0; +} + +// Returns true iff the test part non-fatally failed. +static bool TestPartNonfatallyFailed(const TestPartResult& result) { + return result.nonfatally_failed(); +} + +// Returns true iff the test has a non-fatal failure. +bool TestResult::HasNonfatalFailure() const { + return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; } // Gets the number of all test parts. This is the sum of the number // of successful test parts and the number of failed test parts. int TestResult::total_part_count() const { - return test_part_results_.size(); + return static_cast<int>(test_part_results_.size()); } -} // namespace internal +// Returns the number of the test properties. +int TestResult::test_property_count() const { + return static_cast<int>(test_properties_.size()); +} // class Test @@ -1897,7 +1948,23 @@ void Test::RecordProperty(const char* key, int value) { RecordProperty(key, value_message.GetString().c_str()); } -#ifdef GTEST_OS_WINDOWS +namespace internal { + +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const String& message) { + // This function is a friend of UnitTest and as such has access to + // AddTestPartResult. + UnitTest::GetInstance()->AddTestPartResult( + result_type, + NULL, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. + message, + String()); // No stack trace, either. +} + +} // namespace internal + +#if GTEST_OS_WINDOWS // We are on Windows. // Adds an "exception thrown" fatal failure to the current test. @@ -1907,15 +1974,8 @@ static void AddExceptionThrownFailure(DWORD exception_code, message << "Exception thrown with code 0x" << std::setbase(16) << exception_code << std::setbase(10) << " in " << location << "."; - UnitTest* const unit_test = UnitTest::GetInstance(); - unit_test->AddTestPartResult( - TPRT_FATAL_FAILURE, - static_cast<const char *>(NULL), - // We have no info about the source file where the exception - // occurred. - -1, // We have no info on which line caused the exception. - message.GetString(), - internal::String("")); + internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, + message.GetString()); } #endif // GTEST_OS_WINDOWS @@ -1931,7 +1991,7 @@ bool Test::HasSameFixtureClass() { // Info about the first test in the current test case. const internal::TestInfoImpl* const first_test_info = - test_case->test_info_list().Head()->element()->impl(); + test_case->test_info_list()[0]->impl(); const internal::TypeId first_fixture_id = first_test_info->fixture_class_id(); const char* const first_test_name = first_test_info->name(); @@ -1993,8 +2053,8 @@ void Test::Run() { if (!HasSameFixtureClass()) return; internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); -#if defined(GTEST_OS_WINDOWS) && !defined(__MINGW32__) - // We are on Windows. +#if GTEST_HAS_SEH + // Catch SEH-style exceptions. impl->os_stack_trace_getter()->UponLeavingGTest(); __try { SetUp(); @@ -2025,7 +2085,7 @@ void Test::Run() { AddExceptionThrownFailure(GetExceptionCode(), "TearDown()"); } -#else // We are on Linux, Mac or MingW - exceptions are disabled. +#else // We are on a compiler or platform that doesn't support SEH. impl->os_stack_trace_getter()->UponLeavingGTest(); SetUp(); @@ -2040,7 +2100,7 @@ void Test::Run() { // failed. impl->os_stack_trace_getter()->UponLeavingGTest(); TearDown(); -#endif // GTEST_OS_WINDOWS +#endif // GTEST_HAS_SEH } @@ -2049,18 +2109,24 @@ bool Test::HasFatalFailure() { return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); } +// Returns true iff the current test has a non-fatal failure. +bool Test::HasNonfatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()-> + HasNonfatalFailure(); +} + // class TestInfo // Constructs a TestInfo object. It assumes ownership of the test factory // object via impl_. -TestInfo::TestInfo(const char* test_case_name, - const char* name, - const char* test_case_comment, - const char* comment, +TestInfo::TestInfo(const char* a_test_case_name, + const char* a_name, + const char* a_test_case_comment, + const char* a_comment, internal::TypeId fixture_class_id, internal::TestFactoryBase* factory) { - impl_ = new internal::TestInfoImpl(this, test_case_name, name, - test_case_comment, comment, + impl_ = new internal::TestInfoImpl(this, a_test_case_name, a_name, + a_test_case_comment, a_comment, fixture_class_id, factory); } @@ -2102,7 +2168,7 @@ TestInfo* MakeAndRegisterTestInfo( return test_info; } -#ifdef GTEST_HAS_PARAM_TEST +#if GTEST_HAS_PARAM_TEST void ReportInvalidTestCaseType(const char* test_case_name, const char* file, int line) { Message errors; @@ -2146,8 +2212,11 @@ const char* TestInfo::comment() const { // Returns true if this test should run. bool TestInfo::should_run() const { return impl_->should_run(); } +// Returns true if this test matches the user-specified filter. +bool TestInfo::matches_filter() const { return impl_->matches_filter(); } + // Returns the result of the test. -const internal::TestResult* TestInfo::result() const { return impl_->result(); } +const TestResult* TestInfo::result() const { return impl_->result(); } // Increments the number of death tests encountered in this test so // far. @@ -2184,24 +2253,13 @@ class TestNameIs { } // namespace -// Finds and returns a TestInfo with the given name. If one doesn't -// exist, returns NULL. -TestInfo * TestCase::GetTestInfo(const char* test_name) { - // Can we find a TestInfo with the given name? - internal::ListNode<TestInfo *> * const node = test_info_list_->FindIf( - TestNameIs(test_name)); - - // Returns the TestInfo found. - return node ? node->element() : NULL; -} - namespace internal { // This method expands all parameterized tests registered with macros TEST_P // and INSTANTIATE_TEST_CASE_P into regular tests and registers those. // This will be done just once during the program runtime. void UnitTestImpl::RegisterParameterizedTests() { -#ifdef GTEST_HAS_PARAM_TEST +#if GTEST_HAS_PARAM_TEST if (!parameterized_tests_registered_) { parameterized_test_registry_.RegisterTests(); parameterized_tests_registered_ = true; @@ -2218,17 +2276,16 @@ void TestInfoImpl::Run() { UnitTestImpl* const impl = internal::GetUnitTestImpl(); impl->set_current_test_info(parent_); - // Notifies the unit test event listener that a test is about to - // start. - UnitTestEventListenerInterface* const result_printer = - impl->result_printer(); - result_printer->OnTestStart(parent_); + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + // Notifies the unit test event listeners that a test is about to start. + repeater->OnTestStart(*parent_); const TimeInMillis start = GetTimeInMillis(); impl->os_stack_trace_getter()->UponLeavingGTest(); -#if defined(GTEST_OS_WINDOWS) && !defined(__MINGW32__) - // We are on Windows. +#if GTEST_HAS_SEH + // Catch SEH-style exceptions. Test* test = NULL; __try { @@ -2240,7 +2297,7 @@ void TestInfoImpl::Run() { "the test fixture's constructor"); return; } -#else // We are on Linux, Mac OS or MingW - exceptions are disabled. +#else // We are on a compiler or platform that doesn't support SEH. // TODO(wan): If test->Run() throws, test won't be deleted. This is // not a problem now as we don't use exceptions. If we were to @@ -2249,7 +2306,7 @@ void TestInfoImpl::Run() { // Creates the test object. Test* test = factory_->CreateTest(); -#endif // GTEST_OS_WINDOWS +#endif // GTEST_HAS_SEH // Runs the test only if the constructor of the test fixture didn't // generate a fatal failure. @@ -2265,7 +2322,7 @@ void TestInfoImpl::Run() { result_.set_elapsed_time(GetTimeInMillis() - start); // Notifies the unit test event listener that a test has just finished. - result_printer->OnTestEnd(parent_); + repeater->OnTestEnd(*parent_); // Tells UnitTest to stop associating assertion results to this // test. @@ -2278,26 +2335,26 @@ void TestInfoImpl::Run() { // Gets the number of successful tests in this test case. int TestCase::successful_test_count() const { - return test_info_list_->CountIf(TestPassed); + return CountIf(test_info_list_, TestPassed); } // Gets the number of failed tests in this test case. int TestCase::failed_test_count() const { - return test_info_list_->CountIf(TestFailed); + return CountIf(test_info_list_, TestFailed); } int TestCase::disabled_test_count() const { - return test_info_list_->CountIf(TestDisabled); + return CountIf(test_info_list_, TestDisabled); } // Get the number of tests in this test case that should run. int TestCase::test_to_run_count() const { - return test_info_list_->CountIf(ShouldRunTest); + return CountIf(test_info_list_, ShouldRunTest); } // Gets the number of all tests. int TestCase::total_test_count() const { - return test_info_list_->size(); + return static_cast<int>(test_info_list_.size()); } // Creates a TestCase with the given name. @@ -2307,32 +2364,42 @@ int TestCase::total_test_count() const { // name: name of the test case // set_up_tc: pointer to the function that sets up the test case // tear_down_tc: pointer to the function that tears down the test case -TestCase::TestCase(const char* name, const char* comment, +TestCase::TestCase(const char* a_name, const char* a_comment, Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc) - : name_(name), - comment_(comment), + : name_(a_name), + comment_(a_comment), set_up_tc_(set_up_tc), tear_down_tc_(tear_down_tc), should_run_(false), elapsed_time_(0) { - test_info_list_ = new internal::List<TestInfo *>; } // Destructor of TestCase. TestCase::~TestCase() { // Deletes every Test in the collection. - test_info_list_->ForEach(internal::Delete<TestInfo>); + ForEach(test_info_list_, internal::Delete<TestInfo>); +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +const TestInfo* TestCase::GetTestInfo(int i) const { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} - // Then deletes the Test collection. - delete test_info_list_; - test_info_list_ = NULL; +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +TestInfo* TestCase::GetMutableTestInfo(int i) { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; } // Adds a test to this test case. Will delete the test upon // destruction of the TestCase object. void TestCase::AddTestInfo(TestInfo * test_info) { - test_info_list_->PushBack(test_info); + test_info_list_.push_back(test_info); + test_indices_.push_back(static_cast<int>(test_indices_.size())); } // Runs every test in this TestCase. @@ -2342,38 +2409,62 @@ void TestCase::Run() { internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); impl->set_current_test_case(this); - UnitTestEventListenerInterface * const result_printer = - impl->result_printer(); + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); - result_printer->OnTestCaseStart(this); + repeater->OnTestCaseStart(*this); impl->os_stack_trace_getter()->UponLeavingGTest(); set_up_tc_(); const internal::TimeInMillis start = internal::GetTimeInMillis(); - test_info_list_->ForEach(internal::TestInfoImpl::RunTest); + for (int i = 0; i < total_test_count(); i++) { + GetMutableTestInfo(i)->impl()->Run(); + } elapsed_time_ = internal::GetTimeInMillis() - start; impl->os_stack_trace_getter()->UponLeavingGTest(); tear_down_tc_(); - result_printer->OnTestCaseEnd(this); + repeater->OnTestCaseEnd(*this); impl->set_current_test_case(NULL); } // Clears the results of all tests in this test case. void TestCase::ClearResult() { - test_info_list_->ForEach(internal::TestInfoImpl::ClearTestResult); + ForEach(test_info_list_, internal::TestInfoImpl::ClearTestResult); +} + +// Returns true iff test passed. +bool TestCase::TestPassed(const TestInfo * test_info) { + const internal::TestInfoImpl* const impl = test_info->impl(); + return impl->should_run() && impl->result()->Passed(); } +// Returns true iff test failed. +bool TestCase::TestFailed(const TestInfo * test_info) { + const internal::TestInfoImpl* const impl = test_info->impl(); + return impl->should_run() && impl->result()->Failed(); +} -// class UnitTestEventListenerInterface +// Returns true iff test is disabled. +bool TestCase::TestDisabled(const TestInfo * test_info) { + return test_info->impl()->is_disabled(); +} -// The virtual d'tor. -UnitTestEventListenerInterface::~UnitTestEventListenerInterface() { +// Returns true if the given test should run. +bool TestCase::ShouldRunTest(const TestInfo *test_info) { + return test_info->impl()->should_run(); } -// A result printer that never prints anything. Used in the child process -// of an exec-style death test to avoid needless output clutter. -class NullUnitTestResultPrinter : public UnitTestEventListenerInterface {}; +// Shuffles the tests in this test case. +void TestCase::ShuffleTests(internal::Random* random) { + Shuffle(random, &test_indices_); +} + +// Restores the test order to before the first shuffle. +void TestCase::UnshuffleTests() { + for (size_t i = 0; i < test_indices_.size(); i++) { + test_indices_[i] = static_cast<int>(i); + } +} // Formats a countable noun. Depending on its quantity, either the // singular form or the plural form is used. e.g. @@ -2397,17 +2488,17 @@ static internal::String FormatTestCaseCount(int test_case_count) { return FormatCountableNoun(test_case_count, "test case", "test cases"); } -// Converts a TestPartResultType enum to human-friendly string -// representation. Both TPRT_NONFATAL_FAILURE and TPRT_FATAL_FAILURE -// are translated to "Failure", as the user usually doesn't care about -// the difference between the two when viewing the test result. -static const char * TestPartResultTypeToString(TestPartResultType type) { +// Converts a TestPartResult::Type enum to human-friendly string +// representation. Both kNonFatalFailure and kFatalFailure are translated +// to "Failure", as the user usually doesn't care about the difference +// between the two when viewing the test result. +static const char * TestPartResultTypeToString(TestPartResult::Type type) { switch (type) { - case TPRT_SUCCESS: + case TestPartResult::kSuccess: return "Success"; - case TPRT_NONFATAL_FAILURE: - case TPRT_FATAL_FAILURE: + case TestPartResult::kNonFatalFailure: + case TestPartResult::kFatalFailure: #ifdef _MSC_VER return "error: "; #else @@ -2418,15 +2509,33 @@ static const char * TestPartResultTypeToString(TestPartResultType type) { return "Unknown result type"; } +// Prints a TestPartResult to a String. +static internal::String PrintTestPartResultToString( + const TestPartResult& test_part_result) { + return (Message() + << internal::FormatFileLocation(test_part_result.file_name(), + test_part_result.line_number()) + << " " << TestPartResultTypeToString(test_part_result.type()) + << test_part_result.message()).GetString(); +} + // Prints a TestPartResult. -static void PrintTestPartResult( - const TestPartResult & test_part_result) { - printf("%s %s%s\n", - internal::FormatFileLocation(test_part_result.file_name(), - test_part_result.line_number()).c_str(), - TestPartResultTypeToString(test_part_result.type()), - test_part_result.message()); +static void PrintTestPartResult(const TestPartResult& test_part_result) { + const internal::String& result = + PrintTestPartResultToString(test_part_result); + printf("%s\n", result.c_str()); fflush(stdout); + // If the test program runs in Visual Studio or a debugger, the + // following statements add the test part result message to the Output + // window such that the user can double-click on it to jump to the + // corresponding source code location; otherwise they do nothing. +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + // We don't call OutputDebugString*() on Windows Mobile, as printing + // to stdout is done by OutputDebugString() there already - we don't + // want the same message printed twice. + ::OutputDebugStringA(result.c_str()); + ::OutputDebugStringA("\n"); +#endif } // class PrettyUnitTestResultPrinter @@ -2434,12 +2543,13 @@ static void PrintTestPartResult( namespace internal { enum GTestColor { + COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW }; -#if defined(GTEST_OS_WINDOWS) && !defined(_WIN32_WCE) +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE // Returns the character attribute for the given color. WORD GetColorAttribute(GTestColor color) { @@ -2447,39 +2557,42 @@ WORD GetColorAttribute(GTestColor color) { case COLOR_RED: return FOREGROUND_RED; case COLOR_GREEN: return FOREGROUND_GREEN; case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; + default: return 0; } - return 0; } #else -// Returns the ANSI color code for the given color. +// Returns the ANSI color code for the given color. COLOR_DEFAULT is +// an invalid input. const char* GetAnsiColorCode(GTestColor color) { switch (color) { case COLOR_RED: return "1"; case COLOR_GREEN: return "2"; case COLOR_YELLOW: return "3"; + default: return NULL; }; - return NULL; } -#endif // GTEST_OS_WINDOWS && !_WIN32_WCE +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE // Returns true iff Google Test should use colors in the output. bool ShouldUseColor(bool stdout_is_tty) { const char* const gtest_color = GTEST_FLAG(color).c_str(); if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS // On Windows the TERM variable is usually not set, but the // console there does support colors. return stdout_is_tty; #else // On non-Windows platforms, we rely on the TERM variable. - const char* const term = GetEnv("TERM"); + const char* const term = posix::GetEnv("TERM"); const bool term_supports_color = String::CStringEquals(term, "xterm") || String::CStringEquals(term, "xterm-color") || + String::CStringEquals(term, "xterm-256color") || + String::CStringEquals(term, "linux") || String::CStringEquals(term, "cygwin"); return stdout_is_tty && term_supports_color; #endif // GTEST_OS_WINDOWS @@ -2502,11 +2615,13 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) { va_list args; va_start(args, fmt); -#if defined(_WIN32_WCE) || defined(GTEST_OS_SYMBIAN) || defined(GTEST_OS_ZOS) - static const bool use_color = false; +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + const bool use_color = false; #else - static const bool use_color = ShouldUseColor(isatty(fileno(stdout)) != 0); -#endif // !_WIN32_WCE + static const bool in_color_mode = + ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); + const bool use_color = in_color_mode && (color != COLOR_DEFAULT); +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS // The '!= 0' comparison is necessary to satisfy MSVC 7.1. if (!use_color) { @@ -2515,7 +2630,7 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) { return; } -#if defined(GTEST_OS_WINDOWS) && !defined(_WIN32_WCE) +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); // Gets the current text color. @@ -2523,220 +2638,229 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) { GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); const WORD old_color_attrs = buffer_info.wAttributes; + // We need to flush the stream buffers into the console before each + // SetConsoleTextAttribute call lest it affect the text that is already + // printed but has not yet reached the console. + fflush(stdout); SetConsoleTextAttribute(stdout_handle, GetColorAttribute(color) | FOREGROUND_INTENSITY); vprintf(fmt, args); + fflush(stdout); // Restores the text color. SetConsoleTextAttribute(stdout_handle, old_color_attrs); #else printf("\033[0;3%sm", GetAnsiColorCode(color)); vprintf(fmt, args); printf("\033[m"); // Resets the terminal to default. -#endif // GTEST_OS_WINDOWS && !_WIN32_WCE +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE va_end(args); } -} // namespace internal - -using internal::ColoredPrintf; -using internal::COLOR_RED; -using internal::COLOR_GREEN; -using internal::COLOR_YELLOW; - -// This class implements the UnitTestEventListenerInterface interface. +// This class implements the TestEventListener interface. // // Class PrettyUnitTestResultPrinter is copyable. -class PrettyUnitTestResultPrinter : public UnitTestEventListenerInterface { +class PrettyUnitTestResultPrinter : public TestEventListener { public: PrettyUnitTestResultPrinter() {} static void PrintTestName(const char * test_case, const char * test) { printf("%s.%s", test_case, test); } - // The following methods override what's in the - // UnitTestEventListenerInterface class. - virtual void OnUnitTestStart(const UnitTest * unit_test); - virtual void OnGlobalSetUpStart(const UnitTest*); - virtual void OnTestCaseStart(const TestCase * test_case); - virtual void OnTestCaseEnd(const TestCase * test_case); - virtual void OnTestStart(const TestInfo * test_info); - virtual void OnNewTestPartResult(const TestPartResult * result); - virtual void OnTestEnd(const TestInfo * test_info); - virtual void OnGlobalTearDownStart(const UnitTest*); - virtual void OnUnitTestEnd(const UnitTest * unit_test); + // The following methods override what's in the TestEventListener class. + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} private: + static void PrintFailedTests(const UnitTest& unit_test); + internal::String test_case_name_; }; -// Called before the unit test starts. -void PrettyUnitTestResultPrinter::OnUnitTestStart( - const UnitTest * unit_test) { - const char * const filter = GTEST_FLAG(filter).c_str(); + // Fired before each iteration of tests starts. +void PrettyUnitTestResultPrinter::OnTestIterationStart( + const UnitTest& unit_test, int iteration) { + if (GTEST_FLAG(repeat) != 1) + printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); + + const char* const filter = GTEST_FLAG(filter).c_str(); // Prints the filter if it's not *. This reminds the user that some // tests may be skipped. if (!internal::String::CStringEquals(filter, kUniversalFilter)) { ColoredPrintf(COLOR_YELLOW, - "Note: %s filter = %s\n", GTEST_NAME, filter); + "Note: %s filter = %s\n", GTEST_NAME_, filter); + } + + if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { + ColoredPrintf(COLOR_YELLOW, + "Note: This is test shard %s of %s.\n", + internal::posix::GetEnv(kTestShardIndex), + internal::posix::GetEnv(kTestTotalShards)); + } + + if (GTEST_FLAG(shuffle)) { + ColoredPrintf(COLOR_YELLOW, + "Note: Randomizing tests' orders with a seed of %d .\n", + unit_test.random_seed()); } - const internal::UnitTestImpl* const impl = unit_test->impl(); ColoredPrintf(COLOR_GREEN, "[==========] "); printf("Running %s from %s.\n", - FormatTestCount(impl->test_to_run_count()).c_str(), - FormatTestCaseCount(impl->test_case_to_run_count()).c_str()); + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); fflush(stdout); } -void PrettyUnitTestResultPrinter::OnGlobalSetUpStart(const UnitTest*) { +void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( + const UnitTest& /*unit_test*/) { ColoredPrintf(COLOR_GREEN, "[----------] "); printf("Global test environment set-up.\n"); fflush(stdout); } -void PrettyUnitTestResultPrinter::OnTestCaseStart( - const TestCase * test_case) { - test_case_name_ = test_case->name(); +void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { + test_case_name_ = test_case.name(); const internal::String counts = - FormatCountableNoun(test_case->test_to_run_count(), "test", "tests"); + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); ColoredPrintf(COLOR_GREEN, "[----------] "); printf("%s from %s", counts.c_str(), test_case_name_.c_str()); - if (test_case->comment()[0] == '\0') { + if (test_case.comment()[0] == '\0') { printf("\n"); } else { - printf(", where %s\n", test_case->comment()); + printf(", where %s\n", test_case.comment()); } fflush(stdout); } -void PrettyUnitTestResultPrinter::OnTestCaseEnd( - const TestCase * test_case) { - if (!GTEST_FLAG(print_time)) return; - - test_case_name_ = test_case->name(); - const internal::String counts = - FormatCountableNoun(test_case->test_to_run_count(), "test", "tests"); - ColoredPrintf(COLOR_GREEN, "[----------] "); - printf("%s from %s (%s ms total)\n\n", - counts.c_str(), test_case_name_.c_str(), - internal::StreamableToString(test_case->elapsed_time()).c_str()); - fflush(stdout); -} - -void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo * test_info) { +void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { ColoredPrintf(COLOR_GREEN, "[ RUN ] "); - PrintTestName(test_case_name_.c_str(), test_info->name()); - if (test_info->comment()[0] == '\0') { + PrintTestName(test_case_name_.c_str(), test_info.name()); + if (test_info.comment()[0] == '\0') { printf("\n"); } else { - printf(", where %s\n", test_info->comment()); + printf(", where %s\n", test_info.comment()); } fflush(stdout); } -void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo * test_info) { - if (test_info->result()->Passed()) { +// Called after an assertion failure. +void PrettyUnitTestResultPrinter::OnTestPartResult( + const TestPartResult& result) { + // If the test part succeeded, we don't need to do anything. + if (result.type() == TestPartResult::kSuccess) + return; + + // Print failure message from the assertion (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { + if (test_info.result()->Passed()) { ColoredPrintf(COLOR_GREEN, "[ OK ] "); } else { ColoredPrintf(COLOR_RED, "[ FAILED ] "); } - PrintTestName(test_case_name_.c_str(), test_info->name()); + PrintTestName(test_case_name_.c_str(), test_info.name()); if (GTEST_FLAG(print_time)) { printf(" (%s ms)\n", internal::StreamableToString( - test_info->result()->elapsed_time()).c_str()); + test_info.result()->elapsed_time()).c_str()); } else { printf("\n"); } fflush(stdout); } -// Called after an assertion failure. -void PrettyUnitTestResultPrinter::OnNewTestPartResult( - const TestPartResult * result) { - // If the test part succeeded, we don't need to do anything. - if (result->type() == TPRT_SUCCESS) - return; +void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { + if (!GTEST_FLAG(print_time)) return; - // Print failure message from the assertion (e.g. expected this and got that). - PrintTestPartResult(*result); + test_case_name_ = test_case.name(); + const internal::String counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s (%s ms total)\n\n", + counts.c_str(), test_case_name_.c_str(), + internal::StreamableToString(test_case.elapsed_time()).c_str()); fflush(stdout); } -void PrettyUnitTestResultPrinter::OnGlobalTearDownStart(const UnitTest*) { +void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( + const UnitTest& /*unit_test*/) { ColoredPrintf(COLOR_GREEN, "[----------] "); printf("Global test environment tear-down\n"); fflush(stdout); } -namespace internal { - // Internal helper for printing the list of failed tests. -static void PrintFailedTestsPretty(const UnitTestImpl* impl) { - const int failed_test_count = impl->failed_test_count(); +void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { + const int failed_test_count = unit_test.failed_test_count(); if (failed_test_count == 0) { return; } - for (const internal::ListNode<TestCase*>* node = impl->test_cases()->Head(); - node != NULL; node = node->next()) { - const TestCase* const tc = node->element(); - if (!tc->should_run() || (tc->failed_test_count() == 0)) { + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + const TestCase& test_case = *unit_test.GetTestCase(i); + if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { continue; } - for (const internal::ListNode<TestInfo*>* tinode = - tc->test_info_list().Head(); - tinode != NULL; tinode = tinode->next()) { - const TestInfo* const ti = tinode->element(); - if (!tc->ShouldRunTest(ti) || tc->TestPassed(ti)) { + for (int j = 0; j < test_case.total_test_count(); ++j) { + const TestInfo& test_info = *test_case.GetTestInfo(j); + if (!test_info.should_run() || test_info.result()->Passed()) { continue; } ColoredPrintf(COLOR_RED, "[ FAILED ] "); - printf("%s.%s", ti->test_case_name(), ti->name()); - if (ti->test_case_comment()[0] != '\0' || - ti->comment()[0] != '\0') { - printf(", where %s", ti->test_case_comment()); - if (ti->test_case_comment()[0] != '\0' && - ti->comment()[0] != '\0') { + printf("%s.%s", test_case.name(), test_info.name()); + if (test_case.comment()[0] != '\0' || + test_info.comment()[0] != '\0') { + printf(", where %s", test_case.comment()); + if (test_case.comment()[0] != '\0' && + test_info.comment()[0] != '\0') { printf(" and "); } } - printf("%s\n", ti->comment()); + printf("%s\n", test_info.comment()); } } } -} // namespace internal - -void PrettyUnitTestResultPrinter::OnUnitTestEnd( - const UnitTest * unit_test) { - const internal::UnitTestImpl* const impl = unit_test->impl(); - + void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { ColoredPrintf(COLOR_GREEN, "[==========] "); printf("%s from %s ran.", - FormatTestCount(impl->test_to_run_count()).c_str(), - FormatTestCaseCount(impl->test_case_to_run_count()).c_str()); + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); if (GTEST_FLAG(print_time)) { printf(" (%s ms total)", - internal::StreamableToString(impl->elapsed_time()).c_str()); + internal::StreamableToString(unit_test.elapsed_time()).c_str()); } printf("\n"); ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); - printf("%s.\n", FormatTestCount(impl->successful_test_count()).c_str()); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); - int num_failures = impl->failed_test_count(); - if (!impl->Passed()) { - const int failed_test_count = impl->failed_test_count(); + int num_failures = unit_test.failed_test_count(); + if (!unit_test.Passed()) { + const int failed_test_count = unit_test.failed_test_count(); ColoredPrintf(COLOR_RED, "[ FAILED ] "); printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); - internal::PrintFailedTestsPretty(impl); + PrintFailedTests(unit_test); printf("\n%2d FAILED %s\n", num_failures, num_failures == 1 ? "TEST" : "TESTS"); } - int num_disabled = impl->disabled_test_count(); - if (num_disabled) { + int num_disabled = unit_test.disabled_test_count(); + if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { if (!num_failures) { printf("\n"); // Add a spacer if no FAILURE banner is displayed. } @@ -2751,81 +2875,127 @@ void PrettyUnitTestResultPrinter::OnUnitTestEnd( // End PrettyUnitTestResultPrinter -// class UnitTestEventsRepeater +// class TestEventRepeater // // This class forwards events to other event listeners. -class UnitTestEventsRepeater : public UnitTestEventListenerInterface { +class TestEventRepeater : public TestEventListener { public: - typedef internal::List<UnitTestEventListenerInterface *> Listeners; - typedef internal::ListNode<UnitTestEventListenerInterface *> ListenersNode; - UnitTestEventsRepeater() {} - virtual ~UnitTestEventsRepeater(); - void AddListener(UnitTestEventListenerInterface *listener); - - virtual void OnUnitTestStart(const UnitTest* unit_test); - virtual void OnUnitTestEnd(const UnitTest* unit_test); - virtual void OnGlobalSetUpStart(const UnitTest* unit_test); - virtual void OnGlobalSetUpEnd(const UnitTest* unit_test); - virtual void OnGlobalTearDownStart(const UnitTest* unit_test); - virtual void OnGlobalTearDownEnd(const UnitTest* unit_test); - virtual void OnTestCaseStart(const TestCase* test_case); - virtual void OnTestCaseEnd(const TestCase* test_case); - virtual void OnTestStart(const TestInfo* test_info); - virtual void OnTestEnd(const TestInfo* test_info); - virtual void OnNewTestPartResult(const TestPartResult* result); + TestEventRepeater() : forwarding_enabled_(true) {} + virtual ~TestEventRepeater(); + void Append(TestEventListener *listener); + TestEventListener* Release(TestEventListener* listener); + + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled() const { return forwarding_enabled_; } + void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } + + virtual void OnTestProgramStart(const UnitTest& unit_test); + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& unit_test); private: - Listeners listeners_; + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled_; + // The list of listeners that receive events. + std::vector<TestEventListener*> listeners_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestEventsRepeater); + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); }; -UnitTestEventsRepeater::~UnitTestEventsRepeater() { - for (ListenersNode* listener = listeners_.Head(); - listener != NULL; - listener = listener->next()) { - delete listener->element(); - } +TestEventRepeater::~TestEventRepeater() { + ForEach(listeners_, Delete<TestEventListener>); } -void UnitTestEventsRepeater::AddListener( - UnitTestEventListenerInterface *listener) { - listeners_.PushBack(listener); +void TestEventRepeater::Append(TestEventListener *listener) { + listeners_.push_back(listener); } -// Since the methods are identical, use a macro to reduce boilerplate. -// This defines a member that repeats the call to all listeners. +// TODO(vladl@google.com): Factor the search functionality into Vector::Find. +TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { + for (size_t i = 0; i < listeners_.size(); ++i) { + if (listeners_[i] == listener) { + listeners_.erase(listeners_.begin() + i); + return listener; + } + } + + return NULL; +} + +// Since most methods are very similar, use macros to reduce boilerplate. +// This defines a member that forwards the call to all listeners. #define GTEST_REPEATER_METHOD_(Name, Type) \ -void UnitTestEventsRepeater::Name(const Type* parameter) { \ - for (ListenersNode* listener = listeners_.Head(); \ - listener != NULL; \ - listener = listener->next()) { \ - listener->element()->Name(parameter); \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = 0; i < listeners_.size(); i++) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} +// This defines a member that forwards the call to all listeners in reverse +// order. +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \ + listeners_[i]->Name(parameter); \ + } \ } \ } -GTEST_REPEATER_METHOD_(OnUnitTestStart, UnitTest) -GTEST_REPEATER_METHOD_(OnUnitTestEnd, UnitTest) -GTEST_REPEATER_METHOD_(OnGlobalSetUpStart, UnitTest) -GTEST_REPEATER_METHOD_(OnGlobalSetUpEnd, UnitTest) -GTEST_REPEATER_METHOD_(OnGlobalTearDownStart, UnitTest) -GTEST_REPEATER_METHOD_(OnGlobalTearDownEnd, UnitTest) +GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) +GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) -GTEST_REPEATER_METHOD_(OnTestCaseEnd, TestCase) GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) -GTEST_REPEATER_METHOD_(OnTestEnd, TestInfo) -GTEST_REPEATER_METHOD_(OnNewTestPartResult, TestPartResult) +GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) +GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) +GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) +GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) #undef GTEST_REPEATER_METHOD_ +#undef GTEST_REVERSE_REPEATER_METHOD_ -// End PrettyUnitTestResultPrinter +void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (size_t i = 0; i < listeners_.size(); i++) { + listeners_[i]->OnTestIterationStart(unit_test, iteration); + } + } +} + +void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { + listeners_[i]->OnTestIterationEnd(unit_test, iteration); + } + } +} + +// End TestEventRepeater // This class generates an XML output file. -class XmlUnitTestResultPrinter : public UnitTestEventListenerInterface { +class XmlUnitTestResultPrinter : public EmptyTestEventListener { public: explicit XmlUnitTestResultPrinter(const char* output_file); - virtual void OnUnitTestEnd(const UnitTest* unit_test); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); private: // Is c a whitespace character that is normalized to a space character @@ -2843,39 +3013,41 @@ class XmlUnitTestResultPrinter : public UnitTestEventListenerInterface { // is_attribute is true, the text is meant to appear as an attribute // value, and normalizable whitespace is preserved by replacing it // with character references. - static internal::String EscapeXml(const char* str, - bool is_attribute); + static String EscapeXml(const char* str, bool is_attribute); + + // Returns the given string with all characters invalid in XML removed. + static String RemoveInvalidXmlCharacters(const char* str); // Convenience wrapper around EscapeXml when str is an attribute value. - static internal::String EscapeXmlAttribute(const char* str) { + static String EscapeXmlAttribute(const char* str) { return EscapeXml(str, true); } // Convenience wrapper around EscapeXml when str is not an attribute value. - static internal::String EscapeXmlText(const char* str) { - return EscapeXml(str, false); - } + static String EscapeXmlText(const char* str) { return EscapeXml(str, false); } + + // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. + static void OutputXmlCDataSection(::std::ostream* stream, const char* data); - // Prints an XML representation of a TestInfo object. - static void PrintXmlTestInfo(FILE* out, - const char* test_case_name, - const TestInfo* test_info); + // Streams an XML representation of a TestInfo object. + static void OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info); // Prints an XML representation of a TestCase object - static void PrintXmlTestCase(FILE* out, const TestCase* test_case); + static void PrintXmlTestCase(FILE* out, const TestCase& test_case); // Prints an XML summary of unit_test to output stream out. - static void PrintXmlUnitTest(FILE* out, const UnitTest* unit_test); + static void PrintXmlUnitTest(FILE* out, const UnitTest& unit_test); // Produces a string representing the test properties in a result as space // delimited XML attributes based on the property key="value" pairs. // When the String is not empty, it includes a space at the beginning, // to delimit this attribute from prior attributes. - static internal::String TestPropertiesAsXmlAttributes( - const internal::TestResult* result); + static String TestPropertiesAsXmlAttributes(const TestResult& result); // The output file. - const internal::String output_file_; + const String output_file_; GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); }; @@ -2891,23 +3063,14 @@ XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) } // Called after the unit test ends. -void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest* unit_test) { +void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { FILE* xmlout = NULL; - internal::FilePath output_file(output_file_); - internal::FilePath output_dir(output_file.RemoveFileName()); + FilePath output_file(output_file_); + FilePath output_dir(output_file.RemoveFileName()); if (output_dir.CreateDirectoriesRecursively()) { - // MSVC 8 deprecates fopen(), so we want to suppress warning 4996 - // (deprecated function) there. -#ifdef GTEST_OS_WINDOWS - // We are on Windows. -#pragma warning(push) // Saves the current warning state. -#pragma warning(disable:4996) // Temporarily disables warning 4996. - xmlout = fopen(output_file_.c_str(), "w"); -#pragma warning(pop) // Restores the warning state. -#else // We are on Linux or Mac OS. - xmlout = fopen(output_file_.c_str(), "w"); -#endif // GTEST_OS_WINDOWS + xmlout = posix::FOpen(output_file_.c_str(), "w"); } if (xmlout == NULL) { // TODO(wan): report the reason of the failure. @@ -2942,8 +3105,7 @@ void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest* unit_test) { // most invalid characters can be retained using character references. // TODO(wan): It might be nice to have a minimally invasive, human-readable // escaping scheme for invalid characters, rather than dropping them. -internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str, - bool is_attribute) { +String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) { Message m; if (str != NULL) { @@ -2973,7 +3135,7 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str, default: if (IsValidXmlCharacter(*src)) { if (is_attribute && IsNormalizableWhitespace(*src)) - m << internal::String::Format("&#x%02X;", unsigned(*src)); + m << String::Format("&#x%02X;", unsigned(*src)); else m << *src; } @@ -2985,13 +3147,28 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str, return m.GetString(); } +// Returns the given string with all characters invalid in XML removed. +// Currently invalid characters are dropped from the string. An +// alternative is to replace them with certain characters such as . or ?. +String XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const char* str) { + char* const output = new char[strlen(str) + 1]; + char* appender = output; + for (char ch = *str; ch != '\0'; ch = *++str) + if (IsValidXmlCharacter(ch)) + *appender++ = ch; + *appender = '\0'; + + String ret_value(output); + delete[] output; + return ret_value; +} // The following routines generate an XML representation of a UnitTest // object. // // This is how Google Test concepts map to the DTD: // -// <testsuite name="AllTests"> <-- corresponds to a UnitTest object +// <testsuites name="AllTests"> <-- corresponds to a UnitTest object // <testsuite name="testcase-name"> <-- corresponds to a TestCase object // <testcase name="test-name"> <-- corresponds to a TestInfo object // <failure message="...">...</failure> @@ -3000,118 +3177,122 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str, // <-- individual assertion failures // </testcase> // </testsuite> -// </testsuite> - -namespace internal { - -// Formats the given time in milliseconds as seconds. The returned -// C-string is owned by this function and cannot be released by the -// caller. Calling the function again invalidates the previous -// result. -const char* FormatTimeInMillisAsSeconds(TimeInMillis ms) { - static String str; - str = (Message() << (ms/1000.0)).GetString(); - return str.c_str(); +// </testsuites> + +// Formats the given time in milliseconds as seconds. +std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { + ::std::stringstream ss; + ss << ms/1000.0; + return ss.str(); +} + +// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. +void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, + const char* data) { + const char* segment = data; + *stream << "<![CDATA["; + for (;;) { + const char* const next_segment = strstr(segment, "]]>"); + if (next_segment != NULL) { + stream->write( + segment, static_cast<std::streamsize>(next_segment - segment)); + *stream << "]]>]]><![CDATA["; + segment = next_segment + strlen("]]>"); + } else { + *stream << segment; + break; + } + } + *stream << "]]>"; } -} // namespace internal - // Prints an XML representation of a TestInfo object. // TODO(wan): There is also value in printing properties with the plain printer. -void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out, - const char* test_case_name, - const TestInfo* test_info) { - const internal::TestResult * const result = test_info->result(); - const internal::List<TestPartResult> &results = result->test_part_results(); - fprintf(out, - " <testcase name=\"%s\" status=\"%s\" time=\"%s\" " - "classname=\"%s\"%s", - EscapeXmlAttribute(test_info->name()).c_str(), - test_info->should_run() ? "run" : "notrun", - internal::FormatTimeInMillisAsSeconds(result->elapsed_time()), - EscapeXmlAttribute(test_case_name).c_str(), - TestPropertiesAsXmlAttributes(result).c_str()); +void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info) { + const TestResult& result = *test_info.result(); + *stream << " <testcase name=\"" + << EscapeXmlAttribute(test_info.name()).c_str() + << "\" status=\"" + << (test_info.should_run() ? "run" : "notrun") + << "\" time=\"" + << FormatTimeInMillisAsSeconds(result.elapsed_time()) + << "\" classname=\"" << EscapeXmlAttribute(test_case_name).c_str() + << "\"" << TestPropertiesAsXmlAttributes(result).c_str(); int failures = 0; - for (const internal::ListNode<TestPartResult>* part_node = results.Head(); - part_node != NULL; - part_node = part_node->next()) { - const TestPartResult& part = part_node->element(); + for (int i = 0; i < result.total_part_count(); ++i) { + const TestPartResult& part = result.GetTestPartResult(i); if (part.failed()) { - const internal::String message = - internal::String::Format("%s:%d\n%s", part.file_name(), - part.line_number(), part.message()); if (++failures == 1) - fprintf(out, ">\n"); - fprintf(out, - " <failure message=\"%s\" type=\"\"><![CDATA[%s]]>" - "</failure>\n", - EscapeXmlAttribute(part.summary()).c_str(), message.c_str()); + *stream << ">\n"; + *stream << " <failure message=\"" + << EscapeXmlAttribute(part.summary()).c_str() + << "\" type=\"\">"; + const String message = RemoveInvalidXmlCharacters(String::Format( + "%s:%d\n%s", + part.file_name(), part.line_number(), + part.message()).c_str()); + OutputXmlCDataSection(stream, message.c_str()); + *stream << "</failure>\n"; } } if (failures == 0) - fprintf(out, " />\n"); + *stream << " />\n"; else - fprintf(out, " </testcase>\n"); + *stream << " </testcase>\n"; } // Prints an XML representation of a TestCase object void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out, - const TestCase* test_case) { + const TestCase& test_case) { fprintf(out, " <testsuite name=\"%s\" tests=\"%d\" failures=\"%d\" " "disabled=\"%d\" ", - EscapeXmlAttribute(test_case->name()).c_str(), - test_case->total_test_count(), - test_case->failed_test_count(), - test_case->disabled_test_count()); + EscapeXmlAttribute(test_case.name()).c_str(), + test_case.total_test_count(), + test_case.failed_test_count(), + test_case.disabled_test_count()); fprintf(out, "errors=\"0\" time=\"%s\">\n", - internal::FormatTimeInMillisAsSeconds(test_case->elapsed_time())); - for (const internal::ListNode<TestInfo*>* info_node = - test_case->test_info_list().Head(); - info_node != NULL; - info_node = info_node->next()) { - PrintXmlTestInfo(out, test_case->name(), info_node->element()); + FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str()); + for (int i = 0; i < test_case.total_test_count(); ++i) { + StrStream stream; + OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i)); + fprintf(out, "%s", StrStreamToString(&stream).c_str()); } fprintf(out, " </testsuite>\n"); } // Prints an XML summary of unit_test to output stream out. void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out, - const UnitTest* unit_test) { - const internal::UnitTestImpl* const impl = unit_test->impl(); + const UnitTest& unit_test) { fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fprintf(out, - "<testsuite tests=\"%d\" failures=\"%d\" disabled=\"%d\" " + "<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" " "errors=\"0\" time=\"%s\" ", - impl->total_test_count(), - impl->failed_test_count(), - impl->disabled_test_count(), - internal::FormatTimeInMillisAsSeconds(impl->elapsed_time())); - fprintf(out, "name=\"AllTests\">\n"); - for (const internal::ListNode<TestCase*>* case_node = - impl->test_cases()->Head(); - case_node != NULL; - case_node = case_node->next()) { - PrintXmlTestCase(out, case_node->element()); + unit_test.total_test_count(), + unit_test.failed_test_count(), + unit_test.disabled_test_count(), + FormatTimeInMillisAsSeconds(unit_test.elapsed_time()).c_str()); + if (GTEST_FLAG(shuffle)) { + fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed()); } - fprintf(out, "</testsuite>\n"); + fprintf(out, "name=\"AllTests\">\n"); + for (int i = 0; i < unit_test.total_test_case_count(); ++i) + PrintXmlTestCase(out, *unit_test.GetTestCase(i)); + fprintf(out, "</testsuites>\n"); } // Produces a string representing the test properties in a result as space // delimited XML attributes based on the property key="value" pairs. -internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( - const internal::TestResult* result) { - using internal::TestProperty; +String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( + const TestResult& result) { Message attributes; - const internal::List<TestProperty>& properties = result->test_properties(); - for (const internal::ListNode<TestProperty>* property_node = - properties.Head(); - property_node != NULL; - property_node = property_node->next()) { - const TestProperty& property = property_node->element(); + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); attributes << " " << property.key() << "=" << "\"" << EscapeXmlAttribute(property.value()) << "\""; } @@ -3120,8 +3301,6 @@ internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( // End XmlUnitTestResultPrinter -namespace internal { - // Class ScopedTrace // Pushes the given source file location and message onto a per-thread @@ -3164,10 +3343,85 @@ void OsStackTraceGetter::UponLeavingGTest() { const char* const OsStackTraceGetter::kElidedFramesMarker = - "... " GTEST_NAME " internal frames ..."; + "... " GTEST_NAME_ " internal frames ..."; } // namespace internal +// class TestEventListeners + +TestEventListeners::TestEventListeners() + : repeater_(new internal::TestEventRepeater()), + default_result_printer_(NULL), + default_xml_generator_(NULL) { +} + +TestEventListeners::~TestEventListeners() { delete repeater_; } + +// Returns the standard listener responsible for the default console +// output. Can be removed from the listeners list to shut down default +// console output. Note that removing this object from the listener list +// with Release transfers its ownership to the user. +void TestEventListeners::Append(TestEventListener* listener) { + repeater_->Append(listener); +} + +// Removes the given event listener from the list and returns it. It then +// becomes the caller's responsibility to delete the listener. Returns +// NULL if the listener is not found in the list. +TestEventListener* TestEventListeners::Release(TestEventListener* listener) { + if (listener == default_result_printer_) + default_result_printer_ = NULL; + else if (listener == default_xml_generator_) + default_xml_generator_ = NULL; + return repeater_->Release(listener); +} + +// Returns repeater that broadcasts the TestEventListener events to all +// subscribers. +TestEventListener* TestEventListeners::repeater() { return repeater_; } + +// Sets the default_result_printer attribute to the provided listener. +// The listener is also added to the listener list and previous +// default_result_printer is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { + if (default_result_printer_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_result_printer_); + default_result_printer_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Sets the default_xml_generator attribute to the provided listener. The +// listener is also added to the listener list and previous +// default_xml_generator is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { + if (default_xml_generator_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_xml_generator_); + default_xml_generator_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Controls whether events will be forwarded by the repeater to the +// listeners in the list. +bool TestEventListeners::EventForwardingEnabled() const { + return repeater_->forwarding_enabled(); +} + +void TestEventListeners::SuppressEventForwarding() { + repeater_->set_forwarding_enabled(false); +} + // class UnitTest // Gets the singleton UnitTest object. The first time this method is @@ -3184,13 +3438,88 @@ UnitTest * UnitTest::GetInstance() { // different implementation in this case to bypass the compiler bug. // This implementation makes the compiler happy, at the cost of // leaking the UnitTest object. -#if _MSC_VER == 1310 && !defined(_DEBUG) // MSVC 7.1 and optimized build. + + // CodeGear C++Builder insists on a public destructor for the + // default implementation. Use this implementation to keep good OO + // design with private destructor. + +#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) static UnitTest* const instance = new UnitTest; return instance; #else static UnitTest instance; return &instance; -#endif // _MSC_VER==1310 && !defined(_DEBUG) +#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +} + +// Gets the number of successful test cases. +int UnitTest::successful_test_case_count() const { + return impl()->successful_test_case_count(); +} + +// Gets the number of failed test cases. +int UnitTest::failed_test_case_count() const { + return impl()->failed_test_case_count(); +} + +// Gets the number of all test cases. +int UnitTest::total_test_case_count() const { + return impl()->total_test_case_count(); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTest::test_case_to_run_count() const { + return impl()->test_case_to_run_count(); +} + +// Gets the number of successful tests. +int UnitTest::successful_test_count() const { + return impl()->successful_test_count(); +} + +// Gets the number of failed tests. +int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } + +// Gets the number of disabled tests. +int UnitTest::disabled_test_count() const { + return impl()->disabled_test_count(); +} + +// Gets the number of all tests. +int UnitTest::total_test_count() const { return impl()->total_test_count(); } + +// Gets the number of tests that should run. +int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } + +// Gets the elapsed time, in milliseconds. +internal::TimeInMillis UnitTest::elapsed_time() const { + return impl()->elapsed_time(); +} + +// Returns true iff the unit test passed (i.e. all test cases passed). +bool UnitTest::Passed() const { return impl()->Passed(); } + +// Returns true iff the unit test failed (i.e. some test case failed +// or something outside of all tests failed). +bool UnitTest::Failed() const { return impl()->Failed(); } + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +const TestCase* UnitTest::GetTestCase(int i) const { + return impl()->GetTestCase(i); +} + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +TestCase* UnitTest::GetMutableTestCase(int i) { + return impl()->GetMutableTestCase(i); +} + +// Returns the list of event listeners that can be used to track events +// inside Google Test. +TestEventListeners& UnitTest::listeners() { + return *impl()->listeners(); } // Registers and returns a global test environment. When a test @@ -3208,17 +3537,29 @@ Environment* UnitTest::AddEnvironment(Environment* env) { return NULL; } - impl_->environments()->PushBack(env); - impl_->environments_in_reverse_order()->PushFront(env); + impl_->environments().push_back(env); return env; } +#if GTEST_HAS_EXCEPTIONS +// A failed Google Test assertion will throw an exception of this type +// when exceptions are enabled. We derive it from std::runtime_error, +// which is for errors presumably detectable only at run time. Since +// std::runtime_error inherits from std::exception, many testing +// frameworks know how to extract and print the message inside it. +class GoogleTestFailureException : public ::std::runtime_error { + public: + explicit GoogleTestFailureException(const TestPartResult& failure) + : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} +}; +#endif + // Adds a TestPartResult to the current TestResult object. All Google Test // assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call // this to report their results. The user code should use the // assertion macros instead of calling this directly. // L < mutex_ -void UnitTest::AddTestPartResult(TestPartResultType result_type, +void UnitTest::AddTestPartResult(TestPartResult::Type result_type, const char* file_name, int line_number, const internal::String& message, @@ -3227,15 +3568,14 @@ void UnitTest::AddTestPartResult(TestPartResultType result_type, msg << message; internal::MutexLock lock(&mutex_); - if (impl_->gtest_trace_stack()->size() > 0) { - msg << "\n" << GTEST_NAME << " trace:"; - - for (internal::ListNode<internal::TraceInfo>* node = - impl_->gtest_trace_stack()->Head(); - node != NULL; - node = node->next()) { - const internal::TraceInfo& trace = node->element(); - msg << "\n" << trace.file << ":" << trace.line << ": " << trace.message; + if (impl_->gtest_trace_stack().size() > 0) { + msg << "\n" << GTEST_NAME_ << " trace:"; + + for (int i = static_cast<int>(impl_->gtest_trace_stack().size()); + i > 0; --i) { + const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; + msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) + << " " << trace.message; } } @@ -3249,11 +3589,30 @@ void UnitTest::AddTestPartResult(TestPartResultType result_type, impl_->GetTestPartResultReporterForCurrentThread()-> ReportTestPartResult(result); - // If this is a failure and the user wants the debugger to break on - // failures ... - if (result_type != TPRT_SUCCESS && GTEST_FLAG(break_on_failure)) { - // ... then we generate a seg fault. - *static_cast<int*>(NULL) = 1; + if (result_type != TestPartResult::kSuccess) { + // gtest_break_on_failure takes precedence over + // gtest_throw_on_failure. This allows a user to set the latter + // in the code (perhaps in order to use Google Test assertions + // with another testing framework) and specify the former on the + // command line for debugging. + if (GTEST_FLAG(break_on_failure)) { +#if GTEST_OS_WINDOWS + // Using DebugBreak on Windows allows gtest to still break into a debugger + // when a failure happens and both the --gtest_break_on_failure and + // the --gtest_catch_exceptions flags are specified. + DebugBreak(); +#else + abort(); +#endif // GTEST_OS_WINDOWS + } else if (GTEST_FLAG(throw_on_failure)) { +#if GTEST_HAS_EXCEPTIONS + throw GoogleTestFailureException(result); +#else + // We cannot call abort() as it generates a pop-up in debug mode + // that cannot be suppressed in VC 7.1 or below. + exit(1); +#endif + } } } @@ -3261,7 +3620,7 @@ void UnitTest::AddTestPartResult(TestPartResultType result_type, // the supplied value already exists, updates its value instead. void UnitTest::RecordPropertyForCurrentTest(const char* key, const char* value) { - const internal::TestProperty test_property(key, value); + const TestProperty test_property(key, value); impl_->current_test_result()->RecordProperty(test_property); } @@ -3271,18 +3630,48 @@ void UnitTest::RecordPropertyForCurrentTest(const char* key, // We don't protect this under mutex_, as we only support calling it // from the main thread. int UnitTest::Run() { -#if defined(GTEST_OS_WINDOWS) && !defined(__MINGW32__) - -#if !defined(_WIN32_WCE) - // SetErrorMode doesn't exist on CE. - if (GTEST_FLAG(catch_exceptions)) { - // The user wants Google Test to catch exceptions thrown by the tests. - - // This lets fatal errors be handled by us, instead of causing pop-ups. +#if GTEST_HAS_SEH + // Catch SEH-style exceptions. + + const bool in_death_test_child_process = + internal::GTEST_FLAG(internal_run_death_test).length() > 0; + + // Either the user wants Google Test to catch exceptions thrown by the + // tests or this is executing in the context of death test child + // process. In either case the user does not want to see pop-up dialogs + // about crashes - they are expected.. + if (GTEST_FLAG(catch_exceptions) || in_death_test_child_process) { +#if !GTEST_OS_WINDOWS_MOBILE + // SetErrorMode doesn't exist on CE. SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); +#endif // !GTEST_OS_WINDOWS_MOBILE + +#if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE + // Death test children can be terminated with _abort(). On Windows, + // _abort() can show a dialog with a warning message. This forces the + // abort message to go to stderr instead. + _set_error_mode(_OUT_TO_STDERR); +#endif + +#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program. We need to suppress + // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement + // executed. Google Test will notify the user of any unexpected + // failure via stderr. + // + // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. + // Users of prior VC versions shall suffer the agony and pain of + // clicking through the countless debug dialogs. + // TODO(vladl@google.com): find a way to suppress the abort dialog() in the + // debug mode when compiled with VC 7.1 or lower. + if (!GTEST_FLAG(break_on_failure)) + _set_abort_behavior( + 0x0, // Clear the following flags: + _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. +#endif } -#endif // _WIN32_WCE __try { return impl_->RunAllTests(); @@ -3293,11 +3682,10 @@ int UnitTest::Run() { return 1; } -#else - // We are on Linux, Mac OS or MingW. There is no exception of any kind. +#else // We are on a compiler or platform that doesn't support SEH. return impl_->RunAllTests(); -#endif // GTEST_OS_WINDOWS +#endif // GTEST_HAS_SEH } // Returns the working directory when the first TEST() or TEST_F() was @@ -3322,7 +3710,10 @@ const TestInfo* UnitTest::current_test_info() const { return impl_->current_test_info(); } -#ifdef GTEST_HAS_PARAM_TEST +// Returns the random seed used at the start of the current test run. +int UnitTest::random_seed() const { return impl_->random_seed(); } + +#if GTEST_HAS_PARAM_TEST // Returns ParameterizedTestCaseRegistry object used to keep track of // value-parameterized tests and instantiate and register them. // L < mutex_ @@ -3347,14 +3738,14 @@ UnitTest::~UnitTest() { // L < mutex_ void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) { internal::MutexLock lock(&mutex_); - impl_->gtest_trace_stack()->PushFront(trace); + impl_->gtest_trace_stack().push_back(trace); } // Pops a trace from the per-thread Google Test trace stack. // L < mutex_ void UnitTest::PopGTestTrace() { internal::MutexLock lock(&mutex_); - impl_->gtest_trace_stack()->PopFront(NULL); + impl_->gtest_trace_stack().pop_back(); } namespace internal { @@ -3376,39 +3767,87 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent) &default_global_test_part_result_reporter_), per_thread_test_part_result_reporter_( &default_per_thread_test_part_result_reporter_), - test_cases_(), -#ifdef GTEST_HAS_PARAM_TEST +#if GTEST_HAS_PARAM_TEST parameterized_test_registry_(), parameterized_tests_registered_(false), #endif // GTEST_HAS_PARAM_TEST - last_death_test_case_(NULL), + last_death_test_case_(-1), current_test_case_(NULL), current_test_info_(NULL), ad_hoc_test_result_(), - result_printer_(NULL), os_stack_trace_getter_(NULL), -#ifdef GTEST_HAS_DEATH_TEST + post_flag_parse_init_performed_(false), + random_seed_(0), // Will be overridden by the flag before first use. + random_(0), // Will be reseeded before first use. +#if GTEST_HAS_DEATH_TEST elapsed_time_(0), internal_run_death_test_flag_(NULL), death_test_factory_(new DefaultDeathTestFactory) { #else elapsed_time_(0) { #endif // GTEST_HAS_DEATH_TEST + listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); } UnitTestImpl::~UnitTestImpl() { // Deletes every TestCase. - test_cases_.ForEach(internal::Delete<TestCase>); + ForEach(test_cases_, internal::Delete<TestCase>); // Deletes every Environment. - environments_.ForEach(internal::Delete<Environment>); - - // Deletes the current test result printer. - delete result_printer_; + ForEach(environments_, internal::Delete<Environment>); delete os_stack_trace_getter_; } +#if GTEST_HAS_DEATH_TEST +// Disables event forwarding if the control is currently in a death test +// subprocess. Must not be called before InitGoogleTest. +void UnitTestImpl::SuppressTestEventsIfInSubprocess() { + if (internal_run_death_test_flag_.get() != NULL) + listeners()->SuppressEventForwarding(); +} +#endif // GTEST_HAS_DEATH_TEST + +// Initializes event listeners performing XML output as specified by +// UnitTestOptions. Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureXmlOutput() { + const String& output_format = UnitTestOptions::GetOutputFormat(); + if (output_format == "xml") { + listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); + } else if (output_format != "") { + printf("WARNING: unrecognized output format \"%s\" ignored.\n", + output_format.c_str()); + fflush(stdout); + } +} + +// Performs initialization dependent upon flag values obtained in +// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to +// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest +// this function is also called from RunAllTests. Since this function can be +// called more than once, it has to be idempotent. +void UnitTestImpl::PostFlagParsingInit() { + // Ensures that this function does not execute more than once. + if (!post_flag_parse_init_performed_) { + post_flag_parse_init_performed_ = true; + +#if GTEST_HAS_DEATH_TEST + InitDeathTestSubprocessControlInfo(); + SuppressTestEventsIfInSubprocess(); +#endif // GTEST_HAS_DEATH_TEST + + // Registers parameterized tests. This makes parameterized tests + // available to the UnitTest reflection API without running + // RUN_ALL_TESTS. + RegisterParameterizedTests(); + + // Configures listeners for XML output. This makes it possible for users + // to shut down the default XML output before invoking RUN_ALL_TESTS. + ConfigureXmlOutput(); + } +} + // A predicate that checks the name of a TestCase against a known // value. // @@ -3433,7 +3872,9 @@ class TestCaseNameIs { }; // Finds and returns a TestCase with the given name. If one doesn't -// exist, creates one and returns it. +// exist, creates one and returns it. It's the CALLER'S +// RESPONSIBILITY to ensure that this function is only called WHEN THE +// TESTS ARE NOT SHUFFLED. // // Arguments: // @@ -3445,34 +3886,38 @@ TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc) { // Can we find a TestCase with the given name? - internal::ListNode<TestCase*>* node = test_cases_.FindIf( - TestCaseNameIs(test_case_name)); + const std::vector<TestCase*>::const_iterator test_case = + std::find_if(test_cases_.begin(), test_cases_.end(), + TestCaseNameIs(test_case_name)); + + if (test_case != test_cases_.end()) + return *test_case; - if (node == NULL) { - // No. Let's create one. - TestCase* const test_case = + // No. Let's create one. + TestCase* const new_test_case = new TestCase(test_case_name, comment, set_up_tc, tear_down_tc); - // Is this a death test case? - if (internal::UnitTestOptions::MatchesFilter(String(test_case_name), - kDeathTestCaseFilter)) { - // Yes. Inserts the test case after the last death test case - // defined so far. - node = test_cases_.InsertAfter(last_death_test_case_, test_case); - last_death_test_case_ = node; - } else { - // No. Appends to the end of the list. - test_cases_.PushBack(test_case); - node = test_cases_.Last(); - } + // Is this a death test case? + if (internal::UnitTestOptions::MatchesFilter(String(test_case_name), + kDeathTestCaseFilter)) { + // Yes. Inserts the test case after the last death test case + // defined so far. This only works when the test cases haven't + // been shuffled. Otherwise we may end up running a death test + // after a non-death test. + ++last_death_test_case_; + test_cases_.insert(test_cases_.begin() + last_death_test_case_, + new_test_case); + } else { + // No. Appends to the end of the list. + test_cases_.push_back(new_test_case); } - // Returns the TestCase found. - return node->element(); + test_case_indices_.push_back(static_cast<int>(test_case_indices_.size())); + return new_test_case; } // Helpers for setting up / tearing down the given environment. They -// are for use in the List::ForEach() method. +// are for use in the ForEach() function. static void SetUpEnvironment(Environment* env) { env->SetUp(); } static void TearDownEnvironment(Environment* env) { env->TearDown(); } @@ -3482,7 +3927,7 @@ static void TearDownEnvironment(Environment* env) { env->TearDown(); } // considered to be failed, but the rest of the tests will still be // run. (We disable exceptions on Linux and Mac OS X, so the issue // doesn't apply there.) -// When parameterized tests are enabled, it explands and registers +// When parameterized tests are enabled, it expands and registers // parameterized tests first in RegisterParameterizedTests(). // All other functions called from RunAllTests() may safely assume that // parameterized tests are ready to be counted and run. @@ -3495,189 +3940,300 @@ int UnitTestImpl::RunAllTests() { return 1; } - RegisterParameterizedTests(); - - // Lists all the tests and exits if the --gtest_list_tests - // flag was specified. - if (GTEST_FLAG(list_tests)) { - ListAllTests(); + // Do not run any test if the --help flag was specified. + if (g_help_flag) return 0; - } + + // Repeats the call to the post-flag parsing initialization in case the + // user didn't call InitGoogleTest. + PostFlagParsingInit(); + + // Even if sharding is not on, test runners may want to use the + // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding + // protocol. + internal::WriteToShardStatusFileIfNeeded(); // True iff we are in a subprocess for running a thread-safe-style // death test. bool in_subprocess_for_death_test = false; -#ifdef GTEST_HAS_DEATH_TEST - internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); +#if GTEST_HAS_DEATH_TEST in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); #endif // GTEST_HAS_DEATH_TEST - UnitTestEventListenerInterface * const printer = result_printer(); + const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, + in_subprocess_for_death_test); // Compares the full test names with the filter to decide which // tests to run. - const bool has_tests_to_run = FilterTests() > 0; + const bool has_tests_to_run = FilterTests(should_shard + ? HONOR_SHARDING_PROTOCOL + : IGNORE_SHARDING_PROTOCOL) > 0; + + // Lists the tests and exits if the --gtest_list_tests flag was specified. + if (GTEST_FLAG(list_tests)) { + // This must be called *after* FilterTests() has been called. + ListTestsMatchingFilter(); + return 0; + } + + random_seed_ = GTEST_FLAG(shuffle) ? + GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; + // True iff at least one test has failed. bool failed = false; + TestEventListener* repeater = listeners()->repeater(); + + repeater->OnTestProgramStart(*parent_); + // How many times to repeat the tests? We don't want to repeat them // when we are inside the subprocess of a death test. const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); // Repeats forever if the repeat count is negative. const bool forever = repeat < 0; for (int i = 0; forever || i != repeat; i++) { - if (repeat != 1) { - printf("\nRepeating all tests (iteration %d) . . .\n\n", i + 1); - } - - // Tells the unit test event listener that the tests are about to - // start. - printer->OnUnitTestStart(parent_); + ClearResult(); const TimeInMillis start = GetTimeInMillis(); + // Shuffles test cases and tests if requested. + if (has_tests_to_run && GTEST_FLAG(shuffle)) { + random()->Reseed(random_seed_); + // This should be done before calling OnTestIterationStart(), + // such that a test event listener can see the actual test order + // in the event. + ShuffleTests(); + } + + // Tells the unit test event listeners that the tests are about to start. + repeater->OnTestIterationStart(*parent_, i); + // Runs each test case if there is at least one test to run. if (has_tests_to_run) { // Sets up all environments beforehand. - printer->OnGlobalSetUpStart(parent_); - environments_.ForEach(SetUpEnvironment); - printer->OnGlobalSetUpEnd(parent_); + repeater->OnEnvironmentsSetUpStart(*parent_); + ForEach(environments_, SetUpEnvironment); + repeater->OnEnvironmentsSetUpEnd(*parent_); // Runs the tests only if there was no fatal failure during global // set-up. if (!Test::HasFatalFailure()) { - test_cases_.ForEach(TestCase::RunTestCase); + for (int test_index = 0; test_index < total_test_case_count(); + test_index++) { + GetMutableTestCase(test_index)->Run(); + } } // Tears down all environments in reverse order afterwards. - printer->OnGlobalTearDownStart(parent_); - environments_in_reverse_order_.ForEach(TearDownEnvironment); - printer->OnGlobalTearDownEnd(parent_); + repeater->OnEnvironmentsTearDownStart(*parent_); + std::for_each(environments_.rbegin(), environments_.rend(), + TearDownEnvironment); + repeater->OnEnvironmentsTearDownEnd(*parent_); } elapsed_time_ = GetTimeInMillis() - start; - // Tells the unit test event listener that the tests have just - // finished. - printer->OnUnitTestEnd(parent_); + // Tells the unit test event listener that the tests have just finished. + repeater->OnTestIterationEnd(*parent_, i); // Gets the result and clears it. if (!Passed()) { failed = true; } - ClearResult(); + + // Restores the original test order after the iteration. This + // allows the user to quickly repro a failure that happens in the + // N-th iteration without repeating the first (N - 1) iterations. + // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in + // case the user somehow changes the value of the flag somewhere + // (it's always safe to unshuffle the tests). + UnshuffleTests(); + + if (GTEST_FLAG(shuffle)) { + // Picks a new random seed for each iteration. + random_seed_ = GetNextRandomSeed(random_seed_); + } } + repeater->OnTestProgramEnd(*parent_); + // Returns 0 if all tests passed, or 1 other wise. return failed ? 1 : 0; } +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded() { + const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); + if (test_shard_file != NULL) { + FILE* const file = posix::FOpen(test_shard_file, "w"); + if (file == NULL) { + ColoredPrintf(COLOR_RED, + "Could not write to the test shard status file \"%s\" " + "specified by the %s environment variable.\n", + test_shard_file, kTestShardStatusFile); + fflush(stdout); + exit(EXIT_FAILURE); + } + fclose(file); + } +} + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (i.e., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +bool ShouldShard(const char* total_shards_env, + const char* shard_index_env, + bool in_subprocess_for_death_test) { + if (in_subprocess_for_death_test) { + return false; + } + + const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); + const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); + + if (total_shards == -1 && shard_index == -1) { + return false; + } else if (total_shards == -1 && shard_index != -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestShardIndex << " = " << shard_index + << ", but have left " << kTestTotalShards << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (total_shards != -1 && shard_index == -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestTotalShards << " = " << total_shards + << ", but have left " << kTestShardIndex << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (shard_index < 0 || shard_index >= total_shards) { + const Message msg = Message() + << "Invalid environment variables: we require 0 <= " + << kTestShardIndex << " < " << kTestTotalShards + << ", but you have " << kTestShardIndex << "=" << shard_index + << ", " << kTestTotalShards << "=" << total_shards << ".\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } + + return total_shards > 1; +} + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error +// and aborts. +Int32 Int32FromEnvOrDie(const char* const var, Int32 default_val) { + const char* str_val = posix::GetEnv(var); + if (str_val == NULL) { + return default_val; + } + + Int32 result; + if (!ParseInt32(Message() << "The value of environment variable " << var, + str_val, &result)) { + exit(EXIT_FAILURE); + } + return result; +} + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { + return (test_id % total_shards) == shard_index; +} + // Compares the name of each test with the user-specified filter to // decide whether the test should be run, then records the result in // each TestCase and TestInfo object. +// If shard_tests == true, further filters tests based on sharding +// variables in the environment - see +// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. // Returns the number of tests that should run. -int UnitTestImpl::FilterTests() { +int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { + const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestTotalShards, -1) : -1; + const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestShardIndex, -1) : -1; + + // num_runnable_tests are the number of tests that will + // run across all shards (i.e., match filter and are not disabled). + // num_selected_tests are the number of tests to be run on + // this shard. int num_runnable_tests = 0; - for (const internal::ListNode<TestCase *> *test_case_node = - test_cases_.Head(); - test_case_node != NULL; - test_case_node = test_case_node->next()) { - TestCase * const test_case = test_case_node->element(); + int num_selected_tests = 0; + for (size_t i = 0; i < test_cases_.size(); i++) { + TestCase* const test_case = test_cases_[i]; const String &test_case_name = test_case->name(); test_case->set_should_run(false); - for (const internal::ListNode<TestInfo *> *test_info_node = - test_case->test_info_list().Head(); - test_info_node != NULL; - test_info_node = test_info_node->next()) { - TestInfo * const test_info = test_info_node->element(); + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + TestInfo* const test_info = test_case->test_info_list()[j]; const String test_name(test_info->name()); // A test is disabled if test case name or test name matches // kDisableTestFilter. const bool is_disabled = - internal::UnitTestOptions::MatchesFilter(test_case_name, - kDisableTestFilter) || - internal::UnitTestOptions::MatchesFilter(test_name, - kDisableTestFilter); + internal::UnitTestOptions::MatchesFilter(test_case_name, + kDisableTestFilter) || + internal::UnitTestOptions::MatchesFilter(test_name, + kDisableTestFilter); test_info->impl()->set_is_disabled(is_disabled); - const bool should_run = !is_disabled && + const bool matches_filter = internal::UnitTestOptions::FilterMatchesTest(test_case_name, test_name); - test_info->impl()->set_should_run(should_run); - test_case->set_should_run(test_case->should_run() || should_run); - if (should_run) { - num_runnable_tests++; - } - } - } - return num_runnable_tests; -} + test_info->impl()->set_matches_filter(matches_filter); -// Lists all tests by name. -void UnitTestImpl::ListAllTests() { - for (const internal::ListNode<TestCase*>* test_case_node = test_cases_.Head(); - test_case_node != NULL; - test_case_node = test_case_node->next()) { - const TestCase* const test_case = test_case_node->element(); + const bool is_runnable = + (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && + matches_filter; - // Prints the test case name following by an indented list of test nodes. - printf("%s.\n", test_case->name()); + const bool is_selected = is_runnable && + (shard_tests == IGNORE_SHARDING_PROTOCOL || + ShouldRunTestOnShard(total_shards, shard_index, + num_runnable_tests)); - for (const internal::ListNode<TestInfo*>* test_info_node = - test_case->test_info_list().Head(); - test_info_node != NULL; - test_info_node = test_info_node->next()) { - const TestInfo* const test_info = test_info_node->element(); + num_runnable_tests += is_runnable; + num_selected_tests += is_selected; - printf(" %s\n", test_info->name()); + test_info->impl()->set_should_run(is_selected); + test_case->set_should_run(test_case->should_run() || is_selected); } } - fflush(stdout); -} - -// Sets the unit test result printer. -// -// Does nothing if the input and the current printer object are the -// same; otherwise, deletes the old printer object and makes the -// input the current printer. -void UnitTestImpl::set_result_printer( - UnitTestEventListenerInterface* result_printer) { - if (result_printer_ != result_printer) { - delete result_printer_; - result_printer_ = result_printer; - } -} - -// Returns the current unit test result printer if it is not NULL; -// otherwise, creates an appropriate result printer, makes it the -// current printer, and returns it. -UnitTestEventListenerInterface* UnitTestImpl::result_printer() { - if (result_printer_ != NULL) { - return result_printer_; - } - -#ifdef GTEST_HAS_DEATH_TEST - if (internal_run_death_test_flag_.get() != NULL) { - result_printer_ = new NullUnitTestResultPrinter; - return result_printer_; - } -#endif // GTEST_HAS_DEATH_TEST - - UnitTestEventsRepeater *repeater = new UnitTestEventsRepeater; - const String& output_format = internal::UnitTestOptions::GetOutputFormat(); - if (output_format == "xml") { - repeater->AddListener(new XmlUnitTestResultPrinter( - internal::UnitTestOptions::GetOutputFile().c_str())); - } else if (output_format != "") { - printf("WARNING: unrecognized output format \"%s\" ignored.\n", - output_format.c_str()); - fflush(stdout); + return num_selected_tests; +} + +// Prints the names of the tests matching the user-specified filter flag. +void UnitTestImpl::ListTestsMatchingFilter() { + for (size_t i = 0; i < test_cases_.size(); i++) { + const TestCase* const test_case = test_cases_[i]; + bool printed_test_case_name = false; + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + const TestInfo* const test_info = + test_case->test_info_list()[j]; + if (test_info->matches_filter()) { + if (!printed_test_case_name) { + printed_test_case_name = true; + printf("%s.\n", test_case->name()); + } + printf(" %s\n", test_info->name()); + } + } } - repeater->AddListener(new PrettyUnitTestResultPrinter); - result_printer_ = repeater; - return result_printer_; + fflush(stdout); } // Sets the OS stack trace getter. @@ -3706,28 +4262,55 @@ OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { // Returns the TestResult for the test that's currently running, or // the TestResult for the ad hoc test if no test is running. -internal::TestResult* UnitTestImpl::current_test_result() { +TestResult* UnitTestImpl::current_test_result() { return current_test_info_ ? current_test_info_->impl()->result() : &ad_hoc_test_result_; } +// Shuffles all test cases, and the tests within each test case, +// making sure that death tests are still run first. +void UnitTestImpl::ShuffleTests() { + // Shuffles the death test cases. + ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); + + // Shuffles the non-death test cases. + ShuffleRange(random(), last_death_test_case_ + 1, + static_cast<int>(test_cases_.size()), &test_case_indices_); + + // Shuffles the tests inside each test case. + for (size_t i = 0; i < test_cases_.size(); i++) { + test_cases_[i]->ShuffleTests(random()); + } +} + +// Restores the test cases and tests to their order before the first shuffle. +void UnitTestImpl::UnshuffleTests() { + for (size_t i = 0; i < test_cases_.size(); i++) { + // Unshuffles the tests in each test case. + test_cases_[i]->UnshuffleTests(); + // Resets the index of each test case. + test_case_indices_[i] = static_cast<int>(i); + } +} + // TestInfoImpl constructor. The new instance assumes ownership of the test // factory object. TestInfoImpl::TestInfoImpl(TestInfo* parent, - const char* test_case_name, - const char* name, - const char* test_case_comment, - const char* comment, - TypeId fixture_class_id, + const char* a_test_case_name, + const char* a_name, + const char* a_test_case_comment, + const char* a_comment, + TypeId a_fixture_class_id, internal::TestFactoryBase* factory) : parent_(parent), - test_case_name_(String(test_case_name)), - name_(String(name)), - test_case_comment_(String(test_case_comment)), - comment_(String(comment)), - fixture_class_id_(fixture_class_id), + test_case_name_(String(a_test_case_name)), + name_(String(a_name)), + test_case_comment_(String(a_test_case_comment)), + comment_(String(a_comment)), + fixture_class_id_(a_fixture_class_id), should_run_(false), is_disabled_(false), + matches_filter_(false), factory_(factory) { } @@ -3746,15 +4329,41 @@ TestInfoImpl::~TestInfoImpl() { // For example, if Foo() calls Bar(), which in turn calls // GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in // the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. -String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test, int skip_count) { +String GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, + int skip_count) { // We pass skip_count + 1 to skip this wrapper function in addition // to what the user really wants to skip. - return unit_test->impl()->CurrentOsStackTraceExceptTop(skip_count + 1); + return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); } -// Returns the number of failed test parts in the given test result object. -int GetFailedPartCount(const TestResult* result) { - return result->failed_part_count(); +// Used by the GTEST_HIDE_UNREACHABLE_CODE_ macro to suppress unreachable +// code warnings. +namespace { +class ClassUniqueToAlwaysTrue {}; +} + +bool IsTrue(bool condition) { return condition; } + +bool AlwaysTrue() { +#if GTEST_HAS_EXCEPTIONS + // This condition is always false so AlwaysTrue() never actually throws, + // but it makes the compiler think that it may throw. + if (IsTrue(false)) + throw ClassUniqueToAlwaysTrue(); +#endif // GTEST_HAS_EXCEPTIONS + return true; +} + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr) { + const size_t prefix_len = strlen(prefix); + if (strncmp(*pstr, prefix, prefix_len) == 0) { + *pstr += prefix_len; + return true; + } + return false; } // Parses a string as a command line flag. The string should have @@ -3768,9 +4377,9 @@ const char* ParseFlagValue(const char* str, // str and flag must not be NULL. if (str == NULL || flag == NULL) return NULL; - // The flag must start with "--" followed by GTEST_FLAG_PREFIX. - const String flag_str = String::Format("--%s%s", GTEST_FLAG_PREFIX, flag); - const size_t flag_len = flag_str.GetLength(); + // The flag must start with "--" followed by GTEST_FLAG_PREFIX_. + const String flag_str = String::Format("--%s%s", GTEST_FLAG_PREFIX_, flag); + const size_t flag_len = flag_str.length(); if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; // Skips the flag name. @@ -3846,6 +4455,127 @@ bool ParseStringFlag(const char* str, const char* flag, String* value) { return true; } +// Determines whether a string has a prefix that Google Test uses for its +// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. +// If Google Test detects that a command line flag has its prefix but is not +// recognized, it will print its help message. Flags starting with +// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test +// internal flags and do not trigger the help message. +static bool HasGoogleTestFlagPrefix(const char* str) { + return (SkipPrefix("--", &str) || + SkipPrefix("-", &str) || + SkipPrefix("/", &str)) && + !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && + (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || + SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); +} + +// Prints a string containing code-encoded text. The following escape +// sequences can be used in the string to control the text color: +// +// @@ prints a single '@' character. +// @R changes the color to red. +// @G changes the color to green. +// @Y changes the color to yellow. +// @D changes to the default terminal text color. +// +// TODO(wan@google.com): Write tests for this once we add stdout +// capturing to Google Test. +static void PrintColorEncoded(const char* str) { + GTestColor color = COLOR_DEFAULT; // The current color. + + // Conceptually, we split the string into segments divided by escape + // sequences. Then we print one segment at a time. At the end of + // each iteration, the str pointer advances to the beginning of the + // next segment. + for (;;) { + const char* p = strchr(str, '@'); + if (p == NULL) { + ColoredPrintf(color, "%s", str); + return; + } + + ColoredPrintf(color, "%s", String(str, p - str).c_str()); + + const char ch = p[1]; + str = p + 2; + if (ch == '@') { + ColoredPrintf(color, "@"); + } else if (ch == 'D') { + color = COLOR_DEFAULT; + } else if (ch == 'R') { + color = COLOR_RED; + } else if (ch == 'G') { + color = COLOR_GREEN; + } else if (ch == 'Y') { + color = COLOR_YELLOW; + } else { + --str; + } + } +} + +static const char kColorEncodedHelpMessage[] = +"This program contains tests written using " GTEST_NAME_ ". You can use the\n" +"following command line flags to control its behavior:\n" +"\n" +"Test Selection:\n" +" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" +" List the names of all tests instead of running them. The name of\n" +" TEST(Foo, Bar) is \"Foo.Bar\".\n" +" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" + "[@G-@YNEGATIVE_PATTERNS]@D\n" +" Run only the tests whose name matches one of the positive patterns but\n" +" none of the negative patterns. '?' matches any single character; '*'\n" +" matches any substring; ':' separates two patterns.\n" +" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" +" Run all disabled tests too.\n" +"\n" +"Test Execution:\n" +" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" +" Run the tests repeatedly; use a negative count to repeat forever.\n" +" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" +" Randomize tests' orders on every iteration.\n" +" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" +" Random number seed to use for shuffling test orders (between 1 and\n" +" 99999, or 0 to use a seed based on the current time).\n" +"\n" +"Test Output:\n" +" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" +" Enable/disable colored output. The default is @Gauto@D.\n" +" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" +" Don't print the elapsed time of each test.\n" +" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" + GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" +" Generate an XML report in the given directory or with the given file\n" +" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" +"\n" +"Assertion Behavior:\n" +#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" +" Set the default death test style.\n" +#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" +" Turn assertion failures into debugger break-points.\n" +" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" +" Turn assertion failures into C++ exceptions.\n" +#if GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions@D\n" +" Suppress pop-ups caused by exceptions.\n" +#endif // GTEST_OS_WINDOWS +"\n" +"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " + "the corresponding\n" +"environment variable of a flag (all letters in upper-case). For example, to\n" +"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ + "color=no@D or set\n" +"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" +"\n" +"For more information, please read the " GTEST_NAME_ " documentation at\n" +"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" +"(not one in your own code or tests), please report it to\n" +"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; + // Parses the command line for Google Test flags, without initializing // other parts of Google Test. The type parameter CharType can be // instantiated to either char or wchar_t. @@ -3860,20 +4590,29 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { using internal::ParseStringFlag; // Do we see a Google Test flag? - if (ParseBoolFlag(arg, kBreakOnFailureFlag, + if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, + >EST_FLAG(also_run_disabled_tests)) || + ParseBoolFlag(arg, kBreakOnFailureFlag, >EST_FLAG(break_on_failure)) || ParseBoolFlag(arg, kCatchExceptionsFlag, >EST_FLAG(catch_exceptions)) || ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || ParseStringFlag(arg, kDeathTestStyleFlag, >EST_FLAG(death_test_style)) || + ParseBoolFlag(arg, kDeathTestUseFork, + >EST_FLAG(death_test_use_fork)) || ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || ParseStringFlag(arg, kInternalRunDeathTestFlag, >EST_FLAG(internal_run_death_test)) || ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || - ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) + ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || + ParseInt32Flag(arg, kStackTraceDepthFlag, + >EST_FLAG(stack_trace_depth)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, >EST_FLAG(throw_on_failure)) ) { // Yes. Shift the remainder of the argv list left by one. Note // that argv has (*argc + 1) elements, the last one always being @@ -3889,8 +4628,21 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { // We also need to decrement the iterator as we just removed // an element. i--; + } else if (arg_string == "--help" || arg_string == "-h" || + arg_string == "-?" || arg_string == "/?" || + HasGoogleTestFlagPrefix(arg)) { + // Both help flag and unrecognized Google Test flags (excluding + // internal ones) trigger help display. + g_help_flag = true; } } + + if (g_help_flag) { + // We print the help here instead of in RUN_ALL_TESTS(), as the + // latter may not be called at all if the user is using Google + // Test with another testing framework. + PrintColorEncoded(kColorEncodedHelpMessage); + } } // Parses the command line for Google Test flags, without initializing @@ -3917,7 +4669,7 @@ void InitGoogleTestImpl(int* argc, CharType** argv) { internal::g_executable_path = internal::StreamableToString(argv[0]); -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST g_argvs.clear(); for (int i = 0; i != *argc; i++) { g_argvs.push_back(StreamableToString(argv[i])); @@ -3925,6 +4677,7 @@ void InitGoogleTestImpl(int* argc, CharType** argv) { #endif // GTEST_HAS_DEATH_TEST ParseGoogleTestFlagsOnly(argc, argv); + GetUnitTestImpl()->PostFlagParsingInit(); } } // namespace internal diff --git a/utils/unittest/googletest/include/gtest/gtest-death-test.h b/utils/unittest/googletest/include/gtest/gtest-death-test.h index f0e109a3..121dc1f 100644 --- a/utils/unittest/googletest/include/gtest/gtest-death-test.h +++ b/utils/unittest/googletest/include/gtest/gtest-death-test.h @@ -49,7 +49,7 @@ namespace testing { // after forking. GTEST_DECLARE_string_(death_test_style); -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST // The following macros are useful for writing death tests. @@ -86,6 +86,57 @@ GTEST_DECLARE_string_(death_test_style); // // ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); // +// On the regular expressions used in death tests: +// +// On POSIX-compliant systems (*nix), we use the <regex.h> library, +// which uses the POSIX extended regex syntax. +// +// On other platforms (e.g. Windows), we only support a simple regex +// syntax implemented as part of Google Test. This limited +// implementation should be enough most of the time when writing +// death tests; though it lacks many features you can find in PCRE +// or POSIX extended regex syntax. For example, we don't support +// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and +// repetition count ("x{5,7}"), among others. +// +// Below is the syntax that we do support. We chose it to be a +// subset of both PCRE and POSIX extended regex, so it's easy to +// learn wherever you come from. In the following: 'A' denotes a +// literal character, period (.), or a single \\ escape sequence; +// 'x' and 'y' denote regular expressions; 'm' and 'n' are for +// natural numbers. +// +// c matches any literal character c +// \\d matches any decimal digit +// \\D matches any character that's not a decimal digit +// \\f matches \f +// \\n matches \n +// \\r matches \r +// \\s matches any ASCII whitespace, including \n +// \\S matches any character that's not a whitespace +// \\t matches \t +// \\v matches \v +// \\w matches any letter, _, or decimal digit +// \\W matches any character that \\w doesn't match +// \\c matches any literal character c, which must be a punctuation +// . matches any single character except \n +// A? matches 0 or 1 occurrences of A +// A* matches 0 or many occurrences of A +// A+ matches 1 or many occurrences of A +// ^ matches the beginning of a string (not that of each line) +// $ matches the end of a string (not that of each line) +// xy matches x followed by y +// +// If you accidentally use PCRE or POSIX extended regex features +// not implemented by us, you will get a run-time failure. In that +// case, please try to rewrite your regular expression within the +// above syntax. +// +// This implementation is *not* meant to be as highly tuned or robust +// as a compiled regex library, but should perform well enough for a +// death test, which already incurs significant overhead by launching +// a child process. +// // Known caveats: // // A "threadsafe" style death test obtains the path to the test @@ -125,23 +176,28 @@ GTEST_DECLARE_string_(death_test_style); // Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: // Tests that an exit code describes a normal exit with a given exit code. -class ExitedWithCode { +class GTEST_API_ ExitedWithCode { public: explicit ExitedWithCode(int exit_code); bool operator()(int exit_status) const; private: + // No implementation - assignment is unsupported. + void operator=(const ExitedWithCode& other); + const int exit_code_; }; +#if !GTEST_OS_WINDOWS // Tests that an exit code describes an exit due to termination by a // given signal. -class KilledBySignal { +class GTEST_API_ KilledBySignal { public: explicit KilledBySignal(int signum); bool operator()(int exit_status) const; private: const int signum_; }; +#endif // !GTEST_OS_WINDOWS // EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. // The death testing framework causes this to have interesting semantics, @@ -189,10 +245,10 @@ class KilledBySignal { #ifdef NDEBUG #define EXPECT_DEBUG_DEATH(statement, regex) \ - do { statement; } while (false) + do { statement; } while (::testing::internal::AlwaysFalse()) #define ASSERT_DEBUG_DEATH(statement, regex) \ - do { statement; } while (false) + do { statement; } while (::testing::internal::AlwaysFalse()) #else @@ -204,6 +260,24 @@ class KilledBySignal { #endif // NDEBUG for EXPECT_DEBUG_DEATH #endif // GTEST_HAS_DEATH_TEST + +// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and +// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if +// death tests are supported; otherwise they just issue a warning. This is +// useful when you are combining death test assertions with normal test +// assertions in one test. +#if GTEST_HAS_DEATH_TEST +#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + EXPECT_DEATH(statement, regex) +#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + ASSERT_DEATH(statement, regex) +#else +#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) +#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) +#endif + } // namespace testing #endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ diff --git a/utils/unittest/googletest/include/gtest/gtest-message.h b/utils/unittest/googletest/include/gtest/gtest-message.h index 7effd08..f135b69 100644 --- a/utils/unittest/googletest/include/gtest/gtest-message.h +++ b/utils/unittest/googletest/include/gtest/gtest-message.h @@ -46,6 +46,8 @@ #ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ #define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#include <limits> + #include <gtest/internal/gtest-string.h> #include <gtest/internal/gtest-internal.h> @@ -77,7 +79,7 @@ namespace testing { // latter (it causes an access violation if you do). The Message // class hides this difference by treating a NULL char pointer as // "(null)". -class Message { +class GTEST_API_ Message { private: // The type of basic IO manipulators (endl, ends, and flush) for // narrow streams. @@ -89,7 +91,11 @@ class Message { // ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's // stack frame leading to huge stack frames in some cases; gcc does not reuse // the stack space. - Message() : ss_(new internal::StrStream) {} + Message() : ss_(new internal::StrStream) { + // By default, we want there to be enough precision when printing + // a double to a Message. + *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2); + } // Copy constructor. Message(const Message& msg) : ss_(new internal::StrStream) { // NOLINT @@ -102,7 +108,7 @@ class Message { } ~Message() { delete ss_; } -#ifdef GTEST_OS_SYMBIAN +#if GTEST_OS_SYMBIAN // Streams a value (either a pointer or not) to this object. template <typename T> inline Message& operator <<(const T& value) { @@ -187,13 +193,13 @@ class Message { } private: -#ifdef GTEST_OS_SYMBIAN +#if GTEST_OS_SYMBIAN // These are needed as the Nokia Symbian Compiler cannot decide between // const T& and const T* in a function template. The Nokia compiler _can_ // decide between class template specializations for T and T*, so a // tr1::type_traits-like is_pointer works, and we can overload on that. template <typename T> - inline void StreamHelper(internal::true_type dummy, T* pointer) { + inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) { if (pointer == NULL) { *ss_ << "(null)"; } else { @@ -201,7 +207,7 @@ class Message { } } template <typename T> - inline void StreamHelper(internal::false_type dummy, const T& value) { + inline void StreamHelper(internal::false_type /*dummy*/, const T& value) { ::GTestStreamToHelper(ss_, value); } #endif // GTEST_OS_SYMBIAN diff --git a/utils/unittest/googletest/include/gtest/gtest-param-test.h b/utils/unittest/googletest/include/gtest/gtest-param-test.h index 0cf05dc..3184d07 100644 --- a/utils/unittest/googletest/include/gtest/gtest-param-test.h +++ b/utils/unittest/googletest/include/gtest/gtest-param-test.h @@ -133,9 +133,12 @@ INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); // in the given test case, whether their definitions come before or // AFTER the INSTANTIATE_TEST_CASE_P statement. // -// Please also note that generator expressions are evaluated in -// RUN_ALL_TESTS(), after main() has started. This allows evaluation of -// parameter list based on command line parameters. +// Please also note that generator expressions (including parameters to the +// generators) are evaluated in InitGoogleTest(), after main() has started. +// This allows the user on one hand, to adjust generator parameters in order +// to dynamically determine a set of tests to run and on the other hand, +// give the user a chance to inspect the generated tests with Google Test +// reflection API before RUN_ALL_TESTS() is executed. // // You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc // for more examples. @@ -146,16 +149,20 @@ INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); #endif // 0 - -#include <utility> - #include <gtest/internal/gtest-port.h> -#ifdef GTEST_HAS_PARAM_TEST +#if !GTEST_OS_SYMBIAN +#include <utility> +#endif +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. #include <gtest/internal/gtest-internal.h> #include <gtest/internal/gtest-param-util.h> +#if GTEST_HAS_PARAM_TEST + namespace testing { // Functions producing parameter generators. @@ -1190,7 +1197,7 @@ inline internal::ParamGenerator<bool> Bool() { return Values(false, true); } -#ifdef GTEST_HAS_COMBINE +#if GTEST_HAS_COMBINE // Combine() allows the user to combine two or more sequences to produce // values of a Cartesian product of those sequences' elements. // diff --git a/utils/unittest/googletest/include/gtest/gtest-spi.h b/utils/unittest/googletest/include/gtest/gtest-spi.h index a4e387a..c41da48 100644 --- a/utils/unittest/googletest/include/gtest/gtest-spi.h +++ b/utils/unittest/googletest/include/gtest/gtest-spi.h @@ -48,7 +48,7 @@ namespace testing { // generated in the same thread that created this object or it can intercept // all generated failures. The scope of this mock object can be controlled with // the second argument to the two arguments constructor. -class ScopedFakeTestPartResultReporter +class GTEST_API_ ScopedFakeTestPartResultReporter : public TestPartResultReporterInterface { public: // The two possible mocking modes of this object. @@ -93,16 +93,16 @@ namespace internal { // TestPartResultArray contains exactly one failure that has the given // type and contains the given substring. If that's not the case, a // non-fatal failure will be generated. -class SingleFailureChecker { +class GTEST_API_ SingleFailureChecker { public: // The constructor remembers the arguments. SingleFailureChecker(const TestPartResultArray* results, - TestPartResultType type, + TestPartResult::Type type, const char* substr); ~SingleFailureChecker(); private: const TestPartResultArray* const results_; - const TestPartResultType type_; + const TestPartResult::Type type_; const String substr_; GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); @@ -143,14 +143,14 @@ class SingleFailureChecker { };\ ::testing::TestPartResultArray gtest_failures;\ ::testing::internal::SingleFailureChecker gtest_checker(\ - >est_failures, ::testing::TPRT_FATAL_FAILURE, (substr));\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ {\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter:: \ INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ GTestExpectFatalFailureHelper::Execute();\ }\ - } while (false) + } while (::testing::internal::AlwaysFalse()) #define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ do { \ @@ -160,14 +160,14 @@ class SingleFailureChecker { };\ ::testing::TestPartResultArray gtest_failures;\ ::testing::internal::SingleFailureChecker gtest_checker(\ - >est_failures, ::testing::TPRT_FATAL_FAILURE, (substr));\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ {\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter:: \ INTERCEPT_ALL_THREADS, >est_failures);\ GTestExpectFatalFailureHelper::Execute();\ }\ - } while (false) + } while (::testing::internal::AlwaysFalse()) // A macro for testing Google Test assertions or code that's expected to // generate Google Test non-fatal failures. It asserts that the given @@ -190,32 +190,43 @@ class SingleFailureChecker { // Note that even though the implementations of the following two // macros are much alike, we cannot refactor them to use a common // helper macro, due to some peculiarity in how the preprocessor -// works. The AcceptsMacroThatExpandsToUnprotectedComma test in -// gtest_unittest.cc will fail to compile if we do that. +// works. If we do that, the code won't compile when the user gives +// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that +// expands to code containing an unprotected comma. The +// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc +// catches that. +// +// For the same reason, we have to write +// if (::testing::internal::AlwaysTrue()) { statement; } +// instead of +// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) +// to avoid an MSVC warning on unreachable code. #define EXPECT_NONFATAL_FAILURE(statement, substr) \ do {\ ::testing::TestPartResultArray gtest_failures;\ ::testing::internal::SingleFailureChecker gtest_checker(\ - >est_failures, ::testing::TPRT_NONFATAL_FAILURE, (substr));\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ {\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter:: \ INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ - statement;\ + if (::testing::internal::AlwaysTrue()) { statement; }\ }\ - } while (false) + } while (::testing::internal::AlwaysFalse()) #define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ do {\ ::testing::TestPartResultArray gtest_failures;\ ::testing::internal::SingleFailureChecker gtest_checker(\ - >est_failures, ::testing::TPRT_NONFATAL_FAILURE, (substr));\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ {\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\ >est_failures);\ - statement;\ + if (::testing::internal::AlwaysTrue()) { statement; }\ }\ - } while (false) + } while (::testing::internal::AlwaysFalse()) #endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ diff --git a/utils/unittest/googletest/include/gtest/gtest-test-part.h b/utils/unittest/googletest/include/gtest/gtest-test-part.h index 1a281af..f714759 100644 --- a/utils/unittest/googletest/include/gtest/gtest-test-part.h +++ b/utils/unittest/googletest/include/gtest/gtest-test-part.h @@ -34,41 +34,42 @@ #define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ #include <iosfwd> +#include <vector> #include <gtest/internal/gtest-internal.h> #include <gtest/internal/gtest-string.h> namespace testing { -// The possible outcomes of a test part (i.e. an assertion or an -// explicit SUCCEED(), FAIL(), or ADD_FAILURE()). -enum TestPartResultType { - TPRT_SUCCESS, // Succeeded. - TPRT_NONFATAL_FAILURE, // Failed but the test can continue. - TPRT_FATAL_FAILURE // Failed and the test should be terminated. -}; - // A copyable object representing the result of a test part (i.e. an // assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). // // Don't inherit from TestPartResult as its destructor is not virtual. -class TestPartResult { +class GTEST_API_ TestPartResult { public: + // The possible outcomes of a test part (i.e. an assertion or an + // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). + enum Type { + kSuccess, // Succeeded. + kNonFatalFailure, // Failed but the test can continue. + kFatalFailure // Failed and the test should be terminated. + }; + // C'tor. TestPartResult does NOT have a default constructor. // Always use this constructor (with parameters) to create a // TestPartResult object. - TestPartResult(TestPartResultType type, - const char* file_name, - int line_number, - const char* message) - : type_(type), - file_name_(file_name), - line_number_(line_number), - summary_(ExtractSummary(message)), - message_(message) { + TestPartResult(Type a_type, + const char* a_file_name, + int a_line_number, + const char* a_message) + : type_(a_type), + file_name_(a_file_name), + line_number_(a_line_number), + summary_(ExtractSummary(a_message)), + message_(a_message) { } // Gets the outcome of the test part. - TestPartResultType type() const { return type_; } + Type type() const { return type_; } // Gets the name of the source file where the test part took place, or // NULL if it's unknown. @@ -85,18 +86,18 @@ class TestPartResult { const char* message() const { return message_.c_str(); } // Returns true iff the test part passed. - bool passed() const { return type_ == TPRT_SUCCESS; } + bool passed() const { return type_ == kSuccess; } // Returns true iff the test part failed. - bool failed() const { return type_ != TPRT_SUCCESS; } + bool failed() const { return type_ != kSuccess; } // Returns true iff the test part non-fatally failed. - bool nonfatally_failed() const { return type_ == TPRT_NONFATAL_FAILURE; } + bool nonfatally_failed() const { return type_ == kNonFatalFailure; } // Returns true iff the test part fatally failed. - bool fatally_failed() const { return type_ == TPRT_FATAL_FAILURE; } + bool fatally_failed() const { return type_ == kFatalFailure; } private: - TestPartResultType type_; + Type type_; // Gets the summary of the failure message by omitting the stack // trace in it. @@ -117,15 +118,11 @@ std::ostream& operator<<(std::ostream& os, const TestPartResult& result); // An array of TestPartResult objects. // -// We define this class as we cannot use STL containers when compiling -// Google Test with MSVC 7.1 and exceptions disabled. -// // Don't inherit from TestPartResultArray as its destructor is not // virtual. -class TestPartResultArray { +class GTEST_API_ TestPartResultArray { public: - TestPartResultArray(); - ~TestPartResultArray(); + TestPartResultArray() {} // Appends the given TestPartResult to the array. void Append(const TestPartResult& result); @@ -135,10 +132,9 @@ class TestPartResultArray { // Returns the number of TestPartResult objects in the array. int size() const; + private: - // Internally we use a list to simulate the array. Yes, this means - // that random access is O(N) in time, but it's OK for its purpose. - internal::List<TestPartResult>* const list_; + std::vector<TestPartResult> array_; GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); }; @@ -159,7 +155,8 @@ namespace internal { // reported, it only delegates the reporting to the former result reporter. // The original result reporter is restored in the destructor. // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -class HasNewFatalFailureHelper : public TestPartResultReporterInterface { +class GTEST_API_ HasNewFatalFailureHelper + : public TestPartResultReporterInterface { public: HasNewFatalFailureHelper(); virtual ~HasNewFatalFailureHelper(); diff --git a/utils/unittest/googletest/include/gtest/gtest-typed-test.h b/utils/unittest/googletest/include/gtest/gtest-typed-test.h index dec42cf..1ec8eb8 100644 --- a/utils/unittest/googletest/include/gtest/gtest-typed-test.h +++ b/utils/unittest/googletest/include/gtest/gtest-typed-test.h @@ -151,7 +151,7 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); // Implements typed tests. -#ifdef GTEST_HAS_TYPED_TEST +#if GTEST_HAS_TYPED_TEST // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // @@ -159,8 +159,11 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); // given test case. #define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types<int>) #define TYPED_TEST_CASE(CaseName, Types) \ - typedef ::testing::internal::TypeList<Types>::type \ + typedef ::testing::internal::TypeList< Types >::type \ GTEST_TYPE_PARAMS_(CaseName) #define TYPED_TEST(CaseName, TestName) \ @@ -186,7 +189,7 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); // Implements type-parameterized tests. -#ifdef GTEST_HAS_TYPED_TEST_P +#if GTEST_HAS_TYPED_TEST_P // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // @@ -241,11 +244,14 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ __FILE__, __LINE__, #__VA_ARGS__) +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types<int>) #define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ bool gtest_##Prefix##_##CaseName = \ ::testing::internal::TypeParameterizedTestCase<CaseName, \ GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \ - ::testing::internal::TypeList<Types>::type>::Register(\ + ::testing::internal::TypeList< Types >::type>::Register(\ #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) #endif // GTEST_HAS_TYPED_TEST_P diff --git a/utils/unittest/googletest/include/gtest/gtest.h b/utils/unittest/googletest/include/gtest/gtest.h index ebd3123..921fad1 100644 --- a/utils/unittest/googletest/include/gtest/gtest.h +++ b/utils/unittest/googletest/include/gtest/gtest.h @@ -51,17 +51,9 @@ #ifndef GTEST_INCLUDE_GTEST_GTEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_H_ -// The following platform macros are used throughout Google Test: -// _WIN32_WCE Windows CE (set in project files) -// -// Note that even though _MSC_VER and _WIN32_WCE really indicate a compiler -// and a Win32 implementation, respectively, we use them to indicate the -// combination of compiler - Win 32 API - C library, since the code currently -// only supports: -// Windows proper with Visual C++ and MS C library (_MSC_VER && !_WIN32_WCE) and -// Windows Mobile with Visual C++ and no C library (_WIN32_WCE). - #include <limits> +#include <vector> + #include <gtest/internal/gtest-internal.h> #include <gtest/internal/gtest-string.h> #include <gtest/gtest-death-test.h> @@ -72,41 +64,99 @@ #include <gtest/gtest-typed-test.h> // Depending on the platform, different string classes are available. -// On Windows, ::std::string compiles only when exceptions are -// enabled. On Linux, in addition to ::std::string, Google also makes -// use of class ::string, which has the same interface as -// ::std::string, but has a different implementation. -// -// The user can tell us whether ::std::string is available in his -// environment by defining the macro GTEST_HAS_STD_STRING to either 1 -// or 0 on the compiler command line. He can also define -// GTEST_HAS_GLOBAL_STRING to 1 to indicate that ::string is available -// AND is a distinct type to ::std::string, or define it to 0 to -// indicate otherwise. +// On Linux, in addition to ::std::string, Google also makes use of +// class ::string, which has the same interface as ::std::string, but +// has a different implementation. +// +// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that +// ::string is available AND is a distinct type to ::std::string, or +// define it to 0 to indicate otherwise. // // If the user's ::std::string and ::string are the same class due to -// aliasing, he should define GTEST_HAS_STD_STRING to 1 and -// GTEST_HAS_GLOBAL_STRING to 0. +// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. // -// If the user doesn't define GTEST_HAS_STD_STRING and/or -// GTEST_HAS_GLOBAL_STRING, they are defined heuristically. +// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined +// heuristically. namespace testing { -// The upper limit for valid stack trace depths. -const int kMaxStackTraceDepth = 100; +// Declares the flags. -// This flag specifies the maximum number of stack frames to be -// printed in a failure message. -GTEST_DECLARE_int32_(stack_trace_depth); +// This flag temporary enables the disabled tests. +GTEST_DECLARE_bool_(also_run_disabled_tests); + +// This flag brings the debugger on an assertion failure. +GTEST_DECLARE_bool_(break_on_failure); + +// This flag controls whether Google Test catches all test-thrown exceptions +// and logs them as failures. +GTEST_DECLARE_bool_(catch_exceptions); + +// This flag enables using colors in terminal output. Available values are +// "yes" to enable colors, "no" (disable colors), or "auto" (the default) +// to let Google Test decide. +GTEST_DECLARE_string_(color); + +// This flag sets up the filter to select by name using a glob pattern +// the tests to run. If the filter is not given all tests are executed. +GTEST_DECLARE_string_(filter); + +// This flag causes the Google Test to list tests. None of the tests listed +// are actually run if the flag is provided. +GTEST_DECLARE_bool_(list_tests); + +// This flag controls whether Google Test emits a detailed XML report to a file +// in addition to its normal textual output. +GTEST_DECLARE_string_(output); + +// This flags control whether Google Test prints the elapsed time for each +// test. +GTEST_DECLARE_bool_(print_time); + +// This flag specifies the random number seed. +GTEST_DECLARE_int32_(random_seed); + +// This flag sets how many times the tests are repeated. The default value +// is 1. If the value is -1 the tests are repeating forever. +GTEST_DECLARE_int32_(repeat); // This flag controls whether Google Test includes Google Test internal // stack frames in failure stack traces. GTEST_DECLARE_bool_(show_internal_stack_frames); +// When this flag is specified, tests' order is randomized on every iteration. +GTEST_DECLARE_bool_(shuffle); + +// This flag specifies the maximum number of stack frames to be +// printed in a failure message. +GTEST_DECLARE_int32_(stack_trace_depth); + +// When this flag is specified, a failed assertion will throw an +// exception if exceptions are enabled, or exit the program with a +// non-zero code otherwise. +GTEST_DECLARE_bool_(throw_on_failure); + +// The upper limit for valid stack trace depths. +const int kMaxStackTraceDepth = 100; + namespace internal { +class AssertHelper; +class DefaultGlobalTestPartResultReporter; +class ExecDeathTest; +class NoExecDeathTest; +class FinalSuccessChecker; class GTestFlagSaver; +class TestInfoImpl; +class TestResultAccessor; +class TestEventListenersAccessor; +class TestEventRepeater; +class WindowsDeathTest; +class UnitTestImpl* GetUnitTestImpl(); +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const String& message); +class PrettyUnitTestResultPrinter; +class XmlUnitTestResultPrinter; // Converts a streamable value to a String. A NULL pointer is // converted to "(null)". When the input value is a ::string, @@ -124,64 +174,146 @@ String StreamableToString(const T& streamable) { // A class for indicating whether an assertion was successful. When // the assertion wasn't successful, the AssertionResult object -// remembers a non-empty message that described how it failed. +// remembers a non-empty message that describes how it failed. // -// This class is useful for defining predicate-format functions to be -// used with predicate assertions (ASSERT_PRED_FORMAT*, etc). -// -// The constructor of AssertionResult is private. To create an -// instance of this class, use one of the factory functions +// To create an instance of this class, use one of the factory functions // (AssertionSuccess() and AssertionFailure()). // -// For example, in order to be able to write: +// 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 just need to define: +// you need to define: // // testing::AssertionResult IsEven(const char* expr, int n) { -// if ((n % 2) == 0) return testing::AssertionSuccess(); -// -// Message msg; -// msg << "Expected: " << expr << " is even\n" -// << " Actual: it's " << n; -// return testing::AssertionFailure(msg); +// 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 AssertionResult { +// +class GTEST_API_ AssertionResult { public: - // Declares factory functions for making successful and failed - // assertion results as friends. - friend AssertionResult AssertionSuccess(); - friend AssertionResult AssertionFailure(const Message&); + // Copy constructor. + // Used in EXPECT_TRUE/FALSE(assertion_result). + AssertionResult(const AssertionResult& other); + // Used in the EXPECT_TRUE/FALSE(bool_expression). + explicit AssertionResult(bool success) : success_(success) {} // Returns true iff the assertion succeeded. - operator bool() const { return failure_message_.c_str() == NULL; } // NOLINT + 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() != NULL && message_->c_str() != NULL ? + message_->c_str() : ""; + } + // TODO(vladl@google.com): Remove this after making sure no clients use it. + // Deprecated; please use message() instead. + const char* failure_message() const { return message(); } - // Returns the assertion's failure message. - const char* failure_message() const { return failure_message_.c_str(); } + // Streams a custom failure message into this object. + template <typename T> AssertionResult& operator<<(const T& value); private: - // The default constructor. It is used when the assertion succeeded. - AssertionResult() {} - - // The constructor used when the assertion failed. - explicit AssertionResult(const internal::String& failure_message); - - // Stores the assertion's failure message. - internal::String failure_message_; -}; + // No implementation - we want AssertionResult to be + // copy-constructible but not assignable. + void operator=(const 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. + internal::scoped_ptr<internal::String> message_; +}; // class AssertionResult + +// Streams a custom failure message into this object. +template <typename T> +AssertionResult& AssertionResult::operator<<(const T& value) { + Message msg; + if (message_.get() != NULL) + msg << *message_; + msg << value; + message_.reset(new internal::String(msg.GetString())); + return *this; +} // Makes a successful assertion result. -AssertionResult AssertionSuccess(); +GTEST_API_ AssertionResult AssertionSuccess(); + +// Makes a failed assertion result. +GTEST_API_ AssertionResult AssertionFailure(); // Makes a failed assertion result with the given failure message. -AssertionResult AssertionFailure(const Message& msg); +// Deprecated; use AssertionFailure() << msg. +GTEST_API_ AssertionResult AssertionFailure(const Message& msg); // The abstract class that all tests inherit from. // @@ -206,7 +338,7 @@ AssertionResult AssertionFailure(const Message& msg); // TEST_F(FooTest, Baz) { ... } // // Test is not copyable. -class Test { +class GTEST_API_ Test { public: friend class internal::TestInfoImpl; @@ -237,6 +369,13 @@ class Test { // Returns true iff the current test has a fatal failure. static bool HasFatalFailure(); + // Returns true iff the current test has a non-fatal failure. + static bool HasNonfatalFailure(); + + // Returns true iff the current test has a (either fatal or + // non-fatal) failure. + static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } + // Logs a property for the current test. Only the last value for a given // key is remembered. // These are public static so they can be called from utility functions @@ -304,6 +443,155 @@ class Test { GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); }; +typedef internal::TimeInMillis TimeInMillis; + +// A copyable object representing a user specified test property which can be +// output as a key/value string pair. +// +// Don't inherit from TestProperty as its destructor is not virtual. +class TestProperty { + public: + // C'tor. TestProperty does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestProperty object. + TestProperty(const char* a_key, const char* a_value) : + key_(a_key), value_(a_value) { + } + + // Gets the user supplied key. + const char* key() const { + return key_.c_str(); + } + + // Gets the user supplied value. + const char* value() const { + return value_.c_str(); + } + + // Sets a new value, overriding the one supplied in the constructor. + void SetValue(const char* new_value) { + value_ = new_value; + } + + private: + // The key supplied by the user. + internal::String key_; + // The value supplied by the user. + internal::String value_; +}; + +// The result of a single Test. This includes a list of +// TestPartResults, a list of TestProperties, a count of how many +// death tests there are in the Test, and how much time it took to run +// the Test. +// +// TestResult is not copyable. +class GTEST_API_ TestResult { + public: + // Creates an empty TestResult. + TestResult(); + + // D'tor. Do not inherit from TestResult. + ~TestResult(); + + // Gets the number of all test parts. This is the sum of the number + // of successful test parts and the number of failed test parts. + int total_part_count() const; + + // Returns the number of the test properties. + int test_property_count() const; + + // Returns true iff the test passed (i.e. no test part failed). + bool Passed() const { return !Failed(); } + + // Returns true iff the test failed. + bool Failed() const; + + // Returns true iff the test fatally failed. + bool HasFatalFailure() const; + + // Returns true iff the test has a non-fatal failure. + bool HasNonfatalFailure() const; + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test part result among all the results. i can range + // from 0 to test_property_count() - 1. If i is not in that range, aborts + // the program. + const TestPartResult& GetTestPartResult(int i) const; + + // Returns the i-th test property. i can range from 0 to + // test_property_count() - 1. If i is not in that range, aborts the + // program. + const TestProperty& GetTestProperty(int i) const; + + private: + friend class TestInfo; + friend class UnitTest; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::ExecDeathTest; + friend class internal::TestInfoImpl; + friend class internal::TestResultAccessor; + friend class internal::UnitTestImpl; + friend class internal::WindowsDeathTest; + + // Gets the vector of TestPartResults. + const std::vector<TestPartResult>& test_part_results() const { + return test_part_results_; + } + + // Gets the vector of TestProperties. + const std::vector<TestProperty>& test_properties() const { + return test_properties_; + } + + // Sets the elapsed time. + void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } + + // Adds a test property to the list. The property is validated and may add + // a non-fatal failure if invalid (e.g., if it conflicts with reserved + // key names). If a property is already recorded for the same key, the + // value will be updated, rather than storing multiple values for the same + // key. + void RecordProperty(const TestProperty& test_property); + + // Adds a failure if the key is a reserved attribute of Google Test + // testcase tags. Returns true if the property is valid. + // TODO(russr): Validate attribute names are legal and human readable. + static bool ValidateTestProperty(const TestProperty& test_property); + + // Adds a test part result to the list. + void AddTestPartResult(const TestPartResult& test_part_result); + + // Returns the death test count. + int death_test_count() const { return death_test_count_; } + + // Increments the death test count, returning the new count. + int increment_death_test_count() { return ++death_test_count_; } + + // Clears the test part results. + void ClearTestPartResults(); + + // Clears the object. + void Clear(); + + // Protects mutable state of the property vector and of owned + // properties, whose values may be updated. + internal::Mutex test_properites_mutex_; + + // The vector of TestPartResults + std::vector<TestPartResult> test_part_results_; + // The vector of TestProperties + std::vector<TestProperty> test_properties_; + // Running count of death tests. + int death_test_count_; + // The elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestResult. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); +}; // class TestResult // A TestInfo object stores the following information about a test: // @@ -316,7 +604,7 @@ class Test { // The constructor of TestInfo registers itself with the UnitTest // singleton such that the RUN_ALL_TESTS() macro knows which tests to // run. -class TestInfo { +class GTEST_API_ TestInfo { public: // Destructs a TestInfo object. This function is not virtual, so // don't inherit from TestInfo. @@ -334,7 +622,9 @@ class TestInfo { // Returns the test comment. const char* comment() const; - // Returns true if this test should run. + // Returns true if this test should run, that is if the test is not disabled + // (or it is disabled but the also_run_disabled_tests flag has been specified) + // and its full name matches the user-specified filter. // // Google Test allows the user to filter the tests by their full names. // The full name of a test Bar in test case Foo is defined as @@ -351,15 +641,16 @@ class TestInfo { bool should_run() const; // Returns the result of the test. - const internal::TestResult* result() const; + const TestResult* result() const; + private: -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST friend class internal::DefaultDeathTestFactory; #endif // GTEST_HAS_DEATH_TEST - friend class internal::TestInfoImpl; - friend class internal::UnitTestImpl; friend class Test; friend class TestCase; + friend class internal::TestInfoImpl; + friend class internal::UnitTestImpl; friend TestInfo* internal::MakeAndRegisterTestInfo( const char* test_case_name, const char* name, const char* test_case_comment, const char* comment, @@ -368,6 +659,9 @@ class TestInfo { Test::TearDownTestCaseFunc tear_down_tc, internal::TestFactoryBase* factory); + // Returns true if this test matches the user-specified filter. + bool matches_filter() const; + // Increments the number of death tests encountered in this test so // far. int increment_death_test_count(); @@ -389,6 +683,141 @@ class TestInfo { GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); }; +// A test case, which consists of a vector of TestInfos. +// +// TestCase is not copyable. +class GTEST_API_ TestCase { + public: + // Creates a TestCase with the given name. + // + // TestCase does NOT have a default constructor. Always use this + // constructor to create a TestCase object. + // + // Arguments: + // + // name: name of the test case + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase(const char* name, const char* comment, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Destructor of TestCase. + virtual ~TestCase(); + + // Gets the name of the TestCase. + const char* name() const { return name_.c_str(); } + + // Returns the test case comment. + const char* comment() const { return comment_.c_str(); } + + // Returns true if any test in this test case should run. + bool should_run() const { return should_run_; } + + // Gets the number of successful tests in this test case. + int successful_test_count() const; + + // Gets the number of failed tests in this test case. + int failed_test_count() const; + + // Gets the number of disabled tests in this test case. + int disabled_test_count() const; + + // Get the number of tests in this test case that should run. + int test_to_run_count() const; + + // Gets the number of all tests in this test case. + int total_test_count() const; + + // Returns true iff the test case passed. + bool Passed() const { return !Failed(); } + + // Returns true iff the test case failed. + bool Failed() const { return failed_test_count() > 0; } + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + const TestInfo* GetTestInfo(int i) const; + + private: + friend class Test; + friend class internal::UnitTestImpl; + + // Gets the (mutable) vector of TestInfos in this TestCase. + std::vector<TestInfo*>& test_info_list() { return test_info_list_; } + + // Gets the (immutable) vector of TestInfos in this TestCase. + const std::vector<TestInfo*>& test_info_list() const { + return test_info_list_; + } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + TestInfo* GetMutableTestInfo(int i); + + // Sets the should_run member. + void set_should_run(bool should) { should_run_ = should; } + + // Adds a TestInfo to this test case. Will delete the TestInfo upon + // destruction of the TestCase object. + void AddTestInfo(TestInfo * test_info); + + // Clears the results of all tests in this test case. + void ClearResult(); + + // Clears the results of all tests in the given test case. + static void ClearTestCaseResult(TestCase* test_case) { + test_case->ClearResult(); + } + + // Runs every test in this TestCase. + void Run(); + + // Returns true iff test passed. + static bool TestPassed(const TestInfo * test_info); + + // Returns true iff test failed. + static bool TestFailed(const TestInfo * test_info); + + // Returns true iff test is disabled. + static bool TestDisabled(const TestInfo * test_info); + + // Returns true if the given test should run. + static bool ShouldRunTest(const TestInfo *test_info); + + // Shuffles the tests in this test case. + void ShuffleTests(internal::Random* random); + + // Restores the test order to before the first shuffle. + void UnshuffleTests(); + + // Name of the test case. + internal::String name_; + // Comment on the test case. + internal::String comment_; + // The vector of TestInfos in their original order. It owns the + // elements in the vector. + std::vector<TestInfo*> test_info_list_; + // Provides a level of indirection for the test list to allow easy + // shuffling and restoring the test order. The i-th element in this + // vector is the index of the i-th test in the shuffled test list. + std::vector<int> test_indices_; + // Pointer to the function that sets up the test case. + Test::SetUpTestCaseFunc set_up_tc_; + // Pointer to the function that tears down the test case. + Test::TearDownTestCaseFunc tear_down_tc_; + // True iff any test in this test case should run. + bool should_run_; + // Elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestCases. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); +}; + // An Environment object is capable of setting up and tearing down an // environment. The user should subclass this to define his own // environment(s). @@ -420,7 +849,159 @@ class Environment { virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } }; -// A UnitTest consists of a list of TestCases. +// The interface for tracing execution of tests. The methods are organized in +// the order the corresponding events are fired. +class TestEventListener { + public: + virtual ~TestEventListener() {} + + // Fired before any test activity starts. + virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; + + // Fired before each iteration of tests starts. There may be more than + // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration + // index, starting from 0. + virtual void OnTestIterationStart(const UnitTest& unit_test, + int iteration) = 0; + + // Fired before environment set-up for each iteration of tests starts. + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; + + // Fired after environment set-up for each iteration of tests ends. + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; + + // Fired before the test case starts. + virtual void OnTestCaseStart(const TestCase& test_case) = 0; + + // Fired before the test starts. + virtual void OnTestStart(const TestInfo& test_info) = 0; + + // Fired after a failed assertion or a SUCCESS(). + virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; + + // Fired after the test ends. + virtual void OnTestEnd(const TestInfo& test_info) = 0; + + // Fired after the test case ends. + virtual void OnTestCaseEnd(const TestCase& test_case) = 0; + + // Fired before environment tear-down for each iteration of tests starts. + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; + + // Fired after environment tear-down for each iteration of tests ends. + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; + + // Fired after each iteration of tests finishes. + virtual void OnTestIterationEnd(const UnitTest& unit_test, + int iteration) = 0; + + // Fired after all test activities have ended. + virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; +}; + +// The convenience class for users who need to override just one or two +// methods and are not concerned that a possible change to a signature of +// the methods they override will not be caught during the build. For +// comments about each method please see the definition of TestEventListener +// above. +class EmptyTestEventListener : public TestEventListener { + public: + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} + virtual void OnTestStart(const TestInfo& /*test_info*/) {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} +}; + +// TestEventListeners lets users add listeners to track events in Google Test. +class GTEST_API_ TestEventListeners { + public: + TestEventListeners(); + ~TestEventListeners(); + + // Appends an event listener to the end of the list. Google Test assumes + // the ownership of the listener (i.e. it will delete the listener when + // the test program finishes). + void Append(TestEventListener* listener); + + // Removes the given event listener from the list and returns it. It then + // becomes the caller's responsibility to delete the listener. Returns + // NULL if the listener is not found in the list. + TestEventListener* Release(TestEventListener* listener); + + // Returns the standard listener responsible for the default console + // output. Can be removed from the listeners list to shut down default + // console output. Note that removing this object from the listener list + // with Release transfers its ownership to the caller and makes this + // function return NULL the next time. + TestEventListener* default_result_printer() const { + return default_result_printer_; + } + + // Returns the standard listener responsible for the default XML output + // controlled by the --gtest_output=xml flag. Can be removed from the + // listeners list by users who want to shut down the default XML output + // controlled by this flag and substitute it with custom one. Note that + // removing this object from the listener list with Release transfers its + // ownership to the caller and makes this function return NULL the next + // time. + TestEventListener* default_xml_generator() const { + return default_xml_generator_; + } + + private: + friend class TestCase; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::NoExecDeathTest; + friend class internal::TestEventListenersAccessor; + friend class internal::TestInfoImpl; + friend class internal::UnitTestImpl; + + // Returns repeater that broadcasts the TestEventListener events to all + // subscribers. + TestEventListener* repeater(); + + // Sets the default_result_printer attribute to the provided listener. + // The listener is also added to the listener list and previous + // default_result_printer is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultResultPrinter(TestEventListener* listener); + + // Sets the default_xml_generator attribute to the provided listener. The + // listener is also added to the listener list and previous + // default_xml_generator is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultXmlGenerator(TestEventListener* listener); + + // Controls whether events will be forwarded by the repeater to the + // listeners in the list. + bool EventForwardingEnabled() const; + void SuppressEventForwarding(); + + // The actual list of listeners. + internal::TestEventRepeater* repeater_; + // Listener responsible for the standard result output. + TestEventListener* default_result_printer_; + // Listener responsible for the creation of the XML output file. + TestEventListener* default_xml_generator_; + + // We disallow copying TestEventListeners. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); +}; + +// A UnitTest consists of a vector of TestCases. // // This is a singleton class. The only instance of UnitTest is // created when UnitTest::GetInstance() is first called. This @@ -430,40 +1011,13 @@ class Environment { // // This class is thread-safe as long as the methods are called // according to their specification. -class UnitTest { +class GTEST_API_ UnitTest { public: // Gets the singleton UnitTest object. The first time this method // is called, a UnitTest object is constructed and returned. // Consecutive calls will return the same object. static UnitTest* GetInstance(); - // Registers and returns a global test environment. When a test - // program is run, all global test environments will be set-up in - // the order they were registered. After all tests in the program - // have finished, all global test environments will be torn-down in - // the *reverse* order they were registered. - // - // The UnitTest object takes ownership of the given environment. - // - // This method can only be called from the main thread. - Environment* AddEnvironment(Environment* env); - - // Adds a TestPartResult to the current TestResult object. All - // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) - // eventually call this to report their results. The user code - // should use the assertion macros instead of calling this directly. - // - // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. - void AddTestPartResult(TestPartResultType result_type, - const char* file_name, - int line_number, - const internal::String& message, - const internal::String& os_stack_trace); - - // Adds a TestProperty to the current TestResult object. If the result already - // contains a property with the same key, the value will be updated. - void RecordPropertyForCurrentTest(const char* key, const char* value); - // Runs all tests in this UnitTest object and prints the result. // Returns 0 if successful, or 1 otherwise. // @@ -484,19 +1038,107 @@ class UnitTest { // or NULL if no test is running. const TestInfo* current_test_info() const; -#ifdef GTEST_HAS_PARAM_TEST + // Returns the random seed used at the start of the current test run. + int random_seed() const; + +#if GTEST_HAS_PARAM_TEST // Returns the ParameterizedTestCaseRegistry object used to keep track of // value-parameterized tests and instantiate and register them. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. internal::ParameterizedTestCaseRegistry& parameterized_test_registry(); #endif // GTEST_HAS_PARAM_TEST + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const; + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const; + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const; + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const; + + // Returns the list of event listeners that can be used to track events + // inside Google Test. + TestEventListeners& listeners(); + + private: + // Registers and returns a global test environment. When a test + // program is run, all global test environments will be set-up in + // the order they were registered. After all tests in the program + // have finished, all global test environments will be torn-down in + // the *reverse* order they were registered. + // + // The UnitTest object takes ownership of the given environment. + // + // This method can only be called from the main thread. + Environment* AddEnvironment(Environment* env); + + // Adds a TestPartResult to the current TestResult object. All + // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) + // eventually call this to report their results. The user code + // should use the assertion macros instead of calling this directly. + void AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const internal::String& message, + const internal::String& os_stack_trace); + + // Adds a TestProperty to the current TestResult object. If the result already + // contains a property with the same key, the value will be updated. + void RecordPropertyForCurrentTest(const char* key, const char* value); + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i); + // Accessors for the implementation object. internal::UnitTestImpl* impl() { return impl_; } const internal::UnitTestImpl* impl() const { return impl_; } - private: - // ScopedTrace is a friend as it needs to modify the per-thread - // trace stack, which is a private member of UnitTest. + + // These classes and funcions are friends as they need to access private + // members of UnitTest. + friend class Test; + friend class internal::AssertHelper; friend class internal::ScopedTrace; + friend Environment* AddGlobalTestEnvironment(Environment* env); + friend internal::UnitTestImpl* internal::GetUnitTestImpl(); + friend void internal::ReportFailureInUnknownLocation( + TestPartResult::Type result_type, + const internal::String& message); // Creates an empty UnitTest. UnitTest(); @@ -556,36 +1198,34 @@ inline Environment* AddGlobalTestEnvironment(Environment* env) { // updated. // // Calling the function for the second time has no user-visible effect. -void InitGoogleTest(int* argc, char** argv); +GTEST_API_ void InitGoogleTest(int* argc, char** argv); // This overloaded version can be used in Windows programs compiled in // UNICODE mode. -void InitGoogleTest(int* argc, wchar_t** argv); +GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); namespace internal { // These overloaded versions handle ::std::string and ::std::wstring. -#if GTEST_HAS_STD_STRING -inline String FormatForFailureMessage(const ::std::string& str) { +GTEST_API_ inline String FormatForFailureMessage(const ::std::string& str) { return (Message() << '"' << str << '"').GetString(); } -#endif // GTEST_HAS_STD_STRING #if GTEST_HAS_STD_WSTRING -inline String FormatForFailureMessage(const ::std::wstring& wstr) { +GTEST_API_ inline String FormatForFailureMessage(const ::std::wstring& wstr) { return (Message() << "L\"" << wstr << '"').GetString(); } #endif // GTEST_HAS_STD_WSTRING // These overloaded versions handle ::string and ::wstring. #if GTEST_HAS_GLOBAL_STRING -inline String FormatForFailureMessage(const ::string& str) { +GTEST_API_ inline String FormatForFailureMessage(const ::string& str) { return (Message() << '"' << str << '"').GetString(); } #endif // GTEST_HAS_GLOBAL_STRING #if GTEST_HAS_GLOBAL_WSTRING -inline String FormatForFailureMessage(const ::wstring& wstr) { +GTEST_API_ inline String FormatForFailureMessage(const ::wstring& wstr) { return (Message() << "L\"" << wstr << '"').GetString(); } #endif // GTEST_HAS_GLOBAL_WSTRING @@ -614,10 +1254,20 @@ AssertionResult CmpHelperEQ(const char* expected_expression, const char* actual_expression, const T1& expected, const T2& actual) { +#ifdef _MSC_VER +#pragma warning(push) // Saves the current warning state. +#pragma warning(disable:4389) // Temporarily disables warning on + // signed/unsigned mismatch. +#endif + if (expected == actual) { return AssertionSuccess(); } +#ifdef _MSC_VER +#pragma warning(pop) // Restores the warning state. +#endif + return EqFailure(expected_expression, actual_expression, FormatForComparisonFailureMessage(expected, actual), @@ -628,10 +1278,10 @@ AssertionResult CmpHelperEQ(const char* expected_expression, // With this overloaded version, we allow anonymous enums to be used // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums // can be implicitly cast to BiggestInt. -AssertionResult CmpHelperEQ(const char* expected_expression, - const char* actual_expression, - BiggestInt expected, - BiggestInt actual); +GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual); // The helper class for {ASSERT|EXPECT}_EQ. The template argument // lhs_is_null_literal is true iff the first argument to ASSERT_EQ() @@ -688,7 +1338,7 @@ class EqHelper<true> { template <typename T1, typename T2> static AssertionResult Compare(const char* expected_expression, const char* actual_expression, - const T1& expected, + const T1& /* expected */, T2* actual) { // We already know that 'expected' is a null pointer. return CmpHelperEQ(expected_expression, actual_expression, @@ -720,72 +1370,72 @@ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ return AssertionFailure(msg);\ }\ }\ -AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ - BiggestInt val1, BiggestInt val2); +GTEST_API_ AssertionResult CmpHelper##op_name(\ + const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // Implements the helper function for {ASSERT|EXPECT}_NE -GTEST_IMPL_CMP_HELPER_(NE, !=) +GTEST_IMPL_CMP_HELPER_(NE, !=); // Implements the helper function for {ASSERT|EXPECT}_LE -GTEST_IMPL_CMP_HELPER_(LE, <=) +GTEST_IMPL_CMP_HELPER_(LE, <=); // Implements the helper function for {ASSERT|EXPECT}_LT -GTEST_IMPL_CMP_HELPER_(LT, < ) +GTEST_IMPL_CMP_HELPER_(LT, < ); // Implements the helper function for {ASSERT|EXPECT}_GE -GTEST_IMPL_CMP_HELPER_(GE, >=) +GTEST_IMPL_CMP_HELPER_(GE, >=); // Implements the helper function for {ASSERT|EXPECT}_GT -GTEST_IMPL_CMP_HELPER_(GT, > ) +GTEST_IMPL_CMP_HELPER_(GT, > ); #undef GTEST_IMPL_CMP_HELPER_ // The helper function for {ASSERT|EXPECT}_STREQ. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -AssertionResult CmpHelperSTREQ(const char* expected_expression, - const char* actual_expression, - const char* expected, - const char* actual); +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); // The helper function for {ASSERT|EXPECT}_STRCASEEQ. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, - const char* actual_expression, - const char* expected, - const char* actual); +GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); // The helper function for {ASSERT|EXPECT}_STRNE. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -AssertionResult CmpHelperSTRNE(const char* s1_expression, - const char* s2_expression, - const char* s1, - const char* s2); +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); // The helper function for {ASSERT|EXPECT}_STRCASENE. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -AssertionResult CmpHelperSTRCASENE(const char* s1_expression, - const char* s2_expression, - const char* s1, - const char* s2); +GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); // Helper function for *_STREQ on wide strings. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -AssertionResult CmpHelperSTREQ(const char* expected_expression, - const char* actual_expression, - const wchar_t* expected, - const wchar_t* actual); +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual); // Helper function for *_STRNE on wide strings. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -AssertionResult CmpHelperSTRNE(const char* s1_expression, - const char* s2_expression, - const wchar_t* s1, - const wchar_t* s2); +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2); } // namespace internal @@ -797,32 +1447,30 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression, // // The {needle,haystack}_expr arguments are the stringified // expressions that generated the two real arguments. -AssertionResult IsSubstring( +GTEST_API_ AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const char* needle, const char* haystack); -AssertionResult IsSubstring( +GTEST_API_ AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const wchar_t* needle, const wchar_t* haystack); -AssertionResult IsNotSubstring( +GTEST_API_ AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const char* needle, const char* haystack); -AssertionResult IsNotSubstring( +GTEST_API_ AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const wchar_t* needle, const wchar_t* haystack); -#if GTEST_HAS_STD_STRING -AssertionResult IsSubstring( +GTEST_API_ AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const ::std::string& needle, const ::std::string& haystack); -AssertionResult IsNotSubstring( +GTEST_API_ AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const ::std::string& needle, const ::std::string& haystack); -#endif // GTEST_HAS_STD_STRING #if GTEST_HAS_STD_WSTRING -AssertionResult IsSubstring( +GTEST_API_ AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const ::std::wstring& needle, const ::std::wstring& haystack); -AssertionResult IsNotSubstring( +GTEST_API_ AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const ::std::wstring& needle, const ::std::wstring& haystack); #endif // GTEST_HAS_STD_WSTRING @@ -865,35 +1513,57 @@ AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression, // Helper function for implementing ASSERT_NEAR. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. -AssertionResult DoubleNearPredFormat(const char* expr1, - const char* expr2, - const char* abs_error_expr, - double val1, - double val2, - double abs_error); +GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error); // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // A class that enables one to stream messages to assertion macros -class AssertHelper { +class GTEST_API_ AssertHelper { public: // Constructor. - AssertHelper(TestPartResultType type, const char* file, int line, + AssertHelper(TestPartResult::Type type, + const char* file, + int line, const char* message); + ~AssertHelper(); + // Message assignment is a semantic trick to enable assertion // streaming; see the GTEST_MESSAGE_ macro below. void operator=(const Message& message) const; + private: - TestPartResultType const type_; - const char* const file_; - int const line_; - String const message_; + // We put our data in a struct so that the size of the AssertHelper class can + // be as small as possible. This is important because gcc is incapable of + // re-using stack space even for temporary variables, so every EXPECT_EQ + // reserves stack space for another AssertHelper. + struct AssertHelperData { + AssertHelperData(TestPartResult::Type t, + const char* srcfile, + int line_num, + const char* msg) + : type(t), file(srcfile), line(line_num), message(msg) { } + + TestPartResult::Type const type; + const char* const file; + int const line; + String const message; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); + }; + + AssertHelperData* const data_; GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); }; } // namespace internal -#ifdef GTEST_HAS_PARAM_TEST +#if GTEST_HAS_PARAM_TEST // The abstract base class that all value-parameterized tests inherit from. // // This class adds support for accessing the test parameter value via @@ -981,10 +1651,22 @@ const T* TestWithParam<T>::parameter_ = NULL; #define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") // Generates a fatal failure with a generic message. -#define FAIL() GTEST_FATAL_FAILURE_("Failed") +#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") + +// Define this macro to 1 to omit the definition of FAIL(), which is a +// generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_FAIL +#define FAIL() GTEST_FAIL() +#endif // Generates a success with a generic message. -#define SUCCEED() GTEST_SUCCESS_("Succeeded") +#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") + +// Define this macro to 1 to omit the definition of SUCCEED(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_SUCCEED +#define SUCCEED() GTEST_SUCCEED() +#endif // Macros for testing exceptions. // @@ -1008,7 +1690,9 @@ const T* TestWithParam<T>::parameter_ = NULL; #define ASSERT_ANY_THROW(statement) \ GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) -// Boolean assertions. +// Boolean assertions. Condition can be either a Boolean expression or an +// AssertionResult. For more information on how to use AssertionResult with +// these macros see comments on that class. #define EXPECT_TRUE(condition) \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_NONFATAL_FAILURE_) @@ -1181,13 +1865,13 @@ const T* TestWithParam<T>::parameter_ = NULL; // Asserts that val1 is less than, or almost equal to, val2. Fails // otherwise. In particular, it fails if either val1 or val2 is NaN. -AssertionResult FloatLE(const char* expr1, const char* expr2, - float val1, float val2); -AssertionResult DoubleLE(const char* expr1, const char* expr2, - double val1, double val2); +GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2); +GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2); -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS // Macros that test for HRESULT failure and success, these are only useful // on Windows, and rely on Windows SDK macros and APIs to compile. @@ -1242,6 +1926,52 @@ AssertionResult DoubleLE(const char* expr1, const char* expr2, ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ __FILE__, __LINE__, ::testing::Message() << (message)) +namespace internal { + +// This template is declared, but intentionally undefined. +template <typename T1, typename T2> +struct StaticAssertTypeEqHelper; + +template <typename T> +struct StaticAssertTypeEqHelper<T, T> {}; + +} // namespace internal + +// Compile-time assertion for type equality. +// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are +// the same type. The value it returns is not interesting. +// +// Instead of making StaticAssertTypeEq a class template, we make it a +// function template that invokes a helper class template. This +// prevents a user from misusing StaticAssertTypeEq<T1, T2> by +// defining objects of that type. +// +// CAVEAT: +// +// When used inside a method of a class template, +// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is +// instantiated. For example, given: +// +// template <typename T> class Foo { +// public: +// void Bar() { testing::StaticAssertTypeEq<int, T>(); } +// }; +// +// the code: +// +// void Test1() { Foo<bool> foo; } +// +// will NOT generate a compiler error, as Foo<bool>::Bar() is never +// actually instantiated. Instead, you need: +// +// void Test2() { Foo<bool> foo; foo.Bar(); } +// +// to cause a compiler error. +template <typename T1, typename T2> +bool StaticAssertTypeEq() { + internal::StaticAssertTypeEqHelper<T1, T2>(); + return true; +} // Defines a test. // @@ -1268,10 +1998,15 @@ AssertionResult DoubleLE(const char* expr1, const char* expr2, // code. GetTestTypeId() is guaranteed to always return the same // value, as it always calls GetTypeId<>() from the Google Test // framework. -#define TEST(test_case_name, test_name)\ - GTEST_TEST_(test_case_name, test_name,\ +#define GTEST_TEST(test_case_name, test_name)\ + GTEST_TEST_(test_case_name, test_name, \ ::testing::Test, ::testing::internal::GetTestTypeId()) +// Define this macro to 1 to omit the definition of TEST(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_TEST +#define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) +#endif // Defines a test that uses a test fixture. // @@ -1300,7 +2035,7 @@ AssertionResult DoubleLE(const char* expr1, const char* expr2, // } #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>()) // Use this macro in main() to run all tests. It returns 0 if all diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h b/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h index 0769fca..e433084 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h @@ -46,9 +46,10 @@ GTEST_DECLARE_string_(internal_run_death_test); // Names of the flags (needed for parsing Google Test flags). const char kDeathTestStyleFlag[] = "death_test_style"; +const char kDeathTestUseFork[] = "death_test_use_fork"; const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST // DeathTest is a class that hides much of the complexity of the // GTEST_DEATH_TEST_ macro. It is abstract; its static Create method @@ -63,7 +64,7 @@ const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; // by wait(2) // exit code: The integer code passed to exit(3), _exit(2), or // returned from main() -class DeathTest { +class GTEST_API_ DeathTest { public: // Create returns false if there was an error determining the // appropriate action to take for the current death test; for example, @@ -120,7 +121,12 @@ class DeathTest { // the last death test. static const char* LastMessage(); + static void set_last_death_test_message(const String& message); + private: + // A string containing a description of the outcome of the last death test. + static String last_death_test_message_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); }; @@ -141,13 +147,13 @@ class DefaultDeathTestFactory : public DeathTestFactory { // Returns true if exit_status describes a process that was terminated // by a signal, or exited normally with a nonzero exit code. -bool ExitedUnsuccessfully(int exit_status); +GTEST_API_ bool ExitedUnsuccessfully(int exit_status); // This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, // ASSERT_EXIT*, and EXPECT_EXIT*. #define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (true) { \ + if (::testing::internal::AlwaysTrue()) { \ const ::testing::internal::RE& gtest_regex = (regex); \ ::testing::internal::DeathTest* gtest_dt; \ if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ @@ -166,7 +172,7 @@ bool ExitedUnsuccessfully(int exit_status); case ::testing::internal::DeathTest::EXECUTE_TEST: { \ ::testing::internal::DeathTest::ReturnSentinel \ gtest_sentinel(gtest_dt); \ - { statement; } \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ break; \ } \ @@ -178,14 +184,35 @@ bool ExitedUnsuccessfully(int exit_status); // The symbol "fail" here expands to something into which a message // can be streamed. -// A struct representing the parsed contents of the +// A class representing the parsed contents of the // --gtest_internal_run_death_test flag, as it existed when // RUN_ALL_TESTS was called. -struct InternalRunDeathTestFlag { - String file; - int line; - int index; - int status_fd; +class InternalRunDeathTestFlag { + public: + InternalRunDeathTestFlag(const String& a_file, + int a_line, + int an_index, + int a_write_fd) + : file_(a_file), line_(a_line), index_(an_index), + write_fd_(a_write_fd) {} + + ~InternalRunDeathTestFlag() { + if (write_fd_ >= 0) + posix::Close(write_fd_); + } + + String file() const { return file_; } + int line() const { return line_; } + int index() const { return index_; } + int write_fd() const { return write_fd_; } + + private: + String file_; + int line_; + int index_; + int write_fd_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); }; // Returns a newly created InternalRunDeathTestFlag object with fields @@ -193,6 +220,53 @@ struct InternalRunDeathTestFlag { // the flag is specified; otherwise returns NULL. InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); +#else // GTEST_HAS_DEATH_TEST + +// This macro is used for implementing macros such as +// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where +// death tests are not supported. Those macros must compile on such systems +// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on +// systems that support death tests. This allows one to write such a macro +// on a system that does not support death tests and be sure that it will +// compile on a death-test supporting system. +// +// Parameters: +// statement - A statement that a macro such as EXPECT_DEATH would test +// for program termination. This macro has to make sure this +// statement is compiled but not executed, to ensure that +// EXPECT_DEATH_IF_SUPPORTED compiles with a certain +// parameter iff EXPECT_DEATH compiles with it. +// regex - A regex that a macro such as EXPECT_DEATH would use to test +// the output of statement. This parameter has to be +// compiled but not evaluated by this macro, to ensure that +// this macro only accepts expressions that a macro such as +// EXPECT_DEATH would accept. +// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED +// and a return statement for ASSERT_DEATH_IF_SUPPORTED. +// This ensures that ASSERT_DEATH_IF_SUPPORTED will not +// compile inside functions where ASSERT_DEATH doesn't +// compile. +// +// The branch that has an always false condition is used to ensure that +// statement and regex are compiled (and thus syntactically correct) but +// never executed. The unreachable code macro protects the terminator +// statement from generating an 'unreachable code' warning in case +// statement unconditionally returns or throws. The Message constructor at +// the end allows the syntax of streaming additional messages into the +// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. +#define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_LOG_(WARNING) \ + << "Death tests are not supported on this platform.\n" \ + << "Statement '" #statement "' cannot be verified."; \ + } else if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::RE::PartialMatch(".*", (regex)); \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + terminator; \ + } else \ + ::testing::Message() + #endif // GTEST_HAS_DEATH_TEST } // namespace internal diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h b/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h index 9a0682a..4b76d79 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h @@ -34,7 +34,7 @@ // This header file declares classes and functions used internally by // Google Test. They are subject to change without notice. // -// This file is #included in testing/base/internal/gtest-internal.h +// This file is #included in <gtest/internal/gtest-internal.h>. // Do not include this header file separately! #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ @@ -56,7 +56,7 @@ namespace internal { // Names are NOT checked for syntax correctness -- no checking for illegal // characters, malformed paths, etc. -class FilePath { +class GTEST_API_ FilePath { public: FilePath() : pathname_("") { } FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } @@ -93,6 +93,12 @@ class FilePath { int number, const char* extension); + // Given directory = "dir", relative_path = "test.xml", + // returns "dir/test.xml". + // On Windows, uses \ as the separator rather than /. + static FilePath ConcatPaths(const FilePath& directory, + const FilePath& relative_path); + // Returns a pathname for a file that does not currently exist. The pathname // will be directory/base_name.extension or // directory/base_name_<number>.extension if directory/base_name.extension @@ -164,6 +170,9 @@ class FilePath { // root directory per disk drive.) bool IsRootDirectory() const; + // Returns true if pathname describes an absolute path. + bool IsAbsolutePath() const; + private: // Replaces multiple consecutive separators with a single separator. // For example, "bar///foo" becomes "bar/foo". Does not eliminate other @@ -180,9 +189,18 @@ class FilePath { // particular, RemoveTrailingPathSeparator() only removes one separator, and // it is called in CreateDirectoriesRecursively() assuming that it will change // a pathname from directory syntax (trailing separator) to filename syntax. + // + // On Windows this method also replaces the alternate path separator '/' with + // the primary path separator '\\', so that for example "bar\\/\\foo" becomes + // "bar\\foo". void Normalize(); + // Returns a pointer to the last occurence of a valid path separator in + // the FilePath. On Windows, for example, both '/' and '\' are valid path + // separators. Returns NULL if no path separator was found. + const char* FindLastPathSeparator() const; + String pathname_; }; // class FilePath diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h b/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h index b8f67c1..855b215 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h @@ -37,50 +37,51 @@ #ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ #define GTEST_SRC_GTEST_INTERNAL_INL_H_ -// GTEST_IMPLEMENTATION is defined iff the current translation unit is -// part of Google Test's implementation. -#ifndef GTEST_IMPLEMENTATION +// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is +// part of Google Test's implementation; otherwise it's undefined. +#if !GTEST_IMPLEMENTATION_ // A user is trying to include this from his code - just say no. #error "gtest-internal-inl.h is part of Google Test's internal implementation." #error "It must not be included except by Google Test itself." -#endif // GTEST_IMPLEMENTATION +#endif // GTEST_IMPLEMENTATION_ +#ifndef _WIN32_WCE +#include <errno.h> +#endif // !_WIN32_WCE #include <stddef.h> +#include <stdlib.h> // For strtoll/_strtoul64/malloc/free. +#include <string.h> // For memmove. + +#include <algorithm> +#include <string> +#include <vector> #include <gtest/internal/gtest-port.h> -#ifdef GTEST_OS_WINDOWS -#include <windows.h> // NOLINT +#if GTEST_OS_WINDOWS +#include <windows.h> // For DWORD. #endif // GTEST_OS_WINDOWS -#include <gtest/gtest.h> +#include <gtest/gtest.h> // NOLINT #include <gtest/gtest-spi.h> namespace testing { // Declares the flags. // -// We don't want the users to modify these flags in the code, but want -// Google Test's own unit tests to be able to access them. Therefore we -// declare them here as opposed to in gtest.h. -GTEST_DECLARE_bool_(break_on_failure); -GTEST_DECLARE_bool_(catch_exceptions); -GTEST_DECLARE_string_(color); -GTEST_DECLARE_string_(filter); -GTEST_DECLARE_bool_(list_tests); -GTEST_DECLARE_string_(output); -GTEST_DECLARE_bool_(print_time); -GTEST_DECLARE_int32_(repeat); -GTEST_DECLARE_int32_(stack_trace_depth); -GTEST_DECLARE_bool_(show_internal_stack_frames); +// We don't want the users to modify this flag in the code, but want +// Google Test's own unit tests to be able to access it. Therefore we +// declare it here as opposed to in gtest.h. +GTEST_DECLARE_bool_(death_test_use_fork); namespace internal { // The value of GetTestTypeId() as seen from within the Google Test // library. This is solely for testing GetTestTypeId(). -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"; @@ -88,7 +89,60 @@ const char kFilterFlag[] = "filter"; const char kListTestsFlag[] = "list_tests"; const char kOutputFlag[] = "output"; const char kPrintTimeFlag[] = "print_time"; +const char kRandomSeedFlag[] = "random_seed"; const char kRepeatFlag[] = "repeat"; +const char kShuffleFlag[] = "shuffle"; +const char kStackTraceDepthFlag[] = "stack_trace_depth"; +const char kThrowOnFailureFlag[] = "throw_on_failure"; + +// A valid random seed must be in [1, kMaxRandomSeed]. +const int kMaxRandomSeed = 99999; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +GTEST_API_ extern bool g_help_flag; + +// Returns the current time in milliseconds. +GTEST_API_ TimeInMillis GetTimeInMillis(); + +// Returns true iff Google Test should use colors in the output. +GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); + +// Formats the given time in milliseconds as seconds. +GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); + +// Parses a string for an Int32 flag, in the form of "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +GTEST_API_ bool ParseInt32Flag( + const char* str, const char* flag, Int32* value); + +// Returns a random seed in range [1, kMaxRandomSeed] based on the +// given --gtest_random_seed flag value. +inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { + const unsigned int raw_seed = (random_seed_flag == 0) ? + static_cast<unsigned int>(GetTimeInMillis()) : + static_cast<unsigned int>(random_seed_flag); + + // Normalizes the actual seed to range [1, kMaxRandomSeed] such that + // it's easy to type. + const int normalized_seed = + static_cast<int>((raw_seed - 1U) % + static_cast<unsigned int>(kMaxRandomSeed)) + 1; + return normalized_seed; +} + +// Returns the first valid random seed after 'seed'. The behavior is +// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is +// considered to be 1. +inline int GetNextRandomSeed(int seed) { + GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) + << "Invalid random seed " << seed << " - must be in [1, " + << kMaxRandomSeed << "]."; + const int next_seed = seed + 1; + return (next_seed > kMaxRandomSeed) ? 1 : next_seed; +} // This class saves the values of all Google Test flags in its c'tor, and // restores them in its d'tor. @@ -96,44 +150,62 @@ class GTestFlagSaver { public: // The c'tor. GTestFlagSaver() { + also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); break_on_failure_ = GTEST_FLAG(break_on_failure); catch_exceptions_ = GTEST_FLAG(catch_exceptions); color_ = GTEST_FLAG(color); death_test_style_ = GTEST_FLAG(death_test_style); + death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); filter_ = GTEST_FLAG(filter); internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); list_tests_ = GTEST_FLAG(list_tests); output_ = GTEST_FLAG(output); print_time_ = GTEST_FLAG(print_time); + random_seed_ = GTEST_FLAG(random_seed); repeat_ = GTEST_FLAG(repeat); + shuffle_ = GTEST_FLAG(shuffle); + stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); + throw_on_failure_ = GTEST_FLAG(throw_on_failure); } // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. ~GTestFlagSaver() { + GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; GTEST_FLAG(break_on_failure) = break_on_failure_; GTEST_FLAG(catch_exceptions) = catch_exceptions_; GTEST_FLAG(color) = color_; GTEST_FLAG(death_test_style) = death_test_style_; + GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; GTEST_FLAG(filter) = filter_; GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; GTEST_FLAG(list_tests) = list_tests_; GTEST_FLAG(output) = output_; GTEST_FLAG(print_time) = print_time_; + GTEST_FLAG(random_seed) = random_seed_; GTEST_FLAG(repeat) = repeat_; + GTEST_FLAG(shuffle) = shuffle_; + GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; + GTEST_FLAG(throw_on_failure) = throw_on_failure_; } private: // Fields for saving the original values of flags. + bool also_run_disabled_tests_; bool break_on_failure_; bool catch_exceptions_; String color_; String death_test_style_; + bool death_test_use_fork_; String filter_; String internal_run_death_test_; bool list_tests_; String output_; bool print_time_; bool pretty_; + internal::Int32 random_seed_; internal::Int32 repeat_; + bool shuffle_; + internal::Int32 stack_trace_depth_; + bool throw_on_failure_; } GTEST_ATTRIBUTE_UNUSED_; // Converts a Unicode code point to a narrow string in UTF-8 encoding. @@ -144,7 +216,7 @@ class GTestFlagSaver { // If the code_point is not a valid Unicode code point // (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output // as '(Invalid Unicode 0xXXXXXXXX)'. -char* CodePointToUtf8(UInt32 code_point, char* str); +GTEST_API_ char* CodePointToUtf8(UInt32 code_point, char* str); // Converts a wide string to a narrow string in UTF-8 encoding. // The wide string is assumed to have the following encoding: @@ -159,300 +231,95 @@ char* CodePointToUtf8(UInt32 code_point, char* str); // as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding // and contains invalid UTF-16 surrogate pairs, values in those pairs // will be encoded as individual Unicode characters from Basic Normal Plane. -String WideStringToUtf8(const wchar_t* str, int num_chars); - -// Returns the number of active threads, or 0 when there is an error. -size_t GetThreadCount(); - -// List is a simple singly-linked list container. -// -// We cannot use std::list as Microsoft's implementation of STL has -// problems when exception is disabled. There is a hack to work -// around this, but we've seen cases where the hack fails to work. -// -// TODO(wan): switch to std::list when we have a reliable fix for the -// STL problem, e.g. when we upgrade to the next version of Visual -// C++, or (more likely) switch to STLport. -// -// The element type must support copy constructor. - -// Forward declare List -template <typename E> // E is the element type. -class List; - -// ListNode is a node in a singly-linked list. It consists of an -// element and a pointer to the next node. The last node in the list -// has a NULL value for its next pointer. -template <typename E> // E is the element type. -class ListNode { - friend class List<E>; - - private: - - E element_; - ListNode * next_; - - // The c'tor is private s.t. only in the ListNode class and in its - // friend class List we can create a ListNode object. - // - // Creates a node with a given element value. The next pointer is - // set to NULL. - // - // ListNode does NOT have a default constructor. Always use this - // constructor (with parameter) to create a ListNode object. - explicit ListNode(const E & element) : element_(element), next_(NULL) {} - - // We disallow copying ListNode - GTEST_DISALLOW_COPY_AND_ASSIGN_(ListNode); - - public: - - // Gets the element in this node. - E & element() { return element_; } - const E & element() const { return element_; } - - // Gets the next node in the list. - ListNode * next() { return next_; } - const ListNode * next() const { return next_; } -}; - - -// List is a simple singly-linked list container. -template <typename E> // E is the element type. -class List { - public: - - // Creates an empty list. - List() : head_(NULL), last_(NULL), size_(0) {} - - // D'tor. - virtual ~List(); - - // Clears the list. - void Clear() { - if ( size_ > 0 ) { - // 1. Deletes every node. - ListNode<E> * node = head_; - ListNode<E> * next = node->next(); - for ( ; ; ) { - delete node; - node = next; - if ( node == NULL ) break; - next = node->next(); - } - - // 2. Resets the member variables. - head_ = last_ = NULL; - size_ = 0; - } - } - - // Gets the number of elements. - int size() const { return size_; } - - // Returns true if the list is empty. - bool IsEmpty() const { return size() == 0; } - - // Gets the first element of the list, or NULL if the list is empty. - ListNode<E> * Head() { return head_; } - const ListNode<E> * Head() const { return head_; } - - // Gets the last element of the list, or NULL if the list is empty. - ListNode<E> * Last() { return last_; } - const ListNode<E> * Last() const { return last_; } - - // Adds an element to the end of the list. A copy of the element is - // created using the copy constructor, and then stored in the list. - // Changes made to the element in the list doesn't affect the source - // object, and vice versa. - void PushBack(const E & element) { - ListNode<E> * new_node = new ListNode<E>(element); - - if ( size_ == 0 ) { - head_ = last_ = new_node; - size_ = 1; - } else { - last_->next_ = new_node; - last_ = new_node; - size_++; - } - } - - // Adds an element to the beginning of this list. - void PushFront(const E& element) { - ListNode<E>* const new_node = new ListNode<E>(element); - - if ( size_ == 0 ) { - head_ = last_ = new_node; - size_ = 1; - } else { - new_node->next_ = head_; - head_ = new_node; - size_++; - } - } - - // Removes an element from the beginning of this list. If the - // result argument is not NULL, the removed element is stored in the - // memory it points to. Otherwise the element is thrown away. - // Returns true iff the list wasn't empty before the operation. - bool PopFront(E* result) { - if (size_ == 0) return false; - - if (result != NULL) { - *result = head_->element_; - } - - ListNode<E>* const old_head = head_; - size_--; - if (size_ == 0) { - head_ = last_ = NULL; - } else { - head_ = head_->next_; - } - delete old_head; - - return true; - } - - // Inserts an element after a given node in the list. It's the - // caller's responsibility to ensure that the given node is in the - // list. If the given node is NULL, inserts the element at the - // front of the list. - ListNode<E>* InsertAfter(ListNode<E>* node, const E& element) { - if (node == NULL) { - PushFront(element); - return Head(); - } - - ListNode<E>* const new_node = new ListNode<E>(element); - new_node->next_ = node->next_; - node->next_ = new_node; - size_++; - if (node == last_) { - last_ = new_node; - } - - return new_node; - } - - // Returns the number of elements that satisfy a given predicate. - // The parameter 'predicate' is a Boolean function or functor that - // accepts a 'const E &', where E is the element type. - template <typename P> // P is the type of the predicate function/functor - int CountIf(P predicate) const { - int count = 0; - for ( const ListNode<E> * node = Head(); - node != NULL; - node = node->next() ) { - if ( predicate(node->element()) ) { - count++; - } - } - - return count; - } - - // Applies a function/functor to each element in the list. The - // parameter 'functor' is a function/functor that accepts a 'const - // E &', where E is the element type. This method does not change - // the elements. - template <typename F> // F is the type of the function/functor - void ForEach(F functor) const { - for ( const ListNode<E> * node = Head(); - node != NULL; - node = node->next() ) { - functor(node->element()); - } - } - - // Returns the first node whose element satisfies a given predicate, - // or NULL if none is found. The parameter 'predicate' is a - // function/functor that accepts a 'const E &', where E is the - // element type. This method does not change the elements. - template <typename P> // P is the type of the predicate function/functor. - const ListNode<E> * FindIf(P predicate) const { - for ( const ListNode<E> * node = Head(); - node != NULL; - node = node->next() ) { - if ( predicate(node->element()) ) { - return node; - } - } +GTEST_API_ String WideStringToUtf8(const wchar_t* str, int num_chars); + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded(); + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (e.g., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +GTEST_API_ bool ShouldShard(const char* total_shards_str, + const char* shard_index_str, + bool in_subprocess_for_death_test); + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error and +// and aborts. +GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +GTEST_API_ bool ShouldRunTestOnShard( + int total_shards, int shard_index, int test_id); + +// STL container utilities. + +// Returns the number of elements in the given container that satisfy +// the given predicate. +template <class Container, typename Predicate> +inline int CountIf(const Container& c, Predicate predicate) { + return static_cast<int>(std::count_if(c.begin(), c.end(), predicate)); +} - return NULL; - } +// Applies a function/functor to each element in the container. +template <class Container, typename Functor> +void ForEach(const Container& c, Functor functor) { + std::for_each(c.begin(), c.end(), functor); +} - template <typename P> - ListNode<E> * FindIf(P predicate) { - for ( ListNode<E> * node = Head(); - node != NULL; - node = node->next() ) { - if ( predicate(node->element() ) ) { - return node; - } - } +// Returns the i-th element of the vector, or default_value if i is not +// in range [0, v.size()). +template <typename E> +inline E GetElementOr(const std::vector<E>& v, int i, E default_value) { + return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i]; +} - return NULL; +// Performs an in-place shuffle of a range of the vector's elements. +// 'begin' and 'end' are element indices as an STL-style range; +// i.e. [begin, end) are shuffled, where 'end' == size() means to +// shuffle to the end of the vector. +template <typename E> +void ShuffleRange(internal::Random* random, int begin, int end, + std::vector<E>* v) { + const int size = static_cast<int>(v->size()); + GTEST_CHECK_(0 <= begin && begin <= size) + << "Invalid shuffle range start " << begin << ": must be in range [0, " + << size << "]."; + GTEST_CHECK_(begin <= end && end <= size) + << "Invalid shuffle range finish " << end << ": must be in range [" + << begin << ", " << size << "]."; + + // Fisher-Yates shuffle, from + // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + for (int range_width = end - begin; range_width >= 2; range_width--) { + const int last_in_range = begin + range_width - 1; + const int selected = begin + random->Generate(range_width); + std::swap((*v)[selected], (*v)[last_in_range]); } +} - private: - ListNode<E>* head_; // The first node of the list. - ListNode<E>* last_; // The last node of the list. - int size_; // The number of elements in the list. - - // We disallow copying List. - GTEST_DISALLOW_COPY_AND_ASSIGN_(List); -}; - -// The virtual destructor of List. +// Performs an in-place shuffle of the vector's elements. template <typename E> -List<E>::~List() { - Clear(); +inline void Shuffle(internal::Random* random, std::vector<E>* v) { + ShuffleRange(random, 0, static_cast<int>(v->size()), v); } // A function for deleting an object. Handy for being used as a // functor. template <typename T> -static void Delete(T * x) { +static void Delete(T* x) { delete x; } -// A copyable object representing a user specified test property which can be -// output as a key/value string pair. -// -// Don't inherit from TestProperty as its destructor is not virtual. -class TestProperty { - public: - // C'tor. TestProperty does NOT have a default constructor. - // Always use this constructor (with parameters) to create a - // TestProperty object. - TestProperty(const char* key, const char* value) : - key_(key), value_(value) { - } - - // Gets the user supplied key. - const char* key() const { - return key_.c_str(); - } - - // Gets the user supplied value. - const char* value() const { - return value_.c_str(); - } - - // Sets a new value, overriding the one supplied in the constructor. - void SetValue(const char* new_value) { - value_ = new_value; - } - - private: - // The key supplied by the user. - String key_; - // The value supplied by the user. - String value_; -}; - // A predicate that checks the key of a TestProperty against a known key. // // TestPropertyKeyIs is copyable. @@ -473,96 +340,6 @@ class TestPropertyKeyIs { String key_; }; -// The result of a single Test. This includes a list of -// TestPartResults, a list of TestProperties, a count of how many -// death tests there are in the Test, and how much time it took to run -// the Test. -// -// TestResult is not copyable. -class TestResult { - public: - // Creates an empty TestResult. - TestResult(); - - // D'tor. Do not inherit from TestResult. - ~TestResult(); - - // Gets the list of TestPartResults. - const internal::List<TestPartResult> & test_part_results() const { - return test_part_results_; - } - - // Gets the list of TestProperties. - const internal::List<internal::TestProperty> & test_properties() const { - return test_properties_; - } - - // Gets the number of successful test parts. - int successful_part_count() const; - - // Gets the number of failed test parts. - int failed_part_count() const; - - // Gets the number of all test parts. This is the sum of the number - // of successful test parts and the number of failed test parts. - int total_part_count() const; - - // Returns true iff the test passed (i.e. no test part failed). - bool Passed() const { return !Failed(); } - - // Returns true iff the test failed. - bool Failed() const { return failed_part_count() > 0; } - - // Returns true iff the test fatally failed. - bool HasFatalFailure() const; - - // Returns the elapsed time, in milliseconds. - TimeInMillis elapsed_time() const { return elapsed_time_; } - - // Sets the elapsed time. - void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } - - // Adds a test part result to the list. - void AddTestPartResult(const TestPartResult& test_part_result); - - // Adds a test property to the list. The property is validated and may add - // a non-fatal failure if invalid (e.g., if it conflicts with reserved - // key names). If a property is already recorded for the same key, the - // value will be updated, rather than storing multiple values for the same - // key. - void RecordProperty(const internal::TestProperty& test_property); - - // Adds a failure if the key is a reserved attribute of Google Test - // testcase tags. Returns true if the property is valid. - // TODO(russr): Validate attribute names are legal and human readable. - static bool ValidateTestProperty(const internal::TestProperty& test_property); - - // Returns the death test count. - int death_test_count() const { return death_test_count_; } - - // Increments the death test count, returning the new count. - int increment_death_test_count() { return ++death_test_count_; } - - // Clears the object. - void Clear(); - private: - // Protects mutable state of the property list and of owned properties, whose - // values may be updated. - internal::Mutex test_properites_mutex_; - - // The list of TestPartResults - internal::List<TestPartResult> test_part_results_; - // The list of TestProperties - internal::List<internal::TestProperty> test_properties_; - // Running count of death tests. - int death_test_count_; - // The elapsed time, in milliseconds. - TimeInMillis elapsed_time_; - - // We disallow copying TestResult. - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); -}; // class TestResult - class TestInfoImpl { public: TestInfoImpl(TestInfo* parent, const char* test_case_name, @@ -583,6 +360,12 @@ class TestInfoImpl { // Sets the is_disabled member. void set_is_disabled(bool is) { is_disabled_ = is; } + // Returns true if this test matches the filter specified by the user. + bool matches_filter() const { return matches_filter_; } + + // Sets the matches_filter member. + void set_matches_filter(bool matches) { matches_filter_ = matches; } + // Returns the test case name. const char* test_case_name() const { return test_case_name_.c_str(); } @@ -599,18 +382,13 @@ class TestInfoImpl { TypeId fixture_class_id() const { return fixture_class_id_; } // Returns the test result. - internal::TestResult* result() { return &result_; } - const internal::TestResult* result() const { return &result_; } + TestResult* result() { return &result_; } + const TestResult* result() const { return &result_; } // Creates the test object, runs it, records its result, and then // deletes it. void Run(); - // Calls the given TestInfo object's Run() method. - static void RunTest(TestInfo * test_info) { - test_info->impl()->Run(); - } - // Clears the test result. void ClearResult() { result_.Clear(); } @@ -629,150 +407,18 @@ class TestInfoImpl { const TypeId fixture_class_id_; // ID of the test fixture class bool should_run_; // True iff this test should run bool is_disabled_; // True iff this test is disabled + bool matches_filter_; // True if this test matches the + // user-specified filter. internal::TestFactoryBase* const factory_; // The factory that creates // the test object // This field is mutable and needs to be reset before running the // test for the second time. - internal::TestResult result_; + TestResult result_; GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfoImpl); }; -} // namespace internal - -// A test case, which consists of a list of TestInfos. -// -// TestCase is not copyable. -class TestCase { - public: - // Creates a TestCase with the given name. - // - // TestCase does NOT have a default constructor. Always use this - // constructor to create a TestCase object. - // - // Arguments: - // - // name: name of the test case - // set_up_tc: pointer to the function that sets up the test case - // tear_down_tc: pointer to the function that tears down the test case - TestCase(const char* name, const char* comment, - Test::SetUpTestCaseFunc set_up_tc, - Test::TearDownTestCaseFunc tear_down_tc); - - // Destructor of TestCase. - virtual ~TestCase(); - - // Gets the name of the TestCase. - const char* name() const { return name_.c_str(); } - - // Returns the test case comment. - const char* comment() const { return comment_.c_str(); } - - // Returns true if any test in this test case should run. - bool should_run() const { return should_run_; } - - // Sets the should_run member. - void set_should_run(bool should) { should_run_ = should; } - - // Gets the (mutable) list of TestInfos in this TestCase. - internal::List<TestInfo*>& test_info_list() { return *test_info_list_; } - - // Gets the (immutable) list of TestInfos in this TestCase. - const internal::List<TestInfo *> & test_info_list() const { - return *test_info_list_; - } - - // Gets the number of successful tests in this test case. - int successful_test_count() const; - - // Gets the number of failed tests in this test case. - int failed_test_count() const; - - // Gets the number of disabled tests in this test case. - int disabled_test_count() const; - - // Get the number of tests in this test case that should run. - int test_to_run_count() const; - - // Gets the number of all tests in this test case. - int total_test_count() const; - - // Returns true iff the test case passed. - bool Passed() const { return !Failed(); } - - // Returns true iff the test case failed. - bool Failed() const { return failed_test_count() > 0; } - - // Returns the elapsed time, in milliseconds. - internal::TimeInMillis elapsed_time() const { return elapsed_time_; } - - // Adds a TestInfo to this test case. Will delete the TestInfo upon - // destruction of the TestCase object. - void AddTestInfo(TestInfo * test_info); - - // Finds and returns a TestInfo with the given name. If one doesn't - // exist, returns NULL. - TestInfo* GetTestInfo(const char* test_name); - - // Clears the results of all tests in this test case. - void ClearResult(); - - // Clears the results of all tests in the given test case. - static void ClearTestCaseResult(TestCase* test_case) { - test_case->ClearResult(); - } - - // Runs every test in this TestCase. - void Run(); - - // Runs every test in the given TestCase. - static void RunTestCase(TestCase * test_case) { test_case->Run(); } - - // Returns true iff test passed. - static bool TestPassed(const TestInfo * test_info) { - const internal::TestInfoImpl* const impl = test_info->impl(); - return impl->should_run() && impl->result()->Passed(); - } - - // Returns true iff test failed. - static bool TestFailed(const TestInfo * test_info) { - const internal::TestInfoImpl* const impl = test_info->impl(); - return impl->should_run() && impl->result()->Failed(); - } - - // Returns true iff test is disabled. - static bool TestDisabled(const TestInfo * test_info) { - return test_info->impl()->is_disabled(); - } - - // Returns true if the given test should run. - static bool ShouldRunTest(const TestInfo *test_info) { - return test_info->impl()->should_run(); - } - - private: - // Name of the test case. - internal::String name_; - // Comment on the test case. - internal::String comment_; - // List of TestInfos. - internal::List<TestInfo*>* test_info_list_; - // Pointer to the function that sets up the test case. - Test::SetUpTestCaseFunc set_up_tc_; - // Pointer to the function that tears down the test case. - Test::TearDownTestCaseFunc tear_down_tc_; - // True iff any test in this test case should run. - bool should_run_; - // Elapsed time, in milliseconds. - internal::TimeInMillis elapsed_time_; - - // We disallow copying TestCases. - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); -}; - -namespace internal { - // Class UnitTestOptions. // // This class contains functions for processing options the user @@ -783,16 +429,17 @@ namespace internal { // test filter using either GTEST_FILTER or --gtest_filter. If both // the variable and the flag are present, the latter overrides the // former. -class UnitTestOptions { +class GTEST_API_ UnitTestOptions { public: // Functions for processing the gtest_output flag. // Returns the output format, or "" for normal printed output. static String GetOutputFormat(); - // Returns the name of the requested output file, or the default if none - // was explicitly specified. - static String GetOutputFile(); + // Returns the absolute path of the requested output file, or the + // default (test_detail.xml in the original working directory) if + // none was explicitly specified. + static String GetAbsolutePathToOutputFile(); // Functions for processing the gtest_filter flag. @@ -808,7 +455,7 @@ class UnitTestOptions { static bool FilterMatchesTest(const String &test_case_name, const String &test_name); -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS // Function for supporting the gtest_catch_exception flag. // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the @@ -824,7 +471,7 @@ class UnitTestOptions { // Returns the current application's name, removing directory path if that // is present. Used by UnitTestOptions::GetOutputFile. -FilePath GetCurrentExecutableName(); +GTEST_API_ FilePath GetCurrentExecutableName(); // The role interface for getting the OS stack trace as a string. class OsStackTraceGetterInterface { @@ -852,7 +499,7 @@ class OsStackTraceGetterInterface { // A working implementation of the OsStackTraceGetterInterface interface. class OsStackTraceGetter : public OsStackTraceGetterInterface { public: - OsStackTraceGetter() {} + OsStackTraceGetter() : caller_frame_(NULL) {} virtual String CurrentStackTrace(int max_depth, int skip_count); virtual void UponLeavingGTest(); @@ -891,6 +538,8 @@ class DefaultGlobalTestPartResultReporter private: UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); }; // This is the default per thread test part result reporter used in @@ -905,13 +554,15 @@ class DefaultPerThreadTestPartResultReporter private: UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); }; // The private implementation of the UnitTest class. We don't protect // the methods under a mutex, as this class is not accessible by a // user and the UnitTest class that delegates work to this class does // proper locking. -class UnitTestImpl { +class GTEST_API_ UnitTestImpl { public: explicit UnitTestImpl(UnitTest* parent); virtual ~UnitTestImpl(); @@ -977,26 +628,29 @@ class UnitTestImpl { return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); } - // Returns the TestResult for the test that's currently running, or - // the TestResult for the ad hoc test if no test is running. - internal::TestResult* current_test_result(); + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[i]; + } - // Returns the TestResult for the ad hoc test. - const internal::TestResult* ad_hoc_test_result() const { - return &ad_hoc_test_result_; + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i) { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[index]; } - // Sets the unit test result printer. - // - // Does nothing if the input and the current printer object are the - // same; otherwise, deletes the old printer object and makes the - // input the current printer. - void set_result_printer(UnitTestEventListenerInterface * result_printer); + // Provides access to the event listener list. + TestEventListeners* listeners() { return &listeners_; } + + // Returns the TestResult for the test that's currently running, or + // the TestResult for the ad hoc test if no test is running. + TestResult* current_test_result(); - // Returns the current unit test result printer if it is not NULL; - // otherwise, creates an appropriate result printer, makes it the - // current printer, and returns it. - UnitTestEventListenerInterface* result_printer(); + // Returns the TestResult for the ad hoc test. + const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } // Sets the OS stack trace getter. // @@ -1054,10 +708,8 @@ class UnitTestImpl { // before main() is reached. if (original_working_dir_.IsEmpty()) { original_working_dir_.Set(FilePath::GetCurrentDir()); - if (original_working_dir_.IsEmpty()) { - printf("%s\n", "Failed to get the current working directory."); - abort(); - } + GTEST_CHECK_(!original_working_dir_.IsEmpty()) + << "Failed to get the current working directory."; } GetTestCase(test_info->test_case_name(), @@ -1066,7 +718,7 @@ class UnitTestImpl { tear_down_tc)->AddTestInfo(test_info); } -#ifdef GTEST_HAS_PARAM_TEST +#if GTEST_HAS_PARAM_TEST // Returns ParameterizedTestCaseRegistry object used to keep track of // value-parameterized tests and instantiate and register them. internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { @@ -1075,15 +727,15 @@ class UnitTestImpl { #endif // GTEST_HAS_PARAM_TEST // Sets the TestCase object for the test that's currently running. - void set_current_test_case(TestCase* current_test_case) { - current_test_case_ = current_test_case; + void set_current_test_case(TestCase* a_current_test_case) { + current_test_case_ = a_current_test_case; } // Sets the TestInfo object for the test that's currently running. If // current_test_info is NULL, the assertion results will be stored in // ad_hoc_test_result_. - void set_current_test_info(TestInfo* current_test_info) { - current_test_info_ = current_test_info; + void set_current_test_info(TestInfo* a_current_test_info) { + current_test_info_ = a_current_test_info; } // Registers all parameterized tests defined using TEST_P and @@ -1104,45 +756,50 @@ class UnitTestImpl { // Clears the results of all tests, including the ad hoc test. void ClearResult() { - test_cases_.ForEach(TestCase::ClearTestCaseResult); + ForEach(test_cases_, TestCase::ClearTestCaseResult); ad_hoc_test_result_.Clear(); } + enum ReactionToSharding { + HONOR_SHARDING_PROTOCOL, + IGNORE_SHARDING_PROTOCOL + }; + // Matches the full name of each test against the user-specified // filter to decide whether the test should run, then records the // result in each TestCase and TestInfo object. + // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests + // based on sharding variables in the environment. // Returns the number of tests that should run. - int FilterTests(); + int FilterTests(ReactionToSharding shard_tests); - // Lists all the tests by name. - void ListAllTests(); + // Prints the names of the tests matching the user-specified filter flag. + void ListTestsMatchingFilter(); const TestCase* current_test_case() const { return current_test_case_; } TestInfo* current_test_info() { return current_test_info_; } const TestInfo* current_test_info() const { return current_test_info_; } - // Returns the list of environments that need to be set-up/torn-down + // Returns the vector of environments that need to be set-up/torn-down // before/after the tests are run. - internal::List<Environment*>* environments() { return &environments_; } - internal::List<Environment*>* environments_in_reverse_order() { - return &environments_in_reverse_order_; - } - - internal::List<TestCase*>* test_cases() { return &test_cases_; } - const internal::List<TestCase*>* test_cases() const { return &test_cases_; } + std::vector<Environment*>& environments() { return environments_; } // Getters for the per-thread Google Test trace stack. - internal::List<TraceInfo>* gtest_trace_stack() { - return gtest_trace_stack_.pointer(); + std::vector<TraceInfo>& gtest_trace_stack() { + return *(gtest_trace_stack_.pointer()); } - const internal::List<TraceInfo>* gtest_trace_stack() const { - return gtest_trace_stack_.pointer(); + const std::vector<TraceInfo>& gtest_trace_stack() const { + return gtest_trace_stack_.get(); } -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST + void InitDeathTestSubprocessControlInfo() { + internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); + } // Returns a pointer to the parsed --gtest_internal_run_death_test // flag, or NULL if that flag was not specified. // This information is useful only in a death test child process. + // Must not be called before a call to InitGoogleTest. const InternalRunDeathTestFlag* internal_run_death_test_flag() const { return internal_run_death_test_flag_.get(); } @@ -1152,9 +809,35 @@ class UnitTestImpl { return death_test_factory_.get(); } + void SuppressTestEventsIfInSubprocess(); + friend class ReplaceDeathTestFactory; #endif // GTEST_HAS_DEATH_TEST + // Initializes the event listener performing XML output as specified by + // UnitTestOptions. Must not be called before InitGoogleTest. + void ConfigureXmlOutput(); + + // Performs initialization dependent upon flag values obtained in + // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to + // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest + // this function is also called from RunAllTests. Since this function can be + // called more than once, it has to be idempotent. + void PostFlagParsingInit(); + + // Gets the random seed used at the start of the current test iteration. + int random_seed() const { return random_seed_; } + + // Gets the random number generator. + internal::Random* random() { return &random_; } + + // Shuffles all test cases, and the tests within each test case, + // making sure that death tests are still run first. + void ShuffleTests(); + + // Restores the test cases and tests to their order before the first shuffle. + void UnshuffleTests(); + private: friend class ::testing::UnitTest; @@ -1180,15 +863,21 @@ class UnitTestImpl { internal::ThreadLocal<TestPartResultReporterInterface*> per_thread_test_part_result_reporter_; - // The list of environments that need to be set-up/torn-down - // before/after the tests are run. environments_in_reverse_order_ - // simply mirrors environments_ in reverse order. - internal::List<Environment*> environments_; - internal::List<Environment*> environments_in_reverse_order_; + // The vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector<Environment*> environments_; + + // The vector of TestCases in their original order. It owns the + // elements in the vector. + std::vector<TestCase*> test_cases_; - internal::List<TestCase*> test_cases_; // The list of TestCases. + // Provides a level of indirection for the test case list to allow + // easy shuffling and restoring the test case order. The i-th + // element of this vector is the index of the i-th test case in the + // shuffled order. + std::vector<int> test_case_indices_; -#ifdef GTEST_HAS_PARAM_TEST +#if GTEST_HAS_PARAM_TEST // ParameterizedTestRegistry object used to register value-parameterized // tests. internal::ParameterizedTestCaseRegistry parameterized_test_registry_; @@ -1197,13 +886,13 @@ class UnitTestImpl { bool parameterized_tests_registered_; #endif // GTEST_HAS_PARAM_TEST - // Points to the last death test case registered. Initially NULL. - internal::ListNode<TestCase*>* last_death_test_case_; + // Index of the last death test case registered. Initially -1. + int last_death_test_case_; // This points to the TestCase for the currently running test. It // changes as Google Test goes through one test case after another. // When no test is running, this is set to NULL and Google Test - // stores assertion results in ad_hoc_test_result_. Initally NULL. + // stores assertion results in ad_hoc_test_result_. Initially NULL. TestCase* current_test_case_; // This points to the TestInfo for the currently running test. It @@ -1220,13 +909,11 @@ class UnitTestImpl { // If an assertion is encountered when no TEST or TEST_F is running, // Google Test attributes the assertion result to an imaginary "ad hoc" // test, and records the result in ad_hoc_test_result_. - internal::TestResult ad_hoc_test_result_; + TestResult ad_hoc_test_result_; - // The unit test result printer. Will be deleted when the UnitTest - // object is destructed. By default, a plain text printer is used, - // but the user can set this field to use a custom printer if that - // is desired. - UnitTestEventListenerInterface* result_printer_; + // The list of event listeners that can be used to track events inside + // Google Test. + TestEventListeners listeners_; // The OS stack trace getter. Will be deleted when the UnitTest // object is destructed. By default, an OsStackTraceGetter is used, @@ -1234,10 +921,19 @@ class UnitTestImpl { // desired. OsStackTraceGetterInterface* os_stack_trace_getter_; + // True iff PostFlagParsingInit() has been called. + bool post_flag_parse_init_performed_; + + // The random number seed used at the beginning of the test run. + int random_seed_; + + // Our random number generator. + internal::Random random_; + // How long the test took to run, in milliseconds. TimeInMillis elapsed_time_; -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST // The decomposed components of the gtest_internal_run_death_test flag, // parsed when RUN_ALL_TESTS is called. internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_; @@ -1245,7 +941,7 @@ class UnitTestImpl { #endif // GTEST_HAS_DEATH_TEST // A per-thread stack of traces created by the SCOPED_TRACE() macro. - internal::ThreadLocal<internal::List<TraceInfo> > gtest_trace_stack_; + internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_; GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); }; // class UnitTestImpl @@ -1256,10 +952,121 @@ inline UnitTestImpl* GetUnitTestImpl() { return UnitTest::GetInstance()->impl(); } +// Internal helper functions for implementing the simple regular +// expression matcher. +GTEST_API_ bool IsInSet(char ch, const char* str); +GTEST_API_ bool IsDigit(char ch); +GTEST_API_ bool IsPunct(char ch); +GTEST_API_ bool IsRepeat(char ch); +GTEST_API_ bool IsWhiteSpace(char ch); +GTEST_API_ bool IsWordChar(char ch); +GTEST_API_ bool IsValidEscape(char ch); +GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); +GTEST_API_ bool ValidateRegex(const char* regex); +GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); +GTEST_API_ bool MatchRepetitionAndRegexAtHead( + bool escaped, char ch, char repeat, const char* regex, const char* str); +GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); + // Parses the command line for Google Test flags, without initializing // other parts of Google Test. -void ParseGoogleTestFlagsOnly(int* argc, char** argv); -void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); + +#if GTEST_HAS_DEATH_TEST + +// Returns the message describing the last system error, regardless of the +// platform. +String GetLastErrnoDescription(); + +#if GTEST_OS_WINDOWS +// Provides leak-safe Windows kernel handle ownership. +class AutoHandle { + public: + AutoHandle() : handle_(INVALID_HANDLE_VALUE) {} + explicit AutoHandle(HANDLE handle) : handle_(handle) {} + + ~AutoHandle() { Reset(); } + + HANDLE Get() const { return handle_; } + void Reset() { Reset(INVALID_HANDLE_VALUE); } + void Reset(HANDLE handle) { + if (handle != handle_) { + if (handle_ != INVALID_HANDLE_VALUE) + ::CloseHandle(handle_); + handle_ = handle; + } + } + + private: + HANDLE handle_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle); +}; +#endif // GTEST_OS_WINDOWS + +// Attempts to parse a string into a positive integer pointed to by the +// number parameter. Returns true if that is possible. +// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use +// it here. +template <typename Integer> +bool ParseNaturalNumber(const ::std::string& str, Integer* number) { + // Fail fast if the given string does not begin with a digit; + // this bypasses strtoXXX's "optional leading whitespace and plus + // or minus sign" semantics, which are undesirable here. + if (str.empty() || !isdigit(str[0])) { + return false; + } + errno = 0; + + char* end; + // BiggestConvertible is the largest integer type that system-provided + // string-to-number conversion routines can return. +#if GTEST_OS_WINDOWS && !defined(__GNUC__) + // MSVC and C++ Builder define __int64 instead of the standard long long. + typedef unsigned __int64 BiggestConvertible; + const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); +#else + typedef unsigned long long BiggestConvertible; // NOLINT + const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); +#endif // GTEST_OS_WINDOWS && !defined(__GNUC__) + const bool parse_success = *end == '\0' && errno == 0; + + // TODO(vladl@google.com): Convert this to compile time assertion when it is + // available. + GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); + + const Integer result = static_cast<Integer>(parsed); + if (parse_success && static_cast<BiggestConvertible>(result) == parsed) { + *number = result; + return true; + } + return false; +} +#endif // GTEST_HAS_DEATH_TEST + +// TestResult contains some private methods that should be hidden from +// Google Test user but are required for testing. This class allow our tests +// to access them. +// +// This class is supplied only for the purpose of testing Google Test's own +// constructs. Do not use it in user tests, either directly or indirectly. +class TestResultAccessor { + public: + static void RecordProperty(TestResult* test_result, + const TestProperty& property) { + test_result->RecordProperty(property); + } + + static void ClearTestPartResults(TestResult* test_result) { + test_result->ClearTestPartResults(); + } + + static const std::vector<testing::TestPartResult>& test_part_results( + const TestResult& test_result) { + return test_result.test_part_results(); + } +}; } // namespace internal } // namespace testing diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-internal.h b/utils/unittest/googletest/include/gtest/internal/gtest-internal.h index 242ffea..0b90132 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-internal.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-internal.h @@ -39,7 +39,7 @@ #include <gtest/internal/gtest-port.h> -#ifdef GTEST_OS_LINUX +#if GTEST_OS_LINUX #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> @@ -121,32 +121,26 @@ namespace testing { // Forward declaration of classes. +class AssertionResult; // Result of an assertion. class Message; // Represents a failure message. class Test; // Represents a test. -class TestCase; // A collection of related tests. -class TestPartResult; // Result of a test part. class TestInfo; // Information about a test. +class TestPartResult; // Result of a test part. class UnitTest; // A collection of test cases. -class UnitTestEventListenerInterface; // Listens to Google Test events. -class AssertionResult; // Result of an assertion. namespace internal { struct TraceInfo; // Information about a trace point. class ScopedTrace; // Implements scoped trace. class TestInfoImpl; // Opaque implementation of TestInfo -class TestResult; // Result of a single Test. class UnitTestImpl; // Opaque implementation of UnitTest -template <typename E> class List; // A generic list. -template <typename E> class ListNode; // A node in a generic list. - // How many times InitGoogleTest() has been called. extern int g_init_gtest_count; // The text used in failure messages to indicate the start of the // stack trace. -extern const char kStackTraceMarker[]; +GTEST_API_ extern const char kStackTraceMarker[]; // A secret type that Google Test users don't know about. It has no // definition on purpose. Therefore it's impossible to create a @@ -173,24 +167,21 @@ char (&IsNullLiteralHelper(...))[2]; // NOLINT // A compile-time bool constant that is true if and only if x is a // null pointer literal (i.e. NULL or any 0-valued compile-time // integral constant). -#ifdef GTEST_ELLIPSIS_NEEDS_COPY_ -// Passing non-POD classes through ellipsis (...) crashes the ARM -// compiler. The Nokia Symbian and the IBM XL C/C++ compiler try to -// instantiate a copy constructor for objects passed through ellipsis -// (...), failing for uncopyable objects. Hence we define this to -// false (and lose support for NULL detection). +#ifdef GTEST_ELLIPSIS_NEEDS_POD_ +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). #define GTEST_IS_NULL_LITERAL_(x) false #else #define GTEST_IS_NULL_LITERAL_(x) \ (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) -#endif // GTEST_ELLIPSIS_NEEDS_COPY_ +#endif // GTEST_ELLIPSIS_NEEDS_POD_ // Appends the user-supplied message to the Google-Test-generated message. -String AppendUserMessage(const String& gtest_msg, - const Message& user_msg); +GTEST_API_ String AppendUserMessage(const String& gtest_msg, + const Message& user_msg); // A helper class for creating scoped traces in user programs. -class ScopedTrace { +class GTEST_API_ ScopedTrace { public: // The c'tor pushes the given source file location and message onto // a trace stack maintained by Google Test. @@ -231,13 +222,13 @@ String StreamableToString(const T& streamable); // This overload makes sure that all pointers (including // those to char or wchar_t) are printed as raw pointers. template <typename T> -inline String FormatValueForFailureMessage(internal::true_type dummy, +inline String FormatValueForFailureMessage(internal::true_type /*dummy*/, T* pointer) { return StreamableToString(static_cast<const void*>(pointer)); } template <typename T> -inline String FormatValueForFailureMessage(internal::false_type dummy, +inline String FormatValueForFailureMessage(internal::false_type /*dummy*/, const T& value) { return StreamableToString(value); } @@ -269,8 +260,8 @@ inline String FormatForFailureMessage(T* pointer) { #endif // GTEST_NEEDS_IS_POINTER_ // These overloaded versions handle narrow and wide characters. -String FormatForFailureMessage(char ch); -String FormatForFailureMessage(wchar_t wchar); +GTEST_API_ String FormatForFailureMessage(char ch); +GTEST_API_ String FormatForFailureMessage(wchar_t wchar); // When this operand is a const char* or char*, and the other operand // is a ::std::string or ::string, we print this operand as a C string @@ -287,9 +278,7 @@ inline String FormatForComparisonFailureMessage(\ return operand1_printer(str);\ } -#if GTEST_HAS_STD_STRING GTEST_FORMAT_IMPL_(::std::string, String::ShowCStringQuoted) -#endif // GTEST_HAS_STD_STRING #if GTEST_HAS_STD_WSTRING GTEST_FORMAT_IMPL_(::std::wstring, String::ShowWideCStringQuoted) #endif // GTEST_HAS_STD_WSTRING @@ -318,12 +307,18 @@ GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted) // The ignoring_case parameter is true iff the assertion is a // *_STRCASEEQ*. When it's true, the string " (ignoring case)" will // be inserted into the message. -AssertionResult EqFailure(const char* expected_expression, - const char* actual_expression, - const String& expected_value, - const String& actual_value, - bool ignoring_case); - +GTEST_API_ AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const String& expected_value, + const String& actual_value, + bool ignoring_case); + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +GTEST_API_ String GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value); // This template class represents an IEEE floating-point number // (either single-precision or double-precision, depending on the @@ -403,7 +398,7 @@ class FloatingPoint { // around may change its bits, although the new value is guaranteed // to be also a NAN. Therefore, don't expect this constructor to // preserve the bits in x when x is a NAN. - explicit FloatingPoint(const RawType& x) : value_(x) {} + explicit FloatingPoint(const RawType& x) { u_.value_ = x; } // Static methods @@ -412,8 +407,8 @@ class FloatingPoint { // This function is needed to test the AlmostEquals() method. static RawType ReinterpretBits(const Bits bits) { FloatingPoint fp(0); - fp.bits_ = bits; - return fp.value_; + fp.u_.bits_ = bits; + return fp.u_.value_; } // Returns the floating-point number that represent positive infinity. @@ -424,16 +419,16 @@ class FloatingPoint { // Non-static methods // Returns the bits that represents this number. - const Bits &bits() const { return bits_; } + const Bits &bits() const { return u_.bits_; } // Returns the exponent bits of this number. - Bits exponent_bits() const { return kExponentBitMask & bits_; } + Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } // Returns the fraction bits of this number. - Bits fraction_bits() const { return kFractionBitMask & bits_; } + Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } // Returns the sign bit of this number. - Bits sign_bit() const { return kSignBitMask & bits_; } + Bits sign_bit() const { return kSignBitMask & u_.bits_; } // Returns true iff this is NAN (not a number). bool is_nan() const { @@ -453,10 +448,17 @@ class FloatingPoint { // a NAN must return false. if (is_nan() || rhs.is_nan()) return false; - return DistanceBetweenSignAndMagnitudeNumbers(bits_, rhs.bits_) <= kMaxUlps; + return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) + <= kMaxUlps; } private: + // The data type used to store the actual floating-point number. + union FloatingPointUnion { + RawType value_; // The raw floating-point number. + Bits bits_; // The bits that represent the number. + }; + // Converts an integer from the sign-and-magnitude representation to // the biased representation. More precisely, let N be 2 to the // power of (kBitCount - 1), an integer x is represented by the @@ -491,10 +493,7 @@ class FloatingPoint { return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); } - union { - RawType value_; // The raw floating-point number. - Bits bits_; // The bits that represent the number. - }; + FloatingPointUnion u_; }; // Typedefs the instances of the FloatingPoint template class that we @@ -539,7 +538,7 @@ TypeId GetTypeId() { // ::testing::Test, as the latter may give the wrong result due to a // suspected linker bug when compiling Google Test as a Mac OS X // framework. -TypeId GetTestTypeId(); +GTEST_API_ TypeId GetTestTypeId(); // Defines the abstract factory interface that creates instances // of a Test object. @@ -566,14 +565,16 @@ class TestFactoryImpl : public TestFactoryBase { virtual Test* CreateTest() { return new TestClass; } }; -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS // Predicate-formatters for implementing the HRESULT checking macros // {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} // We pass a long instead of HRESULT to avoid causing an // include dependency for the HRESULT type. -AssertionResult IsHRESULTSuccess(const char* expr, long hr); // NOLINT -AssertionResult IsHRESULTFailure(const char* expr, long hr); // NOLINT +GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, + long hr); // NOLINT +GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, + long hr); // NOLINT #endif // GTEST_OS_WINDOWS @@ -612,7 +613,7 @@ typedef void (*TearDownTestCaseFunc)(); // factory: pointer to the factory that creates a test object. // The newly created TestInfo instance will assume // ownership of the factory object. -TestInfo* MakeAndRegisterTestInfo( +GTEST_API_ TestInfo* MakeAndRegisterTestInfo( const char* test_case_name, const char* name, const char* test_case_comment, const char* comment, TypeId fixture_class_id, @@ -620,10 +621,15 @@ TestInfo* MakeAndRegisterTestInfo( TearDownTestCaseFunc tear_down_tc, TestFactoryBase* factory); -#if defined(GTEST_HAS_TYPED_TEST) || defined(GTEST_HAS_TYPED_TEST_P) +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr); + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P // State of the definition of a type-parameterized test case. -class TypedTestCasePState { +class GTEST_API_ TypedTestCasePState { public: TypedTestCasePState() : registered_(false) {} @@ -636,7 +642,8 @@ class TypedTestCasePState { fprintf(stderr, "%s Test %s must be defined before " "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", FormatFileLocation(file, line).c_str(), test_name, case_name); - abort(); + fflush(stderr); + posix::Abort(); } defined_test_names_.insert(test_name); return true; @@ -745,8 +752,8 @@ class TypeParameterizedTestCase { template <GTEST_TEMPLATE_ Fixture, typename Types> class TypeParameterizedTestCase<Fixture, Templates0, Types> { public: - static bool Register(const char* prefix, const char* case_name, - const char* test_names) { + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/) { return true; } }; @@ -763,10 +770,39 @@ class TypeParameterizedTestCase<Fixture, Templates0, Types> { // For example, if Foo() calls Bar(), which in turn calls // GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in // the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. -String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test, int skip_count); +GTEST_API_ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test, + int skip_count); + +// Helpers for suppressing warnings on unreachable code or constant +// condition. + +// Always returns true. +GTEST_API_ bool AlwaysTrue(); + +// Always returns false. +inline bool AlwaysFalse() { return !AlwaysTrue(); } + +// A simple Linear Congruential Generator for generating random +// numbers with a uniform distribution. Unlike rand() and srand(), it +// doesn't use global state (and therefore can't interfere with user +// code). Unlike rand_r(), it's portable. An LCG isn't very random, +// but it's good enough for our purposes. +class GTEST_API_ Random { + public: + static const UInt32 kMaxRange = 1u << 31; + + explicit Random(UInt32 seed) : state_(seed) {} -// Returns the number of failed test parts in the given test result object. -int GetFailedPartCount(const TestResult* result); + void Reseed(UInt32 seed) { state_ = seed; } + + // Generates a random number from [0, range). Crashes if 'range' is + // 0 or greater than kMaxRange. + UInt32 Generate(UInt32 range); + + private: + UInt32 state_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); +}; } // namespace internal } // namespace testing @@ -776,20 +812,26 @@ int GetFailedPartCount(const TestResult* result); = ::testing::Message() #define GTEST_FATAL_FAILURE_(message) \ - return GTEST_MESSAGE_(message, ::testing::TPRT_FATAL_FAILURE) + return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) #define GTEST_NONFATAL_FAILURE_(message) \ - GTEST_MESSAGE_(message, ::testing::TPRT_NONFATAL_FAILURE) + GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) #define GTEST_SUCCESS_(message) \ - GTEST_MESSAGE_(message, ::testing::TPRT_SUCCESS) + GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) + +// Suppresses MSVC warnings 4072 (unreachable code) for the code following +// statement if it returns or throws (or doesn't return or throw in some +// situations). +#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ + if (::testing::internal::AlwaysTrue()) { statement; } #define GTEST_TEST_THROW_(statement, expected_exception, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (const char* gtest_msg = "") { \ bool gtest_caught_expected = false; \ try { \ - statement; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ catch (expected_exception const&) { \ gtest_caught_expected = true; \ @@ -813,7 +855,7 @@ int GetFailedPartCount(const TestResult* result); GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (const char* gtest_msg = "") { \ try { \ - statement; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ catch (...) { \ gtest_msg = "Expected: " #statement " doesn't throw an exception.\n" \ @@ -829,7 +871,7 @@ int GetFailedPartCount(const TestResult* result); if (const char* gtest_msg = "") { \ bool gtest_caught_any = false; \ try { \ - statement; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ catch (...) { \ gtest_caught_any = true; \ @@ -844,18 +886,23 @@ int GetFailedPartCount(const TestResult* result); fail(gtest_msg) -#define GTEST_TEST_BOOLEAN_(boolexpr, booltext, actual, expected, fail) \ +// Implements Boolean test assertions such as EXPECT_TRUE. expression can be +// either a boolean expression or an AssertionResult. text is a textual +// represenation of expression as it was passed into the EXPECT_TRUE. +#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (boolexpr) \ + if (const ::testing::AssertionResult gtest_ar_ = \ + ::testing::AssertionResult(expression)) \ ; \ else \ - fail("Value of: " booltext "\n Actual: " #actual "\nExpected: " #expected) + fail(::testing::internal::GetBoolAssertionFailureMessage(\ + gtest_ar_, text, #actual, #expected).c_str()) #define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (const char* gtest_msg = "") { \ ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ - { statement; } \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ gtest_msg = "Expected: " #statement " doesn't generate new fatal " \ "failures in the current thread.\n" \ diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h b/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h index d4c7a39..2404ea8 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h @@ -77,7 +77,7 @@ namespace testing { namespace internal { // Protects copying of all linked_ptr objects. -extern Mutex g_linked_ptr_mutex; +GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); // This is used internally by all instances of linked_ptr<>. It needs to be // a non-template class because different types of linked_ptr<> can refer to diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h b/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h index 17f3f7b..ab4ab56 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h @@ -44,13 +44,30 @@ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +#include <gtest/internal/gtest-param-util.h> #include <gtest/internal/gtest-port.h> -#ifdef GTEST_HAS_PARAM_TEST - -#include <gtest/internal/gtest-param-util.h> +#if GTEST_HAS_PARAM_TEST namespace testing { + +// Forward declarations of ValuesIn(), which is implemented in +// include/gtest/gtest-param-test.h. +template <typename ForwardIterator> +internal::ParamGenerator< + typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn( + ForwardIterator begin, ForwardIterator end); + +template <typename T, size_t N> +internal::ParamGenerator<T> ValuesIn(const T (&array)[N]); + +template <class Container> +internal::ParamGenerator<typename Container::value_type> ValuesIn( + const Container& container); + namespace internal { // Used in the Values() function to provide polymorphic capabilities. @@ -63,6 +80,9 @@ class ValueArray1 { operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray1& other); + const T1 v1_; }; @@ -78,6 +98,9 @@ class ValueArray2 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray2& other); + const T1 v1_; const T2 v2_; }; @@ -94,6 +117,9 @@ class ValueArray3 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray3& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -112,6 +138,9 @@ class ValueArray4 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray4& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -131,6 +160,9 @@ class ValueArray5 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray5& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -152,6 +184,9 @@ class ValueArray6 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray6& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -174,6 +209,9 @@ class ValueArray7 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray7& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -198,6 +236,9 @@ class ValueArray8 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray8& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -223,6 +264,9 @@ class ValueArray9 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray9& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -249,6 +293,9 @@ class ValueArray10 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray10& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -277,6 +324,9 @@ class ValueArray11 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray11& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -307,6 +357,9 @@ class ValueArray12 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray12& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -339,6 +392,9 @@ class ValueArray13 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray13& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -372,6 +428,9 @@ class ValueArray14 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray14& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -406,6 +465,9 @@ class ValueArray15 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray15& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -443,6 +505,9 @@ class ValueArray16 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray16& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -481,6 +546,9 @@ class ValueArray17 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray17& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -520,6 +588,9 @@ class ValueArray18 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray18& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -560,6 +631,9 @@ class ValueArray19 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray19& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -602,6 +676,9 @@ class ValueArray20 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray20& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -646,6 +723,9 @@ class ValueArray21 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray21& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -691,6 +771,9 @@ class ValueArray22 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray22& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -739,6 +822,9 @@ class ValueArray23 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray23& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -788,6 +874,9 @@ class ValueArray24 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray24& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -838,6 +927,9 @@ class ValueArray25 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray25& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -890,6 +982,9 @@ class ValueArray26 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray26& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -944,6 +1039,9 @@ class ValueArray27 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray27& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -999,6 +1097,9 @@ class ValueArray28 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray28& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1055,6 +1156,9 @@ class ValueArray29 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray29& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1113,6 +1217,9 @@ class ValueArray30 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray30& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1173,6 +1280,9 @@ class ValueArray31 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray31& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1234,6 +1344,9 @@ class ValueArray32 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray32& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1297,6 +1410,9 @@ class ValueArray33 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray33& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1361,6 +1477,9 @@ class ValueArray34 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray34& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1427,6 +1546,9 @@ class ValueArray35 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray35& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1495,6 +1617,9 @@ class ValueArray36 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray36& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1565,6 +1690,9 @@ class ValueArray37 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray37& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1636,6 +1764,9 @@ class ValueArray38 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray38& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1708,6 +1839,9 @@ class ValueArray39 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray39& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1782,6 +1916,9 @@ class ValueArray40 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray40& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1858,6 +1995,9 @@ class ValueArray41 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray41& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -1935,6 +2075,9 @@ class ValueArray42 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray42& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -2013,6 +2156,9 @@ class ValueArray43 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray43& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -2093,6 +2239,9 @@ class ValueArray44 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray44& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -2174,6 +2323,9 @@ class ValueArray45 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray45& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -2257,6 +2409,9 @@ class ValueArray46 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray46& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -2343,6 +2498,9 @@ class ValueArray47 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray47& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -2430,6 +2588,9 @@ class ValueArray48 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray48& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -2518,6 +2679,9 @@ class ValueArray49 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray49& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -2607,6 +2771,9 @@ class ValueArray50 { } private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray50& other); + const T1 v1_; const T2 v2_; const T3 v3_; @@ -2659,7 +2826,7 @@ class ValueArray50 { const T50 v50_; }; -#ifdef GTEST_HAS_COMBINE +#if GTEST_HAS_COMBINE // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Generates values from the Cartesian product of values produced @@ -2757,6 +2924,9 @@ class CartesianProductGenerator2 current2_ == end2_; } + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<ParamType>* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. @@ -2767,11 +2937,14 @@ class CartesianProductGenerator2 const typename ParamGenerator<T2>::iterator end2_; typename ParamGenerator<T2>::iterator current2_; ParamType current_value_; - }; + }; // class CartesianProductGenerator2::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator2& other); const ParamGenerator<T1> g1_; const ParamGenerator<T2> g2_; -}; +}; // class CartesianProductGenerator2 template <typename T1, typename T2, typename T3> @@ -2879,6 +3052,9 @@ class CartesianProductGenerator3 current3_ == end3_; } + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<ParamType>* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. @@ -2892,12 +3068,15 @@ class CartesianProductGenerator3 const typename ParamGenerator<T3>::iterator end3_; typename ParamGenerator<T3>::iterator current3_; ParamType current_value_; - }; + }; // class CartesianProductGenerator3::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator3& other); const ParamGenerator<T1> g1_; const ParamGenerator<T2> g2_; const ParamGenerator<T3> g3_; -}; +}; // class CartesianProductGenerator3 template <typename T1, typename T2, typename T3, typename T4> @@ -3020,6 +3199,9 @@ class CartesianProductGenerator4 current4_ == end4_; } + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<ParamType>* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. @@ -3036,13 +3218,16 @@ class CartesianProductGenerator4 const typename ParamGenerator<T4>::iterator end4_; typename ParamGenerator<T4>::iterator current4_; ParamType current_value_; - }; + }; // class CartesianProductGenerator4::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator4& other); const ParamGenerator<T1> g1_; const ParamGenerator<T2> g2_; const ParamGenerator<T3> g3_; const ParamGenerator<T4> g4_; -}; +}; // class CartesianProductGenerator4 template <typename T1, typename T2, typename T3, typename T4, typename T5> @@ -3177,6 +3362,9 @@ class CartesianProductGenerator5 current5_ == end5_; } + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<ParamType>* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. @@ -3196,14 +3384,17 @@ class CartesianProductGenerator5 const typename ParamGenerator<T5>::iterator end5_; typename ParamGenerator<T5>::iterator current5_; ParamType current_value_; - }; + }; // class CartesianProductGenerator5::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator5& other); const ParamGenerator<T1> g1_; const ParamGenerator<T2> g2_; const ParamGenerator<T3> g3_; const ParamGenerator<T4> g4_; const ParamGenerator<T5> g5_; -}; +}; // class CartesianProductGenerator5 template <typename T1, typename T2, typename T3, typename T4, typename T5, @@ -3353,6 +3544,9 @@ class CartesianProductGenerator6 current6_ == end6_; } + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<ParamType>* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. @@ -3375,7 +3569,10 @@ class CartesianProductGenerator6 const typename ParamGenerator<T6>::iterator end6_; typename ParamGenerator<T6>::iterator current6_; ParamType current_value_; - }; + }; // class CartesianProductGenerator6::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator6& other); const ParamGenerator<T1> g1_; const ParamGenerator<T2> g2_; @@ -3383,7 +3580,7 @@ class CartesianProductGenerator6 const ParamGenerator<T4> g4_; const ParamGenerator<T5> g5_; const ParamGenerator<T6> g6_; -}; +}; // class CartesianProductGenerator6 template <typename T1, typename T2, typename T3, typename T4, typename T5, @@ -3546,6 +3743,9 @@ class CartesianProductGenerator7 current7_ == end7_; } + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<ParamType>* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. @@ -3571,7 +3771,10 @@ class CartesianProductGenerator7 const typename ParamGenerator<T7>::iterator end7_; typename ParamGenerator<T7>::iterator current7_; ParamType current_value_; - }; + }; // class CartesianProductGenerator7::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator7& other); const ParamGenerator<T1> g1_; const ParamGenerator<T2> g2_; @@ -3580,7 +3783,7 @@ class CartesianProductGenerator7 const ParamGenerator<T5> g5_; const ParamGenerator<T6> g6_; const ParamGenerator<T7> g7_; -}; +}; // class CartesianProductGenerator7 template <typename T1, typename T2, typename T3, typename T4, typename T5, @@ -3758,6 +3961,9 @@ class CartesianProductGenerator8 current8_ == end8_; } + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<ParamType>* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. @@ -3786,7 +3992,10 @@ class CartesianProductGenerator8 const typename ParamGenerator<T8>::iterator end8_; typename ParamGenerator<T8>::iterator current8_; ParamType current_value_; - }; + }; // class CartesianProductGenerator8::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator8& other); const ParamGenerator<T1> g1_; const ParamGenerator<T2> g2_; @@ -3796,7 +4005,7 @@ class CartesianProductGenerator8 const ParamGenerator<T6> g6_; const ParamGenerator<T7> g7_; const ParamGenerator<T8> g8_; -}; +}; // class CartesianProductGenerator8 template <typename T1, typename T2, typename T3, typename T4, typename T5, @@ -3987,6 +4196,9 @@ class CartesianProductGenerator9 current9_ == end9_; } + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<ParamType>* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. @@ -4018,7 +4230,10 @@ class CartesianProductGenerator9 const typename ParamGenerator<T9>::iterator end9_; typename ParamGenerator<T9>::iterator current9_; ParamType current_value_; - }; + }; // class CartesianProductGenerator9::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator9& other); const ParamGenerator<T1> g1_; const ParamGenerator<T2> g2_; @@ -4029,7 +4244,7 @@ class CartesianProductGenerator9 const ParamGenerator<T7> g7_; const ParamGenerator<T8> g8_; const ParamGenerator<T9> g9_; -}; +}; // class CartesianProductGenerator9 template <typename T1, typename T2, typename T3, typename T4, typename T5, @@ -4233,6 +4448,9 @@ class CartesianProductGenerator10 current10_ == end10_; } + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<ParamType>* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. @@ -4267,7 +4485,10 @@ class CartesianProductGenerator10 const typename ParamGenerator<T10>::iterator end10_; typename ParamGenerator<T10>::iterator current10_; ParamType current_value_; - }; + }; // class CartesianProductGenerator10::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator10& other); const ParamGenerator<T1> g1_; const ParamGenerator<T2> g2_; @@ -4279,7 +4500,7 @@ class CartesianProductGenerator10 const ParamGenerator<T8> g8_; const ParamGenerator<T9> g9_; const ParamGenerator<T10> g10_; -}; +}; // class CartesianProductGenerator10 // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. @@ -4302,9 +4523,12 @@ CartesianProductHolder2(const Generator1& g1, const Generator2& g2) } private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder2& other); + const Generator1 g1_; const Generator2 g2_; -}; +}; // class CartesianProductHolder2 template <class Generator1, class Generator2, class Generator3> class CartesianProductHolder3 { @@ -4322,10 +4546,13 @@ CartesianProductHolder3(const Generator1& g1, const Generator2& g2, } private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder3& other); + const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; -}; +}; // class CartesianProductHolder3 template <class Generator1, class Generator2, class Generator3, class Generator4> @@ -4345,11 +4572,14 @@ CartesianProductHolder4(const Generator1& g1, const Generator2& g2, } private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder4& other); + const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; -}; +}; // class CartesianProductHolder4 template <class Generator1, class Generator2, class Generator3, class Generator4, class Generator5> @@ -4370,12 +4600,15 @@ CartesianProductHolder5(const Generator1& g1, const Generator2& g2, } private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder5& other); + const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; const Generator5 g5_; -}; +}; // class CartesianProductHolder5 template <class Generator1, class Generator2, class Generator3, class Generator4, class Generator5, class Generator6> @@ -4399,13 +4632,16 @@ CartesianProductHolder6(const Generator1& g1, const Generator2& g2, } private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder6& other); + const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; const Generator5 g5_; const Generator6 g6_; -}; +}; // class CartesianProductHolder6 template <class Generator1, class Generator2, class Generator3, class Generator4, class Generator5, class Generator6, class Generator7> @@ -4431,6 +4667,9 @@ CartesianProductHolder7(const Generator1& g1, const Generator2& g2, } private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder7& other); + const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; @@ -4438,7 +4677,7 @@ CartesianProductHolder7(const Generator1& g1, const Generator2& g2, const Generator5 g5_; const Generator6 g6_; const Generator7 g7_; -}; +}; // class CartesianProductHolder7 template <class Generator1, class Generator2, class Generator3, class Generator4, class Generator5, class Generator6, class Generator7, @@ -4467,6 +4706,9 @@ CartesianProductHolder8(const Generator1& g1, const Generator2& g2, } private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder8& other); + const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; @@ -4475,7 +4717,7 @@ CartesianProductHolder8(const Generator1& g1, const Generator2& g2, const Generator6 g6_; const Generator7 g7_; const Generator8 g8_; -}; +}; // class CartesianProductHolder8 template <class Generator1, class Generator2, class Generator3, class Generator4, class Generator5, class Generator6, class Generator7, @@ -4507,6 +4749,9 @@ CartesianProductHolder9(const Generator1& g1, const Generator2& g2, } private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder9& other); + const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; @@ -4516,7 +4761,7 @@ CartesianProductHolder9(const Generator1& g1, const Generator2& g2, const Generator7 g7_; const Generator8 g8_; const Generator9 g9_; -}; +}; // class CartesianProductHolder9 template <class Generator1, class Generator2, class Generator3, class Generator4, class Generator5, class Generator6, class Generator7, @@ -4550,6 +4795,9 @@ CartesianProductHolder10(const Generator1& g1, const Generator2& g2, } private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder10& other); + const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; @@ -4560,7 +4808,7 @@ CartesianProductHolder10(const Generator1& g1, const Generator2& g2, const Generator8 g8_; const Generator9 g9_; const Generator10 g10_; -}; +}; // class CartesianProductHolder10 #endif // GTEST_HAS_COMBINE diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h b/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h index 3bb07ec..0cbb58c 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h @@ -38,16 +38,14 @@ #include <utility> #include <vector> +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +#include <gtest/internal/gtest-internal.h> +#include <gtest/internal/gtest-linked_ptr.h> #include <gtest/internal/gtest-port.h> -#ifdef GTEST_HAS_PARAM_TEST - -#if GTEST_HAS_RTTI -#include <typeinfo> -#endif // GTEST_HAS_RTTI - -#include <gtest/internal/gtest-linked_ptr.h> -#include <gtest/internal/gtest-internal.h> +#if GTEST_HAS_PARAM_TEST namespace testing { namespace internal { @@ -58,26 +56,8 @@ namespace internal { // fixture class for the same test case. This may happen when // TEST_P macro is used to define two tests with the same name // but in different namespaces. -void ReportInvalidTestCaseType(const char* test_case_name, - const char* file, int line); - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Downcasts the pointer of type Base to Derived. -// Derived must be a subclass of Base. The parameter MUST -// point to a class of type Derived, not any subclass of it. -// When RTTI is available, the function performs a runtime -// check to enforce this. -template <class Derived, class Base> -Derived* CheckedDowncastToActualType(Base* base) { -#if GTEST_HAS_RTTI - GTEST_CHECK_(typeid(*base) == typeid(Derived)); - Derived* derived = dynamic_cast<Derived*>(base); // NOLINT -#else - Derived* derived = static_cast<Derived*>(base); // Poor man's downcast. -#endif // GTEST_HAS_RTTI - return derived; -} +GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line); template <typename> class ParamGeneratorInterface; template <typename> class ParamGenerator; @@ -169,7 +149,7 @@ class ParamGeneratorInterface { virtual ParamIteratorInterface<T>* End() const = 0; }; -// Wraps ParamGeneratorInetrface<T> and provides general generator syntax +// Wraps ParamGeneratorInterface<T> and provides general generator syntax // compatible with the STL Container concept. // This class implements copy initialization semantics and the contained // ParamGeneratorInterface<T> instance is shared among all copies @@ -245,9 +225,13 @@ class RangeGenerator : public ParamGeneratorInterface<T> { private: Iterator(const Iterator& other) - : base_(other.base_), value_(other.value_), index_(other.index_), + : ParamIteratorInterface<T>(), + base_(other.base_), value_(other.value_), index_(other.index_), step_(other.step_) {} + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + const ParamGeneratorInterface<T>* const base_; T value_; int index_; @@ -263,6 +247,9 @@ class RangeGenerator : public ParamGeneratorInterface<T> { return end_index; } + // No implementation - assignment is unsupported. + void operator=(const RangeGenerator& other); + const T begin_; const T end_; const IncrementT step_; @@ -349,7 +336,10 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> { // Use of scoped_ptr helps manage cached value's lifetime, // which is bound by the lifespan of the iterator itself. mutable scoped_ptr<const T> value_; - }; + }; // class ValuesInIteratorRangeGenerator::Iterator + + // No implementation - assignment is unsupported. + void operator=(const ValuesInIteratorRangeGenerator& other); const ContainerType container_; }; // class ValuesInIteratorRangeGenerator @@ -483,8 +473,8 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { // about a generator. int AddTestCaseInstantiation(const char* instantiation_name, GeneratorCreationFunc* func, - const char* file, - int line) { + const char* /* file */, + int /* line */) { instantiations_.push_back(::std::make_pair(instantiation_name, func)); return 0; // Return value used only to run this method in namespace scope. } @@ -533,12 +523,12 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { // LocalTestInfo structure keeps information about a single test registered // with TEST_P macro. struct TestInfo { - TestInfo(const char* test_case_base_name, - const char* test_base_name, - TestMetaFactoryBase<ParamType>* test_meta_factory) : - test_case_base_name(test_case_base_name), - test_base_name(test_base_name), - test_meta_factory(test_meta_factory) {} + TestInfo(const char* a_test_case_base_name, + const char* a_test_base_name, + TestMetaFactoryBase<ParamType>* a_test_meta_factory) : + test_case_base_name(a_test_case_base_name), + test_base_name(a_test_base_name), + test_meta_factory(a_test_meta_factory) {} const String test_case_base_name; const String test_base_name; diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-port.h b/utils/unittest/googletest/include/gtest/internal/gtest-port.h index 20a95c9..9683271 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-port.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-port.h @@ -42,6 +42,8 @@ // // GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) // is/isn't available. +// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions +// are enabled. // GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string // is/isn't available (some systems define // ::string, which is different to std::string). @@ -52,32 +54,42 @@ // is/isn't available. // GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't // enabled. -// GTEST_HAS_STD_STRING - Define it to 1/0 to indicate that -// std::string does/doesn't work (Google Test can -// be used where std::string is unavailable). // GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that // std::wstring does/doesn't work (Google Test can // be used where std::wstring is unavailable). -// GTEST_HAS_TR1_TUPLE 1 - Define it to 1/0 to indicate tr1::tuple +// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple // is/isn't available. +// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the +// compiler supports Microsoft's "Structured +// Exception Handling". +// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google +// Test's own tr1 tuple implementation should be +// used. Unused when the user sets +// GTEST_HAS_TR1_TUPLE to 0. +// GTEST_LINKED_AS_SHARED_LIBRARY +// - Define to 1 when compiling tests that use +// Google Test as a shared library (known as +// DLL on Windows). +// GTEST_CREATE_SHARED_LIBRARY +// - Define to 1 when compiling Google Test itself +// as a shared library. // This header defines the following utilities: // -// Macros indicating the name of the Google C++ Testing Framework project: -// GTEST_NAME - a string literal of the project name. -// GTEST_FLAG_PREFIX - a string literal of the prefix all Google -// Test flag names share. -// GTEST_FLAG_PREFIX_UPPER - a string literal of the prefix all Google -// Test flag names share, in upper case. -// -// Macros indicating the current platform: -// GTEST_OS_CYGWIN - defined iff compiled on Cygwin. -// GTEST_OS_LINUX - defined iff compiled on Linux. -// GTEST_OS_MAC - defined iff compiled on Mac OS X. -// GTEST_OS_SOLARIS - defined iff compiled on Sun Solaris. -// GTEST_OS_SYMBIAN - defined iff compiled for Symbian. -// GTEST_OS_WINDOWS - defined iff compiled on Windows. -// GTEST_OS_ZOS - defined iff compiled on IBM z/OS. +// Macros indicating the current platform (defined to 1 if compiled on +// the given platform; otherwise undefined): +// GTEST_OS_AIX - IBM AIX +// GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_HAIKU - Haiku +// GTEST_OS_LINUX - Linux +// GTEST_OS_MAC - Mac OS X +// GTEST_OS_SOLARIS - Sun Solaris +// GTEST_OS_SYMBIAN - Symbian +// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) +// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop +// GTEST_OS_WINDOWS_MINGW - MinGW +// GTEST_OS_WINDOWS_MOBILE - Windows Mobile +// GTEST_OS_ZOS - z/OS // // Among the platforms, Cygwin, Linux, Max OS X, and Windows have the // most stable support. Since core members of the Google Test project @@ -86,22 +98,26 @@ // googletestframework@googlegroups.com (patches for fixing them are // even more welcome!). // -// Note that it is possible that none of the GTEST_OS_ macros are defined. +// Note that it is possible that none of the GTEST_OS_* macros are defined. // -// Macros indicating available Google Test features: -// GTEST_HAS_COMBINE - defined iff Combine construct is supported -// in value-parameterized tests. -// GTEST_HAS_DEATH_TEST - defined iff death tests are supported. -// GTEST_HAS_PARAM_TEST - defined iff value-parameterized tests are -// supported. -// GTEST_HAS_TYPED_TEST - defined iff typed tests are supported. -// GTEST_HAS_TYPED_TEST_P - defined iff type-parameterized tests are -// supported. +// Macros indicating available Google Test features (defined to 1 if +// the corresponding feature is supported; otherwise undefined): +// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized +// tests) +// GTEST_HAS_DEATH_TEST - death tests +// GTEST_HAS_PARAM_TEST - value-parameterized tests +// GTEST_HAS_TYPED_TEST - typed tests +// GTEST_HAS_TYPED_TEST_P - type-parameterized tests +// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. +// GTEST_USES_SIMPLE_RE - our own simple regex is used; +// the above two are mutually exclusive. +// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). // // Macros for basic C++ coding: // GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. -// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances don't have to -// be used. +// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a +// variable don't have to be used. +// GTEST_DISALLOW_ASSIGN_ - disables operator=. // GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. // GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. // @@ -128,7 +144,10 @@ // LogToStderr() - directs all log messages to stderr. // FlushInfoLog() - flushes informational log messages. // -// Stderr capturing: +// Stdout and stderr capturing: +// CaptureStdout() - starts capturing stdout. +// GetCapturedStdout() - stops capturing stdout and returns the captured +// string. // CaptureStderr() - starts capturing stderr. // GetCapturedStderr() - stops capturing stderr and returns the captured // string. @@ -151,13 +170,24 @@ // Int32FromGTestEnv() - parses an Int32 environment variable. // StringFromGTestEnv() - parses a string environment variable. +#include <stddef.h> // For ptrdiff_t #include <stdlib.h> #include <stdio.h> -#include <iostream> // Used for GTEST_CHECK_ +#include <string.h> +#ifndef _WIN32_WCE +#include <sys/stat.h> +#endif // !_WIN32_WCE + +#include <iostream> // NOLINT +#include <sstream> // NOLINT +#include <string> // NOLINT -#define GTEST_NAME "Google Test" -#define GTEST_FLAG_PREFIX "gtest_" -#define GTEST_FLAG_PREFIX_UPPER "GTEST_" +#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" +#define GTEST_FLAG_PREFIX_ "gtest_" +#define GTEST_FLAG_PREFIX_DASH_ "gtest-" +#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" +#define GTEST_NAME_ "Google Test" +#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/" // Determines the version of gcc that is used to compile this. #ifdef __GNUC__ @@ -168,50 +198,104 @@ // Determines the platform on which Google Test is compiled. #ifdef __CYGWIN__ -#define GTEST_OS_CYGWIN -#elif __SYMBIAN32__ -#define GTEST_OS_SYMBIAN -#elif defined _MSC_VER -// TODO(kenton@google.com): GTEST_OS_WINDOWS is currently used to mean -// both "The OS is Windows" and "The compiler is MSVC". These -// meanings really should be separated in order to better support -// Windows compilers other than MSVC. -#define GTEST_OS_WINDOWS +#define GTEST_OS_CYGWIN 1 +#elif defined __SYMBIAN32__ +#define GTEST_OS_SYMBIAN 1 +#elif defined _WIN32 +#define GTEST_OS_WINDOWS 1 +#ifdef _WIN32_WCE +#define GTEST_OS_WINDOWS_MOBILE 1 +#elif defined(__MINGW__) || defined(__MINGW32__) +#define GTEST_OS_WINDOWS_MINGW 1 +#else +#define GTEST_OS_WINDOWS_DESKTOP 1 +#endif // _WIN32_WCE #elif defined __APPLE__ -#define GTEST_OS_MAC +#define GTEST_OS_MAC 1 #elif defined __linux__ -#define GTEST_OS_LINUX +#define GTEST_OS_LINUX 1 #elif defined __MVS__ -#define GTEST_OS_ZOS +#define GTEST_OS_ZOS 1 #elif defined(__sun) && defined(__SVR4) -#define GTEST_OS_SOLARIS +#define GTEST_OS_SOLARIS 1 +#elif defined(_AIX) +#define GTEST_OS_AIX 1 #elif defined(__HAIKU__) -#define GTEST_OS_HAIKU -#endif // _MSC_VER +#define GTEST_OS_HAIKU 1 +#endif // __CYGWIN__ + +#if GTEST_OS_CYGWIN || GTEST_OS_HAIKU || GTEST_OS_LINUX || GTEST_OS_MAC || \ + GTEST_OS_SYMBIAN || GTEST_OS_SOLARIS || GTEST_OS_AIX + +// On some platforms, <regex.h> needs someone to define size_t, and +// won't compile otherwise. We can #include it here as we already +// included <stdlib.h>, which is guaranteed to define size_t through +// <stddef.h>. +#include <regex.h> // NOLINT +#include <strings.h> // NOLINT +#include <sys/types.h> // NOLINT +#include <time.h> // NOLINT +#include <unistd.h> // NOLINT -// Determines whether ::std::string and ::string are available. +#define GTEST_USES_POSIX_RE 1 + +#elif GTEST_OS_WINDOWS + +#if !GTEST_OS_WINDOWS_MOBILE +#include <direct.h> // NOLINT +#include <io.h> // NOLINT +#endif -#ifndef GTEST_HAS_STD_STRING -// The user didn't tell us whether ::std::string is available, so we -// need to figure it out. +// <regex.h> is not available on Windows. Use our own simple regex +// implementation instead. +#define GTEST_USES_SIMPLE_RE 1 -#ifdef GTEST_OS_WINDOWS +#else + +// <regex.h> may not be available on this platform. Use our own +// simple regex implementation instead. +#define GTEST_USES_SIMPLE_RE 1 + +#endif // GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC || + // GTEST_OS_SYMBIAN || GTEST_OS_SOLARIS || GTEST_OS_AIX + +#ifndef GTEST_HAS_EXCEPTIONS +// The user didn't tell us whether exceptions are enabled, so we need +// to figure it out. +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +// macro to enable exceptions, so we'll do the same. // Assumes that exceptions are enabled by default. #ifndef _HAS_EXCEPTIONS #define _HAS_EXCEPTIONS 1 #endif // _HAS_EXCEPTIONS -// GTEST_HAS_EXCEPTIONS is non-zero iff exceptions are enabled. It is -// always defined, while _HAS_EXCEPTIONS is defined only on Windows. #define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS -// On Windows, we can use ::std::string if the compiler version is VS -// 2005 or above, or if exceptions are enabled. -#define GTEST_HAS_STD_STRING ((_MSC_VER >= 1400) || GTEST_HAS_EXCEPTIONS) -#else // We are on Linux or Mac OS. +#elif defined(__GNUC__) && __EXCEPTIONS +// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. +#define GTEST_HAS_EXCEPTIONS 1 +#elif defined(__SUNPRO_CC) +// Sun Pro CC supports exceptions. However, there is no compile-time way of +// detecting whether they are enabled or not. Therefore, we assume that +// they are enabled unless the user tells us otherwise. +#define GTEST_HAS_EXCEPTIONS 1 +#elif defined(__IBMCPP__) && __EXCEPTIONS +// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. +#define GTEST_HAS_EXCEPTIONS 1 +#else +// For other compilers, we assume exceptions are disabled to be +// conservative. #define GTEST_HAS_EXCEPTIONS 0 -#define GTEST_HAS_STD_STRING 1 -#endif // GTEST_OS_WINDOWS +#endif // defined(_MSC_VER) || defined(__BORLANDC__) +#endif // GTEST_HAS_EXCEPTIONS -#endif // GTEST_HAS_STD_STRING +#if !defined(GTEST_HAS_STD_STRING) +// Even though we don't use this macro any longer, we keep it in case +// some clients still depend on it. +#define GTEST_HAS_STD_STRING 1 +#elif !GTEST_HAS_STD_STRING +// The user told us that ::std::string isn't available. +#error "Google Test cannot be used where ::std::string isn't available." +#endif // !defined(GTEST_HAS_STD_STRING) #ifndef GTEST_HAS_GLOBAL_STRING // The user didn't tell us whether ::string is available, so we need @@ -227,35 +311,21 @@ // TODO(wan@google.com): uses autoconf to detect whether ::std::wstring // is available. -#if defined(GTEST_OS_CYGWIN) || defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_HAIKU) || defined(_MINIX) -// At least some versions of cygwin don't support ::std::wstring. +// Cygwin 1.5 and below doesn't support ::std::wstring. +// Cygwin 1.7 might add wstring support; this should be updated when clear. // Solaris' libc++ doesn't support it either. // Minix currently doesn't support it either. -#define GTEST_HAS_STD_WSTRING 0 -#else -#define GTEST_HAS_STD_WSTRING GTEST_HAS_STD_STRING -#endif // defined(GTEST_OS_CYGWIN) || defined(GTEST_OS_SOLARIS) +#define GTEST_HAS_STD_WSTRING (!(GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || GTEST_OS_HAIKU || defined(_MINIX))) #endif // GTEST_HAS_STD_WSTRING #ifndef GTEST_HAS_GLOBAL_WSTRING // The user didn't tell us whether ::wstring is available, so we need // to figure it out. -#define GTEST_HAS_GLOBAL_WSTRING GTEST_HAS_GLOBAL_STRING +#define GTEST_HAS_GLOBAL_WSTRING \ + (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) #endif // GTEST_HAS_GLOBAL_WSTRING -#if GTEST_HAS_STD_STRING || GTEST_HAS_GLOBAL_STRING || \ - GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING -#include <string> // NOLINT -#endif // GTEST_HAS_STD_STRING || GTEST_HAS_GLOBAL_STRING || - // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING - -#if GTEST_HAS_STD_STRING -#include <sstream> // NOLINT -#else -#include <strstream> // NOLINT -#endif // GTEST_HAS_STD_STRING - // Determines whether RTTI is available. #ifndef GTEST_HAS_RTTI // The user didn't tell us whether RTTI is enabled, so we need to @@ -267,72 +337,128 @@ #define GTEST_HAS_RTTI 1 #else #define GTEST_HAS_RTTI 0 -#endif // _CPPRTTI - -#elif defined(__GNUC__) +#endif // Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. -#if GTEST_GCC_VER_ >= 40302 +#elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) + #ifdef __GXX_RTTI #define GTEST_HAS_RTTI 1 #else #define GTEST_HAS_RTTI 0 #endif // __GXX_RTTI -#else -// For gcc versions smaller than 4.3.2, we assume RTTI is enabled. + +// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if +// both the typeid and dynamic_cast features are present. +#elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) + +#ifdef __RTTI_ALL__ #define GTEST_HAS_RTTI 1 -#endif // GTEST_GCC_VER >= 40302 +#else +#define GTEST_HAS_RTTI 0 +#endif #else -// Unknown compiler - assume RTTI is enabled. +// For all other compilers, we assume RTTI is enabled. #define GTEST_HAS_RTTI 1 #endif // _MSC_VER #endif // GTEST_HAS_RTTI -// Determines whether <pthread.h> is available. -#ifndef GTEST_HAS_PTHREAD -// The user didn't tell us, so we need to figure it out. - -#if defined(GTEST_OS_LINUX) || defined(GTEST_OS_MAC) -#define GTEST_HAS_PTHREAD 1 -#else -#define GTEST_HAS_PTHREAD 0 -#endif // GTEST_OS_LINUX || GTEST_OS_MAC +// It's this header's responsibility to #include <typeinfo> when RTTI +// is enabled. +#if GTEST_HAS_RTTI +#include <typeinfo> +#endif +// Determines whether Google Test can use the pthreads library. +#ifndef GTEST_HAS_PTHREAD +// The user didn't tell us explicitly, so we assume pthreads support is +// available on Linux and Mac. +// +// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 +// to your compiler flags. +#define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC) #endif // GTEST_HAS_PTHREAD -// Determines whether tr1/tuple is available. If you have tr1/tuple -// on your platform, define GTEST_HAS_TR1_TUPLE=1 for both the Google -// Test project and your tests. If you would like Google Test to detect -// tr1/tuple on your platform automatically, please open an issue -// ticket at http://code.google.com/p/googletest. +// Determines whether Google Test can use tr1/tuple. You can define +// this macro to 0 to prevent Google Test from using tuple (any +// feature depending on tuple with be disabled in this mode). #ifndef GTEST_HAS_TR1_TUPLE +// The user didn't tell us not to do it, so we assume it's OK. +#define GTEST_HAS_TR1_TUPLE 1 +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether Google Test's own tr1 tuple implementation +// should be used. +#ifndef GTEST_USE_OWN_TR1_TUPLE // The user didn't tell us, so we need to figure it out. -// GCC provides <tr1/tuple> since 4.0.0. -#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) -#define GTEST_HAS_TR1_TUPLE 1 +// We use our own TR1 tuple if we aren't sure the user has an +// implementation of it already. At this time, GCC 4.0.0+ and MSVC +// 2010 are the only mainstream compilers that come with a TR1 tuple +// implementation. NVIDIA's CUDA NVCC compiler pretends to be GCC by +// defining __GNUC__ and friends, but cannot compile GCC's tuple +// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB +// Feature Pack download, which we cannot assume the user has. +#if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \ + || _MSC_VER >= 1600 +#define GTEST_USE_OWN_TR1_TUPLE 0 #else -#define GTEST_HAS_TR1_TUPLE 0 -#endif // __GNUC__ -#endif // GTEST_HAS_TR1_TUPLE +#define GTEST_USE_OWN_TR1_TUPLE 1 +#endif + +#endif // GTEST_USE_OWN_TR1_TUPLE // To avoid conditional compilation everywhere, we make it // gtest-port.h's responsibility to #include the header implementing // tr1/tuple. #if GTEST_HAS_TR1_TUPLE -#if defined(__GNUC__) -// GCC implements tr1/tuple in the <tr1/tuple> header. This does not -// conform to the TR1 spec, which requires the header to be <tuple>. + +#if GTEST_USE_OWN_TR1_TUPLE +#include <gtest/internal/gtest-tuple.h> +#elif GTEST_OS_SYMBIAN + +// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to +// use STLport's tuple implementation, which unfortunately doesn't +// work as the copy of STLport distributed with Symbian is incomplete. +// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to +// use its own tuple implementation. +#ifdef BOOST_HAS_TR1_TUPLE +#undef BOOST_HAS_TR1_TUPLE +#endif // BOOST_HAS_TR1_TUPLE + +// This prevents <boost/tr1/detail/config.hpp>, which defines +// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>. +#define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED +#include <tuple> + +#elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) +// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does +// not conform to the TR1 spec, which requires the header to be <tuple>. + +#if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 +// Until version 4.3.2, gcc has a bug that causes <tr1/functional>, +// which is #included by <tr1/tuple>, to not compile when RTTI is +// disabled. _TR1_FUNCTIONAL is the header guard for +// <tr1/functional>. Hence the following #define is a hack to prevent +// <tr1/functional> from being included. +#define _TR1_FUNCTIONAL 1 #include <tr1/tuple> +#undef _TR1_FUNCTIONAL // Allows the user to #include + // <tr1/functional> if he chooses to. #else -// If the compiler is not GCC, we assume the user is using a +#include <tr1/tuple> // NOLINT +#endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 + +#else +// If the compiler is not GCC 4.0+, we assume the user is using a // spec-conforming TR1 implementation. -#include <tuple> -#endif // __GNUC__ +#include <tuple> // NOLINT +#endif // GTEST_USE_OWN_TR1_TUPLE + #endif // GTEST_HAS_TR1_TUPLE // Determines whether clone(2) is supported. @@ -342,55 +468,57 @@ #ifndef GTEST_HAS_CLONE // The user didn't tell us, so we need to figure it out. -#if defined(GTEST_OS_LINUX) && !defined(__ia64__) +#if GTEST_OS_LINUX && !defined(__ia64__) #define GTEST_HAS_CLONE 1 #else #define GTEST_HAS_CLONE 0 -#endif // defined(GTEST_OS_LINUX) && !defined(__ia64__) +#endif // GTEST_OS_LINUX && !defined(__ia64__) #endif // GTEST_HAS_CLONE -// Determines whether to support death tests. -#if GTEST_HAS_STD_STRING && GTEST_HAS_CLONE -#define GTEST_HAS_DEATH_TEST -// On some platforms, <regex.h> needs someone to define size_t, and -// won't compile otherwise. We can #include it here as we already -// included <stdlib.h>, which is guaranteed to define size_t through -// <stddef.h>. -#include <regex.h> -#include <vector> -#include <fcntl.h> -#include <sys/mman.h> -#endif // GTEST_HAS_STD_STRING && GTEST_HAS_CLONE +// Determines whether to support stream redirection. This is used to test +// output correctness and to implement death tests. +#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN +#define GTEST_HAS_STREAM_REDIRECTION_ 1 +#endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN -// Determines whether to support value-parameterized tests. +// Determines whether to support death tests. +// Google Test does not support death tests for VC 7.1 and earlier as +// abort() in a VC 7.1 application compiled as GUI in debug config +// pops up a dialog window that cannot be suppressed programmatically. +#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ + GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX) +#define GTEST_HAS_DEATH_TEST 1 +#include <vector> // NOLINT +#endif -#if defined(__GNUC__) || (_MSC_VER >= 1400) -// TODO(vladl@google.com): get the implementation rid of vector and list -// to compile on MSVC 7.1. -#define GTEST_HAS_PARAM_TEST -#endif // defined(__GNUC__) || (_MSC_VER >= 1400) +// We don't support MSVC 7.1 with exceptions disabled now. Therefore +// all the compilers we care about are adequate for supporting +// value-parameterized tests. +#define GTEST_HAS_PARAM_TEST 1 // Determines whether to support type-driven tests. -// Typed tests need <typeinfo> and variadic macros, which gcc and VC -// 8.0+ support. -#if defined(__GNUC__) || (_MSC_VER >= 1400) -#define GTEST_HAS_TYPED_TEST -#define GTEST_HAS_TYPED_TEST_P -#endif // defined(__GNUC__) || (_MSC_VER >= 1400) +// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0, +// Sun Pro CC, and IBM Visual Age support. +#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ + defined(__IBMCPP__) +#define GTEST_HAS_TYPED_TEST 1 +#define GTEST_HAS_TYPED_TEST_P 1 +#endif // Determines whether to support Combine(). This only makes sense when -// value-parameterized tests are enabled. -#if defined(GTEST_HAS_PARAM_TEST) && GTEST_HAS_TR1_TUPLE -#define GTEST_HAS_COMBINE -#endif // defined(GTEST_HAS_PARAM_TEST) && GTEST_HAS_TR1_TUPLE +// value-parameterized tests are enabled. The implementation doesn't +// work on Sun Studio since it doesn't understand templated conversion +// operators. +#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) +#define GTEST_HAS_COMBINE 1 +#endif // Determines whether the system compiler uses UTF-16 for encoding wide strings. -#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_CYGWIN) || \ - defined(GTEST_OS_SYMBIAN) -#define GTEST_WIDE_STRING_USES_UTF16_ 1 -#endif +#define GTEST_WIDE_STRING_USES_UTF16_ \ + (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) // Defines some utility macros. @@ -408,7 +536,7 @@ #define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: // NOLINT #endif -// Use this annotation at the end of a struct / class definition to +// Use this annotation at the end of a struct/class definition to // prevent the compiler from optimizing away instances that are never // used. This is useful when all interesting logic happens inside the // c'tor and / or d'tor. Example: @@ -416,17 +544,25 @@ // struct Foo { // Foo() { ... } // } GTEST_ATTRIBUTE_UNUSED_; +// +// Also use it after a variable or parameter declaration to tell the +// compiler the variable/parameter does not have to be used. #if defined(__GNUC__) && !defined(COMPILER_ICC) #define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) #else #define GTEST_ATTRIBUTE_UNUSED_ #endif -// A macro to disallow the evil copy constructor and operator= functions +// A macro to disallow operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_ASSIGN_(type)\ + void operator=(type const &) + +// A macro to disallow copy constructor and operator= // This should be used in the private: declarations for a class. #define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ - type(const type &);\ - void operator=(const type &) + type(type const &);\ + GTEST_DISALLOW_ASSIGN_(type) // Tell the compiler to warn about unused return values for functions declared // with this macro. The macro should be used on function declarations @@ -439,6 +575,36 @@ #define GTEST_MUST_USE_RESULT_ #endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC +// Determine whether the compiler supports Microsoft's Structured Exception +// Handling. This is supported by several Windows compilers but generally +// does not exist on any other system. +#ifndef GTEST_HAS_SEH +// The user didn't tell us, so we need to figure it out. + +#if defined(_MSC_VER) || defined(__BORLANDC__) +// These two compilers are known to support SEH. +#define GTEST_HAS_SEH 1 +#else +// Assume no SEH. +#define GTEST_HAS_SEH 0 +#endif + +#endif // GTEST_HAS_SEH + +#ifdef _MSC_VER + +#if GTEST_LINKED_AS_SHARED_LIBRARY +#define GTEST_API_ __declspec(dllimport) +#elif GTEST_CREATE_SHARED_LIBRARY +#define GTEST_API_ __declspec(dllexport) +#endif + +#endif // _MSC_VER + +#ifndef GTEST_API_ +#define GTEST_API_ +#endif + namespace testing { class Message; @@ -447,15 +613,11 @@ namespace internal { class String; -// std::strstream is deprecated. However, we have to use it on -// Windows as std::stringstream won't compile on Windows when -// exceptions are disabled. We use std::stringstream on other -// platforms to avoid compiler warnings there. -#if GTEST_HAS_STD_STRING typedef ::std::stringstream StrStream; -#else -typedef ::std::strstream StrStream; -#endif // GTEST_HAS_STD_STRING + +// A helper for suppressing warnings on constant condition. It just +// returns 'condition'. +GTEST_API_ bool IsTrue(bool condition); // Defines scoped_ptr. @@ -464,6 +626,8 @@ typedef ::std::strstream StrStream; template <typename T> class scoped_ptr { public: + typedef T element_type; + explicit scoped_ptr(T* p = NULL) : ptr_(p) {} ~scoped_ptr() { reset(); } @@ -479,7 +643,7 @@ class scoped_ptr { void reset(T* p = NULL) { if (p != ptr_) { - if (sizeof(T) > 0) { // Makes sure T is a complete type. + if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. delete ptr_; } ptr_ = p; @@ -491,18 +655,18 @@ class scoped_ptr { GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); }; -#ifdef GTEST_HAS_DEATH_TEST - // Defines RE. -// A simple C++ wrapper for <regex.h>. It uses the POSIX Enxtended +// A simple C++ wrapper for <regex.h>. It uses the POSIX Extended // Regular Expression syntax. -class RE { +class GTEST_API_ RE { public: + // A copy constructor is required by the Standard to initialize object + // references from r-values. + RE(const RE& other) { Init(other.pattern()); } + // Constructs an RE from a string. -#if GTEST_HAS_STD_STRING RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT -#endif // GTEST_HAS_STD_STRING #if GTEST_HAS_GLOBAL_STRING RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT @@ -521,14 +685,12 @@ class RE { // // TODO(wan@google.com): make FullMatch() and PartialMatch() work // when str contains NUL characters. -#if GTEST_HAS_STD_STRING static bool FullMatch(const ::std::string& str, const RE& re) { return FullMatch(str.c_str(), re); } static bool PartialMatch(const ::std::string& str, const RE& re) { return PartialMatch(str.c_str(), re); } -#endif // GTEST_HAS_STD_STRING #if GTEST_HAS_GLOBAL_STRING static bool FullMatch(const ::string& str, const RE& re) { @@ -550,15 +712,20 @@ class RE { // String type here, in order to simplify dependencies between the // files. const char* pattern_; + bool is_valid_; +#if GTEST_USES_POSIX_RE regex_t full_regex_; // For FullMatch(). regex_t partial_regex_; // For PartialMatch(). - bool is_valid_; -}; +#else // GTEST_USES_SIMPLE_RE + const char* full_pattern_; // For FullMatch(); +#endif -#endif // GTEST_HAS_DEATH_TEST + GTEST_DISALLOW_ASSIGN_(RE); +}; // Defines logging utilities: -// GTEST_LOG_() - logs messages at the specified severity level. +// GTEST_LOG_(severity) - logs messages at the specified severity level. The +// message itself is streamed into the macro. // LogToStderr() - directs all log messages to stderr. // FlushInfoLog() - flushes informational log messages. @@ -569,35 +736,439 @@ enum GTestLogSeverity { GTEST_FATAL }; -void GTestLog(GTestLogSeverity severity, const char* file, - int line, const char* msg); +// Formats log entry severity, provides a stream object for streaming the +// log message, and terminates the message with a newline when going out of +// scope. +class GTEST_API_ GTestLog { + public: + GTestLog(GTestLogSeverity severity, const char* file, int line); + + // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. + ~GTestLog(); -#define GTEST_LOG_(severity, msg)\ - ::testing::internal::GTestLog(\ - ::testing::internal::GTEST_##severity, __FILE__, __LINE__, \ - (::testing::Message() << (msg)).GetString().c_str()) + ::std::ostream& GetStream() { return ::std::cerr; } + + private: + const GTestLogSeverity severity_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); +}; + +#define GTEST_LOG_(severity) \ + ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ + __FILE__, __LINE__).GetStream() inline void LogToStderr() {} inline void FlushInfoLog() { fflush(NULL); } +// INTERNAL IMPLEMENTATION - DO NOT USE. +// +// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition +// is not satisfied. +// Synopsys: +// GTEST_CHECK_(boolean_condition); +// or +// GTEST_CHECK_(boolean_condition) << "Additional message"; +// +// This checks the condition and if the condition is not satisfied +// it prints message about the condition violation, including the +// condition itself, plus additional message streamed into it, if any, +// and then it aborts the program. It aborts the program irrespective of +// whether it is built in the debug mode or not. +#define GTEST_CHECK_(condition) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::IsTrue(condition)) \ + ; \ + else \ + GTEST_LOG_(FATAL) << "Condition " #condition " failed. " + +// An all-mode assert to verify that the given POSIX-style function +// call returns 0 (indicating success). Known limitation: this +// doesn't expand to a balanced 'if' statement, so enclose the macro +// in {} if you need to use it as the only statement in an 'if' +// branch. +#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ + if (const int gtest_error = (posix_call)) \ + GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ + << gtest_error + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Downcasts the pointer of type Base to Derived. +// Derived must be a subclass of Base. The parameter MUST +// point to a class of type Derived, not any subclass of it. +// When RTTI is available, the function performs a runtime +// check to enforce this. +template <class Derived, class Base> +Derived* CheckedDowncastToActualType(Base* base) { +#if GTEST_HAS_RTTI + GTEST_CHECK_(typeid(*base) == typeid(Derived)); + return dynamic_cast<Derived*>(base); // NOLINT +#else + return static_cast<Derived*>(base); // Poor man's downcast. +#endif +} + +#if GTEST_HAS_STREAM_REDIRECTION_ + // Defines the stderr capturer: +// CaptureStdout - starts capturing stdout. +// GetCapturedStdout - stops capturing stdout and returns the captured string. // CaptureStderr - starts capturing stderr. // GetCapturedStderr - stops capturing stderr and returns the captured string. +// +GTEST_API_ void CaptureStdout(); +GTEST_API_ String GetCapturedStdout(); +GTEST_API_ void CaptureStderr(); +GTEST_API_ String GetCapturedStderr(); + +#endif // GTEST_HAS_STREAM_REDIRECTION_ + -#ifdef GTEST_HAS_DEATH_TEST +#if GTEST_HAS_DEATH_TEST // A copy of all command line arguments. Set by InitGoogleTest(). extern ::std::vector<String> g_argvs; -void CaptureStderr(); // GTEST_HAS_DEATH_TEST implies we have ::std::string. -::std::string GetCapturedStderr(); const ::std::vector<String>& GetArgvs(); #endif // GTEST_HAS_DEATH_TEST // Defines synchronization primitives. +#if GTEST_HAS_PTHREAD + +// Sleeps for (roughly) n milli-seconds. This function is only for +// testing Google Test's own constructs. Don't use it in user tests, +// either directly or indirectly. +inline void SleepMilliseconds(int n) { + const timespec time = { + 0, // 0 seconds. + n * 1000L * 1000L, // And n ms. + }; + nanosleep(&time, NULL); +} + +// Allows a controller thread to pause execution of newly created +// threads until notified. Instances of this class must be created +// and destroyed in the controller thread. +// +// This class is only for testing Google Test's own constructs. Do not +// use it in user tests, either directly or indirectly. +class Notification { + public: + Notification() : notified_(false) {} + + // Notifies all threads created with this notification to start. Must + // be called from the controller thread. + void Notify() { notified_ = true; } + + // Blocks until the controller thread notifies. Must be called from a test + // thread. + void WaitForNotification() { + while(!notified_) { + SleepMilliseconds(10); + } + } + + private: + volatile bool notified_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); +}; + +// As a C-function, ThreadFuncWithCLinkage cannot be templated itself. +// Consequently, it cannot select a correct instantiation of ThreadWithParam +// in order to call its Run(). Introducing ThreadWithParamBase as a +// non-templated base class for ThreadWithParam allows us to bypass this +// problem. +class ThreadWithParamBase { + public: + virtual ~ThreadWithParamBase() {} + virtual void Run() = 0; +}; + +// pthread_create() accepts a pointer to a function type with the C linkage. +// According to the Standard (7.5/1), function types with different linkages +// are different even if they are otherwise identical. Some compilers (for +// example, SunStudio) treat them as different types. Since class methods +// cannot be defined with C-linkage we need to define a free C-function to +// pass into pthread_create(). +extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { + static_cast<ThreadWithParamBase*>(thread)->Run(); + return NULL; +} + +// Helper class for testing Google Test's multi-threading constructs. +// To use it, write: +// +// void ThreadFunc(int param) { /* Do things with param */ } +// Notification thread_can_start; +// ... +// // The thread_can_start parameter is optional; you can supply NULL. +// ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start); +// thread_can_start.Notify(); +// +// These classes are only for testing Google Test's own constructs. Do +// not use them in user tests, either directly or indirectly. +template <typename T> +class ThreadWithParam : public ThreadWithParamBase { + public: + typedef void (*UserThreadFunc)(T); + + ThreadWithParam( + UserThreadFunc func, T param, Notification* thread_can_start) + : func_(func), + param_(param), + thread_can_start_(thread_can_start), + finished_(false) { + ThreadWithParamBase* const base = this; + // The thread can be created only after all fields except thread_ + // have been initialized. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); + } + ~ThreadWithParam() { Join(); } + + void Join() { + if (!finished_) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); + finished_ = true; + } + } + + virtual void Run() { + if (thread_can_start_ != NULL) + thread_can_start_->WaitForNotification(); + func_(param_); + } + + private: + const UserThreadFunc func_; // User-supplied thread function. + const T param_; // User-supplied parameter to the thread function. + // When non-NULL, used to block execution until the controller thread + // notifies. + Notification* const thread_can_start_; + bool finished_; // true iff we know that the thread function has finished. + pthread_t thread_; // The native thread object. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); +}; + +// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is +// true. +#include <pthread.h> + +// MutexBase and Mutex implement mutex on pthreads-based platforms. They +// are used in conjunction with class MutexLock: +// +// Mutex mutex; +// ... +// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end +// // of the current scope. +// +// MutexBase implements behavior for both statically and dynamically +// allocated mutexes. Do not use MutexBase directly. Instead, write +// the following to define a static mutex: +// +// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); +// +// You can forward declare a static mutex like this: +// +// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); +// +// To create a dynamic mutex, just define an object of type Mutex. +class MutexBase { + public: + // Acquires this mutex. + void Lock() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); + owner_ = pthread_self(); + } + + // Releases this mutex. + void Unlock() { + // We don't protect writing to owner_ here, as it's the caller's + // responsibility to ensure that the current thread holds the + // mutex when this is called. + owner_ = 0; + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); + } + + // Does nothing if the current thread holds the mutex. Otherwise, crashes + // with high probability. + void AssertHeld() const { + GTEST_CHECK_(owner_ == pthread_self()) + << "The current thread is not holding the mutex @" << this; + } + + // A static mutex may be used before main() is entered. It may even + // be used before the dynamic initialization stage. Therefore we + // must be able to initialize a static mutex object at link time. + // This means MutexBase has to be a POD and its member variables + // have to be public. + public: + pthread_mutex_t mutex_; // The underlying pthread mutex. + pthread_t owner_; // The thread holding the mutex; 0 means no one holds it. +}; + +// Forward-declares a static mutex. +#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::MutexBase mutex + +// Defines and statically (i.e. at link time) initializes a static mutex. +#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ + ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 } + +// The Mutex class can only be used for mutexes created at runtime. It +// shares its API with MutexBase otherwise. +class Mutex : public MutexBase { + public: + Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + owner_ = 0; + } + ~Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); +}; + +// We cannot name this class MutexLock as the ctor declaration would +// conflict with a macro named MutexLock, which is defined on some +// platforms. Hence the typedef trick below. +class GTestMutexLock { + public: + explicit GTestMutexLock(MutexBase* mutex) + : mutex_(mutex) { mutex_->Lock(); } + + ~GTestMutexLock() { mutex_->Unlock(); } + + private: + MutexBase* const mutex_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); +}; + +typedef GTestMutexLock MutexLock; + +// Helpers for ThreadLocal. + +// pthread_key_create() requires DeleteThreadLocalValue() to have +// C-linkage. Therefore it cannot be templatized to access +// ThreadLocal<T>. Hence the need for class +// ThreadLocalValueHolderBase. +class ThreadLocalValueHolderBase { + public: + virtual ~ThreadLocalValueHolderBase() {} +}; + +// Called by pthread to delete thread-local data stored by +// pthread_setspecific(). +extern "C" inline void DeleteThreadLocalValue(void* value_holder) { + delete static_cast<ThreadLocalValueHolderBase*>(value_holder); +} + +// Implements thread-local storage on pthreads-based systems. +// +// // Thread 1 +// ThreadLocal<int> tl(100); // 100 is the default value for each thread. +// +// // Thread 2 +// tl.set(150); // Changes the value for thread 2 only. +// EXPECT_EQ(150, tl.get()); +// +// // Thread 1 +// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value. +// tl.set(200); +// EXPECT_EQ(200, tl.get()); +// +// The template type argument T must have a public copy constructor. +// In addition, the default ThreadLocal constructor requires T to have +// a public default constructor. +// +// An object managed for a thread by a ThreadLocal instance is deleted +// when the thread exits. Or, if the ThreadLocal instance dies in +// that thread, when the ThreadLocal dies. It's the user's +// responsibility to ensure that all other threads using a ThreadLocal +// have exited when it dies, or the per-thread objects for those +// threads will not be deleted. +// +// Google Test only uses global ThreadLocal objects. That means they +// will die after main() has returned. Therefore, no per-thread +// object managed by Google Test will be leaked as long as all threads +// using Google Test have exited when main() returns. +template <typename T> +class ThreadLocal { + public: + ThreadLocal() : key_(CreateKey()), + default_() {} + explicit ThreadLocal(const T& value) : key_(CreateKey()), + default_(value) {} + + ~ThreadLocal() { + // Destroys the managed object for the current thread, if any. + DeleteThreadLocalValue(pthread_getspecific(key_)); + + // Releases resources associated with the key. This will *not* + // delete managed objects for other threads. + GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); + } + + T* pointer() { return GetOrCreateValue(); } + const T* pointer() const { return GetOrCreateValue(); } + const T& get() const { return *pointer(); } + void set(const T& value) { *pointer() = value; } + + private: + // Holds a value of type T. + class ValueHolder : public ThreadLocalValueHolderBase { + public: + explicit ValueHolder(const T& value) : value_(value) {} + + T* pointer() { return &value_; } + + private: + T value_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder); + }; + + static pthread_key_t CreateKey() { + pthread_key_t key; + // When a thread exits, DeleteThreadLocalValue() will be called on + // the object managed for that thread. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_key_create(&key, &DeleteThreadLocalValue)); + return key; + } + + T* GetOrCreateValue() const { + ThreadLocalValueHolderBase* const holder = + static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_)); + if (holder != NULL) { + return CheckedDowncastToActualType<ValueHolder>(holder)->pointer(); + } + + ValueHolder* const new_holder = new ValueHolder(default_); + ThreadLocalValueHolderBase* const holder_base = new_holder; + GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); + return new_holder->pointer(); + } + + // A key pthreads uses for looking up per-thread values. + const pthread_key_t key_; + const T default_; // The default value for each thread. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); +}; + +#define GTEST_IS_THREADSAFE 1 + +#else // GTEST_HAS_PTHREAD + // A dummy implementation of synchronization primitives (mutex, lock, // and thread-local variable). Necessary for compiling Google Test where // mutex is not supported - using Google Test in multiple threads is not @@ -606,14 +1177,14 @@ const ::std::vector<String>& GetArgvs(); class Mutex { public: Mutex() {} - explicit Mutex(int /*unused*/) {} void AssertHeld() const {} - enum { NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX = 0 }; }; -// We cannot call it MutexLock directly as the ctor declaration would -// conflict with a macro named MutexLock, which is defined on some -// platforms. Hence the typedef trick below. +#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::Mutex mutex + +#define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex + class GTestMutexLock { public: explicit GTestMutexLock(Mutex*) {} // NOLINT @@ -634,30 +1205,37 @@ class ThreadLocal { T value_; }; -// There's no portable way to detect the number of threads, so we just -// return 0 to indicate that we cannot detect it. -inline size_t GetThreadCount() { return 0; } - // The above synchronization primitives have dummy implementations. // Therefore Google Test is not thread-safe. #define GTEST_IS_THREADSAFE 0 -#if defined(__SYMBIAN32__) || defined(__IBMCPP__) +#endif // GTEST_HAS_PTHREAD + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +GTEST_API_ size_t GetThreadCount(); // Passing non-POD classes through ellipsis (...) crashes the ARM -// compiler. The Nokia Symbian and the IBM XL C/C++ compiler try to -// instantiate a copy constructor for objects passed through ellipsis -// (...), failing for uncopyable objects. We define this to indicate -// the fact. -#define GTEST_ELLIPSIS_NEEDS_COPY_ 1 +// compiler and generates a warning in Sun Studio. The Nokia Symbian +// and the IBM XL C/C++ compiler try to instantiate a copy constructor +// for objects passed through ellipsis (...), failing for uncopyable +// objects. We define this to ensure that only POD is passed through +// ellipsis on these systems. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +#define GTEST_ELLIPSIS_NEEDS_POD_ 1 +#else +#define GTEST_CAN_COMPARE_NULL 1 +#endif // The Nokia Symbian and IBM XL C/C++ compilers cannot decide between // const T& and const T* in a function template. These compilers // _can_ decide between class template specializations for T and T*, // so a tr1::type_traits-like is_pointer works. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) #define GTEST_NEEDS_IS_POINTER_ 1 - -#endif // defined(__SYMBIAN32__) || defined(__IBMCPP__) +#endif template <bool bool_value> struct bool_constant { @@ -675,15 +1253,146 @@ struct is_pointer : public false_type {}; template <typename T> struct is_pointer<T*> : public true_type {}; -// Defines BiggestInt as the biggest signed integer type the compiler -// supports. - -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS +#define GTEST_PATH_SEP_ "\\" +#define GTEST_HAS_ALT_PATH_SEP_ 1 +// The biggest signed integer type the compiler supports. typedef __int64 BiggestInt; #else +#define GTEST_PATH_SEP_ "/" +#define GTEST_HAS_ALT_PATH_SEP_ 0 typedef long long BiggestInt; // NOLINT #endif // GTEST_OS_WINDOWS +// The testing::internal::posix namespace holds wrappers for common +// POSIX functions. These wrappers hide the differences between +// Windows/MSVC and POSIX systems. Since some compilers define these +// standard functions as macros, the wrapper cannot have the same name +// as the wrapped function. + +namespace posix { + +// Functions with a different name on Windows. + +#if GTEST_OS_WINDOWS + +typedef struct _stat StatStruct; + +#ifdef __BORLANDC__ +inline int IsATTY(int fd) { return isatty(fd); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +#else // !__BORLANDC__ +#if GTEST_OS_WINDOWS_MOBILE +inline int IsATTY(int /* fd */) { return 0; } +#else +inline int IsATTY(int fd) { return _isatty(fd); } +#endif // GTEST_OS_WINDOWS_MOBILE +inline int StrCaseCmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return _strdup(src); } +#endif // __BORLANDC__ + +#if GTEST_OS_WINDOWS_MOBILE +inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); } +// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this +// time and thus not defined there. +#else +inline int FileNo(FILE* file) { return _fileno(file); } +inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } +inline int RmDir(const char* dir) { return _rmdir(dir); } +inline bool IsDir(const StatStruct& st) { + return (_S_IFDIR & st.st_mode) != 0; +} +#endif // GTEST_OS_WINDOWS_MOBILE + +#else + +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int IsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + +#endif // GTEST_OS_WINDOWS + +// Functions deprecated by MSVC 8.0. + +#ifdef _MSC_VER +// Temporarily disable warning 4996 (deprecated function). +#pragma warning(push) +#pragma warning(disable:4996) +#endif + +inline const char* StrNCpy(char* dest, const char* src, size_t n) { + return strncpy(dest, src, n); +} + +// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and +// StrError() aren't needed on Windows CE at this time and thus not +// defined there. + +#if !GTEST_OS_WINDOWS_MOBILE +inline int ChDir(const char* dir) { return chdir(dir); } +#endif +inline FILE* FOpen(const char* path, const char* mode) { + return fopen(path, mode); +} +#if !GTEST_OS_WINDOWS_MOBILE +inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { + return freopen(path, mode, stream); +} +inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } +#endif +inline int FClose(FILE* fp) { return fclose(fp); } +#if !GTEST_OS_WINDOWS_MOBILE +inline int Read(int fd, void* buf, unsigned int count) { + return static_cast<int>(read(fd, buf, count)); +} +inline int Write(int fd, const void* buf, unsigned int count) { + return static_cast<int>(write(fd, buf, count)); +} +inline int Close(int fd) { return close(fd); } +inline const char* StrError(int errnum) { return strerror(errnum); } +#endif +inline const char* GetEnv(const char* name) { +#if GTEST_OS_WINDOWS_MOBILE + // We are on Windows CE, which has no environment variables. + return NULL; +#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) + // Environment variables which we programmatically clear will be set to the + // empty string rather than unset (NULL). Handle that case. + const char* const env = getenv(name); + return (env != NULL && env[0] != '\0') ? env : NULL; +#else + return getenv(name); +#endif +} + +#ifdef _MSC_VER +#pragma warning(pop) // Restores the warning state. +#endif + +#if GTEST_OS_WINDOWS_MOBILE +// Windows CE has no C library. The abort() function is used in +// several places in Google Test. This implementation provides a reasonable +// imitation of standard behaviour. +void Abort(); +#else +inline void Abort() { abort(); } +#endif // GTEST_OS_WINDOWS_MOBILE + +} // namespace posix + // The maximum number a BiggestInt can represent. This definition // works no matter BiggestInt is represented in one's complement or // two's complement. @@ -736,7 +1445,7 @@ class TypeWithSize<4> { template <> class TypeWithSize<8> { public: -#ifdef GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS typedef __int64 Int; typedef unsigned __int64 UInt; #else @@ -754,96 +1463,23 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. // Utilities for command line flags and environment variables. -// A wrapper for getenv() that works on Linux, Windows, and Mac OS. -inline const char* GetEnv(const char* name) { -#ifdef _WIN32_WCE // We are on Windows CE. - // CE has no environment variables. - return NULL; -#elif defined(GTEST_OS_WINDOWS) // We are on Windows proper. - // MSVC 8 deprecates getenv(), so we want to suppress warning 4996 - // (deprecated function) there. -#pragma warning(push) // Saves the current warning state. -#pragma warning(disable:4996) // Temporarily disables warning 4996. - return getenv(name); -#pragma warning(pop) // Restores the warning state. -#else // We are on Linux or Mac OS. - return getenv(name); -#endif -} - -#ifdef _WIN32_WCE -// Windows CE has no C library. The abort() function is used in -// several places in Google Test. This implementation provides a reasonable -// imitation of standard behaviour. -void abort(); -#else -inline void abort() { ::abort(); } -#endif // _WIN32_WCE - -// INTERNAL IMPLEMENTATION - DO NOT USE. -// -// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition -// is not satisfied. -// Synopsys: -// GTEST_CHECK_(boolean_condition); -// or -// GTEST_CHECK_(boolean_condition) << "Additional message"; -// -// This checks the condition and if the condition is not satisfied -// it prints message about the condition violation, including the -// condition itself, plus additional message streamed into it, if any, -// and then it aborts the program. It aborts the program irrespective of -// whether it is built in the debug mode or not. -class GTestCheckProvider { - public: - GTestCheckProvider(const char* condition, const char* file, int line) { - FormatFileLocation(file, line); - ::std::cerr << " ERROR: Condition " << condition << " failed. "; - } - ~GTestCheckProvider() { - ::std::cerr << ::std::endl; - abort(); - } - void FormatFileLocation(const char* file, int line) { - if (file == NULL) - file = "unknown file"; - if (line < 0) { - ::std::cerr << file << ":"; - } else { -#if _MSC_VER - ::std::cerr << file << "(" << line << "):"; -#else - ::std::cerr << file << ":" << line << ":"; -#endif - } - } - ::std::ostream& GetStream() { return ::std::cerr; } -}; -#define GTEST_CHECK_(condition) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (condition) \ - ; \ - else \ - ::testing::internal::GTestCheckProvider(\ - #condition, __FILE__, __LINE__).GetStream() - // Macro for referencing flags. #define GTEST_FLAG(name) FLAGS_gtest_##name // Macros for declaring flags. -#define GTEST_DECLARE_bool_(name) extern bool GTEST_FLAG(name) +#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) #define GTEST_DECLARE_int32_(name) \ - extern ::testing::internal::Int32 GTEST_FLAG(name) + GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) #define GTEST_DECLARE_string_(name) \ - extern ::testing::internal::String GTEST_FLAG(name) + GTEST_API_ extern ::testing::internal::String GTEST_FLAG(name) // Macros for defining flags. #define GTEST_DEFINE_bool_(name, default_val, doc) \ - bool GTEST_FLAG(name) = (default_val) + GTEST_API_ bool GTEST_FLAG(name) = (default_val) #define GTEST_DEFINE_int32_(name, default_val, doc) \ - ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) + GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) #define GTEST_DEFINE_string_(name, default_val, doc) \ - ::testing::internal::String GTEST_FLAG(name) = (default_val) + GTEST_API_ ::testing::internal::String GTEST_FLAG(name) = (default_val) // Parses 'str' for a 32-bit signed integer. If successful, writes the result // to *value and returns true; otherwise leaves *value unchanged and returns @@ -856,7 +1492,7 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value); // Parses a bool/Int32/string from the environment variable // corresponding to the given Google Test flag. bool BoolFromGTestEnv(const char* flag, bool default_val); -Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); const char* StringFromGTestEnv(const char* flag, const char* default_val); } // namespace internal diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-string.h b/utils/unittest/googletest/include/gtest/internal/gtest-string.h index 178f14e..aff093d 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-string.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-string.h @@ -35,32 +35,34 @@ // Google Test. They are subject to change without notice. They should not used // by code external to Google Test. // -// This header file is #included by testing/base/internal/gtest-internal.h. +// This header file is #included by <gtest/internal/gtest-internal.h>. // It should not be #included by other files. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#ifdef __BORLANDC__ +// string.h is not guaranteed to provide strcpy on C++ Builder. +#include <mem.h> +#endif + #include <string.h> #include <gtest/internal/gtest-port.h> -#if GTEST_HAS_GLOBAL_STRING || GTEST_HAS_STD_STRING #include <string> -#endif // GTEST_HAS_GLOBAL_STRING || GTEST_HAS_STD_STRING namespace testing { namespace internal { // String - a UTF-8 string class. // -// We cannot use std::string as Microsoft's STL implementation in -// Visual C++ 7.1 has problems when exception is disabled. There is a -// hack to work around this, but we've seen cases where the hack fails -// to work. +// For historic reasons, we don't use std::string. +// +// TODO(wan@google.com): replace this class with std::string or +// implement it in terms of the latter. // -// Also, String is different from std::string in that it can represent -// both NULL and the empty string, while std::string cannot represent -// NULL. +// Note that String can represent both NULL and the empty string, +// while std::string cannot represent NULL. // // NULL and the empty string are considered different. NULL is less // than anything (including the empty string) except itself. @@ -76,23 +78,10 @@ namespace internal { // // In order to make the representation efficient, the d'tor of String // is not virtual. Therefore DO NOT INHERIT FROM String. -class String { +class GTEST_API_ String { public: // Static utility methods - // Returns the input if it's not NULL, otherwise returns "(null)". - // This function serves two purposes: - // - // 1. ShowCString(NULL) has type 'const char *', instead of the - // type of NULL (which is int). - // - // 2. In MSVC, streaming a null char pointer to StrStream generates - // an access violation, so we need to convert NULL to "(null)" - // before streaming it. - static inline const char* ShowCString(const char* c_str) { - return c_str ? c_str : "(null)"; - } - // Returns the input enclosed in double quotes if it's not NULL; // otherwise returns "(null)". For example, "\"Hello\"" is returned // for input "Hello". @@ -111,7 +100,7 @@ class String { // memory using malloc(). static const char* CloneCString(const char* c_str); -#ifdef _WIN32_WCE +#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be // able to pass strings to Win32 APIs on CE we need to convert them // to 'Unicode', UTF-16. @@ -200,22 +189,29 @@ class String { // C'tors // The default c'tor constructs a NULL string. - String() : c_str_(NULL) {} + String() : c_str_(NULL), length_(0) {} // Constructs a String by cloning a 0-terminated C string. - String(const char* c_str) : c_str_(NULL) { // NOLINT - *this = c_str; + String(const char* a_c_str) { // NOLINT + if (a_c_str == NULL) { + c_str_ = NULL; + length_ = 0; + } else { + ConstructNonNull(a_c_str, strlen(a_c_str)); + } } // Constructs a String by copying a given number of chars from a - // buffer. E.g. String("hello", 3) will create the string "hel". - String(const char* buffer, size_t len); + // buffer. E.g. String("hello", 3) creates the string "hel", + // String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "", + // and String(NULL, 1) results in access violation. + String(const char* buffer, size_t a_length) { + ConstructNonNull(buffer, a_length); + } // The copy c'tor creates a new copy of the string. The two // String objects do not share content. - String(const String& str) : c_str_(NULL) { - *this = str; - } + String(const String& str) : c_str_(NULL), length_(0) { *this = str; } // D'tor. String is intended to be a final class, so the d'tor // doesn't need to be virtual. @@ -227,22 +223,22 @@ class String { // Converting a ::std::string or ::string containing an embedded NUL // character to a String will result in the prefix up to the first // NUL character. -#if GTEST_HAS_STD_STRING - String(const ::std::string& str) : c_str_(NULL) { *this = str.c_str(); } + String(const ::std::string& str) { + ConstructNonNull(str.c_str(), str.length()); + } - operator ::std::string() const { return ::std::string(c_str_); } -#endif // GTEST_HAS_STD_STRING + operator ::std::string() const { return ::std::string(c_str(), length()); } #if GTEST_HAS_GLOBAL_STRING - String(const ::string& str) : c_str_(NULL) { *this = str.c_str(); } + String(const ::string& str) { + ConstructNonNull(str.c_str(), str.length()); + } - operator ::string() const { return ::string(c_str_); } + operator ::string() const { return ::string(c_str(), length()); } #endif // GTEST_HAS_GLOBAL_STRING // Returns true iff this is an empty string (i.e. ""). - bool empty() const { - return (c_str_ != NULL) && (*c_str_ == '\0'); - } + bool empty() const { return (c_str() != NULL) && (length() == 0); } // Compares this with another String. // Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0 @@ -251,19 +247,15 @@ class String { // Returns true iff this String equals the given C string. A NULL // string and a non-NULL string are considered not equal. - bool operator==(const char* c_str) const { - return CStringEquals(c_str_, c_str); - } + bool operator==(const char* a_c_str) const { return Compare(a_c_str) == 0; } - // Returns true iff this String is less than the given C string. A NULL - // string is considered less than "". + // Returns true iff this String is less than the given String. A + // NULL string is considered less than "". bool operator<(const String& rhs) const { return Compare(rhs) < 0; } // Returns true iff this String doesn't equal the given C string. A NULL // string and a non-NULL string are considered not equal. - bool operator!=(const char* c_str) const { - return !CStringEquals(c_str_, c_str); - } + bool operator!=(const char* a_c_str) const { return !(*this == a_c_str); } // Returns true iff this String ends with the given suffix. *Any* // String is considered to end with a NULL or empty suffix. @@ -273,50 +265,73 @@ class String { // case. Any String is considered to end with a NULL or empty suffix. bool EndsWithCaseInsensitive(const char* suffix) const; - // Returns the length of the encapsulated string, or -1 if the + // Returns the length of the encapsulated string, or 0 if the // string is NULL. - int GetLength() const { - return c_str_ ? static_cast<int>(strlen(c_str_)) : -1; - } + size_t length() const { return length_; } // Gets the 0-terminated C string this String object represents. // The String object still owns the string. Therefore the caller // should NOT delete the return value. const char* c_str() const { return c_str_; } - // Sets the 0-terminated C string this String object represents. - // The old string in this object is deleted, and this object will - // own a clone of the input string. This function copies only up to - // length bytes (plus a terminating null byte), or until the first - // null byte, whichever comes first. - // - // This function works even when the c_str parameter has the same - // value as that of the c_str_ field. - void Set(const char* c_str, size_t length); - // Assigns a C string to this object. Self-assignment works. - const String& operator=(const char* c_str); + const String& operator=(const char* a_c_str) { + return *this = String(a_c_str); + } // Assigns a String object to this object. Self-assignment works. - const String& operator=(const String &rhs) { - *this = rhs.c_str_; + const String& operator=(const String& rhs) { + if (this != &rhs) { + delete[] c_str_; + if (rhs.c_str() == NULL) { + c_str_ = NULL; + length_ = 0; + } else { + ConstructNonNull(rhs.c_str(), rhs.length()); + } + } + return *this; } private: - const char* c_str_; -}; + // Constructs a non-NULL String from the given content. This + // function can only be called when data_ has not been allocated. + // ConstructNonNull(NULL, 0) results in an empty string (""). + // ConstructNonNull(NULL, non_zero) is undefined behavior. + void ConstructNonNull(const char* buffer, size_t a_length) { + char* const str = new char[a_length + 1]; + memcpy(str, buffer, a_length); + str[a_length] = '\0'; + c_str_ = str; + length_ = a_length; + } -// Streams a String to an ostream. -inline ::std::ostream& operator <<(::std::ostream& os, const String& str) { - // We call String::ShowCString() to convert NULL to "(null)". - // Otherwise we'll get an access violation on Windows. - return os << String::ShowCString(str.c_str()); + const char* c_str_; + size_t length_; +}; // class String + +// Streams a String to an ostream. Each '\0' character in the String +// is replaced with "\\0". +inline ::std::ostream& operator<<(::std::ostream& os, const String& str) { + if (str.c_str() == NULL) { + os << "(null)"; + } else { + const char* const c_str = str.c_str(); + for (size_t i = 0; i != str.length(); i++) { + if (c_str[i] == '\0') { + os << "\\0"; + } else { + os << c_str[i]; + } + } + } + return os; } // Gets the content of the StrStream's buffer as a String. Each '\0' // character in the buffer is replaced with "\\0". -String StrStreamToString(StrStream* stream); +GTEST_API_ String StrStreamToString(StrStream* stream); // Converts a streamable value to a String. A NULL pointer is // converted to "(null)". When the input value is a ::string, diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h b/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h new file mode 100644 index 0000000..16178fc --- /dev/null +++ b/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h @@ -0,0 +1,968 @@ +// This file was GENERATED by a script. DO NOT EDIT BY HAND!!! + +// Copyright 2009 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Implements a subset of TR1 tuple needed by Google Test and Google Mock. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ + +#include <utility> // For ::std::pair. + +// The compiler used in Symbian has a bug that prevents us from declaring the +// tuple template as a friend (it complains that tuple is redefined). This +// hack bypasses the bug by declaring the members that should otherwise be +// private as public. +// Sun Studio versions < 12 also have the above bug. +#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) +#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: +#else +#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ + template <GTEST_10_TYPENAMES_(U)> friend class tuple; \ + private: +#endif + +// GTEST_n_TUPLE_(T) is the type of an n-tuple. +#define GTEST_0_TUPLE_(T) tuple<> +#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \ + void, void, void> +#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \ + void, void, void> +#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \ + void, void, void> +#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \ + void, void, void> +#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \ + void, void, void> +#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \ + void, void, void> +#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \ + void, void, void> +#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \ + T##7, void, void> +#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \ + T##7, T##8, void> +#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \ + T##7, T##8, T##9> + +// GTEST_n_TYPENAMES_(T) declares a list of n typenames. +#define GTEST_0_TYPENAMES_(T) +#define GTEST_1_TYPENAMES_(T) typename T##0 +#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1 +#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2 +#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3 +#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4 +#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5 +#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6 +#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, typename T##7 +#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8 +#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8, typename T##9 + +// In theory, defining stuff in the ::std namespace is undefined +// behavior. We can do this as we are playing the role of a standard +// library vendor. +namespace std { +namespace tr1 { + +template <typename T0 = void, typename T1 = void, typename T2 = void, + typename T3 = void, typename T4 = void, typename T5 = void, + typename T6 = void, typename T7 = void, typename T8 = void, + typename T9 = void> +class tuple; + +// Anything in namespace gtest_internal is Google Test's INTERNAL +// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. +namespace gtest_internal { + +// ByRef<T>::type is T if T is a reference; otherwise it's const T&. +template <typename T> +struct ByRef { typedef const T& type; }; // NOLINT +template <typename T> +struct ByRef<T&> { typedef T& type; }; // NOLINT + +// A handy wrapper for ByRef. +#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type + +// AddRef<T>::type is T if T is a reference; otherwise it's T&. This +// is the same as tr1::add_reference<T>::type. +template <typename T> +struct AddRef { typedef T& type; }; // NOLINT +template <typename T> +struct AddRef<T&> { typedef T& type; }; // NOLINT + +// A handy wrapper for AddRef. +#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type + +// A helper for implementing get<k>(). +template <int k> class Get; + +// A helper for implementing tuple_element<k, T>. kIndexValid is true +// iff k < the number of fields in tuple type T. +template <bool kIndexValid, int kIndex, class Tuple> +struct TupleElement; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 0, GTEST_10_TUPLE_(T)> { typedef T0 type; }; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 1, GTEST_10_TUPLE_(T)> { typedef T1 type; }; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 2, GTEST_10_TUPLE_(T)> { typedef T2 type; }; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 3, GTEST_10_TUPLE_(T)> { typedef T3 type; }; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 4, GTEST_10_TUPLE_(T)> { typedef T4 type; }; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 5, GTEST_10_TUPLE_(T)> { typedef T5 type; }; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 6, GTEST_10_TUPLE_(T)> { typedef T6 type; }; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 7, GTEST_10_TUPLE_(T)> { typedef T7 type; }; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 8, GTEST_10_TUPLE_(T)> { typedef T8 type; }; + +template <GTEST_10_TYPENAMES_(T)> +struct TupleElement<true, 9, GTEST_10_TUPLE_(T)> { typedef T9 type; }; + +} // namespace gtest_internal + +template <> +class tuple<> { + public: + tuple() {} + tuple(const tuple& /* t */) {} + tuple& operator=(const tuple& /* t */) { return *this; } +}; + +template <GTEST_1_TYPENAMES_(T)> +class GTEST_1_TUPLE_(T) { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} + + tuple(const tuple& t) : f0_(t.f0_) {} + + template <GTEST_1_TYPENAMES_(U)> + tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_1_TYPENAMES_(U)> + tuple& operator=(const GTEST_1_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_1_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { + f0_ = t.f0_; + return *this; + } + + T0 f0_; +}; + +template <GTEST_2_TYPENAMES_(T)> +class GTEST_2_TUPLE_(T) { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_(), f1_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0), + f1_(f1) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {} + + template <GTEST_2_TYPENAMES_(U)> + tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} + template <typename U0, typename U1> + tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_2_TYPENAMES_(U)> + tuple& operator=(const GTEST_2_TUPLE_(U)& t) { + return CopyFrom(t); + } + template <typename U0, typename U1> + tuple& operator=(const ::std::pair<U0, U1>& p) { + f0_ = p.first; + f1_ = p.second; + return *this; + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_2_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + return *this; + } + + T0 f0_; + T1 f1_; +}; + +template <GTEST_3_TYPENAMES_(T)> +class GTEST_3_TUPLE_(T) { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + template <GTEST_3_TYPENAMES_(U)> + tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_3_TYPENAMES_(U)> + tuple& operator=(const GTEST_3_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_3_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; +}; + +template <GTEST_4_TYPENAMES_(T)> +class GTEST_4_TUPLE_(T) { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} + + template <GTEST_4_TYPENAMES_(U)> + tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_4_TYPENAMES_(U)> + tuple& operator=(const GTEST_4_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_4_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; +}; + +template <GTEST_5_TYPENAMES_(T)> +class GTEST_5_TUPLE_(T) { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, + GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_) {} + + template <GTEST_5_TYPENAMES_(U)> + tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_5_TYPENAMES_(U)> + tuple& operator=(const GTEST_5_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_5_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; +}; + +template <GTEST_6_TYPENAMES_(T)> +class GTEST_6_TUPLE_(T) { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_) {} + + template <GTEST_6_TYPENAMES_(U)> + tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_6_TYPENAMES_(U)> + tuple& operator=(const GTEST_6_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_6_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; +}; + +template <GTEST_7_TYPENAMES_(T)> +class GTEST_7_TUPLE_(T) { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + template <GTEST_7_TYPENAMES_(U)> + tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_7_TYPENAMES_(U)> + tuple& operator=(const GTEST_7_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_7_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; +}; + +template <GTEST_8_TYPENAMES_(T)> +class GTEST_8_TUPLE_(T) { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, + GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + template <GTEST_8_TYPENAMES_(U)> + tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_8_TYPENAMES_(U)> + tuple& operator=(const GTEST_8_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_8_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; +}; + +template <GTEST_9_TYPENAMES_(T)> +class GTEST_9_TUPLE_(T) { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7), f8_(f8) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + template <GTEST_9_TYPENAMES_(U)> + tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_9_TYPENAMES_(U)> + tuple& operator=(const GTEST_9_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_9_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; +}; + +template <GTEST_10_TYPENAMES_(T)> +class tuple { + public: + template <int k> friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), + f9_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} + + template <GTEST_10_TYPENAMES_(U)> + tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), + f9_(t.f9_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template <GTEST_10_TYPENAMES_(U)> + tuple& operator=(const GTEST_10_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template <GTEST_10_TYPENAMES_(U)> + tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + f9_ = t.f9_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; + T9 f9_; +}; + +// 6.1.3.2 Tuple creation functions. + +// Known limitations: we don't support passing an +// std::tr1::reference_wrapper<T> to make_tuple(). And we don't +// implement tie(). + +inline tuple<> make_tuple() { return tuple<>(); } + +template <GTEST_1_TYPENAMES_(T)> +inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { + return GTEST_1_TUPLE_(T)(f0); +} + +template <GTEST_2_TYPENAMES_(T)> +inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { + return GTEST_2_TUPLE_(T)(f0, f1); +} + +template <GTEST_3_TYPENAMES_(T)> +inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) { + return GTEST_3_TUPLE_(T)(f0, f1, f2); +} + +template <GTEST_4_TYPENAMES_(T)> +inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3) { + return GTEST_4_TUPLE_(T)(f0, f1, f2, f3); +} + +template <GTEST_5_TYPENAMES_(T)> +inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4) { + return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4); +} + +template <GTEST_6_TYPENAMES_(T)> +inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5) { + return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5); +} + +template <GTEST_7_TYPENAMES_(T)> +inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6) { + return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6); +} + +template <GTEST_8_TYPENAMES_(T)> +inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) { + return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7); +} + +template <GTEST_9_TYPENAMES_(T)> +inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8) { + return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8); +} + +template <GTEST_10_TYPENAMES_(T)> +inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8, const T9& f9) { + return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); +} + +// 6.1.3.3 Tuple helper classes. + +template <typename Tuple> struct tuple_size; + +template <GTEST_0_TYPENAMES_(T)> +struct tuple_size<GTEST_0_TUPLE_(T)> { static const int value = 0; }; + +template <GTEST_1_TYPENAMES_(T)> +struct tuple_size<GTEST_1_TUPLE_(T)> { static const int value = 1; }; + +template <GTEST_2_TYPENAMES_(T)> +struct tuple_size<GTEST_2_TUPLE_(T)> { static const int value = 2; }; + +template <GTEST_3_TYPENAMES_(T)> +struct tuple_size<GTEST_3_TUPLE_(T)> { static const int value = 3; }; + +template <GTEST_4_TYPENAMES_(T)> +struct tuple_size<GTEST_4_TUPLE_(T)> { static const int value = 4; }; + +template <GTEST_5_TYPENAMES_(T)> +struct tuple_size<GTEST_5_TUPLE_(T)> { static const int value = 5; }; + +template <GTEST_6_TYPENAMES_(T)> +struct tuple_size<GTEST_6_TUPLE_(T)> { static const int value = 6; }; + +template <GTEST_7_TYPENAMES_(T)> +struct tuple_size<GTEST_7_TUPLE_(T)> { static const int value = 7; }; + +template <GTEST_8_TYPENAMES_(T)> +struct tuple_size<GTEST_8_TUPLE_(T)> { static const int value = 8; }; + +template <GTEST_9_TYPENAMES_(T)> +struct tuple_size<GTEST_9_TUPLE_(T)> { static const int value = 9; }; + +template <GTEST_10_TYPENAMES_(T)> +struct tuple_size<GTEST_10_TUPLE_(T)> { static const int value = 10; }; + +template <int k, class Tuple> +struct tuple_element { + typedef typename gtest_internal::TupleElement< + k < (tuple_size<Tuple>::value), k, Tuple>::type type; +}; + +#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type + +// 6.1.3.4 Element access. + +namespace gtest_internal { + +template <> +class Get<0> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + Field(Tuple& t) { return t.f0_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + ConstField(const Tuple& t) { return t.f0_; } +}; + +template <> +class Get<1> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + Field(Tuple& t) { return t.f1_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + ConstField(const Tuple& t) { return t.f1_; } +}; + +template <> +class Get<2> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + Field(Tuple& t) { return t.f2_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + ConstField(const Tuple& t) { return t.f2_; } +}; + +template <> +class Get<3> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + Field(Tuple& t) { return t.f3_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + ConstField(const Tuple& t) { return t.f3_; } +}; + +template <> +class Get<4> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + Field(Tuple& t) { return t.f4_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + ConstField(const Tuple& t) { return t.f4_; } +}; + +template <> +class Get<5> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + Field(Tuple& t) { return t.f5_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + ConstField(const Tuple& t) { return t.f5_; } +}; + +template <> +class Get<6> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + Field(Tuple& t) { return t.f6_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + ConstField(const Tuple& t) { return t.f6_; } +}; + +template <> +class Get<7> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + Field(Tuple& t) { return t.f7_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + ConstField(const Tuple& t) { return t.f7_; } +}; + +template <> +class Get<8> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + Field(Tuple& t) { return t.f8_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + ConstField(const Tuple& t) { return t.f8_; } +}; + +template <> +class Get<9> { + public: + template <class Tuple> + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + Field(Tuple& t) { return t.f9_; } // NOLINT + + template <class Tuple> + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + ConstField(const Tuple& t) { return t.f9_; } +}; + +} // namespace gtest_internal + +template <int k, GTEST_10_TYPENAMES_(T)> +GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get<k>::Field(t); +} + +template <int k, GTEST_10_TYPENAMES_(T)> +GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(const GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get<k>::ConstField(t); +} + +// 6.1.3.5 Relational operators + +// We only implement == and !=, as we don't have a need for the rest yet. + +namespace gtest_internal { + +// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the +// first k fields of t1 equals the first k fields of t2. +// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if +// k1 != k2. +template <int kSize1, int kSize2> +struct SameSizeTuplePrefixComparator; + +template <> +struct SameSizeTuplePrefixComparator<0, 0> { + template <class Tuple1, class Tuple2> + static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { + return true; + } +}; + +template <int k> +struct SameSizeTuplePrefixComparator<k, k> { + template <class Tuple1, class Tuple2> + static bool Eq(const Tuple1& t1, const Tuple2& t2) { + return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) && + ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2); + } +}; + +} // namespace gtest_internal + +template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)> +inline bool operator==(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { + return gtest_internal::SameSizeTuplePrefixComparator< + tuple_size<GTEST_10_TUPLE_(T)>::value, + tuple_size<GTEST_10_TUPLE_(U)>::value>::Eq(t, u); +} + +template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)> +inline bool operator!=(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { return !(t == u); } + +// 6.1.4 Pairs. +// Unimplemented. + +} // namespace tr1 +} // namespace std + +#undef GTEST_0_TUPLE_ +#undef GTEST_1_TUPLE_ +#undef GTEST_2_TUPLE_ +#undef GTEST_3_TUPLE_ +#undef GTEST_4_TUPLE_ +#undef GTEST_5_TUPLE_ +#undef GTEST_6_TUPLE_ +#undef GTEST_7_TUPLE_ +#undef GTEST_8_TUPLE_ +#undef GTEST_9_TUPLE_ +#undef GTEST_10_TUPLE_ + +#undef GTEST_0_TYPENAMES_ +#undef GTEST_1_TYPENAMES_ +#undef GTEST_2_TYPENAMES_ +#undef GTEST_3_TYPENAMES_ +#undef GTEST_4_TYPENAMES_ +#undef GTEST_5_TYPENAMES_ +#undef GTEST_6_TYPENAMES_ +#undef GTEST_7_TYPENAMES_ +#undef GTEST_8_TYPENAMES_ +#undef GTEST_9_TYPENAMES_ +#undef GTEST_10_TYPENAMES_ + +#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ +#undef GTEST_BY_REF_ +#undef GTEST_ADD_REF_ +#undef GTEST_TUPLE_ELEMENT_ + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h b/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h index 815da4b..093eee6 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h @@ -1,4 +1,6 @@ -// This file was GENERATED by a script. DO NOT EDIT BY HAND!!! +// This file was GENERATED by command: +// pump.py gtest-type-util.h.pump +// DO NOT EDIT BY HAND!!! // Copyright 2008 Google Inc. // All Rights Reserved. @@ -45,13 +47,13 @@ #include <gtest/internal/gtest-port.h> #include <gtest/internal/gtest-string.h> -#if defined(GTEST_HAS_TYPED_TEST) || defined(GTEST_HAS_TYPED_TEST_P) +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P -#ifdef __GNUC__ +// #ifdef __GNUC__ is too general here. It is possible to use gcc without using +// libstdc++ (which is where cxxabi.h comes from). +#ifdef __GLIBCXX__ #include <cxxabi.h> -#endif // __GNUC__ - -#include <typeinfo> +#endif // __GLIBCXX__ namespace testing { namespace internal { @@ -74,7 +76,7 @@ String GetTypeName() { #if GTEST_HAS_RTTI const char* const name = typeid(T).name(); -#ifdef __GNUC__ +#ifdef __GLIBCXX__ int status = 0; // gcc's implementation of typeid(T).name() mangles the type name, // so we have to demangle it. @@ -84,7 +86,7 @@ String GetTypeName() { return name_str; #else return name; -#endif // __GNUC__ +#endif // __GLIBCXX__ #else return "<type>"; |