Merge branch 'master' into upstream_188748737

This commit is contained in:
Bernhard Bauer 2018-03-12 18:15:35 +00:00 committed by GitHub
commit fc437ef4b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 3159 additions and 620 deletions

View File

@ -46,6 +46,12 @@ config_setting(
values = {"cpu": "x64_windows_msvc"}, values = {"cpu": "x64_windows_msvc"},
) )
config_setting(
name = "has_absl",
values = {"define": "absl=1"},
)
# Google Test including Google Mock # Google Test including Google Mock
cc_library( cc_library(
name = "gtest", name = "gtest",
@ -88,6 +94,21 @@ cc_library(
"-pthread", "-pthread",
], ],
}), }),
defines = select ({
":has_absl": [
"GTEST_HAS_ABSL=1",
],
"//conditions:default": [],
}
),
deps = select ({
":has_absl": [
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/strings"
],
"//conditions:default": [],
}
)
) )
cc_library( cc_library(

View File

@ -103,7 +103,7 @@ package (as described below):
### Windows Requirements ### ### Windows Requirements ###
* Microsoft Visual C++ 2010 or newer * Microsoft Visual C++ 2015 or newer
### Cygwin Requirements ### ### Cygwin Requirements ###

View File

@ -1 +1,8 @@
workspace(name = "com_google_googletest") workspace(name = "com_google_googletest")
# Abseil
http_archive(
name = "com_google_absl",
urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"],
strip_prefix = "abseil-cpp-master",
)

View File

@ -15,25 +15,11 @@ environment:
- compiler: msvc-14-seh - compiler: msvc-14-seh
generator: "Visual Studio 14 2015" generator: "Visual Studio 14 2015"
enabled_on_pr: yes
- compiler: msvc-14-seh - compiler: msvc-14-seh
generator: "Visual Studio 14 2015 Win64" generator: "Visual Studio 14 2015 Win64"
- compiler: msvc-12-seh
generator: "Visual Studio 12 2013"
- compiler: msvc-12-seh
generator: "Visual Studio 12 2013 Win64"
- compiler: msvc-11-seh
generator: "Visual Studio 11 2012"
- compiler: msvc-11-seh
generator: "Visual Studio 11 2012 Win64"
- compiler: msvc-10-seh
generator: "Visual Studio 10 2010"
- compiler: gcc-5.3.0-posix - compiler: gcc-5.3.0-posix
generator: "MinGW Makefiles" generator: "MinGW Makefiles"
cxx_path: 'C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin' cxx_path: 'C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin'
@ -86,7 +72,8 @@ build_script:
if ($LastExitCode -ne 0) { if ($LastExitCode -ne 0) {
throw "Exec: $ErrorMessage" throw "Exec: $ErrorMessage"
} }
& cmake --build . --config $env:configuration $cmake_parallel = if ($env:generator -eq "MinGW Makefiles") {"-j2"} else {"/m"}
& cmake --build . --config $env:configuration -- $cmake_parallel
if ($LastExitCode -ne 0) { if ($LastExitCode -ne 0) {
throw "Exec: $ErrorMessage" throw "Exec: $ErrorMessage"
} }

View File

@ -33,3 +33,4 @@ set -e
bazel build --curses=no //...:all bazel build --curses=no //...:all
bazel test --curses=no //...:all bazel test --curses=no //...:all
bazel test --curses=no //...:all --define absl=1

View File

@ -178,6 +178,8 @@ divided into several categories:
|`Ne(value)` |`argument != value`| |`Ne(value)` |`argument != value`|
|`IsNull()` |`argument` is a `NULL` pointer (raw or smart).| |`IsNull()` |`argument` is a `NULL` pointer (raw or smart).|
|`NotNull()` |`argument` is a non-null pointer (raw or smart).| |`NotNull()` |`argument` is a non-null pointer (raw or smart).|
|`VariantWith<T>(m)` |`argument` is `variant<>` that holds the alternative of
type T with a value matching `m`.|
|`Ref(variable)` |`argument` is a reference to `variable`.| |`Ref(variable)` |`argument` is a reference to `variable`.|
|`TypedEq<type>(value)`|`argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded.| |`TypedEq<type>(value)`|`argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded.|

View File

@ -1403,7 +1403,7 @@ edge from node A to node B wherever A must occur before B, we can get
a DAG. We use the term "sequence" to mean a directed path in this a DAG. We use the term "sequence" to mean a directed path in this
DAG. Now, if we decompose the DAG into sequences, we just need to know DAG. Now, if we decompose the DAG into sequences, we just need to know
which sequences each `EXPECT_CALL()` belongs to in order to be able to which sequences each `EXPECT_CALL()` belongs to in order to be able to
reconstruct the orginal DAG. reconstruct the original DAG.
So, to specify the partial order on the expectations we need to do two So, to specify the partial order on the expectations we need to do two
things: first to define some `Sequence` objects, and then for each things: first to define some `Sequence` objects, and then for each

View File

@ -47,10 +47,9 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "gtest/gtest.h"
#include "gmock/internal/gmock-internal-utils.h" #include "gmock/internal/gmock-internal-utils.h"
#include "gmock/internal/gmock-port.h" #include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h"
#if GTEST_HAS_STD_INITIALIZER_LIST_ #if GTEST_HAS_STD_INITIALIZER_LIST_
# include <initializer_list> // NOLINT -- must be after gtest.h # include <initializer_list> // NOLINT -- must be after gtest.h
@ -515,7 +514,7 @@ template <typename T, typename M>
class MatcherCastImpl { class MatcherCastImpl {
public: public:
static Matcher<T> Cast(const M& polymorphic_matcher_or_value) { static Matcher<T> Cast(const M& polymorphic_matcher_or_value) {
// M can be a polymorhic matcher, in which case we want to use // M can be a polymorphic matcher, in which case we want to use
// its conversion operator to create Matcher<T>. Or it can be a value // its conversion operator to create Matcher<T>. Or it can be a value
// that should be passed to the Matcher<T>'s constructor. // that should be passed to the Matcher<T>'s constructor.
// //
@ -1551,7 +1550,7 @@ class BothOfMatcherImpl : public MatcherInterface<T> {
// MatcherList provides mechanisms for storing a variable number of matchers in // MatcherList provides mechanisms for storing a variable number of matchers in
// a list structure (ListType) and creating a combining matcher from such a // a list structure (ListType) and creating a combining matcher from such a
// list. // list.
// The template is defined recursively using the following template paramters: // The template is defined recursively using the following template parameters:
// * kSize is the length of the MatcherList. // * kSize is the length of the MatcherList.
// * Head is the type of the first matcher of the list. // * Head is the type of the first matcher of the list.
// * Tail denotes the types of the remaining matchers of the list. // * Tail denotes the types of the remaining matchers of the list.
@ -2380,7 +2379,7 @@ class ResultOfMatcher {
private: private:
// Functors often define operator() as non-const method even though // Functors often define operator() as non-const method even though
// they are actualy stateless. But we need to use them even when // they are actually stateless. But we need to use them even when
// 'this' is a const pointer. It's the user's responsibility not to // 'this' is a const pointer. It's the user's responsibility not to
// use stateful callables with ResultOf(), which does't guarantee // use stateful callables with ResultOf(), which does't guarantee
// how many times the callable will be invoked. // how many times the callable will be invoked.
@ -3304,14 +3303,23 @@ typedef ::std::vector<ElementMatcherPair> ElementMatcherPairs;
GTEST_API_ ElementMatcherPairs GTEST_API_ ElementMatcherPairs
FindMaxBipartiteMatching(const MatchMatrix& g); FindMaxBipartiteMatching(const MatchMatrix& g);
GTEST_API_ bool FindPairing(const MatchMatrix& matrix, struct UnorderedMatcherRequire {
MatchResultListener* listener); enum Flags {
Superset = 1 << 0,
Subset = 1 << 1,
ExactMatch = Superset | Subset,
};
};
// Untyped base class for implementing UnorderedElementsAre. By // Untyped base class for implementing UnorderedElementsAre. By
// putting logic that's not specific to the element type here, we // putting logic that's not specific to the element type here, we
// reduce binary bloat and increase compilation speed. // reduce binary bloat and increase compilation speed.
class GTEST_API_ UnorderedElementsAreMatcherImplBase { class GTEST_API_ UnorderedElementsAreMatcherImplBase {
protected: protected:
explicit UnorderedElementsAreMatcherImplBase(
UnorderedMatcherRequire::Flags matcher_flags)
: match_flags_(matcher_flags) {}
// A vector of matcher describers, one for each element matcher. // A vector of matcher describers, one for each element matcher.
// Does not own the describers (and thus can be used only when the // Does not own the describers (and thus can be used only when the
// element matchers are alive). // element matchers are alive).
@ -3323,9 +3331,12 @@ class GTEST_API_ UnorderedElementsAreMatcherImplBase {
// Describes the negation of this UnorderedElementsAre matcher. // Describes the negation of this UnorderedElementsAre matcher.
void DescribeNegationToImpl(::std::ostream* os) const; void DescribeNegationToImpl(::std::ostream* os) const;
bool VerifyAllElementsAndMatchersAreMatched( bool VerifyMatchMatrix(const ::std::vector<std::string>& element_printouts,
const ::std::vector<std::string>& element_printouts, const MatchMatrix& matrix,
const MatchMatrix& matrix, MatchResultListener* listener) const; MatchResultListener* listener) const;
bool FindPairing(const MatchMatrix& matrix,
MatchResultListener* listener) const;
MatcherDescriberVec& matcher_describers() { MatcherDescriberVec& matcher_describers() {
return matcher_describers_; return matcher_describers_;
@ -3335,13 +3346,17 @@ class GTEST_API_ UnorderedElementsAreMatcherImplBase {
return Message() << n << " element" << (n == 1 ? "" : "s"); return Message() << n << " element" << (n == 1 ? "" : "s");
} }
UnorderedMatcherRequire::Flags match_flags() const { return match_flags_; }
private: private:
UnorderedMatcherRequire::Flags match_flags_;
MatcherDescriberVec matcher_describers_; MatcherDescriberVec matcher_describers_;
GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImplBase); GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImplBase);
}; };
// Implements unordered ElementsAre and unordered ElementsAreArray. // Implements UnorderedElementsAre, UnorderedElementsAreArray, IsSubsetOf, and
// IsSupersetOf.
template <typename Container> template <typename Container>
class UnorderedElementsAreMatcherImpl class UnorderedElementsAreMatcherImpl
: public MatcherInterface<Container>, : public MatcherInterface<Container>,
@ -3354,10 +3369,10 @@ class UnorderedElementsAreMatcherImpl
typedef typename StlContainer::const_iterator StlContainerConstIterator; typedef typename StlContainer::const_iterator StlContainerConstIterator;
typedef typename StlContainer::value_type Element; typedef typename StlContainer::value_type Element;
// Constructs the matcher from a sequence of element values or
// element matchers.
template <typename InputIter> template <typename InputIter>
UnorderedElementsAreMatcherImpl(InputIter first, InputIter last) { UnorderedElementsAreMatcherImpl(UnorderedMatcherRequire::Flags matcher_flags,
InputIter first, InputIter last)
: UnorderedElementsAreMatcherImplBase(matcher_flags) {
for (; first != last; ++first) { for (; first != last; ++first) {
matchers_.push_back(MatcherCast<const Element&>(*first)); matchers_.push_back(MatcherCast<const Element&>(*first));
matcher_describers().push_back(matchers_.back().GetDescriber()); matcher_describers().push_back(matchers_.back().GetDescriber());
@ -3378,34 +3393,32 @@ class UnorderedElementsAreMatcherImpl
MatchResultListener* listener) const { MatchResultListener* listener) const {
StlContainerReference stl_container = View::ConstReference(container); StlContainerReference stl_container = View::ConstReference(container);
::std::vector<std::string> element_printouts; ::std::vector<std::string> element_printouts;
MatchMatrix matrix = AnalyzeElements(stl_container.begin(), MatchMatrix matrix =
stl_container.end(), AnalyzeElements(stl_container.begin(), stl_container.end(),
&element_printouts, &element_printouts, listener);
listener);
const size_t actual_count = matrix.LhsSize(); if (matrix.LhsSize() == 0 && matrix.RhsSize() == 0) {
if (actual_count == 0 && matchers_.empty()) {
return true; return true;
} }
if (actual_count != matchers_.size()) {
if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
if (matrix.LhsSize() != matrix.RhsSize()) {
// The element count doesn't match. If the container is empty, // The element count doesn't match. If the container is empty,
// there's no need to explain anything as Google Mock already // there's no need to explain anything as Google Mock already
// prints the empty container. Otherwise we just need to show // prints the empty container. Otherwise we just need to show
// how many elements there actually are. // how many elements there actually are.
if (actual_count != 0 && listener->IsInterested()) { if (matrix.LhsSize() != 0 && listener->IsInterested()) {
*listener << "which has " << Elements(actual_count); *listener << "which has " << Elements(matrix.LhsSize());
} }
return false; return false;
} }
}
return VerifyAllElementsAndMatchersAreMatched(element_printouts, return VerifyMatchMatrix(element_printouts, matrix, listener) &&
matrix, listener) &&
FindPairing(matrix, listener); FindPairing(matrix, listener);
} }
private: private:
typedef ::std::vector<Matcher<const Element&> > MatcherVec;
template <typename ElementIter> template <typename ElementIter>
MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last, MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last,
::std::vector<std::string>* element_printouts, ::std::vector<std::string>* element_printouts,
@ -3432,7 +3445,7 @@ class UnorderedElementsAreMatcherImpl
return matrix; return matrix;
} }
MatcherVec matchers_; ::std::vector<Matcher<const Element&> > matchers_;
GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImpl); GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImpl);
}; };
@ -3465,7 +3478,7 @@ class UnorderedElementsAreMatcher {
TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_, TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_,
::std::back_inserter(matchers)); ::std::back_inserter(matchers));
return MakeMatcher(new UnorderedElementsAreMatcherImpl<Container>( return MakeMatcher(new UnorderedElementsAreMatcherImpl<Container>(
matchers.begin(), matchers.end())); UnorderedMatcherRequire::ExactMatch, matchers.begin(), matchers.end()));
} }
private: private:
@ -3498,24 +3511,23 @@ class ElementsAreMatcher {
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher); GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher);
}; };
// Implements UnorderedElementsAreArray(). // Implements UnorderedElementsAreArray(), IsSubsetOf(), and IsSupersetOf().
template <typename T> template <typename T>
class UnorderedElementsAreArrayMatcher { class UnorderedElementsAreArrayMatcher {
public: public:
UnorderedElementsAreArrayMatcher() {}
template <typename Iter> template <typename Iter>
UnorderedElementsAreArrayMatcher(Iter first, Iter last) UnorderedElementsAreArrayMatcher(UnorderedMatcherRequire::Flags match_flags,
: matchers_(first, last) {} Iter first, Iter last)
: match_flags_(match_flags), matchers_(first, last) {}
template <typename Container> template <typename Container>
operator Matcher<Container>() const { operator Matcher<Container>() const {
return MakeMatcher( return MakeMatcher(new UnorderedElementsAreMatcherImpl<Container>(
new UnorderedElementsAreMatcherImpl<Container>(matchers_.begin(), match_flags_, matchers_.begin(), matchers_.end()));
matchers_.end()));
} }
private: private:
UnorderedMatcherRequire::Flags match_flags_;
::std::vector<T> matchers_; ::std::vector<T> matchers_;
GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreArrayMatcher); GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreArrayMatcher);
@ -3615,10 +3627,6 @@ BoundSecondMatcher<Tuple2Matcher, Second> MatcherBindSecond(
return BoundSecondMatcher<Tuple2Matcher, Second>(tm, second); return BoundSecondMatcher<Tuple2Matcher, Second>(tm, second);
} }
// Joins a vector of strings as if they are fields of a tuple; returns
// the joined string. This function is exported for testing.
GTEST_API_ string JoinAsTuple(const Strings& fields);
// Returns the description for a matcher defined using the MATCHER*() // Returns the description for a matcher defined using the MATCHER*()
// macro where the user-supplied description string is "", if // macro where the user-supplied description string is "", if
// 'negation' is false; otherwise returns the description of the // 'negation' is false; otherwise returns the description of the
@ -3628,9 +3636,69 @@ GTEST_API_ std::string FormatMatcherDescription(bool negation,
const char* matcher_name, const char* matcher_name,
const Strings& param_values); const Strings& param_values);
namespace variant_matcher {
// Overloads to allow VariantMatcher to do proper ADL lookup.
template <typename T>
void holds_alternative() {}
template <typename T>
void get() {}
// Implements a matcher that checks the value of a variant<> type variable.
template <typename T>
class VariantMatcher {
public:
explicit VariantMatcher(::testing::Matcher<const T&> matcher)
: matcher_(internal::move(matcher)) {}
template <typename Variant>
bool MatchAndExplain(const Variant& value,
::testing::MatchResultListener* listener) const {
if (!listener->IsInterested()) {
return holds_alternative<T>(value) && matcher_.Matches(get<T>(value));
}
if (!holds_alternative<T>(value)) {
*listener << "whose value is not of type '" << GetTypeName() << "'";
return false;
}
const T& elem = get<T>(value);
StringMatchResultListener elem_listener;
const bool match = matcher_.MatchAndExplain(elem, &elem_listener);
*listener << "whose value " << PrintToString(elem)
<< (match ? " matches" : " doesn't match");
PrintIfNotEmpty(elem_listener.str(), listener->stream());
return match;
}
void DescribeTo(std::ostream* os) const {
*os << "is a variant<> with value of type '" << GetTypeName()
<< "' and the value ";
matcher_.DescribeTo(os);
}
void DescribeNegationTo(std::ostream* os) const {
*os << "is a variant<> with value of type other than '" << GetTypeName()
<< "' or the value ";
matcher_.DescribeNegationTo(os);
}
private:
static string GetTypeName() {
#if GTEST_HAS_RTTI
return internal::GetTypeName<T>();
#endif
return "the element type";
}
const ::testing::Matcher<const T&> matcher_;
};
} // namespace variant_matcher
} // namespace internal } // namespace internal
// ElementsAreArray(first, last) // ElementsAreArray(iterator_first, iterator_last)
// ElementsAreArray(pointer, count) // ElementsAreArray(pointer, count)
// ElementsAreArray(array) // ElementsAreArray(array)
// ElementsAreArray(container) // ElementsAreArray(container)
@ -3679,20 +3747,26 @@ ElementsAreArray(::std::initializer_list<T> xs) {
} }
#endif #endif
// UnorderedElementsAreArray(first, last) // UnorderedElementsAreArray(iterator_first, iterator_last)
// UnorderedElementsAreArray(pointer, count) // UnorderedElementsAreArray(pointer, count)
// UnorderedElementsAreArray(array) // UnorderedElementsAreArray(array)
// UnorderedElementsAreArray(container) // UnorderedElementsAreArray(container)
// UnorderedElementsAreArray({ e1, e2, ..., en }) // UnorderedElementsAreArray({ e1, e2, ..., en })
// //
// The UnorderedElementsAreArray() functions are like // UnorderedElementsAreArray() verifies that a bijective mapping onto a
// ElementsAreArray(...), but allow matching the elements in any order. // collection of matchers exists.
//
// The matchers can be specified as an array, a pointer and count, a container,
// an initializer list, or an STL iterator range. In each of these cases, the
// underlying matchers can be either values or matchers.
template <typename Iter> template <typename Iter>
inline internal::UnorderedElementsAreArrayMatcher< inline internal::UnorderedElementsAreArrayMatcher<
typename ::std::iterator_traits<Iter>::value_type> typename ::std::iterator_traits<Iter>::value_type>
UnorderedElementsAreArray(Iter first, Iter last) { UnorderedElementsAreArray(Iter first, Iter last) {
typedef typename ::std::iterator_traits<Iter>::value_type T; typedef typename ::std::iterator_traits<Iter>::value_type T;
return internal::UnorderedElementsAreArrayMatcher<T>(first, last); return internal::UnorderedElementsAreArrayMatcher<T>(
internal::UnorderedMatcherRequire::ExactMatch, first, last);
} }
template <typename T> template <typename T>
@ -3734,7 +3808,9 @@ UnorderedElementsAreArray(::std::initializer_list<T> xs) {
const internal::AnythingMatcher _ = {}; const internal::AnythingMatcher _ = {};
// Creates a matcher that matches any value of the given type T. // Creates a matcher that matches any value of the given type T.
template <typename T> template <typename T>
inline Matcher<T> A() { return MakeMatcher(new internal::AnyMatcherImpl<T>()); } inline Matcher<T> A() {
return Matcher<T>(new internal::AnyMatcherImpl<T>());
}
// Creates a matcher that matches any value of the given type T. // Creates a matcher that matches any value of the given type T.
template <typename T> template <typename T>
@ -4304,6 +4380,128 @@ inline internal::ContainsMatcher<M> Contains(M matcher) {
return internal::ContainsMatcher<M>(matcher); return internal::ContainsMatcher<M>(matcher);
} }
// IsSupersetOf(iterator_first, iterator_last)
// IsSupersetOf(pointer, count)
// IsSupersetOf(array)
// IsSupersetOf(container)
// IsSupersetOf({e1, e2, ..., en})
//
// IsSupersetOf() verifies that a surjective partial mapping onto a collection
// of matchers exists. In other words, a container matches
// IsSupersetOf({e1, ..., en}) if and only if there is a permutation
// {y1, ..., yn} of some of the container's elements where y1 matches e1,
// ..., and yn matches en. Obviously, the size of the container must be >= n
// in order to have a match. Examples:
//
// - {1, 2, 3} matches IsSupersetOf({Ge(3), Ne(0)}), as 3 matches Ge(3) and
// 1 matches Ne(0).
// - {1, 2} doesn't match IsSupersetOf({Eq(1), Lt(2)}), even though 1 matches
// both Eq(1) and Lt(2). The reason is that different matchers must be used
// for elements in different slots of the container.
// - {1, 1, 2} matches IsSupersetOf({Eq(1), Lt(2)}), as (the first) 1 matches
// Eq(1) and (the second) 1 matches Lt(2).
// - {1, 2, 3} matches IsSupersetOf(Gt(1), Gt(1)), as 2 matches (the first)
// Gt(1) and 3 matches (the second) Gt(1).
//
// The matchers can be specified as an array, a pointer and count, a container,
// an initializer list, or an STL iterator range. In each of these cases, the
// underlying matchers can be either values or matchers.
template <typename Iter>
inline internal::UnorderedElementsAreArrayMatcher<
typename ::std::iterator_traits<Iter>::value_type>
IsSupersetOf(Iter first, Iter last) {
typedef typename ::std::iterator_traits<Iter>::value_type T;
return internal::UnorderedElementsAreArrayMatcher<T>(
internal::UnorderedMatcherRequire::Superset, first, last);
}
template <typename T>
inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
const T* pointer, size_t count) {
return IsSupersetOf(pointer, pointer + count);
}
template <typename T, size_t N>
inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
const T (&array)[N]) {
return IsSupersetOf(array, N);
}
template <typename Container>
inline internal::UnorderedElementsAreArrayMatcher<
typename Container::value_type>
IsSupersetOf(const Container& container) {
return IsSupersetOf(container.begin(), container.end());
}
#if GTEST_HAS_STD_INITIALIZER_LIST_
template <typename T>
inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
::std::initializer_list<T> xs) {
return IsSupersetOf(xs.begin(), xs.end());
}
#endif
// IsSubsetOf(iterator_first, iterator_last)
// IsSubsetOf(pointer, count)
// IsSubsetOf(array)
// IsSubsetOf(container)
// IsSubsetOf({e1, e2, ..., en})
//
// IsSubsetOf() verifies that an injective mapping onto a collection of matchers
// exists. In other words, a container matches IsSubsetOf({e1, ..., en}) if and
// only if there is a subset of matchers {m1, ..., mk} which would match the
// container using UnorderedElementsAre. Obviously, the size of the container
// must be <= n in order to have a match. Examples:
//
// - {1} matches IsSubsetOf({Gt(0), Lt(0)}), as 1 matches Gt(0).
// - {1, -1} matches IsSubsetOf({Lt(0), Gt(0)}), as 1 matches Gt(0) and -1
// matches Lt(0).
// - {1, 2} doesn't matches IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both
// match Gt(0). The reason is that different matchers must be used for
// elements in different slots of the container.
//
// The matchers can be specified as an array, a pointer and count, a container,
// an initializer list, or an STL iterator range. In each of these cases, the
// underlying matchers can be either values or matchers.
template <typename Iter>
inline internal::UnorderedElementsAreArrayMatcher<
typename ::std::iterator_traits<Iter>::value_type>
IsSubsetOf(Iter first, Iter last) {
typedef typename ::std::iterator_traits<Iter>::value_type T;
return internal::UnorderedElementsAreArrayMatcher<T>(
internal::UnorderedMatcherRequire::Subset, first, last);
}
template <typename T>
inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
const T* pointer, size_t count) {
return IsSubsetOf(pointer, pointer + count);
}
template <typename T, size_t N>
inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
const T (&array)[N]) {
return IsSubsetOf(array, N);
}
template <typename Container>
inline internal::UnorderedElementsAreArrayMatcher<
typename Container::value_type>
IsSubsetOf(const Container& container) {
return IsSubsetOf(container.begin(), container.end());
}
#if GTEST_HAS_STD_INITIALIZER_LIST_
template <typename T>
inline internal::UnorderedElementsAreArrayMatcher<T> IsSubsetOf(
::std::initializer_list<T> xs) {
return IsSubsetOf(xs.begin(), xs.end());
}
#endif
// Matches an STL-style container or a native array that contains only // Matches an STL-style container or a native array that contains only
// elements matching the given value or matcher. // elements matching the given value or matcher.
// //
@ -4402,6 +4600,17 @@ inline internal::AnyOfMatcher<Args...> AnyOf(const Args&... matchers) {
template <typename InnerMatcher> template <typename InnerMatcher>
inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; } inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; }
// Returns a matcher that matches the value of a variant<> type variable.
// The matcher implementation uses ADL to find the holds_alternative and get
// functions.
// It is compatible with std::variant.
template <typename T>
PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith(
const Matcher<const T&>& matcher) {
return MakePolymorphicMatcher(
internal::variant_matcher::VariantMatcher<T>(matcher));
}
// These macros allow using matchers to check values in Google Test // These macros allow using matchers to check values in Google Test
// tests. ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher) // tests. ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
// succeed iff the value matches the matcher. If the assertion fails, // succeed iff the value matches the matcher. If the assertion fails,

View File

@ -53,6 +53,22 @@ MATCHER(IsEmpty, negation ? "isn't empty" : "is empty") {
return false; return false;
} }
// Define a matcher that matches a value that evaluates in boolean
// context to true. Useful for types that define "explicit operator
// bool" operators and so can't be compared for equality with true
// and false.
MATCHER(IsTrue, negation ? "is false" : "is true") {
return static_cast<bool>(arg);
}
// Define a matcher that matches a value that evaluates in boolean
// context to false. Useful for types that define "explicit operator
// bool" operators and so can't be compared for equality with true
// and false.
MATCHER(IsFalse, negation ? "is true" : "is false") {
return !static_cast<bool>(arg);
}
} // namespace testing } // namespace testing
#endif // GMOCK_GMOCK_MORE_MATCHERS_H_ #endif // GMOCK_GMOCK_MORE_MATCHERS_H_

View File

@ -65,11 +65,6 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
#if GTEST_HAS_EXCEPTIONS
# include <stdexcept> // NOLINT
#endif
#include "gmock/gmock-actions.h" #include "gmock/gmock-actions.h"
#include "gmock/gmock-cardinalities.h" #include "gmock/gmock-cardinalities.h"
#include "gmock/gmock-matchers.h" #include "gmock/gmock-matchers.h"
@ -77,6 +72,10 @@
#include "gmock/internal/gmock-port.h" #include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#if GTEST_HAS_EXCEPTIONS
# include <stdexcept> // NOLINT
#endif
namespace testing { namespace testing {
// An abstract handle of an expectation. // An abstract handle of an expectation.

View File

@ -59,8 +59,8 @@
#include "gmock/gmock-cardinalities.h" #include "gmock/gmock-cardinalities.h"
#include "gmock/gmock-generated-actions.h" #include "gmock/gmock-generated-actions.h"
#include "gmock/gmock-generated-function-mockers.h" #include "gmock/gmock-generated-function-mockers.h"
#include "gmock/gmock-generated-nice-strict.h"
#include "gmock/gmock-generated-matchers.h" #include "gmock/gmock-generated-matchers.h"
#include "gmock/gmock-generated-nice-strict.h"
#include "gmock/gmock-matchers.h" #include "gmock/gmock-matchers.h"
#include "gmock/gmock-more-actions.h" #include "gmock/gmock-more-actions.h"
#include "gmock/gmock-more-matchers.h" #include "gmock/gmock-more-matchers.h"

View File

@ -33,7 +33,6 @@
// //
// Adds google3 callback support to CallableTraits. // Adds google3 callback support to CallableTraits.
// //
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_CALLBACK_MATCHERS_H_ #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_CALLBACK_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_CALLBACK_MATCHERS_H_

View File

@ -90,42 +90,48 @@ struct MatcherTuple< ::testing::tuple<A1, A2, A3> > {
template <typename A1, typename A2, typename A3, typename A4> template <typename A1, typename A2, typename A3, typename A4>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4> >
Matcher<A4> > type; type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5> template <typename A1, typename A2, typename A3, typename A4, typename A5>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5> > type; Matcher<A5> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6> typename A6>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6> > type; Matcher<A5>, Matcher<A6> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7> typename A6, typename A7>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6>, Matcher<A7> > type; Matcher<A5>, Matcher<A6>, Matcher<A7> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7, typename A8> typename A6, typename A7, typename A8>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8> > type; Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7, typename A8, typename A9> typename A6, typename A7, typename A8, typename A9>
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > { struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9> > type; Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>,
Matcher<A9> >
type;
}; };
template <typename A1, typename A2, typename A3, typename A4, typename A5, template <typename A1, typename A2, typename A3, typename A4, typename A5,
@ -133,8 +139,9 @@ template <typename A1, typename A2, typename A3, typename A4, typename A5,
struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9, struct MatcherTuple< ::testing::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
A10> > { A10> > {
typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>, typedef ::testing::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9>, Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>,
Matcher<A10> > type; Matcher<A9>, Matcher<A10> >
type;
}; };
// Template struct Function<F>, where F must be a function type, contains // Template struct Function<F>, where F must be a function type, contains

View File

@ -41,7 +41,6 @@
#include <stdio.h> #include <stdio.h>
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include <string> #include <string>
#include "gmock/internal/gmock-generated-internal-utils.h" #include "gmock/internal/gmock-generated-internal-utils.h"
#include "gmock/internal/gmock-port.h" #include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
@ -49,11 +48,15 @@
namespace testing { namespace testing {
namespace internal { namespace internal {
// Joins a vector of strings as if they are fields of a tuple; returns
// the joined string.
GTEST_API_ std::string JoinAsTuple(const Strings& fields);
// Converts an identifier name to a space-separated list of lower-case // Converts an identifier name to a space-separated list of lower-case
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is // words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
// treated as one word. For example, both "FooBar123" and // treated as one word. For example, both "FooBar123" and
// "foo_bar_123" are converted to "foo bar 123". // "foo_bar_123" are converted to "foo bar 123".
GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name); GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name);
// PointeeOf<Pointer>::type is the type of a value pointed to by a // PointeeOf<Pointer>::type is the type of a value pointed to by a
// Pointer, which can be either a smart pointer or a raw pointer. The // Pointer, which can be either a smart pointer or a raw pointer. The
@ -114,9 +117,11 @@ struct LinkedPtrLessThan {
// To gcc, // To gcc,
// wchar_t == signed wchar_t != unsigned wchar_t == unsigned int // wchar_t == signed wchar_t != unsigned wchar_t == unsigned int
#ifdef __GNUC__ #ifdef __GNUC__
#if !defined(__WCHAR_UNSIGNED__)
// signed/unsigned wchar_t are valid types. // signed/unsigned wchar_t are valid types.
# define GMOCK_HAS_SIGNED_WCHAR_T_ 1 # define GMOCK_HAS_SIGNED_WCHAR_T_ 1
#endif #endif
#endif
// In what follows, we use the term "kind" to indicate whether a type // In what follows, we use the term "kind" to indicate whether a type
// is bool, an integer type (excluding bool), a floating-point type, // is bool, an integer type (excluding bool), a floating-point type,
@ -503,8 +508,38 @@ struct RemoveConstFromKey<std::pair<const K, V> > {
template <bool kValue> template <bool kValue>
struct BooleanConstant {}; struct BooleanConstant {};
// Emit an assertion failure due to incorrect DoDefault() usage. Out-of-lined to
// reduce code size.
void IllegalDoDefault(const char* file, int line);
#if GTEST_LANG_CXX11
// Helper types for Apply() below.
template <size_t... Is> struct int_pack { typedef int_pack type; };
template <class Pack, size_t I> struct append;
template <size_t... Is, size_t I>
struct append<int_pack<Is...>, I> : int_pack<Is..., I> {};
template <size_t C>
struct make_int_pack : append<typename make_int_pack<C - 1>::type, C - 1> {};
template <> struct make_int_pack<0> : int_pack<> {};
template <typename F, typename Tuple, size_t... Idx>
auto ApplyImpl(F&& f, Tuple&& args, int_pack<Idx...>) -> decltype(
std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...)) {
return std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...);
}
// Apply the function to a tuple of arguments.
template <typename F, typename Tuple>
auto Apply(F&& f, Tuple&& args)
-> decltype(ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
make_int_pack<std::tuple_size<Tuple>::value>())) {
return ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
make_int_pack<std::tuple_size<Tuple>::value>());
}
#endif
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ #endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_

View File

@ -50,15 +50,11 @@
// portability utilities to Google Test's gtest-port.h instead of // portability utilities to Google Test's gtest-port.h instead of
// here, as Google Mock depends on Google Test. Only add a utility // here, as Google Mock depends on Google Test. Only add a utility
// here if it's truly specific to Google Mock. // here if it's truly specific to Google Mock.
#include "gtest/internal/gtest-linked_ptr.h" #include "gtest/internal/gtest-linked_ptr.h"
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include "gmock/internal/custom/gmock-port.h" #include "gmock/internal/custom/gmock-port.h"
// To avoid conditional compilation everywhere, we make it
// gmock-port.h's responsibility to #include the header implementing
// tr1/tuple. gmock-port.h does this via gtest-port.h, which is
// guaranteed to pull in the tuple header.
// For MS Visual C++, check the compiler version. At least VS 2003 is // For MS Visual C++, check the compiler version. At least VS 2003 is
// required to compile Google Mock. // required to compile Google Mock.
#if defined(_MSC_VER) && _MSC_VER < 1310 #if defined(_MSC_VER) && _MSC_VER < 1310

View File

@ -338,7 +338,7 @@ class Class(_GenericDeclaration):
# TODO(nnorwitz): handle namespaces, etc. # TODO(nnorwitz): handle namespaces, etc.
if self.bases: if self.bases:
for token_list in self.bases: for token_list in self.bases:
# TODO(nnorwitz): bases are tokens, do name comparision. # TODO(nnorwitz): bases are tokens, do name comparison.
for token in token_list: for token in token_list:
if token.name == node.name: if token.name == node.name:
return True return True
@ -381,7 +381,7 @@ class Function(_GenericDeclaration):
def Requires(self, node): def Requires(self, node):
if self.parameters: if self.parameters:
# TODO(nnorwitz): parameters are tokens, do name comparision. # TODO(nnorwitz): parameters are tokens, do name comparison.
for p in self.parameters: for p in self.parameters:
if p.name == node.name: if p.name == node.name:
return True return True
@ -858,7 +858,7 @@ class AstBuilder(object):
last_token = self._GetNextToken() last_token = self._GetNextToken()
return tokens, last_token return tokens, last_token
# TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necesary. # TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necessary.
def _IgnoreUpTo(self, token_type, token): def _IgnoreUpTo(self, token_type, token):
unused_tokens = self._GetTokensUpTo(token_type, token) unused_tokens = self._GetTokensUpTo(token_type, token)

View File

@ -47,12 +47,31 @@
namespace testing { namespace testing {
namespace internal { namespace internal {
// Joins a vector of strings as if they are fields of a tuple; returns
// the joined string.
GTEST_API_ std::string JoinAsTuple(const Strings& fields) {
switch (fields.size()) {
case 0:
return "";
case 1:
return fields[0];
default:
std::string result = "(" + fields[0];
for (size_t i = 1; i < fields.size(); i++) {
result += ", ";
result += fields[i];
}
result += ")";
return result;
}
}
// Converts an identifier name to a space-separated list of lower-case // Converts an identifier name to a space-separated list of lower-case
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is // words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
// treated as one word. For example, both "FooBar123" and // treated as one word. For example, both "FooBar123" and
// "foo_bar_123" are converted to "foo bar 123". // "foo_bar_123" are converted to "foo bar 123".
GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name) { GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name) {
string result; std::string result;
char prev_char = '\0'; char prev_char = '\0';
for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) { for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {
// We don't care about the current locale as the input is // We don't care about the current locale as the input is
@ -169,5 +188,15 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message,
std::cout << ::std::flush; std::cout << ::std::flush;
} }
void IllegalDoDefault(const char* file, int line) {
internal::Assert(
false, file, line,
"You are using DoDefault() inside a composite action like "
"DoAll() or WithArgs(). This is not supported for technical "
"reasons. Please instead spell out the default action, or "
"assign the default action to an Action variable and use "
"the variable in various places.");
}
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing

View File

@ -38,6 +38,7 @@
#include "gmock/gmock-generated-matchers.h" #include "gmock/gmock-generated-matchers.h"
#include <string.h> #include <string.h>
#include <iostream>
#include <sstream> #include <sstream>
#include <string> #include <string>
@ -100,25 +101,6 @@ Matcher<StringPiece>::Matcher(StringPiece s) {
namespace internal { namespace internal {
// Joins a vector of strings as if they are fields of a tuple; returns
// the joined string.
GTEST_API_ string JoinAsTuple(const Strings& fields) {
switch (fields.size()) {
case 0:
return "";
case 1:
return fields[0];
default:
string result = "(" + fields[0];
for (size_t i = 1; i < fields.size(); i++) {
result += ", ";
result += fields[i];
}
result += ")";
return result;
}
}
// Returns the description for a matcher defined using the MATCHER*() // Returns the description for a matcher defined using the MATCHER*()
// macro where the user-supplied description string is "", if // macro where the user-supplied description string is "", if
// 'negation' is false; otherwise returns the description of the // 'negation' is false; otherwise returns the description of the
@ -200,8 +182,7 @@ class MaxBipartiteMatchState {
explicit MaxBipartiteMatchState(const MatchMatrix& graph) explicit MaxBipartiteMatchState(const MatchMatrix& graph)
: graph_(&graph), : graph_(&graph),
left_(graph_->LhsSize(), kUnused), left_(graph_->LhsSize(), kUnused),
right_(graph_->RhsSize(), kUnused) { right_(graph_->RhsSize(), kUnused) {}
}
// Returns the edges of a maximal match, each in the form {left, right}. // Returns the edges of a maximal match, each in the form {left, right}.
ElementMatcherPairs Compute() { ElementMatcherPairs Compute() {
@ -258,10 +239,8 @@ class MaxBipartiteMatchState {
// //
bool TryAugment(size_t ilhs, ::std::vector<char>* seen) { bool TryAugment(size_t ilhs, ::std::vector<char>* seen) {
for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) { for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) {
if ((*seen)[irhs]) if ((*seen)[irhs]) continue;
continue; if (!graph_->HasEdge(ilhs, irhs)) continue;
if (!graph_->HasEdge(ilhs, irhs))
continue;
// There's an available edge from ilhs to irhs. // There's an available edge from ilhs to irhs.
(*seen)[irhs] = 1; (*seen)[irhs] = 1;
// Next a search is performed to determine whether // Next a search is performed to determine whether
@ -304,8 +283,7 @@ class MaxBipartiteMatchState {
const size_t MaxBipartiteMatchState::kUnused; const size_t MaxBipartiteMatchState::kUnused;
GTEST_API_ ElementMatcherPairs GTEST_API_ ElementMatcherPairs FindMaxBipartiteMatching(const MatchMatrix& g) {
FindMaxBipartiteMatching(const MatchMatrix& g) {
return MaxBipartiteMatchState(g).Compute(); return MaxBipartiteMatchState(g).Compute();
} }
@ -324,38 +302,6 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
os << "\n}"; os << "\n}";
} }
// Tries to find a pairing, and explains the result.
GTEST_API_ bool FindPairing(const MatchMatrix& matrix,
MatchResultListener* listener) {
ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix);
size_t max_flow = matches.size();
bool result = (max_flow == matrix.RhsSize());
if (!result) {
if (listener->IsInterested()) {
*listener << "where no permutation of the elements can "
"satisfy all matchers, and the closest match is "
<< max_flow << " of " << matrix.RhsSize()
<< " matchers with the pairings:\n";
LogElementMatcherPairVec(matches, listener->stream());
}
return false;
}
if (matches.size() > 1) {
if (listener->IsInterested()) {
const char *sep = "where:\n";
for (size_t mi = 0; mi < matches.size(); ++mi) {
*listener << sep << " - element #" << matches[mi].first
<< " is matched by matcher #" << matches[mi].second;
sep = ",\n";
}
}
}
return true;
}
bool MatchMatrix::NextGraph() { bool MatchMatrix::NextGraph() {
for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) { for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
for (size_t irhs = 0; irhs < RhsSize(); ++irhs) { for (size_t irhs = 0; irhs < RhsSize(); ++irhs) {
@ -394,6 +340,8 @@ std::string MatchMatrix::DebugString() const {
void UnorderedElementsAreMatcherImplBase::DescribeToImpl( void UnorderedElementsAreMatcherImplBase::DescribeToImpl(
::std::ostream* os) const { ::std::ostream* os) const {
switch (match_flags()) {
case UnorderedMatcherRequire::ExactMatch:
if (matcher_describers_.empty()) { if (matcher_describers_.empty()) {
*os << "is empty"; *os << "is empty";
return; return;
@ -405,33 +353,70 @@ void UnorderedElementsAreMatcherImplBase::DescribeToImpl(
} }
*os << "has " << Elements(matcher_describers_.size()) *os << "has " << Elements(matcher_describers_.size())
<< " and there exists some permutation of elements such that:\n"; << " and there exists some permutation of elements such that:\n";
break;
case UnorderedMatcherRequire::Superset:
*os << "a surjection from elements to requirements exists such that:\n";
break;
case UnorderedMatcherRequire::Subset:
*os << "an injection from elements to requirements exists such that:\n";
break;
}
const char* sep = ""; const char* sep = "";
for (size_t i = 0; i != matcher_describers_.size(); ++i) { for (size_t i = 0; i != matcher_describers_.size(); ++i) {
*os << sep << " - element #" << i << " "; *os << sep;
if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
*os << " - element #" << i << " ";
} else {
*os << " - an element ";
}
matcher_describers_[i]->DescribeTo(os); matcher_describers_[i]->DescribeTo(os);
if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
sep = ", and\n"; sep = ", and\n";
} else {
sep = "\n";
}
} }
} }
void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl( void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
::std::ostream* os) const { ::std::ostream* os) const {
switch (match_flags()) {
case UnorderedMatcherRequire::ExactMatch:
if (matcher_describers_.empty()) { if (matcher_describers_.empty()) {
*os << "isn't empty"; *os << "isn't empty";
return; return;
} }
if (matcher_describers_.size() == 1) { if (matcher_describers_.size() == 1) {
*os << "doesn't have " << Elements(1) *os << "doesn't have " << Elements(1) << ", or has " << Elements(1)
<< ", or has " << Elements(1) << " that "; << " that ";
matcher_describers_[0]->DescribeNegationTo(os); matcher_describers_[0]->DescribeNegationTo(os);
return; return;
} }
*os << "doesn't have " << Elements(matcher_describers_.size()) *os << "doesn't have " << Elements(matcher_describers_.size())
<< ", or there exists no permutation of elements such that:\n"; << ", or there exists no permutation of elements such that:\n";
break;
case UnorderedMatcherRequire::Superset:
*os << "no surjection from elements to requirements exists such that:\n";
break;
case UnorderedMatcherRequire::Subset:
*os << "no injection from elements to requirements exists such that:\n";
break;
}
const char* sep = ""; const char* sep = "";
for (size_t i = 0; i != matcher_describers_.size(); ++i) { for (size_t i = 0; i != matcher_describers_.size(); ++i) {
*os << sep << " - element #" << i << " "; *os << sep;
if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
*os << " - element #" << i << " ";
} else {
*os << " - an element ";
}
matcher_describers_[i]->DescribeTo(os); matcher_describers_[i]->DescribeTo(os);
if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
sep = ", and\n"; sep = ", and\n";
} else {
sep = "\n";
}
} }
} }
@ -440,8 +425,7 @@ void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
// and better error reporting. // and better error reporting.
// Returns false, writing an explanation to 'listener', if and only // Returns false, writing an explanation to 'listener', if and only
// if the success criteria are not met. // if the success criteria are not met.
bool UnorderedElementsAreMatcherImplBase:: bool UnorderedElementsAreMatcherImplBase::VerifyMatchMatrix(
VerifyAllElementsAndMatchersAreMatched(
const ::std::vector<std::string>& element_printouts, const ::std::vector<std::string>& element_printouts,
const MatchMatrix& matrix, MatchResultListener* listener) const { const MatchMatrix& matrix, MatchResultListener* listener) const {
bool result = true; bool result = true;
@ -456,12 +440,11 @@ bool UnorderedElementsAreMatcherImplBase::
} }
} }
{ if (match_flags() & UnorderedMatcherRequire::Superset) {
const char* sep = const char* sep =
"where the following matchers don't match any elements:\n"; "where the following matchers don't match any elements:\n";
for (size_t mi = 0; mi < matcher_matched.size(); ++mi) { for (size_t mi = 0; mi < matcher_matched.size(); ++mi) {
if (matcher_matched[mi]) if (matcher_matched[mi]) continue;
continue;
result = false; result = false;
if (listener->IsInterested()) { if (listener->IsInterested()) {
*listener << sep << "matcher #" << mi << ": "; *listener << sep << "matcher #" << mi << ": ";
@ -471,7 +454,7 @@ bool UnorderedElementsAreMatcherImplBase::
} }
} }
{ if (match_flags() & UnorderedMatcherRequire::Subset) {
const char* sep = const char* sep =
"where the following elements don't match any matchers:\n"; "where the following elements don't match any matchers:\n";
const char* outer_sep = ""; const char* outer_sep = "";
@ -479,8 +462,7 @@ bool UnorderedElementsAreMatcherImplBase::
outer_sep = "\nand "; outer_sep = "\nand ";
} }
for (size_t ei = 0; ei < element_matched.size(); ++ei) { for (size_t ei = 0; ei < element_matched.size(); ++ei) {
if (element_matched[ei]) if (element_matched[ei]) continue;
continue;
result = false; result = false;
if (listener->IsInterested()) { if (listener->IsInterested()) {
*listener << outer_sep << sep << "element #" << ei << ": " *listener << outer_sep << sep << "element #" << ei << ": "
@ -493,5 +475,46 @@ bool UnorderedElementsAreMatcherImplBase::
return result; return result;
} }
bool UnorderedElementsAreMatcherImplBase::FindPairing(
const MatchMatrix& matrix, MatchResultListener* listener) const {
ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix);
size_t max_flow = matches.size();
if ((match_flags() & UnorderedMatcherRequire::Superset) &&
max_flow < matrix.RhsSize()) {
if (listener->IsInterested()) {
*listener << "where no permutation of the elements can satisfy all "
"matchers, and the closest match is "
<< max_flow << " of " << matrix.RhsSize()
<< " matchers with the pairings:\n";
LogElementMatcherPairVec(matches, listener->stream());
}
return false;
}
if ((match_flags() & UnorderedMatcherRequire::Subset) &&
max_flow < matrix.LhsSize()) {
if (listener->IsInterested()) {
*listener
<< "where not all elements can be matched, and the closest match is "
<< max_flow << " of " << matrix.RhsSize()
<< " matchers with the pairings:\n";
LogElementMatcherPairVec(matches, listener->stream());
}
return false;
}
if (matches.size() > 1) {
if (listener->IsInterested()) {
const char* sep = "where:\n";
for (size_t mi = 0; mi < matches.size(); ++mi) {
*listener << sep << " - element #" << matches[mi].first
<< " is matched by matcher #" << matches[mi].second;
sep = ",\n";
}
}
}
return true;
}
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing

View File

@ -136,8 +136,8 @@ static bool ParseGoogleMockIntFlag(const char* str, const char* flag,
if (value_str == NULL) return false; if (value_str == NULL) return false;
// Sets *value to the value of the flag. // Sets *value to the value of the flag.
*value = atoi(value_str); return ParseInt32(Message() << "The value of flag --" << flag,
return true; value_str, value);
} }
// The internal implementation of InitGoogleMock(). // The internal implementation of InitGoogleMock().

View File

@ -53,3 +53,71 @@ cc_test(
}), }),
deps = ["//:gtest"], deps = ["//:gtest"],
) )
# Py tests
py_library(
name = "gmock_test_utils",
testonly = 1,
srcs = ["gmock_test_utils.py"],
)
cc_binary(
name = "gmock_leak_test_",
testonly = 1,
srcs = ["gmock_leak_test_.cc"],
deps = [
"//:gtest_main",
],
)
py_test(
name = "gmock_leak_test",
size = "medium",
srcs = ["gmock_leak_test.py"],
data = [
":gmock_leak_test_",
":gmock_test_utils",
],
)
cc_test(
name = "gmock_link_test",
size = "small",
srcs = [
"gmock_link2_test.cc",
"gmock_link_test.cc",
"gmock_link_test.h",
],
deps = [
"//:gtest_main",
],
)
cc_binary(
name = "gmock_output_test_",
srcs = ["gmock_output_test_.cc"],
deps = [
"//:gtest",
],
)
py_test(
name = "gmock_output_test",
size = "medium",
srcs = ["gmock_output_test.py"],
data = [
":gmock_output_test_",
":gmock_output_test_golden.txt",
],
deps = [":gmock_test_utils"],
)
cc_test(
name = "gmock_test",
size = "small",
srcs = ["gmock_test.cc"],
deps = [
"//:gtest_main",
],
)

View File

@ -107,7 +107,11 @@ TEST(BuiltInDefaultValueTest, IsZeroForNumericTypes) {
EXPECT_EQ(0, BuiltInDefaultValue<signed wchar_t>::Get()); EXPECT_EQ(0, BuiltInDefaultValue<signed wchar_t>::Get());
#endif #endif
#if GMOCK_WCHAR_T_IS_NATIVE_ #if GMOCK_WCHAR_T_IS_NATIVE_
#if !defined(__WCHAR_UNSIGNED__)
EXPECT_EQ(0, BuiltInDefaultValue<wchar_t>::Get()); EXPECT_EQ(0, BuiltInDefaultValue<wchar_t>::Get());
#else
EXPECT_EQ(0U, BuiltInDefaultValue<wchar_t>::Get());
#endif
#endif #endif
EXPECT_EQ(0U, BuiltInDefaultValue<unsigned short>::Get()); // NOLINT EXPECT_EQ(0U, BuiltInDefaultValue<unsigned short>::Get()); // NOLINT
EXPECT_EQ(0, BuiltInDefaultValue<signed short>::Get()); // NOLINT EXPECT_EQ(0, BuiltInDefaultValue<signed short>::Get()); // NOLINT
@ -751,7 +755,7 @@ TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) {
} }
// Tests that DoDefault() returns the default value set by // Tests that DoDefault() returns the default value set by
// DefaultValue<T>::Set() when it's not overriden by an ON_CALL(). // DefaultValue<T>::Set() when it's not overridden by an ON_CALL().
TEST(DoDefaultTest, ReturnsUserSpecifiedPerTypeDefaultValueWhenThereIsOne) { TEST(DoDefaultTest, ReturnsUserSpecifiedPerTypeDefaultValueWhenThereIsOne) {
DefaultValue<int>::Set(1); DefaultValue<int>::Set(1);
MockClass mock; MockClass mock;

View File

@ -146,7 +146,6 @@ using testing::internal::ExplainMatchFailureTupleTo;
using testing::internal::FloatingEqMatcher; using testing::internal::FloatingEqMatcher;
using testing::internal::FormatMatcherDescription; using testing::internal::FormatMatcherDescription;
using testing::internal::IsReadableTypeName; using testing::internal::IsReadableTypeName;
using testing::internal::JoinAsTuple;
using testing::internal::linked_ptr; using testing::internal::linked_ptr;
using testing::internal::MatchMatrix; using testing::internal::MatchMatrix;
using testing::internal::RE; using testing::internal::RE;
@ -915,7 +914,7 @@ TEST(TypedEqTest, CanDescribeSelf) {
// Type<T>::IsTypeOf(v) compiles iff the type of value v is T, where T // Type<T>::IsTypeOf(v) compiles iff the type of value v is T, where T
// is a "bare" type (i.e. not in the form of const U or U&). If v's // is a "bare" type (i.e. not in the form of const U or U&). If v's
// type is not T, the compiler will generate a message about // type is not T, the compiler will generate a message about
// "undefined referece". // "undefined reference".
template <typename T> template <typename T>
struct Type { struct Type {
static bool IsTypeOf(const T& /* v */) { return true; } static bool IsTypeOf(const T& /* v */) { return true; }
@ -1424,7 +1423,7 @@ TEST(PairTest, MatchesCorrectly) {
EXPECT_THAT(p, Pair(25, "foo")); EXPECT_THAT(p, Pair(25, "foo"));
EXPECT_THAT(p, Pair(Ge(20), HasSubstr("o"))); EXPECT_THAT(p, Pair(Ge(20), HasSubstr("o")));
// 'first' doesnt' match, but 'second' matches. // 'first' does not match, but 'second' matches.
EXPECT_THAT(p, Not(Pair(42, "foo"))); EXPECT_THAT(p, Not(Pair(42, "foo")));
EXPECT_THAT(p, Not(Pair(Lt(25), "foo"))); EXPECT_THAT(p, Not(Pair(Lt(25), "foo")));
@ -4263,7 +4262,7 @@ TYPED_TEST(ContainerEqTest, DuplicateDifference) {
#endif // GTEST_HAS_TYPED_TEST #endif // GTEST_HAS_TYPED_TEST
// Tests that mutliple missing values are reported. // Tests that mutliple missing values are reported.
// Using just vector here, so order is predicatble. // Using just vector here, so order is predictable.
TEST(ContainerEqExtraTest, MultipleValuesMissing) { TEST(ContainerEqExtraTest, MultipleValuesMissing) {
static const int vals[] = {1, 1, 2, 3, 5, 8}; static const int vals[] = {1, 1, 2, 3, 5, 8};
static const int test_vals[] = {2, 1, 5}; static const int test_vals[] = {2, 1, 5};
@ -4276,7 +4275,7 @@ TEST(ContainerEqExtraTest, MultipleValuesMissing) {
} }
// Tests that added values are reported. // Tests that added values are reported.
// Using just vector here, so order is predicatble. // Using just vector here, so order is predictable.
TEST(ContainerEqExtraTest, MultipleValuesAdded) { TEST(ContainerEqExtraTest, MultipleValuesAdded) {
static const int vals[] = {1, 1, 2, 3, 5, 8}; static const int vals[] = {1, 1, 2, 3, 5, 8};
static const int test_vals[] = {1, 2, 92, 3, 5, 8, 46}; static const int test_vals[] = {1, 2, 92, 3, 5, 8, 46};
@ -5268,28 +5267,6 @@ TEST(IsReadableTypeNameTest, ReturnsFalseForLongFunctionTypeNames) {
EXPECT_FALSE(IsReadableTypeName("void (&)(int, bool, char, float)")); EXPECT_FALSE(IsReadableTypeName("void (&)(int, bool, char, float)"));
} }
// Tests JoinAsTuple().
TEST(JoinAsTupleTest, JoinsEmptyTuple) {
EXPECT_EQ("", JoinAsTuple(Strings()));
}
TEST(JoinAsTupleTest, JoinsOneTuple) {
const char* fields[] = {"1"};
EXPECT_EQ("1", JoinAsTuple(Strings(fields, fields + 1)));
}
TEST(JoinAsTupleTest, JoinsTwoTuple) {
const char* fields[] = {"1", "a"};
EXPECT_EQ("(1, a)", JoinAsTuple(Strings(fields, fields + 2)));
}
TEST(JoinAsTupleTest, JoinsTenTuple) {
const char* fields[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
EXPECT_EQ("(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)",
JoinAsTuple(Strings(fields, fields + 10)));
}
// Tests FormatMatcherDescription(). // Tests FormatMatcherDescription().
TEST(FormatMatcherDescriptionTest, WorksForEmptyDescription) { TEST(FormatMatcherDescriptionTest, WorksForEmptyDescription) {
@ -5678,5 +5655,69 @@ TEST(UnorderedPointwiseTest, AllowsMonomorphicInnerMatcher) {
EXPECT_THAT(lhs, UnorderedPointwise(m2, rhs)); EXPECT_THAT(lhs, UnorderedPointwise(m2, rhs));
} }
class SampleVariantIntString {
public:
SampleVariantIntString(int i) : i_(i), has_int_(true) {}
SampleVariantIntString(const std::string& s) : s_(s), has_int_(false) {}
template <typename T>
friend bool holds_alternative(const SampleVariantIntString& value) {
return value.has_int_ == internal::IsSame<T, int>::value;
}
template <typename T>
friend const T& get(const SampleVariantIntString& value) {
return value.get_impl(static_cast<T*>(NULL));
}
private:
const int& get_impl(int*) const { return i_; }
const std::string& get_impl(std::string*) const { return s_; }
int i_;
std::string s_;
bool has_int_;
};
TEST(VariantTest, DescribesSelf) {
const Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
EXPECT_THAT(Describe(m), ContainsRegex("is a variant<> with value of type "
"'.*' and the value is equal to 1"));
}
TEST(VariantTest, ExplainsSelf) {
const Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
EXPECT_THAT(Explain(m, SampleVariantIntString(1)),
ContainsRegex("whose value 1"));
EXPECT_THAT(Explain(m, SampleVariantIntString("A")),
HasSubstr("whose value is not of type '"));
EXPECT_THAT(Explain(m, SampleVariantIntString(2)),
"whose value 2 doesn't match");
}
TEST(VariantTest, FullMatch) {
Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
EXPECT_TRUE(m.Matches(SampleVariantIntString(1)));
m = VariantWith<std::string>(Eq("1"));
EXPECT_TRUE(m.Matches(SampleVariantIntString("1")));
}
TEST(VariantTest, TypeDoesNotMatch) {
Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
EXPECT_FALSE(m.Matches(SampleVariantIntString("1")));
m = VariantWith<std::string>(Eq("1"));
EXPECT_FALSE(m.Matches(SampleVariantIntString(1)));
}
TEST(VariantTest, InnerDoesNotMatch) {
Matcher<SampleVariantIntString> m = VariantWith<int>(Eq(1));
EXPECT_FALSE(m.Matches(SampleVariantIntString(2)));
m = VariantWith<std::string>(Eq("1"));
EXPECT_FALSE(m.Matches(SampleVariantIntString("2")));
}
} // namespace gmock_matchers_test } // namespace gmock_matchers_test
} // namespace testing } // namespace testing

View File

@ -90,8 +90,10 @@
// Field // Field
// Property // Property
// ResultOf(function) // ResultOf(function)
// ResultOf(callback)
// Pointee // Pointee
// Truly(predicate) // Truly(predicate)
// AddressSatisfies
// AllOf // AllOf
// AnyOf // AnyOf
// Not // Not
@ -120,13 +122,15 @@
# include <errno.h> # include <errno.h>
#endif #endif
#include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h"
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include "gtest/gtest.h"
#include "gtest/internal/gtest-port.h"
using testing::_; using testing::_;
using testing::A; using testing::A;
using testing::Action;
using testing::AllOf; using testing::AllOf;
using testing::AnyOf; using testing::AnyOf;
using testing::Assign; using testing::Assign;
@ -148,6 +152,8 @@ using testing::Invoke;
using testing::InvokeArgument; using testing::InvokeArgument;
using testing::InvokeWithoutArgs; using testing::InvokeWithoutArgs;
using testing::IsNull; using testing::IsNull;
using testing::IsSubsetOf;
using testing::IsSupersetOf;
using testing::Le; using testing::Le;
using testing::Lt; using testing::Lt;
using testing::Matcher; using testing::Matcher;
@ -592,6 +598,22 @@ TEST(LinkTest, TestMatcherElementsAreArray) {
ON_CALL(mock, VoidFromVector(ElementsAreArray(arr))).WillByDefault(Return()); ON_CALL(mock, VoidFromVector(ElementsAreArray(arr))).WillByDefault(Return());
} }
// Tests the linkage of the IsSubsetOf matcher.
TEST(LinkTest, TestMatcherIsSubsetOf) {
Mock mock;
char arr[] = {'a', 'b'};
ON_CALL(mock, VoidFromVector(IsSubsetOf(arr))).WillByDefault(Return());
}
// Tests the linkage of the IsSupersetOf matcher.
TEST(LinkTest, TestMatcherIsSupersetOf) {
Mock mock;
char arr[] = {'a', 'b'};
ON_CALL(mock, VoidFromVector(IsSupersetOf(arr))).WillByDefault(Return());
}
// Tests the linkage of the ContainerEq matcher. // Tests the linkage of the ContainerEq matcher.
TEST(LinkTest, TestMatcherContainerEq) { TEST(LinkTest, TestMatcherContainerEq) {
Mock mock; Mock mock;

View File

@ -31,7 +31,7 @@
"""Tests the text output of Google C++ Mocking Framework. """Tests the text output of Google C++ Mocking Framework.
SYNOPSIS To update the golden file:
gmock_output_test.py --build_dir=BUILD/DIR --gengolden gmock_output_test.py --build_dir=BUILD/DIR --gengolden
# where BUILD/DIR contains the built gmock_output_test_ file. # where BUILD/DIR contains the built gmock_output_test_ file.
gmock_output_test.py --gengolden gmock_output_test.py --gengolden
@ -176,5 +176,8 @@ if __name__ == '__main__':
golden_file = open(GOLDEN_PATH, 'wb') golden_file = open(GOLDEN_PATH, 'wb')
golden_file.write(output) golden_file.write(output)
golden_file.close() golden_file.close()
# Suppress the error "googletest was imported but a call to its main()
# was never detected."
os._exit(0)
else: else:
gmock_test_utils.Main() gmock_test_utils.Main()

View File

@ -33,12 +33,13 @@
// threads concurrently. // threads concurrently.
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
namespace testing { namespace testing {
namespace { namespace {
// From <gtest/internal/gtest-port.h>. // From "gtest/internal/gtest-port.h".
using ::testing::internal::ThreadWithParam; using ::testing::internal::ThreadWithParam;
// The maximum number of test threads (not including helper threads) // The maximum number of test threads (not including helper threads)

View File

@ -37,6 +37,7 @@
#include <string> #include <string>
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "gtest/internal/custom/gtest.h"
#if !defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) #if !defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
@ -51,9 +52,9 @@ void TestInitGoogleMock(const Char* (&argv)[M], const Char* (&new_argv)[N],
const ::std::string& expected_gmock_verbose) { const ::std::string& expected_gmock_verbose) {
const ::std::string old_verbose = GMOCK_FLAG(verbose); const ::std::string old_verbose = GMOCK_FLAG(verbose);
int argc = M; int argc = M - 1;
InitGoogleMock(&argc, const_cast<Char**>(argv)); InitGoogleMock(&argc, const_cast<Char**>(argv));
ASSERT_EQ(N, argc) << "The new argv has wrong number of elements."; ASSERT_EQ(N - 1, argc) << "The new argv has wrong number of elements.";
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
EXPECT_STREQ(new_argv[i], argv[i]); EXPECT_STREQ(new_argv[i], argv[i]);

View File

@ -1,5 +1,3 @@
#!/usr/bin/env python
#
# Copyright 2006, Google Inc. # Copyright 2006, Google Inc.
# All rights reserved. # All rights reserved.
# #
@ -36,19 +34,19 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
import os import os
import sys import sys
# Determines path to gtest_test_utils and imports it. # Determines path to gtest_test_utils and imports it.
SCRIPT_DIR = os.path.dirname(__file__) or '.' SCRIPT_DIR = os.path.dirname(__file__) or '.'
# isdir resolves symbolic links. # isdir resolves symbolic links.
gtest_tests_util_dir = os.path.join(SCRIPT_DIR, '../gtest/test') gtest_tests_util_dir = os.path.join(SCRIPT_DIR, '../googletest/test')
if os.path.isdir(gtest_tests_util_dir): if os.path.isdir(gtest_tests_util_dir):
GTEST_TESTS_UTIL_DIR = gtest_tests_util_dir GTEST_TESTS_UTIL_DIR = gtest_tests_util_dir
else: else:
GTEST_TESTS_UTIL_DIR = os.path.join(SCRIPT_DIR, '../../gtest/test') GTEST_TESTS_UTIL_DIR = os.path.join(SCRIPT_DIR, '../../googletest/test')
sys.path.append(GTEST_TESTS_UTIL_DIR) sys.path.append(GTEST_TESTS_UTIL_DIR)
import gtest_test_utils # pylint: disable-msg=C6204
# pylint: disable=C6204
import gtest_test_utils
def GetSourceDir(): def GetSourceDir():

View File

@ -27,8 +27,6 @@ option(
"Build gtest with internal symbols hidden in shared libraries." "Build gtest with internal symbols hidden in shared libraries."
OFF) OFF)
set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Generate debug library name with a postfix.")
# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build(). # Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
include(cmake/hermetic_build.cmake OPTIONAL) include(cmake/hermetic_build.cmake OPTIONAL)
@ -306,7 +304,9 @@ if (gtest_build_tests)
cxx_executable(gtest_xml_outfile1_test_ test gtest_main) cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
cxx_executable(gtest_xml_outfile2_test_ test gtest_main) cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
py_test(gtest_xml_outfiles_test) py_test(gtest_xml_outfiles_test)
py_test(gtest_json_outfiles_test)
cxx_executable(gtest_xml_output_unittest_ test gtest) cxx_executable(gtest_xml_output_unittest_ test gtest)
py_test(gtest_xml_output_unittest) py_test(gtest_xml_output_unittest)
py_test(gtest_json_output_unittest)
endif() endif()

View File

@ -91,10 +91,13 @@ macro(config_compiler_and_linker)
set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32") set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN") set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1") set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0") set(cxx_no_exception_flags "-EHs-c- -D_HAS_EXCEPTIONS=0")
set(cxx_no_rtti_flags "-GR-") set(cxx_no_rtti_flags "-GR-")
elseif (CMAKE_COMPILER_IS_GNUCXX) elseif (CMAKE_COMPILER_IS_GNUCXX)
set(cxx_base_flags "-Wall -Wshadow -Werror") set(cxx_base_flags "-Wall -Wshadow -Werror")
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0)
set(cxx_base_flags "${cxx_base_flags} -Wno-error=dangling-else")
endif()
set(cxx_exception_flags "-fexceptions") set(cxx_exception_flags "-fexceptions")
set(cxx_no_exception_flags "-fno-exceptions") set(cxx_no_exception_flags "-fno-exceptions")
# Until version 4.3.2, GCC doesn't define a macro to indicate # Until version 4.3.2, GCC doesn't define a macro to indicate
@ -155,6 +158,10 @@ function(cxx_library_with_type name type cxx_flags)
set_target_properties(${name} set_target_properties(${name}
PROPERTIES PROPERTIES
COMPILE_FLAGS "${cxx_flags}") COMPILE_FLAGS "${cxx_flags}")
# Generate debug library name with a postfix.
set_target_properties(${name}
PROPERTIES
DEBUG_POSTFIX "d")
if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED") if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
set_target_properties(${name} set_target_properties(${name}
PROPERTIES PROPERTIES

View File

@ -872,13 +872,33 @@ TEST(FooTest, Bar) {
} }
``` ```
Since we don't use exceptions, it is technically impossible to To alleviate this, gUnit provides three different solutions. You could use
implement the intended behavior here. To alleviate this, Google Test either exceptions, the `(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
provides two solutions. You could use either the
`(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
`HasFatalFailure()` function. They are described in the following two `HasFatalFailure()` function. They are described in the following two
subsections. subsections.
#### Asserting on Subroutines with an exception
The following code can turn ASSERT-failure into an exception:
```c++
class ThrowListener : public testing::EmptyTestEventListener {
void OnTestPartResult(const testing::TestPartResult& result) override {
if (result.type() == testing::TestPartResult::kFatalFailure) {
throw testing::AssertionException(result);
}
}
};
int main(int argc, char** argv) {
...
testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
return RUN_ALL_TESTS();
}
```
This listener should be added after other listeners if you have any, otherwise
they won't see failed `OnTestPartResult`.
### Asserting on Subroutines ### ### Asserting on Subroutines ###
As shown above, if your test calls a subroutine that has an `ASSERT_*` As shown above, if your test calls a subroutine that has an `ASSERT_*`
@ -1951,6 +1971,17 @@ variable to `0` has the same effect.
_Availability:_ Linux, Windows, Mac. (In Google Test 1.3.0 and lower, _Availability:_ Linux, Windows, Mac. (In Google Test 1.3.0 and lower,
the default behavior is that the elapsed time is **not** printed.) the default behavior is that the elapsed time is **not** printed.)
**Availability**: Linux, Windows, Mac.
#### Suppressing UTF-8 Text Output
In case of assertion failures, gUnit prints expected and actual values of type
`string` both as hex-encoded strings as well as in readable UTF-8 text if they
contain valid non-ASCII UTF-8 characters. If you want to suppress the UTF-8 text
because, for example, you don't have an UTF-8 compatible output medium, run the
test program with `--gunit_print_utf8=0` or set the `GUNIT_PRINT_UTF8`
environment variable to `0`.
### Generating an XML Report ### ### Generating an XML Report ###
Google Test can emit a detailed XML report to a file in addition to its normal Google Test can emit a detailed XML report to a file in addition to its normal
@ -2029,6 +2060,207 @@ Things to note:
_Availability:_ Linux, Windows, Mac. _Availability:_ Linux, Windows, Mac.
#### Generating an JSON Report {#JsonReport}
gUnit can also emit a JSON report as an alternative format to XML. To generate
the JSON report, set the `GUNIT_OUTPUT` environment variable or the
`--gunit_output` flag to the string `"json:path_to_output_file"`, which will
create the file at the given location. You can also just use the string
`"json"`, in which case the output can be found in the `test_detail.json` file
in the current directory.
The report format conforms to the following JSON Schema:
```json
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"definitions": {
"TestCase": {
"type": "object",
"properties": {
"name": { "type": "string" },
"tests": { "type": "integer" },
"failures": { "type": "integer" },
"disabled": { "type": "integer" },
"time": { "type": "string" },
"testsuite": {
"type": "array",
"items": {
"$ref": "#/definitions/TestInfo"
}
}
}
},
"TestInfo": {
"type": "object",
"properties": {
"name": { "type": "string" },
"status": {
"type": "string",
"enum": ["RUN", "NOTRUN"]
},
"time": { "type": "string" },
"classname": { "type": "string" },
"failures": {
"type": "array",
"items": {
"$ref": "#/definitions/Failure"
}
}
}
},
"Failure": {
"type": "object",
"properties": {
"failures": { "type": "string" },
"type": { "type": "string" }
}
}
},
"properties": {
"tests": { "type": "integer" },
"failures": { "type": "integer" },
"disabled": { "type": "integer" },
"errors": { "type": "integer" },
"timestamp": {
"type": "string",
"format": "date-time"
},
"time": { "type": "string" },
"name": { "type": "string" },
"testsuites": {
"type": "array",
"items": {
"$ref": "#/definitions/TestCase"
}
}
}
}
```
The report uses the format that conforms to the following Proto3 using the
[JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json):
```proto
syntax = "proto3";
package googletest;
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
message UnitTest {
int32 tests = 1;
int32 failures = 2;
int32 disabled = 3;
int32 errors = 4;
google.protobuf.Timestamp timestamp = 5;
google.protobuf.Duration time = 6;
string name = 7;
repeated TestCase testsuites = 8;
}
message TestCase {
string name = 1;
int32 tests = 2;
int32 failures = 3;
int32 disabled = 4;
int32 errors = 5;
google.protobuf.Duration time = 6;
repeated TestInfo testsuite = 7;
}
message TestInfo {
string name = 1;
enum Status {
RUN = 0;
NOTRUN = 1;
}
Status status = 2;
google.protobuf.Duration time = 3;
string classname = 4;
message Failure {
string failures = 1;
string type = 2;
}
repeated Failure failures = 5;
}
```
For instance, the following program
```c++
TEST(MathTest, Addition) { ... }
TEST(MathTest, Subtraction) { ... }
TEST(LogicTest, NonContradiction) { ... }
```
could generate this report:
```json
{
"tests": 3,
"failures": 1,
"errors": 0,
"time": "0.035s",
"timestamp": "2011-10-31T18:52:42Z"
"name": "AllTests",
"testsuites": [
{
"name": "MathTest",
"tests": 2,
"failures": 1,
"errors": 0,
"time": "0.015s",
"testsuite": [
{
"name": "Addition",
"status": "RUN",
"time": "0.007s",
"classname": "",
"failures": [
{
"message": "Value of: add(1, 1)\x0A Actual: 3\x0AExpected: 2",
"type": ""
},
{
"message": "Value of: add(1, -1)\x0A Actual: 1\x0AExpected: 0",
"type": ""
}
]
},
{
"name": "Subtraction",
"status": "RUN",
"time": "0.005s",
"classname": ""
}
]
}
{
"name": "LogicTest",
"tests": 1,
"failures": 0,
"errors": 0,
"time": "0.005s",
"testsuite": [
{
"name": "NonContradiction",
"status": "RUN",
"time": "0.005s",
"classname": ""
}
]
}
]
}
```
IMPORTANT: The exact format of the JSON document is subject to change.
**Availability**: Linux, Windows, Mac.
## Controlling How Failures Are Reported ## ## Controlling How Failures Are Reported ##
### Turning Assertion Failures into Break-Points ### ### Turning Assertion Failures into Break-Points ###

View File

@ -12,5 +12,5 @@ the respective git branch/tag).**
To contribute code to Google Test, read: To contribute code to Google Test, read:
* [CONTRIBUTING](../CONTRIBUTING.md) -- read this _before_ writing your first patch. * [CONTRIBUTING](../../CONTRIBUTING.md) -- read this _before_ writing your first patch.
* [PumpManual](PumpManual.md) -- how we generate some of Google Test's source files. * [PumpManual](PumpManual.md) -- how we generate some of Google Test's source files.

View File

@ -460,7 +460,7 @@ following benefits:
You may still want to use `SetUp()/TearDown()` in the following rare cases: You may still want to use `SetUp()/TearDown()` in the following rare cases:
* If the tear-down operation could throw an exception, you must use `TearDown()` as opposed to the destructor, as throwing in a destructor leads to undefined behavior and usually will kill your program right away. Note that many standard libraries (like STL) may throw when exceptions are enabled in the compiler. Therefore you should prefer `TearDown()` if you want to write portable tests that work with or without exceptions. * If the tear-down operation could throw an exception, you must use `TearDown()` as opposed to the destructor, as throwing in a destructor leads to undefined behavior and usually will kill your program right away. Note that many standard libraries (like STL) may throw when exceptions are enabled in the compiler. Therefore you should prefer `TearDown()` if you want to write portable tests that work with or without exceptions.
* The assertion macros throw an exception when flag `--gtest_throw_on_failure` is specified. Therefore, you shouldn't use Google Test assertions in a destructor if you plan to run your tests with this flag. * The assertion macros throw an exception when flag `--gtest_throw_on_failure` is specified. Therefore, you shouldn't use Google Test assertions in a destructor if you plan to run your tests with this flag.
* In a constructor or destructor, you cannot make a virtual function call on this object. (You can call a method declared as virtual, but it will be statically bound.) Therefore, if you need to call a method that will be overriden in a derived class, you have to use `SetUp()/TearDown()`. * In a constructor or destructor, you cannot make a virtual function call on this object. (You can call a method declared as virtual, but it will be statically bound.) Therefore, if you need to call a method that will be overridden in a derived class, you have to use `SetUp()/TearDown()`.
## The compiler complains "no matching function to call" when I use ASSERT\_PREDn. How do I fix it? ## ## The compiler complains "no matching function to call" when I use ASSERT\_PREDn. How do I fix it? ##

View File

@ -239,7 +239,7 @@ To create a test:
1. The test's result is determined by the assertions; if any assertion in the test fails (either fatally or non-fatally), or if the test crashes, the entire test fails. Otherwise, it succeeds. 1. The test's result is determined by the assertions; if any assertion in the test fails (either fatally or non-fatally), or if the test crashes, the entire test fails. Otherwise, it succeeds.
``` ```
TEST(test_case_name, test_name) { TEST(testCaseName, testName) {
... test body ... ... test body ...
} }
``` ```

View File

@ -46,6 +46,10 @@
// 2. operator<<(ostream&, const T&) defined in either foo or the // 2. operator<<(ostream&, const T&) defined in either foo or the
// global namespace. // global namespace.
// //
// However if T is an STL-style container then it is printed element-wise
// unless foo::PrintTo(const T&, ostream*) is defined. Note that
// operator<<() is ignored for container types.
//
// If none of the above is defined, it will print the debug string of // If none of the above is defined, it will print the debug string of
// the value if it is a protocol buffer, or print the raw bytes in the // the value if it is a protocol buffer, or print the raw bytes in the
// value otherwise. // value otherwise.
@ -107,6 +111,11 @@
# include <tuple> # include <tuple>
#endif #endif
#if GTEST_HAS_ABSL
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#endif // GTEST_HAS_ABSL
namespace testing { namespace testing {
// Definitions in the 'internal' and 'internal2' name spaces are // Definitions in the 'internal' and 'internal2' name spaces are
@ -125,6 +134,10 @@ enum TypeKind {
kProtobuf, // a protobuf type kProtobuf, // a protobuf type
kConvertibleToInteger, // a type implicitly convertible to BiggestInt kConvertibleToInteger, // a type implicitly convertible to BiggestInt
// (e.g. a named or unnamed enum type) // (e.g. a named or unnamed enum type)
#if GTEST_HAS_ABSL
kConvertibleToStringView, // a type implicitly convertible to
// absl::string_view
#endif
kOtherType // anything else kOtherType // anything else
}; };
@ -176,6 +189,19 @@ class TypeWithoutFormatter<T, kConvertibleToInteger> {
} }
}; };
#if GTEST_HAS_ABSL
template <typename T>
class TypeWithoutFormatter<T, kConvertibleToStringView> {
public:
// Since T has neither operator<< nor PrintTo() but can be implicitly
// converted to absl::string_view, we print it as a absl::string_view.
//
// Note: the implementation is further below, as it depends on
// internal::PrintTo symbol which is defined later in the file.
static void PrintValue(const T& value, ::std::ostream* os);
};
#endif
// Prints the given value to the given ostream. If the value is a // Prints the given value to the given ostream. If the value is a
// protocol message, its debug string is printed; if it's an enum or // protocol message, its debug string is printed; if it's an enum or
// of a type implicitly convertible to BiggestInt, it's printed as an // of a type implicitly convertible to BiggestInt, it's printed as an
@ -203,10 +229,19 @@ class TypeWithoutFormatter<T, kConvertibleToInteger> {
template <typename Char, typename CharTraits, typename T> template <typename Char, typename CharTraits, typename T>
::std::basic_ostream<Char, CharTraits>& operator<<( ::std::basic_ostream<Char, CharTraits>& operator<<(
::std::basic_ostream<Char, CharTraits>& os, const T& x) { ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
TypeWithoutFormatter<T, TypeWithoutFormatter<T, (internal::IsAProtocolMessage<T>::value
(internal::IsAProtocolMessage<T>::value ? kProtobuf : ? kProtobuf
internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ? : internal::ImplicitlyConvertible<
kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); const T&, internal::BiggestInt>::value
? kConvertibleToInteger
:
#if GTEST_HAS_ABSL
internal::ImplicitlyConvertible<
const T&, absl::string_view>::value
? kConvertibleToStringView
:
#endif
kOtherType)>::PrintValue(x, &os);
return os; return os;
} }
@ -427,7 +462,8 @@ void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */,
*os << "NULL"; *os << "NULL";
} else { } else {
// T is a function type, so '*os << p' doesn't do what we want // T is a function type, so '*os << p' doesn't do what we want
// (it just prints p as bool). Cast p to const void* to print it. // (it just prints p as bool). We want to print p as a const
// void*.
*os << reinterpret_cast<const void*>(p); *os << reinterpret_cast<const void*>(p);
} }
} }
@ -456,17 +492,15 @@ void PrintTo(const T& value, ::std::ostream* os) {
// DefaultPrintTo() is overloaded. The type of its first argument // DefaultPrintTo() is overloaded. The type of its first argument
// determines which version will be picked. // determines which version will be picked.
// //
// Note that we check for recursive and other container types here, prior // Note that we check for container types here, prior to we check
// to we check for protocol message types in our operator<<. The rationale is: // for protocol message types in our operator<<. The rationale is:
// //
// For protocol messages, we want to give people a chance to // For protocol messages, we want to give people a chance to
// override Google Mock's format by defining a PrintTo() or // override Google Mock's format by defining a PrintTo() or
// operator<<. For STL containers, other formats can be // operator<<. For STL containers, other formats can be
// incompatible with Google Mock's format for the container // incompatible with Google Mock's format for the container
// elements; therefore we check for container types here to ensure // elements; therefore we check for container types here to ensure
// that our format is used. To prevent an infinite runtime recursion // that our format is used.
// during the output of recursive container types, we check first for
// those.
// //
// Note that MSVC and clang-cl do allow an implicit conversion from // Note that MSVC and clang-cl do allow an implicit conversion from
// pointer-to-function to pointer-to-object, but clang-cl warns on it. // pointer-to-function to pointer-to-object, but clang-cl warns on it.
@ -593,6 +627,13 @@ inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
} }
#endif // GTEST_HAS_STD_WSTRING #endif // GTEST_HAS_STD_WSTRING
#if GTEST_HAS_ABSL
// Overload for absl::string_view.
inline void PrintTo(absl::string_view sp, ::std::ostream* os) {
PrintTo(::std::string(sp), os);
}
#endif // GTEST_HAS_ABSL
#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_ #if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
// Helper function for printing a tuple. T must be instantiated with // Helper function for printing a tuple. T must be instantiated with
// a tuple type. // a tuple type.
@ -722,6 +763,26 @@ class UniversalPrinter {
GTEST_DISABLE_MSC_WARNINGS_POP_() GTEST_DISABLE_MSC_WARNINGS_POP_()
}; };
#if GTEST_HAS_ABSL
// Printer for absl::optional
template <typename T>
class UniversalPrinter<::absl::optional<T>> {
public:
static void Print(const ::absl::optional<T>& value, ::std::ostream* os) {
*os << '(';
if (!value) {
*os << "nullopt";
} else {
UniversalPrint(*value, os);
}
*os << ')';
}
};
#endif // GTEST_HAS_ABSL
// UniversalPrintArray(begin, len, os) prints an array of 'len' // UniversalPrintArray(begin, len, os) prints an array of 'len'
// elements, starting at address 'begin'. // elements, starting at address 'begin'.
template <typename T> template <typename T>
@ -868,7 +929,7 @@ void UniversalPrint(const T& value, ::std::ostream* os) {
UniversalPrinter<T1>::Print(value, os); UniversalPrinter<T1>::Print(value, os);
} }
typedef ::std::vector<string> Strings; typedef ::std::vector< ::std::string> Strings;
// TuplePolicy<TupleT> must provide: // TuplePolicy<TupleT> must provide:
// - tuple_size // - tuple_size
@ -988,6 +1049,16 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
} // namespace internal } // namespace internal
#if GTEST_HAS_ABSL
namespace internal2 {
template <typename T>
void TypeWithoutFormatter<T, kConvertibleToStringView>::PrintValue(
const T& value, ::std::ostream* os) {
internal::PrintTo(absl::string_view(value), os);
}
} // namespace internal2
#endif
template <typename T> template <typename T>
::std::string PrintToString(const T& value) { ::std::string PrintToString(const T& value) {
::std::stringstream ss; ::std::stringstream ss;

View File

@ -115,6 +115,9 @@ GTEST_DECLARE_string_(output);
// test. // test.
GTEST_DECLARE_bool_(print_time); GTEST_DECLARE_bool_(print_time);
// This flags control whether Google Test prints UTF8 characters as text.
GTEST_DECLARE_bool_(print_utf8);
// This flag specifies the random number seed. // This flag specifies the random number seed.
GTEST_DECLARE_int32_(random_seed); GTEST_DECLARE_int32_(random_seed);
@ -135,7 +138,7 @@ GTEST_DECLARE_int32_(stack_trace_depth);
// When this flag is specified, a failed assertion will throw an // When this flag is specified, a failed assertion will throw an
// exception if exceptions are enabled, or exit the program with a // exception if exceptions are enabled, or exit the program with a
// non-zero code otherwise. // non-zero code otherwise. For use with an external test framework.
GTEST_DECLARE_bool_(throw_on_failure); GTEST_DECLARE_bool_(throw_on_failure);
// When this flag is set with a "host:port" string, on supported // When this flag is set with a "host:port" string, on supported
@ -1001,6 +1004,18 @@ class Environment {
virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
}; };
#if GTEST_HAS_EXCEPTIONS
// Exception which can be thrown from TestEventListener::OnTestPartResult.
class GTEST_API_ AssertionException
: public internal::GoogleTestFailureException {
public:
explicit AssertionException(const TestPartResult& result)
: GoogleTestFailureException(result) {}
};
#endif // GTEST_HAS_EXCEPTIONS
// The interface for tracing execution of tests. The methods are organized in // The interface for tracing execution of tests. The methods are organized in
// the order the corresponding events are fired. // the order the corresponding events are fired.
class TestEventListener { class TestEventListener {
@ -1029,6 +1044,8 @@ class TestEventListener {
virtual void OnTestStart(const TestInfo& test_info) = 0; virtual void OnTestStart(const TestInfo& test_info) = 0;
// Fired after a failed assertion or a SUCCEED() invocation. // Fired after a failed assertion or a SUCCEED() invocation.
// If you want to throw an exception from this function to skip to the next
// TEST, it must be AssertionException defined above, or inherited from it.
virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
// Fired after the test ends. // Fired after the test ends.

View File

@ -40,17 +40,20 @@
// //
// class MyClass { // class MyClass {
// private: // private:
// void MyMethod(); // void PrivateMethod();
// FRIEND_TEST(MyClassTest, MyMethod); // FRIEND_TEST(MyClassTest, PrivateMethodWorks);
// }; // };
// //
// class MyClassTest : public testing::Test { // class MyClassTest : public testing::Test {
// // ... // // ...
// }; // };
// //
// TEST_F(MyClassTest, MyMethod) { // TEST_F(MyClassTest, PrivateMethodWorks) {
// // Can call MyClass::MyMethod() here. // // Can call MyClass::PrivateMethod() here.
// } // }
//
// Note: The test class must be in the same namespace as the class being tested.
// For example, putting MyClassTest in an anonymous namespace will not work.
#define FRIEND_TEST(test_case_name, test_name)\ #define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test friend class test_case_name##_##test_name##_Test

View File

@ -217,13 +217,17 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
// can be streamed. // can be streamed.
// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in // This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
// NDEBUG mode. In this case we need the statements to be executed, the regex is // NDEBUG mode. In this case we need the statements to be executed and the macro
// ignored, and the macro must accept a streamed message even though the message // must accept a streamed message even though the message is never printed.
// is never printed. // The regex object is not evaluated, but it is used to prevent "unused"
// warnings and to avoid an expression that doesn't compile in debug mode.
#define GTEST_EXECUTE_STATEMENT_(statement, regex) \ #define GTEST_EXECUTE_STATEMENT_(statement, regex) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \ if (::testing::internal::AlwaysTrue()) { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} else if (!::testing::internal::AlwaysTrue()) { \
const ::testing::internal::RE& gtest_regex = (regex); \
static_cast<void>(gtest_regex); \
} else \ } else \
::testing::Message() ::testing::Message()

View File

@ -806,31 +806,6 @@ struct RemoveConst<T[N]> {
#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ #define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
// Adds reference to a type if it is not a reference type,
// otherwise leaves it unchanged. This is the same as
// tr1::add_reference, which is not widely available yet.
template <typename T>
struct AddReference { typedef T& type; }; // NOLINT
template <typename T>
struct AddReference<T&> { typedef T& type; }; // NOLINT
// A handy wrapper around AddReference that works when the argument T
// depends on template parameters.
#define GTEST_ADD_REFERENCE_(T) \
typename ::testing::internal::AddReference<T>::type
// Adds a reference to const on top of T as necessary. For example,
// it transforms
//
// char ==> const char&
// const char ==> const char&
// char& ==> const char&
// const char& ==> const char&
//
// The argument T must depend on some template parameters.
#define GTEST_REFERENCE_TO_CONST_(T) \
GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
// ImplicitlyConvertible<From, To>::value is a compile-time bool // ImplicitlyConvertible<From, To>::value is a compile-time bool
// constant that's true iff type From can be implicitly converted to // constant that's true iff type From can be implicitly converted to
// type To. // type To.
@ -1078,7 +1053,7 @@ class NativeArray {
private: private:
enum { enum {
kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper< kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper<
Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value, Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value
}; };
// Initializes this object with a copy of the input. // Initializes this object with a copy of the input.

View File

@ -73,11 +73,9 @@
// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions // GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions
// are enabled. // are enabled.
// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string // GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string
// is/isn't available (some systems define // is/isn't available
// ::string, which is different to std::string). // GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::wstring
// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string // is/isn't available
// is/isn't available (some systems define
// ::wstring, which is different to std::wstring).
// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular // GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular
// expressions are/aren't available. // expressions are/aren't available.
// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that <pthread.h> // GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that <pthread.h>
@ -109,6 +107,12 @@
// GTEST_CREATE_SHARED_LIBRARY // GTEST_CREATE_SHARED_LIBRARY
// - Define to 1 when compiling Google Test itself // - Define to 1 when compiling Google Test itself
// as a shared library. // as a shared library.
// GTEST_DEFAULT_DEATH_TEST_STYLE
// - The default value of --gtest_death_test_style.
// The legacy default has been "fast" in the open
// source version since 2008. The recommended value
// is "threadsafe", and can be set in
// custom/gtest-port.h.
// Platform-indicating macros // Platform-indicating macros
// -------------------------- // --------------------------
@ -178,7 +182,7 @@
// GTEST_HAS_POSIX_RE (see above) which users can // GTEST_HAS_POSIX_RE (see above) which users can
// define themselves. // define themselves.
// GTEST_USES_SIMPLE_RE - our own simple regex is used; // GTEST_USES_SIMPLE_RE - our own simple regex is used;
// the above two are mutually exclusive. // the above RE\b(s) are mutually exclusive.
// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). // GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
// Misc public macros // Misc public macros
@ -207,6 +211,7 @@
// //
// C++11 feature wrappers: // C++11 feature wrappers:
// //
// testing::internal::forward - portability wrapper for std::forward.
// testing::internal::move - portability wrapper for std::move. // testing::internal::move - portability wrapper for std::move.
// //
// Synchronization: // Synchronization:
@ -272,10 +277,12 @@
# include <TargetConditionals.h> # include <TargetConditionals.h>
#endif #endif
// Brings in the definition of HAS_GLOBAL_STRING. This must be done
// BEFORE we test HAS_GLOBAL_STRING.
#include <string> // NOLINT
#include <algorithm> // NOLINT #include <algorithm> // NOLINT
#include <iostream> // NOLINT #include <iostream> // NOLINT
#include <sstream> // NOLINT #include <sstream> // NOLINT
#include <string> // NOLINT
#include <utility> #include <utility>
#include <vector> // NOLINT #include <vector> // NOLINT
@ -464,8 +471,11 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#ifndef GTEST_HAS_EXCEPTIONS #ifndef GTEST_HAS_EXCEPTIONS
// The user didn't tell us whether exceptions are enabled, so we need // The user didn't tell us whether exceptions are enabled, so we need
// to figure it out. // to figure it out.
# if defined(_MSC_VER) || defined(__BORLANDC__) # if defined(_MSC_VER) && defined(_CPPUNWIND)
// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS // MSVC defines _CPPUNWIND to 1 iff exceptions are enabled.
# define GTEST_HAS_EXCEPTIONS 1
# elif defined(__BORLANDC__)
// C++Builder's implementation of the STL uses the _HAS_EXCEPTIONS
// macro to enable exceptions, so we'll do the same. // macro to enable exceptions, so we'll do the same.
// Assumes that exceptions are enabled by default. // Assumes that exceptions are enabled by default.
# ifndef _HAS_EXCEPTIONS # ifndef _HAS_EXCEPTIONS
@ -509,7 +519,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
# define GTEST_HAS_STD_STRING 1 # define GTEST_HAS_STD_STRING 1
#elif !GTEST_HAS_STD_STRING #elif !GTEST_HAS_STD_STRING
// The user told us that ::std::string isn't available. // The user told us that ::std::string isn't available.
# error "Google Test cannot be used where ::std::string isn't available." # error "::std::string isn't available."
#endif // !defined(GTEST_HAS_STD_STRING) #endif // !defined(GTEST_HAS_STD_STRING)
#ifndef GTEST_HAS_GLOBAL_STRING #ifndef GTEST_HAS_GLOBAL_STRING
@ -824,9 +834,10 @@ using ::std::tuple_size;
# define GTEST_HAS_TYPED_TEST_P 1 # define GTEST_HAS_TYPED_TEST_P 1
#endif #endif
// Determines whether to support Combine(). // Determines whether to support Combine(). This only makes sense when
// The implementation doesn't work on Sun Studio since it doesn't // value-parameterized tests are enabled. The implementation doesn't
// understand templated conversion operators. // work on Sun Studio since it doesn't understand templated conversion
// operators.
#if (GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_) && !defined(__SUNPRO_CC) #if (GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_) && !defined(__SUNPRO_CC)
# define GTEST_HAS_COMBINE 1 # define GTEST_HAS_COMBINE 1
#endif #endif
@ -878,6 +889,12 @@ using ::std::tuple_size;
# define GTEST_ATTRIBUTE_UNUSED_ # define GTEST_ATTRIBUTE_UNUSED_
#endif #endif
#if GTEST_LANG_CXX11
# define GTEST_CXX11_EQUALS_DELETE_ = delete
#else // GTEST_LANG_CXX11
# define GTEST_CXX11_EQUALS_DELETE_
#endif // GTEST_LANG_CXX11
// Use this annotation before a function that takes a printf format string. // Use this annotation before a function that takes a printf format string.
#if (defined(__GNUC__) || defined(__clang__)) && !defined(COMPILER_ICC) #if (defined(__GNUC__) || defined(__clang__)) && !defined(COMPILER_ICC)
# if defined(__MINGW_PRINTF_FORMAT) # if defined(__MINGW_PRINTF_FORMAT)
@ -895,15 +912,16 @@ using ::std::tuple_size;
# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) # define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
#endif #endif
// A macro to disallow operator= // A macro to disallow operator=
// This should be used in the private: declarations for a class. // This should be used in the private: declarations for a class.
#define GTEST_DISALLOW_ASSIGN_(type) \ #define GTEST_DISALLOW_ASSIGN_(type) \
void operator=(type const &) void operator=(type const &) GTEST_CXX11_EQUALS_DELETE_
// A macro to disallow copy constructor and operator= // A macro to disallow copy constructor and operator=
// This should be used in the private: declarations for a class. // This should be used in the private: declarations for a class.
#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type) \ #define GTEST_DISALLOW_COPY_AND_ASSIGN_(type) \
type(type const &);\ type(type const &) GTEST_CXX11_EQUALS_DELETE_; \
GTEST_DISALLOW_ASSIGN_(type) GTEST_DISALLOW_ASSIGN_(type)
// Tell the compiler to warn about unused return values for functions declared // Tell the compiler to warn about unused return values for functions declared
@ -972,6 +990,10 @@ using ::std::tuple_size;
# define GTEST_API_ # define GTEST_API_
#endif // GTEST_API_ #endif // GTEST_API_
#ifndef GTEST_DEFAULT_DEATH_TEST_STYLE
# define GTEST_DEFAULT_DEATH_TEST_STYLE "fast"
#endif // GTEST_DEFAULT_DEATH_TEST_STYLE
#ifdef __GNUC__ #ifdef __GNUC__
// Ask the compiler to never inline a given function. // Ask the compiler to never inline a given function.
# define GTEST_NO_INLINE_ __attribute__((noinline)) # define GTEST_NO_INLINE_ __attribute__((noinline))
@ -980,11 +1002,13 @@ using ::std::tuple_size;
#endif #endif
// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. // _LIBCPP_VERSION is defined by the libc++ library from the LLVM project.
#if !defined(GTEST_HAS_CXXABI_H_)
# if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) # if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER))
# define GTEST_HAS_CXXABI_H_ 1 # define GTEST_HAS_CXXABI_H_ 1
# else # else
# define GTEST_HAS_CXXABI_H_ 0 # define GTEST_HAS_CXXABI_H_ 0
# endif # endif
#endif
// A function level attribute to disable checking for use of uninitialized // A function level attribute to disable checking for use of uninitialized
// memory when built with MemorySanitizer. // memory when built with MemorySanitizer.
@ -1126,6 +1150,16 @@ struct StaticAssertTypeEqHelper<T, T> {
enum { value = true }; enum { value = true };
}; };
// Same as std::is_same<>.
template <typename T, typename U>
struct IsSame {
enum { value = false };
};
template <typename T>
struct IsSame<T, T> {
enum { value = true };
};
// Evaluates to the number of elements in 'array'. // Evaluates to the number of elements in 'array'.
#define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0])) #define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0]))
@ -1189,6 +1223,10 @@ class scoped_ptr {
// Defines RE. // Defines RE.
#if GTEST_USES_PCRE
using ::RE;
#elif GTEST_USES_POSIX_RE || GTEST_USES_SIMPLE_RE
// A simple C++ wrapper for <regex.h>. It uses the POSIX Extended // A simple C++ wrapper for <regex.h>. It uses the POSIX Extended
// Regular Expression syntax. // Regular Expression syntax.
class GTEST_API_ RE { class GTEST_API_ RE {
@ -1263,6 +1301,8 @@ class GTEST_API_ RE {
GTEST_DISALLOW_ASSIGN_(RE); GTEST_DISALLOW_ASSIGN_(RE);
}; };
#endif // GTEST_USES_PCRE
// Formats a source file path and a line number as they would appear // Formats a source file path and a line number as they would appear
// in an error message from the compiler used to compile this code. // in an error message from the compiler used to compile this code.
GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
@ -1348,13 +1388,57 @@ inline void FlushInfoLog() { fflush(NULL); }
GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
<< gtest_error << gtest_error
// Adds reference to a type if it is not a reference type,
// otherwise leaves it unchanged. This is the same as
// tr1::add_reference, which is not widely available yet.
template <typename T>
struct AddReference { typedef T& type; }; // NOLINT
template <typename T>
struct AddReference<T&> { typedef T& type; }; // NOLINT
// A handy wrapper around AddReference that works when the argument T
// depends on template parameters.
#define GTEST_ADD_REFERENCE_(T) \
typename ::testing::internal::AddReference<T>::type
// Transforms "T" into "const T&" according to standard reference collapsing
// rules (this is only needed as a backport for C++98 compilers that do not
// support reference collapsing). Specifically, it transforms:
//
// char ==> const char&
// const char ==> const char&
// char& ==> char&
// const char& ==> const char&
//
// Note that the non-const reference will not have "const" added. This is
// standard, and necessary so that "T" can always bind to "const T&".
template <typename T>
struct ConstRef { typedef const T& type; };
template <typename T>
struct ConstRef<T&> { typedef T& type; };
// The argument T must depend on some template parameters.
#define GTEST_REFERENCE_TO_CONST_(T) \
typename ::testing::internal::ConstRef<T>::type
#if GTEST_HAS_STD_MOVE_ #if GTEST_HAS_STD_MOVE_
using std::forward;
using std::move; using std::move;
template <typename T>
struct RvalueRef {
typedef T&& type;
};
#else // GTEST_HAS_STD_MOVE_ #else // GTEST_HAS_STD_MOVE_
template <typename T> template <typename T>
const T& move(const T& t) { const T& move(const T& t) {
return t; return t;
} }
template <typename T>
struct RvalueRef {
typedef const T& type;
};
#endif // GTEST_HAS_STD_MOVE_ #endif // GTEST_HAS_STD_MOVE_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
@ -1455,7 +1539,6 @@ GTEST_API_ void CaptureStderr();
GTEST_API_ std::string GetCapturedStderr(); GTEST_API_ std::string GetCapturedStderr();
#endif // GTEST_HAS_STREAM_REDIRECTION #endif // GTEST_HAS_STREAM_REDIRECTION
// Returns the size (in bytes) of a file. // Returns the size (in bytes) of a file.
GTEST_API_ size_t GetFileSize(FILE* file); GTEST_API_ size_t GetFileSize(FILE* file);
@ -1463,14 +1546,18 @@ GTEST_API_ size_t GetFileSize(FILE* file);
GTEST_API_ std::string ReadEntireFile(FILE* file); GTEST_API_ std::string ReadEntireFile(FILE* file);
// All command line arguments. // All command line arguments.
GTEST_API_ const ::std::vector<testing::internal::string>& GetArgvs(); GTEST_API_ std::vector<std::string> GetArgvs();
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
const ::std::vector<testing::internal::string>& GetInjectableArgvs(); std::vector<std::string> GetInjectableArgvs();
void SetInjectableArgvs(const ::std::vector<testing::internal::string>* // Deprecated: pass the args vector by value instead.
new_argvs); void SetInjectableArgvs(const std::vector<std::string>* new_argvs);
void SetInjectableArgvs(const std::vector<std::string>& new_argvs);
#if GTEST_HAS_GLOBAL_STRING
void SetInjectableArgvs(const std::vector< ::string>& new_argvs);
#endif // GTEST_HAS_GLOBAL_STRING
void ClearInjectableArgvs();
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
@ -2591,7 +2678,6 @@ GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
std::string StringFromGTestEnv(const char* flag, const char* default_val); std::string StringFromGTestEnv(const char* flag, const char* default_val);
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_

View File

@ -73,7 +73,11 @@ namespace testing {
// Constants. // Constants.
// The default death test style. // The default death test style.
static const char kDefaultDeathTestStyle[] = "fast"; //
// This is defined in internal/gtest-port.h as "fast", but can be overridden by
// a definition in internal/custom/gtest-port.h. The recommended value, which is
// used internally at Google, is "threadsafe".
static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
GTEST_DEFINE_string_( GTEST_DEFINE_string_(
death_test_style, death_test_style,
@ -555,7 +559,13 @@ bool DeathTestImpl::Passed(bool status_ok) {
break; break;
case DIED: case DIED:
if (status_ok) { if (status_ok) {
# if GTEST_USES_PCRE
// PCRE regexes support embedded NULs.
// GTEST_USES_PCRE is defined only in google3 mode
const bool matched = RE::PartialMatch(error_message, *regex());
# else
const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
# endif // GTEST_USES_PCRE
if (matched) { if (matched) {
success = true; success = true;
} else { } else {

View File

@ -128,7 +128,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const {
return *this; return *this;
} }
// Returns a pointer to the last occurence of a valid path separator in // Returns a pointer to the last occurrence of a valid path separator in
// the FilePath. On Windows, for example, both '/' and '\' are valid path // the FilePath. On Windows, for example, both '/' and '\' are valid path
// separators. Returns NULL if no path separator was found. // separators. Returns NULL if no path separator was found.
const char* FilePath::FindLastPathSeparator() const { const char* FilePath::FindLastPathSeparator() const {

View File

@ -59,7 +59,7 @@
# include <windows.h> // NOLINT # include <windows.h> // NOLINT
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
#include "gtest/gtest.h" // NOLINT #include "gtest/gtest.h"
#include "gtest/gtest-spi.h" #include "gtest/gtest-spi.h"
namespace testing { namespace testing {
@ -86,6 +86,7 @@ const char kFilterFlag[] = "filter";
const char kListTestsFlag[] = "list_tests"; const char kListTestsFlag[] = "list_tests";
const char kOutputFlag[] = "output"; const char kOutputFlag[] = "output";
const char kPrintTimeFlag[] = "print_time"; const char kPrintTimeFlag[] = "print_time";
const char kPrintUTF8Flag[] = "print_utf8";
const char kRandomSeedFlag[] = "random_seed"; const char kRandomSeedFlag[] = "random_seed";
const char kRepeatFlag[] = "repeat"; const char kRepeatFlag[] = "repeat";
const char kShuffleFlag[] = "shuffle"; const char kShuffleFlag[] = "shuffle";
@ -166,6 +167,7 @@ class GTestFlagSaver {
list_tests_ = GTEST_FLAG(list_tests); list_tests_ = GTEST_FLAG(list_tests);
output_ = GTEST_FLAG(output); output_ = GTEST_FLAG(output);
print_time_ = GTEST_FLAG(print_time); print_time_ = GTEST_FLAG(print_time);
print_utf8_ = GTEST_FLAG(print_utf8);
random_seed_ = GTEST_FLAG(random_seed); random_seed_ = GTEST_FLAG(random_seed);
repeat_ = GTEST_FLAG(repeat); repeat_ = GTEST_FLAG(repeat);
shuffle_ = GTEST_FLAG(shuffle); shuffle_ = GTEST_FLAG(shuffle);
@ -187,6 +189,7 @@ class GTestFlagSaver {
GTEST_FLAG(list_tests) = list_tests_; GTEST_FLAG(list_tests) = list_tests_;
GTEST_FLAG(output) = output_; GTEST_FLAG(output) = output_;
GTEST_FLAG(print_time) = print_time_; GTEST_FLAG(print_time) = print_time_;
GTEST_FLAG(print_utf8) = print_utf8_;
GTEST_FLAG(random_seed) = random_seed_; GTEST_FLAG(random_seed) = random_seed_;
GTEST_FLAG(repeat) = repeat_; GTEST_FLAG(repeat) = repeat_;
GTEST_FLAG(shuffle) = shuffle_; GTEST_FLAG(shuffle) = shuffle_;
@ -208,6 +211,7 @@ class GTestFlagSaver {
bool list_tests_; bool list_tests_;
std::string output_; std::string output_;
bool print_time_; bool print_time_;
bool print_utf8_;
internal::Int32 random_seed_; internal::Int32 random_seed_;
internal::Int32 repeat_; internal::Int32 repeat_;
bool shuffle_; bool shuffle_;
@ -1020,7 +1024,7 @@ class TestResultAccessor {
#if GTEST_CAN_STREAM_RESULTS_ #if GTEST_CAN_STREAM_RESULTS_
// Streams test results to the given port on the given host machine. // Streams test results to the given port on the given host machine.
class GTEST_API_ StreamingListener : public EmptyTestEventListener { class StreamingListener : public EmptyTestEventListener {
public: public:
// Abstract base class for writing strings to a socket. // Abstract base class for writing strings to a socket.
class AbstractSocketWriter { class AbstractSocketWriter {

View File

@ -915,6 +915,7 @@ GTestLog::~GTestLog() {
posix::Abort(); posix::Abort();
} }
} }
// Disable Microsoft deprecation warnings for POSIX functions called from // Disable Microsoft deprecation warnings for POSIX functions called from
// this class (creat, dup, dup2, and close) // this class (creat, dup, dup2, and close)
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996) GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
@ -1007,8 +1008,7 @@ static CapturedStream* g_captured_stderr = NULL;
static CapturedStream* g_captured_stdout = NULL; static CapturedStream* g_captured_stdout = NULL;
// Starts capturing an output stream (stdout/stderr). // Starts capturing an output stream (stdout/stderr).
static void CaptureStream(int fd, static void CaptureStream(int fd, const char* stream_name,
const char* stream_name,
CapturedStream** stream) { CapturedStream** stream) {
if (*stream != NULL) { if (*stream != NULL) {
GTEST_LOG_(FATAL) << "Only one " << stream_name GTEST_LOG_(FATAL) << "Only one " << stream_name
@ -1049,6 +1049,10 @@ std::string GetCapturedStderr() {
#endif // GTEST_HAS_STREAM_REDIRECTION #endif // GTEST_HAS_STREAM_REDIRECTION
size_t GetFileSize(FILE* file) { size_t GetFileSize(FILE* file) {
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
return static_cast<size_t>(ftell(file)); return static_cast<size_t>(ftell(file));
@ -1077,22 +1081,36 @@ std::string ReadEntireFile(FILE* file) {
} }
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
static const std::vector<std::string>* g_injected_test_argvs = NULL; // Owned.
static const ::std::vector<testing::internal::string>* g_injected_test_argvs = std::vector<std::string> GetInjectableArgvs() {
NULL; // Owned.
void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
if (g_injected_test_argvs != argvs)
delete g_injected_test_argvs;
g_injected_test_argvs = argvs;
}
const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
if (g_injected_test_argvs != NULL) { if (g_injected_test_argvs != NULL) {
return *g_injected_test_argvs; return *g_injected_test_argvs;
} }
return GetArgvs(); return GetArgvs();
} }
void SetInjectableArgvs(const std::vector<std::string>* new_argvs) {
if (g_injected_test_argvs != new_argvs) delete g_injected_test_argvs;
g_injected_test_argvs = new_argvs;
}
void SetInjectableArgvs(const std::vector<std::string>& new_argvs) {
SetInjectableArgvs(
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
}
#if GTEST_HAS_GLOBAL_STRING
void SetInjectableArgvs(const std::vector< ::string>& new_argvs) {
SetInjectableArgvs(
new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
}
#endif // GTEST_HAS_GLOBAL_STRING
void ClearInjectableArgvs() {
delete g_injected_test_argvs;
g_injected_test_argvs = NULL;
}
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS_MOBILE

View File

@ -43,12 +43,13 @@
// defines Foo. // defines Foo.
#include "gtest/gtest-printers.h" #include "gtest/gtest-printers.h"
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <cctype>
#include <cwchar> #include <cwchar>
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include <string> #include <string>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include "src/gtest-internal-inl.h"
namespace testing { namespace testing {
@ -123,7 +124,7 @@ namespace internal {
// Depending on the value of a char (or wchar_t), we print it in one // Depending on the value of a char (or wchar_t), we print it in one
// of three formats: // of three formats:
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), // - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
// - as a hexidecimal escape sequence (e.g. '\x7F'), or // - as a hexadecimal escape sequence (e.g. '\x7F'), or
// - as a special escape sequence (e.g. '\r', '\n'). // - as a special escape sequence (e.g. '\r', '\n').
enum CharFormat { enum CharFormat {
kAsIs, kAsIs,
@ -230,7 +231,7 @@ void PrintCharAndCodeTo(Char c, ostream* os) {
return; return;
*os << " (" << static_cast<int>(c); *os << " (" << static_cast<int>(c);
// For more convenience, we print c's code again in hexidecimal, // For more convenience, we print c's code again in hexadecimal,
// unless c was already printed in the form '\x##' or the code is in // unless c was already printed in the form '\x##' or the code is in
// [1, 9]. // [1, 9].
if (format == kHexEscape || (1 <= c && c <= 9)) { if (format == kHexEscape || (1 <= c && c <= 9)) {
@ -262,11 +263,12 @@ template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static void PrintCharsAsStringTo( static CharFormat PrintCharsAsStringTo(
const CharType* begin, size_t len, ostream* os) { const CharType* begin, size_t len, ostream* os) {
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
*os << kQuoteBegin; *os << kQuoteBegin;
bool is_previous_hex = false; bool is_previous_hex = false;
CharFormat print_format = kAsIs;
for (size_t index = 0; index < len; ++index) { for (size_t index = 0; index < len; ++index) {
const CharType cur = begin[index]; const CharType cur = begin[index];
if (is_previous_hex && IsXDigit(cur)) { if (is_previous_hex && IsXDigit(cur)) {
@ -276,8 +278,13 @@ static void PrintCharsAsStringTo(
*os << "\" " << kQuoteBegin; *os << "\" " << kQuoteBegin;
} }
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
// Remember if any characters required hex escaping.
if (is_previous_hex) {
print_format = kHexEscape;
}
} }
*os << "\""; *os << "\"";
return print_format;
} }
// Prints a (const) char/wchar_t array of 'len' elements, starting at address // Prints a (const) char/wchar_t array of 'len' elements, starting at address
@ -347,15 +354,90 @@ void PrintTo(const wchar_t* s, ostream* os) {
} }
#endif // wchar_t is native #endif // wchar_t is native
namespace {
bool ContainsUnprintableControlCodes(const char* str, size_t length) {
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
for (size_t i = 0; i < length; i++) {
unsigned char ch = *s++;
if (std::iscntrl(ch)) {
switch (ch) {
case '\t':
case '\n':
case '\r':
break;
default:
return true;
}
}
}
return false;
}
bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
bool IsValidUTF8(const char* str, size_t length) {
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
for (size_t i = 0; i < length;) {
unsigned char lead = s[i++];
if (lead <= 0x7f) {
continue; // single-byte character (ASCII) 0..7F
}
if (lead < 0xc2) {
return false; // trail byte or non-shortest form
} else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
++i; // 2-byte character
} else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
IsUTF8TrailByte(s[i]) &&
IsUTF8TrailByte(s[i + 1]) &&
// check for non-shortest form and surrogate
(lead != 0xe0 || s[i] >= 0xa0) &&
(lead != 0xed || s[i] < 0xa0)) {
i += 2; // 3-byte character
} else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
IsUTF8TrailByte(s[i]) &&
IsUTF8TrailByte(s[i + 1]) &&
IsUTF8TrailByte(s[i + 2]) &&
// check for non-shortest form
(lead != 0xf0 || s[i] >= 0x90) &&
(lead != 0xf4 || s[i] < 0x90)) {
i += 3; // 4-byte character
} else {
return false;
}
}
return true;
}
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
if (!ContainsUnprintableControlCodes(str, length) &&
IsValidUTF8(str, length)) {
*os << "\n As Text: \"" << str << "\"";
}
}
} // anonymous namespace
// Prints a ::string object. // Prints a ::string object.
#if GTEST_HAS_GLOBAL_STRING #if GTEST_HAS_GLOBAL_STRING
void PrintStringTo(const ::string& s, ostream* os) { void PrintStringTo(const ::string& s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os); if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
if (GTEST_FLAG(print_utf8)) {
ConditionalPrintAsText(s.data(), s.size(), os);
}
}
} }
#endif // GTEST_HAS_GLOBAL_STRING #endif // GTEST_HAS_GLOBAL_STRING
void PrintStringTo(const ::std::string& s, ostream* os) { void PrintStringTo(const ::std::string& s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os); if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
if (GTEST_FLAG(print_utf8)) {
ConditionalPrintAsText(s.data(), s.size(), os);
}
}
} }
// Prints a ::wstring object. // Prints a ::wstring object.

View File

@ -30,6 +30,7 @@
// Author: wan@google.com (Zhanyong Wan) // Author: wan@google.com (Zhanyong Wan)
#include "gtest/gtest-typed-test.h" #include "gtest/gtest-typed-test.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
namespace testing { namespace testing {

View File

@ -160,8 +160,10 @@ static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*";
// A test filter that matches everything. // A test filter that matches everything.
static const char kUniversalFilter[] = "*"; static const char kUniversalFilter[] = "*";
// The default output file for XML output. // The default output format.
static const char kDefaultOutputFile[] = "test_detail.xml"; static const char kDefaultOutputFormat[] = "xml";
// The default output file.
static const char kDefaultOutputFile[] = "test_detail";
// The environment variable name for the test shard index. // The environment variable name for the test shard index.
static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
@ -231,9 +233,9 @@ GTEST_DEFINE_bool_(list_tests, false,
GTEST_DEFINE_string_( GTEST_DEFINE_string_(
output, output,
internal::StringFromGTestEnv("output", ""), internal::StringFromGTestEnv("output", ""),
"A format (currently must be \"xml\"), optionally followed " "A format (defaults to \"xml\" but can be specified to be \"json\"), "
"by a colon and an output file name or directory. A directory " "optionally followed by a colon and an output file name or directory. "
"is indicated by a trailing pathname separator. " "A directory is indicated by a trailing pathname separator. "
"Examples: \"xml:filename.xml\", \"xml::directoryname/\". " "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
"If a directory is specified, output files will be created " "If a directory is specified, output files will be created "
"within that directory, with file-names based on the test " "within that directory, with file-names based on the test "
@ -246,6 +248,12 @@ GTEST_DEFINE_bool_(
"True iff " GTEST_NAME_ "True iff " GTEST_NAME_
" should display elapsed time in text output."); " should display elapsed time in text output.");
GTEST_DEFINE_bool_(
print_utf8,
internal::BoolFromGTestEnv("print_utf8", true),
"True iff " GTEST_NAME_
" prints UTF8 characters as text.");
GTEST_DEFINE_int32_( GTEST_DEFINE_int32_(
random_seed, random_seed,
internal::Int32FromGTestEnv("random_seed", 0), internal::Int32FromGTestEnv("random_seed", 0),
@ -287,7 +295,7 @@ GTEST_DEFINE_bool_(
internal::BoolFromGTestEnv("throw_on_failure", false), internal::BoolFromGTestEnv("throw_on_failure", false),
"When this flag is specified, a failed assertion will throw an exception " "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 " "if exceptions are enabled or exit the program with a non-zero code "
"otherwise."); "otherwise. For use with an external test framework.");
#if GTEST_USE_OWN_FLAGFILE_FLAG_ #if GTEST_USE_OWN_FLAGFILE_FLAG_
GTEST_DEFINE_string_( GTEST_DEFINE_string_(
@ -378,11 +386,14 @@ void AssertHelper::operator=(const Message& message) const {
GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
// A copy of all command line arguments. Set by InitGoogleTest(). // A copy of all command line arguments. Set by InitGoogleTest().
::std::vector<testing::internal::string> g_argvs; ::std::vector<std::string> g_argvs;
const ::std::vector<testing::internal::string>& GetArgvs() { ::std::vector<std::string> GetArgvs() {
#if defined(GTEST_CUSTOM_GET_ARGVS_) #if defined(GTEST_CUSTOM_GET_ARGVS_)
return GTEST_CUSTOM_GET_ARGVS_(); // GTEST_CUSTOM_GET_ARGVS_() may return a container of std::string or
// ::string. This code converts it to the appropriate type.
const auto& custom = GTEST_CUSTOM_GET_ARGVS_();
return ::std::vector<std::string>(custom.begin(), custom.end());
#else // defined(GTEST_CUSTOM_GET_ARGVS_) #else // defined(GTEST_CUSTOM_GET_ARGVS_)
return g_argvs; return g_argvs;
#endif // defined(GTEST_CUSTOM_GET_ARGVS_) #endif // defined(GTEST_CUSTOM_GET_ARGVS_)
@ -422,12 +433,17 @@ std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
if (gtest_output_flag == NULL) if (gtest_output_flag == NULL)
return ""; return "";
std::string format = GetOutputFormat();
if (format.empty())
format = std::string(kDefaultOutputFormat);
const char* const colon = strchr(gtest_output_flag, ':'); const char* const colon = strchr(gtest_output_flag, ':');
if (colon == NULL) if (colon == NULL)
return internal::FilePath::ConcatPaths( return internal::FilePath::MakeFileName(
internal::FilePath( internal::FilePath(
UnitTest::GetInstance()->original_working_dir()), UnitTest::GetInstance()->original_working_dir()),
internal::FilePath(kDefaultOutputFile)).string(); internal::FilePath(kDefaultOutputFile), 0,
format.c_str()).string();
internal::FilePath output_name(colon + 1); internal::FilePath output_name(colon + 1);
if (!output_name.IsAbsolutePath()) if (!output_name.IsAbsolutePath())
@ -2429,6 +2445,8 @@ Result HandleExceptionsInMethodIfSupported(
#if GTEST_HAS_EXCEPTIONS #if GTEST_HAS_EXCEPTIONS
try { try {
return HandleSehExceptionsInMethodIfSupported(object, method, location); return HandleSehExceptionsInMethodIfSupported(object, method, location);
} catch (const AssertionException&) { // NOLINT
// This failure was reported already.
} catch (const internal::GoogleTestFailureException&) { // NOLINT } catch (const internal::GoogleTestFailureException&) { // NOLINT
// This exception type can only be thrown by a failed Google // This exception type can only be thrown by a failed Google
// Test assertion with the intention of letting another testing // Test assertion with the intention of letting another testing
@ -2563,12 +2581,10 @@ void ReportInvalidTestCaseType(const char* test_case_name,
<< "probably rename one of the classes to put the tests into different\n" << "probably rename one of the classes to put the tests into different\n"
<< "test cases."; << "test cases.";
GTEST_LOG_(ERROR) GTEST_LOG_(ERROR) << FormatFileLocation(code_location.file.c_str(),
<< FormatFileLocation(code_location.file.c_str(),
code_location.line) code_location.line)
<< " " << errors.GetString(); << " " << errors.GetString();
} }
} // namespace internal } // namespace internal
namespace { namespace {
@ -2899,15 +2915,19 @@ static int GetBitOffset(WORD color_mask) {
static WORD GetNewColor(GTestColor color, WORD old_color_attrs) { static WORD GetNewColor(GTestColor color, WORD old_color_attrs) {
// Let's reuse the BG // Let's reuse the BG
static const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; static const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
static const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; BACKGROUND_RED | BACKGROUND_INTENSITY;
static const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
FOREGROUND_RED | FOREGROUND_INTENSITY;
const WORD existing_bg = old_color_attrs & background_mask; const WORD existing_bg = old_color_attrs & background_mask;
WORD new_color = GetColorAttribute(color) | existing_bg | FOREGROUND_INTENSITY; WORD new_color =
GetColorAttribute(color) | existing_bg | FOREGROUND_INTENSITY;
static const int bg_bitOffset = GetBitOffset(background_mask); static const int bg_bitOffset = GetBitOffset(background_mask);
static const int fg_bitOffset = GetBitOffset(foreground_mask); static const int fg_bitOffset = GetBitOffset(foreground_mask);
if (((new_color & background_mask) >> bg_bitOffset) == ((new_color & foreground_mask) >> fg_bitOffset)) { if (((new_color & background_mask) >> bg_bitOffset) ==
((new_color & foreground_mask) >> fg_bitOffset)) {
new_color ^= FOREGROUND_INTENSITY; // invert intensity new_color ^= FOREGROUND_INTENSITY; // invert intensity
} }
return new_color; return new_color;
@ -2969,7 +2989,6 @@ bool ShouldUseColor(bool stdout_is_tty) {
// cannot simply emit special characters and have the terminal change colors. // cannot simply emit special characters and have the terminal change colors.
// This routine must actually emit the characters rather than return a string // This routine must actually emit the characters rather than return a string
// that would be colored when printed, as can be done on Linux. // that would be colored when printed, as can be done on Linux.
GTEST_ATTRIBUTE_PRINTF_(2, 3)
static void ColoredPrintf(GTestColor color, const char* fmt, ...) { static void ColoredPrintf(GTestColor color, const char* fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -3019,7 +3038,7 @@ static void ColoredPrintf(GTestColor color, const char* fmt, ...) {
va_end(args); va_end(args);
} }
// Text printed in Google Test's text output and --gunit_list_tests // Text printed in Google Test's text output and --gtest_list_tests
// output to label the type parameter and value parameter for a test. // output to label the type parameter and value parameter for a test.
static const char kTypeParamLabel[] = "TypeParam"; static const char kTypeParamLabel[] = "TypeParam";
static const char kValueParamLabel[] = "GetParam()"; static const char kValueParamLabel[] = "GetParam()";
@ -3098,7 +3117,6 @@ void PrettyUnitTestResultPrinter::OnTestIterationStart(
"Note: Randomizing tests' orders with a seed of %d .\n", "Note: Randomizing tests' orders with a seed of %d .\n",
unit_test.random_seed()); unit_test.random_seed());
} }
ColoredPrintf(COLOR_GREEN, "[==========] "); ColoredPrintf(COLOR_GREEN, "[==========] ");
printf("Running %s from %s.\n", printf("Running %s from %s.\n",
FormatTestCount(unit_test.test_to_run_count()).c_str(), FormatTestCount(unit_test.test_to_run_count()).c_str(),
@ -3430,6 +3448,11 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// to delimit this attribute from prior attributes. // to delimit this attribute from prior attributes.
static std::string TestPropertiesAsXmlAttributes(const TestResult& result); static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
// Streams an XML representation of the test properties of a TestResult
// object.
static void OutputXmlTestProperties(std::ostream* stream,
const TestResult& result);
// The output file. // The output file.
const std::string output_file_; const std::string output_file_;
@ -3465,8 +3488,8 @@ void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
// 3. To interpret the meaning of errno in a thread-safe way, // 3. To interpret the meaning of errno in a thread-safe way,
// we need the strerror_r() function, which is not available on // we need the strerror_r() function, which is not available on
// Windows. // Windows.
GTEST_LOG_(FATAL) << "Unable to open file \""
<< output_file_ << "\""; GTEST_LOG_(FATAL) << "Unable to open file \"" << output_file_ << "\"";
} }
std::stringstream stream; std::stringstream stream;
PrintXmlUnitTest(&stream, unit_test); PrintXmlUnitTest(&stream, unit_test);
@ -3641,6 +3664,10 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
const TestResult& result = *test_info.result(); const TestResult& result = *test_info.result();
const std::string kTestcase = "testcase"; const std::string kTestcase = "testcase";
if (test_info.is_in_another_shard()) {
return;
}
*stream << " <testcase"; *stream << " <testcase";
OutputXmlAttribute(stream, kTestcase, "name", test_info.name()); OutputXmlAttribute(stream, kTestcase, "name", test_info.name());
@ -3657,7 +3684,6 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
OutputXmlAttribute(stream, kTestcase, "time", OutputXmlAttribute(stream, kTestcase, "time",
FormatTimeInMillisAsSeconds(result.elapsed_time())); FormatTimeInMillisAsSeconds(result.elapsed_time()));
OutputXmlAttribute(stream, kTestcase, "classname", test_case_name); OutputXmlAttribute(stream, kTestcase, "classname", test_case_name);
*stream << TestPropertiesAsXmlAttributes(result);
int failures = 0; int failures = 0;
for (int i = 0; i < result.total_part_count(); ++i) { for (int i = 0; i < result.total_part_count(); ++i) {
@ -3679,11 +3705,16 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
} }
} }
if (failures == 0) if (failures == 0 && result.test_property_count() == 0) {
*stream << " />\n"; *stream << " />\n";
else } else {
if (failures == 0) {
*stream << ">\n";
}
OutputXmlTestProperties(stream, result);
*stream << " </testcase>\n"; *stream << " </testcase>\n";
} }
}
// Prints an XML representation of a TestCase object // Prints an XML representation of a TestCase object
void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream, void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream,
@ -3737,7 +3768,6 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
OutputXmlAttribute(stream, kTestsuites, "random_seed", OutputXmlAttribute(stream, kTestsuites, "random_seed",
StreamableToString(unit_test.random_seed())); StreamableToString(unit_test.random_seed()));
} }
*stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result()); *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
@ -3763,8 +3793,374 @@ std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
return attributes.GetString(); return attributes.GetString();
} }
void XmlUnitTestResultPrinter::OutputXmlTestProperties(
std::ostream* stream, const TestResult& result) {
const std::string kProperties = "properties";
const std::string kProperty = "property";
if (result.test_property_count() <= 0) {
return;
}
*stream << "<" << kProperties << ">\n";
for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = result.GetTestProperty(i);
*stream << "<" << kProperty;
*stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\"";
*stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\"";
*stream << "/>\n";
}
*stream << "</" << kProperties << ">\n";
}
// End XmlUnitTestResultPrinter // End XmlUnitTestResultPrinter
// This class generates an JSON output file.
class JsonUnitTestResultPrinter : public EmptyTestEventListener {
public:
explicit JsonUnitTestResultPrinter(const char* output_file);
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
private:
// Returns an JSON-escaped copy of the input string str.
static std::string EscapeJson(const std::string& str);
//// Verifies that the given attribute belongs to the given element and
//// streams the attribute as JSON.
static void OutputJsonKey(std::ostream* stream,
const std::string& element_name,
const std::string& name,
const std::string& value,
const std::string& indent,
bool comma = true);
static void OutputJsonKey(std::ostream* stream,
const std::string& element_name,
const std::string& name,
int value,
const std::string& indent,
bool comma = true);
// Streams a JSON representation of a TestInfo object.
static void OutputJsonTestInfo(::std::ostream* stream,
const char* test_case_name,
const TestInfo& test_info);
// Prints a JSON representation of a TestCase object
static void PrintJsonTestCase(::std::ostream* stream,
const TestCase& test_case);
// Prints a JSON summary of unit_test to output stream out.
static void PrintJsonUnitTest(::std::ostream* stream,
const UnitTest& unit_test);
// Produces a string representing the test properties in a result as
// a JSON dictionary.
static std::string TestPropertiesAsJson(const TestResult& result,
const std::string& indent);
// The output file.
const std::string output_file_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(JsonUnitTestResultPrinter);
};
// Creates a new JsonUnitTestResultPrinter.
JsonUnitTestResultPrinter::JsonUnitTestResultPrinter(const char* output_file)
: output_file_(output_file) {
if (output_file_.empty()) {
GTEST_LOG_(FATAL) << "JSON output file may not be null";
}
}
void JsonUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
int /*iteration*/) {
FILE* jsonout = NULL;
FilePath output_file(output_file_);
FilePath output_dir(output_file.RemoveFileName());
if (output_dir.CreateDirectoriesRecursively()) {
jsonout = posix::FOpen(output_file_.c_str(), "w");
}
if (jsonout == NULL) {
// TODO(phosek): report the reason of the failure.
//
// We don't do it for now as:
//
// 1. There is no urgent need for it.
// 2. It's a bit involved to make the errno variable thread-safe on
// all three operating systems (Linux, Windows, and Mac OS).
// 3. To interpret the meaning of errno in a thread-safe way,
// we need the strerror_r() function, which is not available on
// Windows.
GTEST_LOG_(FATAL) << "Unable to open file \""
<< output_file_ << "\"";
}
std::stringstream stream;
PrintJsonUnitTest(&stream, unit_test);
fprintf(jsonout, "%s", StringStreamToString(&stream).c_str());
fclose(jsonout);
}
// Returns an JSON-escaped copy of the input string str.
std::string JsonUnitTestResultPrinter::EscapeJson(const std::string& str) {
Message m;
for (size_t i = 0; i < str.size(); ++i) {
const char ch = str[i];
switch (ch) {
case '\\':
case '"':
case '/':
m << '\\' << ch;
break;
case '\b':
m << "\\b";
break;
case '\t':
m << "\\t";
break;
case '\n':
m << "\\n";
break;
case '\f':
m << "\\f";
break;
case '\r':
m << "\\r";
break;
default:
if (ch < ' ') {
m << "\\u00" << String::FormatByte(static_cast<unsigned char>(ch));
} else {
m << ch;
}
break;
}
}
return m.GetString();
}
// The following routines generate an JSON representation of a UnitTest
// object.
// Formats the given time in milliseconds as seconds.
static std::string FormatTimeInMillisAsDuration(TimeInMillis ms) {
::std::stringstream ss;
ss << (static_cast<double>(ms) * 1e-3) << "s";
return ss.str();
}
// Converts the given epoch time in milliseconds to a date string in the
// RFC3339 format, without the timezone information.
static std::string FormatEpochTimeInMillisAsRFC3339(TimeInMillis ms) {
struct tm time_struct;
if (!PortableLocaltime(static_cast<time_t>(ms / 1000), &time_struct))
return "";
// YYYY-MM-DDThh:mm:ss
return StreamableToString(time_struct.tm_year + 1900) + "-" +
String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
String::FormatIntWidth2(time_struct.tm_mday) + "T" +
String::FormatIntWidth2(time_struct.tm_hour) + ":" +
String::FormatIntWidth2(time_struct.tm_min) + ":" +
String::FormatIntWidth2(time_struct.tm_sec) + "Z";
}
static inline std::string Indent(int width) {
return std::string(width, ' ');
}
void JsonUnitTestResultPrinter::OutputJsonKey(
std::ostream* stream,
const std::string& element_name,
const std::string& name,
const std::string& value,
const std::string& indent,
bool comma) {
const std::vector<std::string>& allowed_names =
GetReservedAttributesForElement(element_name);
GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
allowed_names.end())
<< "Key \"" << name << "\" is not allowed for value \"" << element_name
<< "\".";
*stream << indent << "\"" << name << "\": \"" << EscapeJson(value) << "\"";
if (comma)
*stream << ",\n";
}
void JsonUnitTestResultPrinter::OutputJsonKey(
std::ostream* stream,
const std::string& element_name,
const std::string& name,
int value,
const std::string& indent,
bool comma) {
const std::vector<std::string>& allowed_names =
GetReservedAttributesForElement(element_name);
GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
allowed_names.end())
<< "Key \"" << name << "\" is not allowed for value \"" << element_name
<< "\".";
*stream << indent << "\"" << name << "\": " << StreamableToString(value);
if (comma)
*stream << ",\n";
}
// Prints a JSON representation of a TestInfo object.
void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream,
const char* test_case_name,
const TestInfo& test_info) {
const TestResult& result = *test_info.result();
const std::string kTestcase = "testcase";
const std::string kIndent = Indent(10);
*stream << Indent(8) << "{\n";
OutputJsonKey(stream, kTestcase, "name", test_info.name(), kIndent);
if (test_info.value_param() != NULL) {
OutputJsonKey(stream, kTestcase, "value_param",
test_info.value_param(), kIndent);
}
if (test_info.type_param() != NULL) {
OutputJsonKey(stream, kTestcase, "type_param", test_info.type_param(),
kIndent);
}
OutputJsonKey(stream, kTestcase, "status",
test_info.should_run() ? "RUN" : "NOTRUN", kIndent);
OutputJsonKey(stream, kTestcase, "time",
FormatTimeInMillisAsDuration(result.elapsed_time()), kIndent);
OutputJsonKey(stream, kTestcase, "classname", test_case_name, kIndent, false);
*stream << TestPropertiesAsJson(result, kIndent);
int failures = 0;
for (int i = 0; i < result.total_part_count(); ++i) {
const TestPartResult& part = result.GetTestPartResult(i);
if (part.failed()) {
*stream << ",\n";
if (++failures == 1) {
*stream << kIndent << "\"" << "failures" << "\": [\n";
}
const std::string location =
internal::FormatCompilerIndependentFileLocation(part.file_name(),
part.line_number());
const std::string message = EscapeJson(location + "\n" + part.message());
*stream << kIndent << " {\n"
<< kIndent << " \"failure\": \"" << message << "\",\n"
<< kIndent << " \"type\": \"\"\n"
<< kIndent << " }";
}
}
if (failures > 0)
*stream << "\n" << kIndent << "]";
*stream << "\n" << Indent(8) << "}";
}
// Prints an JSON representation of a TestCase object
void JsonUnitTestResultPrinter::PrintJsonTestCase(std::ostream* stream,
const TestCase& test_case) {
const std::string kTestsuite = "testsuite";
const std::string kIndent = Indent(6);
*stream << Indent(4) << "{\n";
OutputJsonKey(stream, kTestsuite, "name", test_case.name(), kIndent);
OutputJsonKey(stream, kTestsuite, "tests", test_case.reportable_test_count(),
kIndent);
OutputJsonKey(stream, kTestsuite, "failures", test_case.failed_test_count(),
kIndent);
OutputJsonKey(stream, kTestsuite, "disabled",
test_case.reportable_disabled_test_count(), kIndent);
OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent);
OutputJsonKey(stream, kTestsuite, "time",
FormatTimeInMillisAsDuration(test_case.elapsed_time()), kIndent,
false);
*stream << TestPropertiesAsJson(test_case.ad_hoc_test_result(), kIndent)
<< ",\n";
*stream << kIndent << "\"" << kTestsuite << "\": [\n";
bool comma = false;
for (int i = 0; i < test_case.total_test_count(); ++i) {
if (test_case.GetTestInfo(i)->is_reportable()) {
if (comma) {
*stream << ",\n";
} else {
comma = true;
}
OutputJsonTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i));
}
}
*stream << "\n" << kIndent << "]\n" << Indent(4) << "}";
}
// Prints a JSON summary of unit_test to output stream out.
void JsonUnitTestResultPrinter::PrintJsonUnitTest(std::ostream* stream,
const UnitTest& unit_test) {
const std::string kTestsuites = "testsuites";
const std::string kIndent = Indent(2);
*stream << "{\n";
OutputJsonKey(stream, kTestsuites, "tests", unit_test.reportable_test_count(),
kIndent);
OutputJsonKey(stream, kTestsuites, "failures", unit_test.failed_test_count(),
kIndent);
OutputJsonKey(stream, kTestsuites, "disabled",
unit_test.reportable_disabled_test_count(), kIndent);
OutputJsonKey(stream, kTestsuites, "errors", 0, kIndent);
if (GTEST_FLAG(shuffle)) {
OutputJsonKey(stream, kTestsuites, "random_seed", unit_test.random_seed(),
kIndent);
}
OutputJsonKey(stream, kTestsuites, "timestamp",
FormatEpochTimeInMillisAsRFC3339(unit_test.start_timestamp()),
kIndent);
OutputJsonKey(stream, kTestsuites, "time",
FormatTimeInMillisAsDuration(unit_test.elapsed_time()), kIndent,
false);
*stream << TestPropertiesAsJson(unit_test.ad_hoc_test_result(), kIndent)
<< ",\n";
OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent);
*stream << kIndent << "\"" << kTestsuites << "\": [\n";
bool comma = false;
for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
if (unit_test.GetTestCase(i)->reportable_test_count() > 0) {
if (comma) {
*stream << ",\n";
} else {
comma = true;
}
PrintJsonTestCase(stream, *unit_test.GetTestCase(i));
}
}
*stream << "\n" << kIndent << "]\n" << "}\n";
}
// Produces a string representing the test properties in a result as
// a JSON dictionary.
std::string JsonUnitTestResultPrinter::TestPropertiesAsJson(
const TestResult& result, const std::string& indent) {
Message attributes;
for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = result.GetTestProperty(i);
attributes << ",\n" << indent << "\"" << property.key() << "\": "
<< "\"" << EscapeJson(property.value()) << "\"";
}
return attributes.GetString();
}
// End JsonUnitTestResultPrinter
#if GTEST_CAN_STREAM_RESULTS_ #if GTEST_CAN_STREAM_RESULTS_
// Checks if str contains '=', '&', '%' or '\n' characters. If yes, // Checks if str contains '=', '&', '%' or '\n' characters. If yes,
@ -3852,9 +4248,10 @@ void OsStackTraceGetter::UponLeavingGTest() {}
class ScopedPrematureExitFile { class ScopedPrematureExitFile {
public: public:
explicit ScopedPrematureExitFile(const char* premature_exit_filepath) explicit ScopedPrematureExitFile(const char* premature_exit_filepath)
: premature_exit_filepath_(premature_exit_filepath) { : premature_exit_filepath_(premature_exit_filepath ?
premature_exit_filepath : "") {
// If a path to the premature-exit file is specified... // If a path to the premature-exit file is specified...
if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') { if (!premature_exit_filepath_.empty()) {
// create the file with a single "0" character in it. I/O // create the file with a single "0" character in it. I/O
// errors are ignored as there's nothing better we can do and we // errors are ignored as there's nothing better we can do and we
// don't want to fail the test because of this. // don't want to fail the test because of this.
@ -3865,13 +4262,18 @@ class ScopedPrematureExitFile {
} }
~ScopedPrematureExitFile() { ~ScopedPrematureExitFile() {
if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') { if (!premature_exit_filepath_.empty()) {
remove(premature_exit_filepath_); int retval = remove(premature_exit_filepath_.c_str());
if (retval) {
GTEST_LOG_(ERROR) << "Failed to remove premature exit filepath \""
<< premature_exit_filepath_ << "\" with error "
<< retval;
}
} }
} }
private: private:
const char* const premature_exit_filepath_; const std::string premature_exit_filepath_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile); GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile);
}; };
@ -4391,10 +4793,12 @@ void UnitTestImpl::ConfigureXmlOutput() {
if (output_format == "xml") { if (output_format == "xml") {
listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
} else if (output_format == "json") {
listeners()->SetDefaultXmlGenerator(new JsonUnitTestResultPrinter(
UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
} else if (output_format != "") { } else if (output_format != "") {
GTEST_LOG_(WARNING) << "WARNING: unrecognized output format \"" GTEST_LOG_(WARNING) << "WARNING: unrecognized output format \""
<< output_format << output_format << "\" ignored.";
<< "\" ignored.";
} }
} }
@ -4409,8 +4813,7 @@ void UnitTestImpl::ConfigureStreamingOutput() {
listeners()->Append(new StreamingListener(target.substr(0, pos), listeners()->Append(new StreamingListener(target.substr(0, pos),
target.substr(pos+1))); target.substr(pos+1)));
} else { } else {
GTEST_LOG_(WARNING) << "unrecognized streaming target \"" GTEST_LOG_(WARNING) << "unrecognized streaming target \"" << target
<< target
<< "\" ignored."; << "\" ignored.";
} }
} }
@ -4538,13 +4941,8 @@ static void TearDownEnvironment(Environment* env) { env->TearDown(); }
// All other functions called from RunAllTests() may safely assume that // All other functions called from RunAllTests() may safely assume that
// parameterized tests are ready to be counted and run. // parameterized tests are ready to be counted and run.
bool UnitTestImpl::RunAllTests() { bool UnitTestImpl::RunAllTests() {
// Makes sure InitGoogleTest() was called. // True iff Google Test is initialized before RUN_ALL_TESTS() is called.
if (!GTestIsInitialized()) { const bool gtest_is_initialized_before_run_all_tests = GTestIsInitialized();
GTEST_LOG_(ERROR) <<
"\nThis test program did NOT call ::testing::InitGoogleTest "
"before calling RUN_ALL_TESTS(). Please fix it.";
return false;
}
// Do not run any test if the --help flag was specified. // Do not run any test if the --help flag was specified.
if (g_help_flag) if (g_help_flag)
@ -4672,6 +5070,20 @@ bool UnitTestImpl::RunAllTests() {
repeater->OnTestProgramEnd(*parent_); repeater->OnTestProgramEnd(*parent_);
if (!gtest_is_initialized_before_run_all_tests) {
ColoredPrintf(
COLOR_RED,
"\nIMPORTANT NOTICE - DO NOT IGNORE:\n"
"This test program did NOT call " GTEST_INIT_GOOGLE_TEST_NAME_
"() before calling RUN_ALL_TESTS(). This is INVALID. Soon " GTEST_NAME_
" will start to enforce the valid usage. "
"Please fix it ASAP, or IT WILL START TO FAIL.\n"); // NOLINT
#if GTEST_FOR_GOOGLE_
ColoredPrintf(COLOR_RED,
"For more details, see http://wiki/Main/ValidGUnitMain.\n");
#endif // GTEST_FOR_GOOGLE_
}
return !failed; return !failed;
} }
@ -4718,7 +5130,7 @@ bool ShouldShard(const char* total_shards_env,
<< "Invalid environment variables: you have " << "Invalid environment variables: you have "
<< kTestShardIndex << " = " << shard_index << kTestShardIndex << " = " << shard_index
<< ", but have left " << kTestTotalShards << " unset.\n"; << ", but have left " << kTestTotalShards << " unset.\n";
ColoredPrintf(COLOR_RED, "%s", msg.GetString().c_str()); ColoredPrintf(COLOR_RED, msg.GetString().c_str());
fflush(stdout); fflush(stdout);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} else if (total_shards != -1 && shard_index == -1) { } else if (total_shards != -1 && shard_index == -1) {
@ -4726,7 +5138,7 @@ bool ShouldShard(const char* total_shards_env,
<< "Invalid environment variables: you have " << "Invalid environment variables: you have "
<< kTestTotalShards << " = " << total_shards << kTestTotalShards << " = " << total_shards
<< ", but have left " << kTestShardIndex << " unset.\n"; << ", but have left " << kTestShardIndex << " unset.\n";
ColoredPrintf(COLOR_RED, "%s", msg.GetString().c_str()); ColoredPrintf(COLOR_RED, msg.GetString().c_str());
fflush(stdout); fflush(stdout);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} else if (shard_index < 0 || shard_index >= total_shards) { } else if (shard_index < 0 || shard_index >= total_shards) {
@ -4735,7 +5147,7 @@ bool ShouldShard(const char* total_shards_env,
<< kTestShardIndex << " < " << kTestTotalShards << kTestShardIndex << " < " << kTestTotalShards
<< ", but you have " << kTestShardIndex << "=" << shard_index << ", but you have " << kTestShardIndex << "=" << shard_index
<< ", " << kTestTotalShards << "=" << total_shards << ".\n"; << ", " << kTestTotalShards << "=" << total_shards << ".\n";
ColoredPrintf(COLOR_RED, "%s", msg.GetString().c_str()); ColoredPrintf(COLOR_RED, msg.GetString().c_str());
fflush(stdout); fflush(stdout);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -5002,8 +5414,7 @@ bool SkipPrefix(const char* prefix, const char** pstr) {
// part can be omitted. // part can be omitted.
// //
// Returns the value of the flag, or NULL if the parsing failed. // Returns the value of the flag, or NULL if the parsing failed.
static const char* ParseFlagValue(const char* str, static const char* ParseFlagValue(const char* str, const char* flag,
const char* flag,
bool def_optional) { bool def_optional) {
// str and flag must not be NULL. // str and flag must not be NULL.
if (str == NULL || flag == NULL) return NULL; if (str == NULL || flag == NULL) return NULL;
@ -5074,9 +5485,8 @@ bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
// //
// On success, stores the value of the flag in *value, and returns // On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value. // true. On failure, returns false without changing *value.
static bool ParseStringFlag(const char* str, template <typename String>
const char* flag, static bool ParseStringFlag(const char* str, const char* flag, String* value) {
std::string* value) {
// Gets the value of the flag as a string. // Gets the value of the flag as a string.
const char* const value_str = ParseFlagValue(str, flag, false); const char* const value_str = ParseFlagValue(str, flag, false);
@ -5176,12 +5586,12 @@ static const char kColorEncodedHelpMessage[] =
"Test Output:\n" "Test Output:\n"
" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\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" " Enable/disable colored output. The default is @Gauto@D.\n"
" @G--" GTEST_FLAG_PREFIX_ "print_time=0@D\n" " -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
" Don't print the elapsed time of each test.\n" " Don't print the elapsed time of each test.\n"
" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" " @G--" GTEST_FLAG_PREFIX_ "output=@Y(@Gjson@Y|@Gxml@Y)[@G:@YDIRECTORY_PATH@G"
GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
" Generate an XML report in the given directory or with the given file\n" " Generate a JSON or XML report in the given directory or with the given\n"
" name. @YFILE_PATH@D defaults to @Gtest_detail.xml@D.\n" " file name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n"
# if GTEST_CAN_STREAM_RESULTS_ # if GTEST_CAN_STREAM_RESULTS_
" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" " @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
" Stream test results to the given server.\n" " Stream test results to the given server.\n"
@ -5195,7 +5605,8 @@ static const char kColorEncodedHelpMessage[] =
" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" " @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
" Turn assertion failures into debugger break-points.\n" " Turn assertion failures into debugger break-points.\n"
" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" " @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
" Turn assertion failures into C++ exceptions.\n" " Turn assertion failures into C++ exceptions for use by an external\n"
" test framework.\n"
" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" " @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
" Do not report exceptions as test failures. Instead, allow them\n" " Do not report exceptions as test failures. Instead, allow them\n"
" to crash the program or throw a pop-up (on Windows).\n" " to crash the program or throw a pop-up (on Windows).\n"
@ -5230,6 +5641,7 @@ static bool ParseGoogleTestFlag(const char* const arg) {
ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) || ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) || ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) || ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
ParseBoolFlag(arg, kPrintUTF8Flag, &GTEST_FLAG(print_utf8)) ||
ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) || ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) || ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) || ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
@ -5245,8 +5657,7 @@ static bool ParseGoogleTestFlag(const char* const arg) {
static void LoadFlagsFromFile(const std::string& path) { static void LoadFlagsFromFile(const std::string& path) {
FILE* flagfile = posix::FOpen(path.c_str(), "r"); FILE* flagfile = posix::FOpen(path.c_str(), "r");
if (!flagfile) { if (!flagfile) {
GTEST_LOG_(FATAL) << "Unable to open file \"" GTEST_LOG_(FATAL) << "Unable to open file \"" << GTEST_FLAG(flagfile)
<< GTEST_FLAG(flagfile)
<< "\""; << "\"";
} }
std::string contents(ReadEntireFile(flagfile)); std::string contents(ReadEntireFile(flagfile));
@ -5379,6 +5790,7 @@ std::string TempDir() {
#if defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_) #if defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_)
return GTEST_CUSTOM_TEMPDIR_FUNCTION_(); return GTEST_CUSTOM_TEMPDIR_FUNCTION_();
#endif #endif
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS_MOBILE
return "\\temp\\"; return "\\temp\\";
#elif GTEST_OS_WINDOWS #elif GTEST_OS_WINDOWS

View File

@ -119,6 +119,16 @@ cc_test(
"//:gtest", "//:gtest",
], ],
) )
cc_test(
name = "gtest_unittest",
size = "small",
srcs = ["gtest_unittest.cc"],
args = ["--heap_check=strict"],
shard_count = 2,
deps = ["//:gtest_main"],
)
# Py tests # Py tests
py_library( py_library(
@ -219,6 +229,13 @@ py_test(
deps = [":gtest_test_utils"], deps = [":gtest_test_utils"],
) )
cc_test(
name = "gtest_assert_by_exception_test",
size = "small",
srcs = ["gtest_assert_by_exception_test.cc"],
deps = ["//:gtest"],
)
cc_binary( cc_binary(
name = "gtest_throw_on_failure_test_", name = "gtest_throw_on_failure_test_",
testonly = 1, testonly = 1,

View File

@ -617,7 +617,11 @@ TEST_F(TestForDeathTest, ReturnIsFailure) {
TEST_F(TestForDeathTest, TestExpectDebugDeath) { TEST_F(TestForDeathTest, TestExpectDebugDeath) {
int sideeffect = 0; int sideeffect = 0;
EXPECT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), "death.*DieInDebugElse12") // Put the regex in a local variable to make sure we don't get an "unused"
// warning in opt mode.
const char* regex = "death.*DieInDebugElse12";
EXPECT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), regex)
<< "Must accept a streamed message"; << "Must accept a streamed message";
# ifdef NDEBUG # ifdef NDEBUG

View File

@ -41,8 +41,8 @@
# include <sstream> # include <sstream>
# include <string> # include <string>
# include <vector> # include <vector>
# include "src/gtest-internal-inl.h" // for UnitTestOptions
# include "src/gtest-internal-inl.h" // for UnitTestOptions
# include "test/gtest-param-test_test.h" # include "test/gtest-param-test_test.h"
using ::std::vector; using ::std::vector;
@ -536,6 +536,51 @@ TEST(CombineTest, CombineWithMaxNumberOfParameters) {
VerifyGenerator(gen, expected_values); VerifyGenerator(gen, expected_values);
} }
#if GTEST_LANG_CXX11
class NonDefaultConstructAssignString {
public:
NonDefaultConstructAssignString(const std::string& s) : str_(s) {}
const std::string& str() const { return str_; }
private:
std::string str_;
// Not default constructible
NonDefaultConstructAssignString();
// Not assignable
void operator=(const NonDefaultConstructAssignString&);
};
TEST(CombineTest, NonDefaultConstructAssign) {
const ParamGenerator<tuple<int, NonDefaultConstructAssignString> > gen =
Combine(Values(0, 1), Values(NonDefaultConstructAssignString("A"),
NonDefaultConstructAssignString("B")));
ParamGenerator<tuple<int, NonDefaultConstructAssignString> >::iterator it =
gen.begin();
EXPECT_EQ(0, std::get<0>(*it));
EXPECT_EQ("A", std::get<1>(*it).str());
++it;
EXPECT_EQ(0, std::get<0>(*it));
EXPECT_EQ("B", std::get<1>(*it).str());
++it;
EXPECT_EQ(1, std::get<0>(*it));
EXPECT_EQ("A", std::get<1>(*it).str());
++it;
EXPECT_EQ(1, std::get<0>(*it));
EXPECT_EQ("B", std::get<1>(*it).str());
++it;
EXPECT_TRUE(it == gen.end());
}
#endif // GTEST_LANG_CXX11
# endif // GTEST_HAS_COMBINE # endif // GTEST_HAS_COMBINE
// Tests that an generator produces correct sequence after being // Tests that an generator produces correct sequence after being
@ -839,8 +884,8 @@ class CustomFunctorNamingTest : public TestWithParam<std::string> {};
TEST_P(CustomFunctorNamingTest, CustomTestNames) {} TEST_P(CustomFunctorNamingTest, CustomTestNames) {}
struct CustomParamNameFunctor { struct CustomParamNameFunctor {
std::string operator()(const ::testing::TestParamInfo<std::string>& info) { std::string operator()(const ::testing::TestParamInfo<std::string>& inf) {
return info.param; return inf.param;
} }
}; };
@ -857,8 +902,8 @@ INSTANTIATE_TEST_CASE_P(AllAllowedCharacters,
CustomParamNameFunctor()); CustomParamNameFunctor());
inline std::string CustomParamNameFunction( inline std::string CustomParamNameFunction(
const ::testing::TestParamInfo<std::string>& info) { const ::testing::TestParamInfo<std::string>& inf) {
return info.param; return inf.param;
} }
class CustomFunctionNamingTest : public TestWithParam<std::string> {}; class CustomFunctionNamingTest : public TestWithParam<std::string> {};
@ -876,11 +921,10 @@ INSTANTIATE_TEST_CASE_P(CustomParamNameFunction,
class CustomLambdaNamingTest : public TestWithParam<std::string> {}; class CustomLambdaNamingTest : public TestWithParam<std::string> {};
TEST_P(CustomLambdaNamingTest, CustomTestNames) {} TEST_P(CustomLambdaNamingTest, CustomTestNames) {}
INSTANTIATE_TEST_CASE_P(CustomParamNameLambda, INSTANTIATE_TEST_CASE_P(CustomParamNameLambda, CustomLambdaNamingTest,
CustomLambdaNamingTest,
Values(std::string("LambdaName")), Values(std::string("LambdaName")),
[](const ::testing::TestParamInfo<std::string>& tpinfo) { [](const ::testing::TestParamInfo<std::string>& inf) {
return tpinfo.param; return inf.param;
}); });
#endif // GTEST_LANG_CXX11 #endif // GTEST_LANG_CXX11
@ -1047,6 +1091,7 @@ TEST_F(ParameterizedDeathTest, GetParamDiesFromTestF) {
INSTANTIATE_TEST_CASE_P(RangeZeroToFive, ParameterizedDerivedTest, Range(0, 5)); INSTANTIATE_TEST_CASE_P(RangeZeroToFive, ParameterizedDerivedTest, Range(0, 5));
int main(int argc, char **argv) { int main(int argc, char **argv) {
// Used in TestGenerationTest test case. // Used in TestGenerationTest test case.
AddGlobalTestEnvironment(TestGenerationTest::Environment::Instance()); AddGlobalTestEnvironment(TestGenerationTest::Environment::Instance());

View File

@ -239,7 +239,7 @@ using ::testing::internal::UniversalTersePrint;
#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_ #if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
using ::testing::internal::UniversalTersePrintTupleFieldsToStrings; using ::testing::internal::UniversalTersePrintTupleFieldsToStrings;
#endif #endif
using ::testing::internal::string;
// The hash_* classes are not part of the C++ standard. STLport // The hash_* classes are not part of the C++ standard. STLport
// defines them in namespace std. MSVC defines them in ::stdext. GCC // defines them in namespace std. MSVC defines them in ::stdext. GCC
@ -837,22 +837,22 @@ TEST(PrintTypeWithGenericStreamingTest, TypeImplicitlyConvertible) {
EXPECT_EQ("AllowsGenericStreamingAndImplicitConversionTemplate", Print(a)); EXPECT_EQ("AllowsGenericStreamingAndImplicitConversionTemplate", Print(a));
} }
#if GTEST_HAS_STRING_PIECE_ #if GTEST_HAS_ABSL
// Tests printing StringPiece. // Tests printing ::absl::string_view.
TEST(PrintStringPieceTest, SimpleStringPiece) { TEST(PrintStringViewTest, SimpleStringView) {
const StringPiece sp = "Hello"; const ::absl::string_view sp = "Hello";
EXPECT_EQ("\"Hello\"", Print(sp)); EXPECT_EQ("\"Hello\"", Print(sp));
} }
TEST(PrintStringPieceTest, UnprintableCharacters) { TEST(PrintStringViewTest, UnprintableCharacters) {
const char str[] = "NUL (\0) and \r\t"; const char str[] = "NUL (\0) and \r\t";
const StringPiece sp(str, sizeof(str) - 1); const ::absl::string_view sp(str, sizeof(str) - 1);
EXPECT_EQ("\"NUL (\\0) and \\r\\t\"", Print(sp)); EXPECT_EQ("\"NUL (\\0) and \\r\\t\"", Print(sp));
} }
#endif // GTEST_HAS_STRING_PIECE_ #endif // GTEST_HAS_ABSL
// Tests printing STL containers. // Tests printing STL containers.
@ -1327,7 +1327,7 @@ TEST(FormatForComparisonFailureMessageTest, FormatsNonCharArrayAsPointer) {
} }
// Tests formatting a char pointer when it's compared with another pointer. // Tests formatting a char pointer when it's compared with another pointer.
// In this case we want to print it as a raw pointer, as the comparision is by // In this case we want to print it as a raw pointer, as the comparison is by
// pointer. // pointer.
// char pointer vs pointer // char pointer vs pointer
@ -1552,6 +1552,78 @@ TEST(PrintToStringTest, WorksForCharArrayWithEmbeddedNul) {
EXPECT_PRINT_TO_STRING_(mutable_str_with_nul, "\"hello\\0 world\""); EXPECT_PRINT_TO_STRING_(mutable_str_with_nul, "\"hello\\0 world\"");
} }
TEST(PrintToStringTest, ContainsNonLatin) {
// Sanity test with valid UTF-8. Prints both in hex and as text.
std::string non_ascii_str = ::std::string("오전 4:30");
EXPECT_PRINT_TO_STRING_(non_ascii_str,
"\"\\xEC\\x98\\xA4\\xEC\\xA0\\x84 4:30\"\n"
" As Text: \"오전 4:30\"");
non_ascii_str = ::std::string("From ä — ẑ");
EXPECT_PRINT_TO_STRING_(non_ascii_str,
"\"From \\xC3\\xA4 \\xE2\\x80\\x94 \\xE1\\xBA\\x91\""
"\n As Text: \"From ä — ẑ\"");
}
TEST(IsValidUTF8Test, IllFormedUTF8) {
// The following test strings are ill-formed UTF-8 and are printed
// as hex only (or ASCII, in case of ASCII bytes) because IsValidUTF8() is
// expected to fail, thus output does not contain "As Text:".
static const char *const kTestdata[][2] = {
// 2-byte lead byte followed by a single-byte character.
{"\xC3\x74", "\"\\xC3t\""},
// Valid 2-byte character followed by an orphan trail byte.
{"\xC3\x84\xA4", "\"\\xC3\\x84\\xA4\""},
// Lead byte without trail byte.
{"abc\xC3", "\"abc\\xC3\""},
// 3-byte lead byte, single-byte character, orphan trail byte.
{"x\xE2\x70\x94", "\"x\\xE2p\\x94\""},
// Truncated 3-byte character.
{"\xE2\x80", "\"\\xE2\\x80\""},
// Truncated 3-byte character followed by valid 2-byte char.
{"\xE2\x80\xC3\x84", "\"\\xE2\\x80\\xC3\\x84\""},
// Truncated 3-byte character followed by a single-byte character.
{"\xE2\x80\x7A", "\"\\xE2\\x80z\""},
// 3-byte lead byte followed by valid 3-byte character.
{"\xE2\xE2\x80\x94", "\"\\xE2\\xE2\\x80\\x94\""},
// 4-byte lead byte followed by valid 3-byte character.
{"\xF0\xE2\x80\x94", "\"\\xF0\\xE2\\x80\\x94\""},
// Truncated 4-byte character.
{"\xF0\xE2\x80", "\"\\xF0\\xE2\\x80\""},
// Invalid UTF-8 byte sequences embedded in other chars.
{"abc\xE2\x80\x94\xC3\x74xyc", "\"abc\\xE2\\x80\\x94\\xC3txyc\""},
{"abc\xC3\x84\xE2\x80\xC3\x84xyz",
"\"abc\\xC3\\x84\\xE2\\x80\\xC3\\x84xyz\""},
// Non-shortest UTF-8 byte sequences are also ill-formed.
// The classics: xC0, xC1 lead byte.
{"\xC0\x80", "\"\\xC0\\x80\""},
{"\xC1\x81", "\"\\xC1\\x81\""},
// Non-shortest sequences.
{"\xE0\x80\x80", "\"\\xE0\\x80\\x80\""},
{"\xf0\x80\x80\x80", "\"\\xF0\\x80\\x80\\x80\""},
// Last valid code point before surrogate range, should be printed as text,
// too.
{"\xED\x9F\xBF", "\"\\xED\\x9F\\xBF\"\n As Text: \"\""},
// Start of surrogate lead. Surrogates are not printed as text.
{"\xED\xA0\x80", "\"\\xED\\xA0\\x80\""},
// Last non-private surrogate lead.
{"\xED\xAD\xBF", "\"\\xED\\xAD\\xBF\""},
// First private-use surrogate lead.
{"\xED\xAE\x80", "\"\\xED\\xAE\\x80\""},
// Last private-use surrogate lead.
{"\xED\xAF\xBF", "\"\\xED\\xAF\\xBF\""},
// Mid-point of surrogate trail.
{"\xED\xB3\xBF", "\"\\xED\\xB3\\xBF\""},
// First valid code point after surrogate range, should be printed as text,
// too.
{"\xEE\x80\x80", "\"\\xEE\\x80\\x80\"\n As Text: \"\""}
};
for (int i = 0; i < int(sizeof(kTestdata)/sizeof(kTestdata[0])); ++i) {
EXPECT_PRINT_TO_STRING_(kTestdata[i][0], kTestdata[i][1]);
}
}
#undef EXPECT_PRINT_TO_STRING_ #undef EXPECT_PRINT_TO_STRING_
TEST(UniversalTersePrintTest, WorksForNonReference) { TEST(UniversalTersePrintTest, WorksForNonReference) {
@ -1693,5 +1765,17 @@ TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
#endif // GTEST_HAS_STD_TUPLE_ #endif // GTEST_HAS_STD_TUPLE_
#if GTEST_HAS_ABSL
TEST(PrintOptionalTest, Basic) {
absl::optional<int> value;
EXPECT_EQ("(nullopt)", PrintToString(value));
value = {7};
EXPECT_EQ("(7)", PrintToString(value));
EXPECT_EQ("(1.1)", PrintToString(absl::optional<double>{1.1}));
EXPECT_EQ("(\"A\")", PrintToString(absl::optional<std::string>{"A"}));
}
#endif // GTEST_HAS_ABSL
} // namespace gtest_printers_test } // namespace gtest_printers_test
} // namespace testing } // namespace testing

View File

@ -33,15 +33,15 @@
// //
// Sometimes it's desirable to build most of Google Test's own tests // Sometimes it's desirable to build most of Google Test's own tests
// by compiling a single file. This file serves this purpose. // by compiling a single file. This file serves this purpose.
#include "test/gtest-filepath_test.cc" #include "gtest-filepath_test.cc"
#include "test/gtest-linked_ptr_test.cc" #include "gtest-linked_ptr_test.cc"
#include "test/gtest-message_test.cc" #include "gtest-message_test.cc"
#include "test/gtest-options_test.cc" #include "gtest-options_test.cc"
#include "test/gtest-port_test.cc" #include "gtest-port_test.cc"
#include "test/gtest_pred_impl_unittest.cc" #include "gtest_pred_impl_unittest.cc"
#include "test/gtest_prod_test.cc" #include "gtest_prod_test.cc"
#include "test/gtest-test-part_test.cc" #include "gtest-test-part_test.cc"
#include "test/gtest-typed-test_test.cc" #include "gtest-typed-test_test.cc"
#include "test/gtest-typed-test2_test.cc" #include "gtest-typed-test2_test.cc"
#include "test/gtest_unittest.cc" #include "gtest_unittest.cc"
#include "test/production.cc" #include "production.cc"

View File

@ -0,0 +1,119 @@
// 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)
// Tests Google Test's assert-by-exception mode with exceptions enabled.
#include "gtest/gtest.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdexcept>
class ThrowListener : public testing::EmptyTestEventListener {
void OnTestPartResult(const testing::TestPartResult& result) override {
if (result.type() == testing::TestPartResult::kFatalFailure) {
throw testing::AssertionException(result);
}
}
};
// Prints the given failure message and exits the program with
// non-zero. We use this instead of a Google Test assertion to
// indicate a failure, as the latter is been tested and cannot be
// relied on.
void Fail(const char* msg) {
printf("FAILURE: %s\n", msg);
fflush(stdout);
exit(1);
}
static void AssertFalse() {
ASSERT_EQ(2, 3) << "Expected failure";
}
// Tests that an assertion failure throws a subclass of
// std::runtime_error.
TEST(Test, Test) {
// A successful assertion shouldn't throw.
try {
EXPECT_EQ(3, 3);
} catch(...) {
Fail("A successful assertion wrongfully threw.");
}
// A successful assertion shouldn't throw.
try {
EXPECT_EQ(3, 4);
} catch(...) {
Fail("A failed non-fatal assertion wrongfully threw.");
}
// A failed assertion should throw.
try {
AssertFalse();
} catch(const testing::AssertionException& e) {
if (strstr(e.what(), "Expected failure") != NULL)
throw;
printf("%s",
"A failed assertion did throw an exception of the right type, "
"but the message is incorrect. Instead of containing \"Expected "
"failure\", it is:\n");
Fail(e.what());
} catch(...) {
Fail("A failed assertion threw the wrong type of exception.");
}
Fail("A failed assertion should've thrown but didn't.");
}
int kTestForContinuingTest = 0;
TEST(Test, Test2) {
// FIXME(sokolov): how to force Test2 to be after Test?
kTestForContinuingTest = 1;
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
int result = RUN_ALL_TESTS();
if (result == 0) {
printf("RUN_ALL_TESTS returned %d\n", result);
Fail("Expected failure instead.");
}
if (kTestForContinuingTest == 0) {
Fail("Should have continued with other tests, but did not.");
}
return 0;
}

View File

@ -35,6 +35,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include <iostream> #include <iostream>
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
using ::std::cout; using ::std::cout;

View File

@ -0,0 +1,162 @@
#!/usr/bin/env python
# Copyright 2018, 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.
"""Unit test for the gtest_json_output module."""
import json
import os
import gtest_json_test_utils
import gtest_test_utils
GTEST_OUTPUT_SUBDIR = 'json_outfiles'
GTEST_OUTPUT_1_TEST = 'gtest_xml_outfile1_test_'
GTEST_OUTPUT_2_TEST = 'gtest_xml_outfile2_test_'
EXPECTED_1 = {
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'timestamp': u'*',
u'name': u'AllTests',
u'testsuites': [{
u'name': u'PropertyOne',
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [{
u'name': u'TestSomeProperties',
u'status': u'RUN',
u'time': u'*',
u'classname': u'PropertyOne',
u'SetUpProp': u'1',
u'TestSomeProperty': u'1',
u'TearDownProp': u'1',
}],
}],
}
EXPECTED_2 = {
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'timestamp': u'*',
u'name': u'AllTests',
u'testsuites': [{
u'name': u'PropertyTwo',
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [{
u'name': u'TestSomeProperties',
u'status': u'RUN',
u'time': u'*',
u'classname': u'PropertyTwo',
u'SetUpProp': u'2',
u'TestSomeProperty': u'2',
u'TearDownProp': u'2',
}],
}],
}
class GTestJsonOutFilesTest(gtest_test_utils.TestCase):
"""Unit test for Google Test's JSON output functionality."""
def setUp(self):
# We want the trailing '/' that the last "" provides in os.path.join, for
# telling Google Test to create an output directory instead of a single file
# for xml output.
self.output_dir_ = os.path.join(gtest_test_utils.GetTempDir(),
GTEST_OUTPUT_SUBDIR, '')
self.DeleteFilesAndDir()
def tearDown(self):
self.DeleteFilesAndDir()
def DeleteFilesAndDir(self):
try:
os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_1_TEST + '.json'))
except os.error:
pass
try:
os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_2_TEST + '.json'))
except os.error:
pass
try:
os.rmdir(self.output_dir_)
except os.error:
pass
def testOutfile1(self):
self._TestOutFile(GTEST_OUTPUT_1_TEST, EXPECTED_1)
def testOutfile2(self):
self._TestOutFile(GTEST_OUTPUT_2_TEST, EXPECTED_2)
def _TestOutFile(self, test_name, expected):
gtest_prog_path = gtest_test_utils.GetTestExecutablePath(test_name)
command = [gtest_prog_path, '--gtest_output=json:%s' % self.output_dir_]
p = gtest_test_utils.Subprocess(command,
working_dir=gtest_test_utils.GetTempDir())
self.assert_(p.exited)
self.assertEquals(0, p.exit_code)
# TODO(wan@google.com): libtool causes the built test binary to be
# named lt-gtest_xml_outfiles_test_ instead of
# gtest_xml_outfiles_test_. To account for this possibility, we
# allow both names in the following code. We should remove this
# hack when Chandler Carruth's libtool replacement tool is ready.
output_file_name1 = test_name + '.json'
output_file1 = os.path.join(self.output_dir_, output_file_name1)
output_file_name2 = 'lt-' + output_file_name1
output_file2 = os.path.join(self.output_dir_, output_file_name2)
self.assert_(os.path.isfile(output_file1) or os.path.isfile(output_file2),
output_file1)
if os.path.isfile(output_file1):
with open(output_file1) as f:
actual = json.load(f)
else:
with open(output_file2) as f:
actual = json.load(f)
self.assertEqual(expected, gtest_json_test_utils.normalize(actual))
if __name__ == '__main__':
os.environ['GTEST_STACK_TRACE_DEPTH'] = '0'
gtest_test_utils.Main()

View File

@ -0,0 +1,611 @@
#!/usr/bin/env python
# Copyright 2018, 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.
"""Unit test for the gtest_json_output module."""
import datetime
import errno
import json
import os
import re
import sys
import gtest_json_test_utils
import gtest_test_utils
GTEST_FILTER_FLAG = '--gtest_filter'
GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
GTEST_OUTPUT_FLAG = '--gtest_output'
GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.json'
GTEST_PROGRAM_NAME = 'gtest_xml_output_unittest_'
SUPPORTS_STACK_TRACES = False
if SUPPORTS_STACK_TRACES:
STACK_TRACE_TEMPLATE = '\nStack trace:\n*'
else:
STACK_TRACE_TEMPLATE = ''
EXPECTED_NON_EMPTY = {
u'tests': 23,
u'failures': 4,
u'disabled': 2,
u'errors': 0,
u'timestamp': u'*',
u'time': u'*',
u'ad_hoc_property': u'42',
u'name': u'AllTests',
u'testsuites': [
{
u'name': u'SuccessfulTest',
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'Succeeds',
u'status': u'RUN',
u'time': u'*',
u'classname': u'SuccessfulTest'
}
]
},
{
u'name': u'FailedTest',
u'tests': 1,
u'failures': 1,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'Fails',
u'status': u'RUN',
u'time': u'*',
u'classname': u'FailedTest',
u'failures': [
{
u'failure':
u'gtest_xml_output_unittest_.cc:*\n'
u'Expected equality of these values:\n'
u' 1\n 2' + STACK_TRACE_TEMPLATE,
u'type': u''
}
]
}
]
},
{
u'name': u'DisabledTest',
u'tests': 1,
u'failures': 0,
u'disabled': 1,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'DISABLED_test_not_run',
u'status': u'NOTRUN',
u'time': u'*',
u'classname': u'DisabledTest'
}
]
},
{
u'name': u'MixedResultTest',
u'tests': 3,
u'failures': 1,
u'disabled': 1,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'Succeeds',
u'status': u'RUN',
u'time': u'*',
u'classname': u'MixedResultTest'
},
{
u'name': u'Fails',
u'status': u'RUN',
u'time': u'*',
u'classname': u'MixedResultTest',
u'failures': [
{
u'failure':
u'gtest_xml_output_unittest_.cc:*\n'
u'Expected equality of these values:\n'
u' 1\n 2' + STACK_TRACE_TEMPLATE,
u'type': u''
},
{
u'failure':
u'gtest_xml_output_unittest_.cc:*\n'
u'Expected equality of these values:\n'
u' 2\n 3' + STACK_TRACE_TEMPLATE,
u'type': u''
}
]
},
{
u'name': u'DISABLED_test',
u'status': u'NOTRUN',
u'time': u'*',
u'classname': u'MixedResultTest'
}
]
},
{
u'name': u'XmlQuotingTest',
u'tests': 1,
u'failures': 1,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'OutputsCData',
u'status': u'RUN',
u'time': u'*',
u'classname': u'XmlQuotingTest',
u'failures': [
{
u'failure':
u'gtest_xml_output_unittest_.cc:*\n'
u'Failed\nXML output: <?xml encoding="utf-8">'
u'<top><![CDATA[cdata text]]></top>' +
STACK_TRACE_TEMPLATE,
u'type': u''
}
]
}
]
},
{
u'name': u'InvalidCharactersTest',
u'tests': 1,
u'failures': 1,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'InvalidCharactersInMessage',
u'status': u'RUN',
u'time': u'*',
u'classname': u'InvalidCharactersTest',
u'failures': [
{
u'failure':
u'gtest_xml_output_unittest_.cc:*\n'
u'Failed\nInvalid characters in brackets'
u' [\x01\x02]' + STACK_TRACE_TEMPLATE,
u'type': u''
}
]
}
]
},
{
u'name': u'PropertyRecordingTest',
u'tests': 4,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'SetUpTestCase': u'yes',
u'TearDownTestCase': u'aye',
u'testsuite': [
{
u'name': u'OneProperty',
u'status': u'RUN',
u'time': u'*',
u'classname': u'PropertyRecordingTest',
u'key_1': u'1'
},
{
u'name': u'IntValuedProperty',
u'status': u'RUN',
u'time': u'*',
u'classname': u'PropertyRecordingTest',
u'key_int': u'1'
},
{
u'name': u'ThreeProperties',
u'status': u'RUN',
u'time': u'*',
u'classname': u'PropertyRecordingTest',
u'key_1': u'1',
u'key_2': u'2',
u'key_3': u'3'
},
{
u'name': u'TwoValuesForOneKeyUsesLastValue',
u'status': u'RUN',
u'time': u'*',
u'classname': u'PropertyRecordingTest',
u'key_1': u'2'
}
]
},
{
u'name': u'NoFixtureTest',
u'tests': 3,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'RecordProperty',
u'status': u'RUN',
u'time': u'*',
u'classname': u'NoFixtureTest',
u'key': u'1'
},
{
u'name': u'ExternalUtilityThatCallsRecordIntValuedProperty',
u'status': u'RUN',
u'time': u'*',
u'classname': u'NoFixtureTest',
u'key_for_utility_int': u'1'
},
{
u'name':
u'ExternalUtilityThatCallsRecordStringValuedProperty',
u'status': u'RUN',
u'time': u'*',
u'classname': u'NoFixtureTest',
u'key_for_utility_string': u'1'
}
]
},
{
u'name': u'TypedTest/0',
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'HasTypeParamAttribute',
u'type_param': u'int',
u'status': u'RUN',
u'time': u'*',
u'classname': u'TypedTest/0'
}
]
},
{
u'name': u'TypedTest/1',
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'HasTypeParamAttribute',
u'type_param': u'long',
u'status': u'RUN',
u'time': u'*',
u'classname': u'TypedTest/1'
}
]
},
{
u'name': u'Single/TypeParameterizedTestCase/0',
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'HasTypeParamAttribute',
u'type_param': u'int',
u'status': u'RUN',
u'time': u'*',
u'classname': u'Single/TypeParameterizedTestCase/0'
}
]
},
{
u'name': u'Single/TypeParameterizedTestCase/1',
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'HasTypeParamAttribute',
u'type_param': u'long',
u'status': u'RUN',
u'time': u'*',
u'classname': u'Single/TypeParameterizedTestCase/1'
}
]
},
{
u'name': u'Single/ValueParamTest',
u'tests': 4,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [
{
u'name': u'HasValueParamAttribute/0',
u'value_param': u'33',
u'status': u'RUN',
u'time': u'*',
u'classname': u'Single/ValueParamTest'
},
{
u'name': u'HasValueParamAttribute/1',
u'value_param': u'42',
u'status': u'RUN',
u'time': u'*',
u'classname': u'Single/ValueParamTest'
},
{
u'name': u'AnotherTestThatHasValueParamAttribute/0',
u'value_param': u'33',
u'status': u'RUN',
u'time': u'*',
u'classname': u'Single/ValueParamTest'
},
{
u'name': u'AnotherTestThatHasValueParamAttribute/1',
u'value_param': u'42',
u'status': u'RUN',
u'time': u'*',
u'classname': u'Single/ValueParamTest'
}
]
}
]
}
EXPECTED_FILTERED = {
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'timestamp': u'*',
u'name': u'AllTests',
u'ad_hoc_property': u'42',
u'testsuites': [{
u'name': u'SuccessfulTest',
u'tests': 1,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'testsuite': [{
u'name': u'Succeeds',
u'status': u'RUN',
u'time': u'*',
u'classname': u'SuccessfulTest',
}]
}],
}
EXPECTED_EMPTY = {
u'tests': 0,
u'failures': 0,
u'disabled': 0,
u'errors': 0,
u'time': u'*',
u'timestamp': u'*',
u'name': u'AllTests',
u'testsuites': [],
}
GTEST_PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
SUPPORTS_TYPED_TESTS = 'TypedTest' in gtest_test_utils.Subprocess(
[GTEST_PROGRAM_PATH, GTEST_LIST_TESTS_FLAG], capture_stderr=False).output
class GTestJsonOutputUnitTest(gtest_test_utils.TestCase):
"""Unit test for Google Test's JSON output functionality.
"""
# This test currently breaks on platforms that do not support typed and
# type-parameterized tests, so we don't run it under them.
if SUPPORTS_TYPED_TESTS:
def testNonEmptyJsonOutput(self):
"""Verifies JSON output for a Google Test binary with non-empty output.
Runs a test program that generates a non-empty JSON output, and
tests that the JSON output is expected.
"""
self._TestJsonOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY, 1)
def testEmptyJsonOutput(self):
"""Verifies JSON output for a Google Test binary without actual tests.
Runs a test program that generates an empty JSON output, and
tests that the JSON output is expected.
"""
self._TestJsonOutput('gtest_no_test_unittest', EXPECTED_EMPTY, 0)
def testTimestampValue(self):
"""Checks whether the timestamp attribute in the JSON output is valid.
Runs a test program that generates an empty JSON output, and checks if
the timestamp attribute in the testsuites tag is valid.
"""
actual = self._GetJsonOutput('gtest_no_test_unittest', [], 0)
date_time_str = actual['timestamp']
# datetime.strptime() is only available in Python 2.5+ so we have to
# parse the expected datetime manually.
match = re.match(r'(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)', date_time_str)
self.assertTrue(
re.match,
'JSON datettime string %s has incorrect format' % date_time_str)
date_time_from_json = datetime.datetime(
year=int(match.group(1)), month=int(match.group(2)),
day=int(match.group(3)), hour=int(match.group(4)),
minute=int(match.group(5)), second=int(match.group(6)))
time_delta = abs(datetime.datetime.now() - date_time_from_json)
# timestamp value should be near the current local time
self.assertTrue(time_delta < datetime.timedelta(seconds=600),
'time_delta is %s' % time_delta)
def testDefaultOutputFile(self):
"""Verifies the default output file name.
Confirms that Google Test produces an JSON output file with the expected
default name if no name is explicitly specified.
"""
output_file = os.path.join(gtest_test_utils.GetTempDir(),
GTEST_DEFAULT_OUTPUT_FILE)
gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
'gtest_no_test_unittest')
try:
os.remove(output_file)
except OSError:
e = sys.exc_info()[1]
if e.errno != errno.ENOENT:
raise
p = gtest_test_utils.Subprocess(
[gtest_prog_path, '%s=json' % GTEST_OUTPUT_FLAG],
working_dir=gtest_test_utils.GetTempDir())
self.assert_(p.exited)
self.assertEquals(0, p.exit_code)
self.assert_(os.path.isfile(output_file))
def testSuppressedJsonOutput(self):
"""Verifies that no JSON output is generated.
Tests that no JSON file is generated if the default JSON listener is
shut down before RUN_ALL_TESTS is invoked.
"""
json_path = os.path.join(gtest_test_utils.GetTempDir(),
GTEST_PROGRAM_NAME + 'out.json')
if os.path.isfile(json_path):
os.remove(json_path)
command = [GTEST_PROGRAM_PATH,
'%s=json:%s' % (GTEST_OUTPUT_FLAG, json_path),
'--shut_down_xml']
p = gtest_test_utils.Subprocess(command)
if p.terminated_by_signal:
# p.signal is available only if p.terminated_by_signal is True.
self.assertFalse(
p.terminated_by_signal,
'%s was killed by signal %d' % (GTEST_PROGRAM_NAME, p.signal))
else:
self.assert_(p.exited)
self.assertEquals(1, p.exit_code,
"'%s' exited with code %s, which doesn't match "
'the expected exit code %s.'
% (command, p.exit_code, 1))
self.assert_(not os.path.isfile(json_path))
def testFilteredTestJsonOutput(self):
"""Verifies JSON output when a filter is applied.
Runs a test program that executes only some tests and verifies that
non-selected tests do not show up in the JSON output.
"""
self._TestJsonOutput(GTEST_PROGRAM_NAME, EXPECTED_FILTERED, 0,
extra_args=['%s=SuccessfulTest.*' % GTEST_FILTER_FLAG])
def _GetJsonOutput(self, gtest_prog_name, extra_args, expected_exit_code):
"""Returns the JSON output generated by running the program gtest_prog_name.
Furthermore, the program's exit code must be expected_exit_code.
Args:
gtest_prog_name: Google Test binary name.
extra_args: extra arguments to binary invocation.
expected_exit_code: program's exit code.
"""
json_path = os.path.join(gtest_test_utils.GetTempDir(),
gtest_prog_name + 'out.json')
gtest_prog_path = gtest_test_utils.GetTestExecutablePath(gtest_prog_name)
command = (
[gtest_prog_path, '%s=json:%s' % (GTEST_OUTPUT_FLAG, json_path)] +
extra_args
)
p = gtest_test_utils.Subprocess(command)
if p.terminated_by_signal:
self.assert_(False,
'%s was killed by signal %d' % (gtest_prog_name, p.signal))
else:
self.assert_(p.exited)
self.assertEquals(expected_exit_code, p.exit_code,
"'%s' exited with code %s, which doesn't match "
'the expected exit code %s.'
% (command, p.exit_code, expected_exit_code))
with open(json_path) as f:
actual = json.load(f)
return actual
def _TestJsonOutput(self, gtest_prog_name, expected,
expected_exit_code, extra_args=None):
"""Checks the JSON output generated by the Google Test binary.
Asserts that the JSON document generated by running the program
gtest_prog_name matches expected_json, a string containing another
JSON document. Furthermore, the program's exit code must be
expected_exit_code.
Args:
gtest_prog_name: Google Test binary name.
expected: expected output.
expected_exit_code: program's exit code.
extra_args: extra arguments to binary invocation.
"""
actual = self._GetJsonOutput(gtest_prog_name, extra_args or [],
expected_exit_code)
self.assertEqual(expected, gtest_json_test_utils.normalize(actual))
if __name__ == '__main__':
os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
gtest_test_utils.Main()

View File

@ -0,0 +1,60 @@
# Copyright 2018, 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.
"""Unit test utilities for gtest_json_output."""
import re
def normalize(obj):
"""Normalize output object.
Args:
obj: Google Test's JSON output object to normalize.
Returns:
Normalized output without any references to transient information that may
change from run to run.
"""
def _normalize(key, value):
if key == 'time':
return re.sub(r'^\d+(\.\d+)?s$', '*', value)
elif key == 'timestamp':
return re.sub(r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ$', '*', value)
elif key == 'failure':
value = re.sub(r'^.*[/\\](.*:)\d+\n', '\\1*\n', value)
return re.sub(r'Stack trace:\n(.|\n)*', 'Stack trace:\n*', value)
else:
return normalize(value)
if isinstance(obj, dict):
return {k: _normalize(k, v) for k, v in obj.items()}
if isinstance(obj, list):
return [normalize(x) for x in obj]
else:
return obj

View File

@ -41,5 +41,5 @@ TEST(GTestMainTest, ShouldSucceed) {
} // namespace } // namespace
// We are using the main() function defined in src/gtest_main.cc, so // We are using the main() function defined in gtest_main.cc, so we
// we don't define it here. // don't define it here.

View File

@ -33,7 +33,6 @@
__author__ = 'wan@google.com (Zhanyong Wan)' __author__ = 'wan@google.com (Zhanyong Wan)'
import os
import gtest_test_utils import gtest_test_utils
COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_uninitialized_test_') COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_uninitialized_test_')

View File

@ -538,7 +538,7 @@ TEST(CodePointToUtf8Test, CanEncode8To11Bits) {
// 101 0111 0110 => 110-10101 10-110110 // 101 0111 0110 => 110-10101 10-110110
// Some compilers (e.g., GCC on MinGW) cannot handle non-ASCII codepoints // Some compilers (e.g., GCC on MinGW) cannot handle non-ASCII codepoints
// in wide strings and wide chars. In order to accomodate them, we have to // in wide strings and wide chars. In order to accommodate them, we have to
// introduce such character constants as integers. // introduce such character constants as integers.
EXPECT_EQ("\xD5\xB6", EXPECT_EQ("\xD5\xB6",
CodePointToUtf8(static_cast<wchar_t>(0x576))); CodePointToUtf8(static_cast<wchar_t>(0x576)));
@ -1779,7 +1779,7 @@ TEST(Int32FromEnvOrDieDeathTest, AbortsOnFailure) {
} }
// Tests that Int32FromEnvOrDie() aborts with an error message // Tests that Int32FromEnvOrDie() aborts with an error message
// if the variable cannot be represnted by an Int32. // if the variable cannot be represented by an Int32.
TEST(Int32FromEnvOrDieDeathTest, AbortsOnInt32Overflow) { TEST(Int32FromEnvOrDieDeathTest, AbortsOnInt32Overflow) {
SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "1234567891234567891234"); SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "1234567891234567891234");
EXPECT_DEATH_IF_SUPPORTED( EXPECT_DEATH_IF_SUPPORTED(
@ -2088,7 +2088,7 @@ class UnitTestRecordPropertyTestEnvironment : public Environment {
}; };
// This will test property recording outside of any test or test case. // This will test property recording outside of any test or test case.
Environment* record_property_env GTEST_ATTRIBUTE_UNUSED_ = static Environment* record_property_env =
AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment); AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment);
// This group of tests is for predicate assertions (ASSERT_PRED*, etc) // This group of tests is for predicate assertions (ASSERT_PRED*, etc)
@ -2421,9 +2421,8 @@ TEST(StringAssertionTest, ASSERT_STREQ) {
const char p2[] = "good"; const char p2[] = "good";
ASSERT_STREQ(p1, p2); ASSERT_STREQ(p1, p2);
EXPECT_FATAL_FAILURE( EXPECT_FATAL_FAILURE(ASSERT_STREQ("bad", "good"),
ASSERT_STREQ("bad", "good"), " \"bad\"\n \"good\"");
"Expected equality of these values:\n \"bad\"\n \"good\"");
} }
// Tests ASSERT_STREQ with NULL arguments. // Tests ASSERT_STREQ with NULL arguments.
@ -3361,7 +3360,7 @@ class NoFatalFailureTest : public Test {
void DoAssertNoFatalFailureOnFails() { void DoAssertNoFatalFailureOnFails() {
ASSERT_NO_FATAL_FAILURE(Fails()); ASSERT_NO_FATAL_FAILURE(Fails());
ADD_FAILURE() << "shold not reach here."; ADD_FAILURE() << "should not reach here.";
} }
void DoExpectNoFatalFailureOnFails() { void DoExpectNoFatalFailureOnFails() {
@ -3658,7 +3657,7 @@ TEST(AssertionTest, AssertFalseWithAssertionResult) {
} }
#ifdef __BORLANDC__ #ifdef __BORLANDC__
// Restores warnings after previous "#pragma option push" supressed them // Restores warnings after previous "#pragma option push" suppressed them
# pragma option pop # pragma option pop
#endif #endif
@ -3813,7 +3812,7 @@ void TestEq1(int x) {
// Tests calling a test subroutine that's not part of a fixture. // Tests calling a test subroutine that's not part of a fixture.
TEST(AssertionTest, NonFixtureSubroutine) { TEST(AssertionTest, NonFixtureSubroutine) {
EXPECT_FATAL_FAILURE(TestEq1(2), EXPECT_FATAL_FAILURE(TestEq1(2),
"Which is: 2"); " x\n Which is: 2");
} }
// An uncopyable class. // An uncopyable class.
@ -3952,13 +3951,13 @@ TEST(AssertionTest, AnonymousEnum) {
// ICE's in C++Builder. // ICE's in C++Builder.
EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseB), EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseB),
"kCaseB"); " kCaseB\n Which is: ");
EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC), EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
"Which is: 42"); "\n Which is: 42");
# endif # endif
EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC), EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
"Which is: -1"); "\n Which is: -1");
} }
#endif // !GTEST_OS_MAC && !defined(__SUNPRO_CC) #endif // !GTEST_OS_MAC && !defined(__SUNPRO_CC)
@ -4384,7 +4383,7 @@ TEST(ExpectTest, ExpectFalseWithAssertionResult) {
} }
#ifdef __BORLANDC__ #ifdef __BORLANDC__
// Restores warnings after previous "#pragma option push" supressed them // Restores warnings after previous "#pragma option push" suppressed them
# pragma option pop # pragma option pop
#endif #endif
@ -4426,7 +4425,7 @@ TEST(ExpectTest, EXPECT_EQ_NULL) {
// A failure. // A failure.
int n = 0; int n = 0;
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(NULL, &n), EXPECT_NONFATAL_FAILURE(EXPECT_EQ(NULL, &n),
"&n\n"); " &n\n Which is:");
} }
#endif // GTEST_CAN_COMPARE_NULL #endif // GTEST_CAN_COMPARE_NULL
@ -4442,7 +4441,7 @@ TEST(ExpectTest, EXPECT_EQ_0) {
// A failure. // A failure.
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(0, 5.6), EXPECT_NONFATAL_FAILURE(EXPECT_EQ(0, 5.6),
"Expected equality of these values:\n 0\n 5.6"); " 0\n 5.6");
} }
// Tests EXPECT_NE. // Tests EXPECT_NE.
@ -4542,7 +4541,7 @@ TEST(ExpectTest, EXPECT_ANY_THROW) {
TEST(ExpectTest, ExpectPrecedence) { TEST(ExpectTest, ExpectPrecedence) {
EXPECT_EQ(1 < 2, true); EXPECT_EQ(1 < 2, true);
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(true, true && false), EXPECT_NONFATAL_FAILURE(EXPECT_EQ(true, true && false),
"true && false"); " true && false\n Which is: false");
} }
@ -4689,14 +4688,14 @@ TEST(EqAssertionTest, Bool) {
EXPECT_FATAL_FAILURE({ EXPECT_FATAL_FAILURE({
bool false_value = false; bool false_value = false;
ASSERT_EQ(false_value, true); ASSERT_EQ(false_value, true);
}, "Which is: false"); }, " false_value\n Which is: false\n true");
} }
// Tests using int values in {EXPECT|ASSERT}_EQ. // Tests using int values in {EXPECT|ASSERT}_EQ.
TEST(EqAssertionTest, Int) { TEST(EqAssertionTest, Int) {
ASSERT_EQ(32, 32); ASSERT_EQ(32, 32);
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(32, 33), EXPECT_NONFATAL_FAILURE(EXPECT_EQ(32, 33),
"33"); " 32\n 33");
} }
// Tests using time_t values in {EXPECT|ASSERT}_EQ. // Tests using time_t values in {EXPECT|ASSERT}_EQ.
@ -4713,9 +4712,9 @@ TEST(EqAssertionTest, Char) {
ASSERT_EQ('z', 'z'); ASSERT_EQ('z', 'z');
const char ch = 'b'; const char ch = 'b';
EXPECT_NONFATAL_FAILURE(EXPECT_EQ('\0', ch), EXPECT_NONFATAL_FAILURE(EXPECT_EQ('\0', ch),
"ch"); " ch\n Which is: 'b'");
EXPECT_NONFATAL_FAILURE(EXPECT_EQ('a', ch), EXPECT_NONFATAL_FAILURE(EXPECT_EQ('a', ch),
"ch"); " ch\n Which is: 'b'");
} }
// Tests using wchar_t values in {EXPECT|ASSERT}_EQ. // Tests using wchar_t values in {EXPECT|ASSERT}_EQ.
@ -4735,7 +4734,7 @@ TEST(EqAssertionTest, WideChar) {
"wchar"); "wchar");
wchar = 0x8119; wchar = 0x8119;
EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<wchar_t>(0x8120), wchar), EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<wchar_t>(0x8120), wchar),
"wchar"); " wchar\n Which is: L'");
} }
// Tests using ::std::string values in {EXPECT|ASSERT}_EQ. // Tests using ::std::string values in {EXPECT|ASSERT}_EQ.
@ -4764,8 +4763,7 @@ TEST(EqAssertionTest, StdString) {
static ::std::string str3(str1); static ::std::string str3(str1);
str3.at(2) = '\0'; str3.at(2) = '\0';
EXPECT_FATAL_FAILURE(ASSERT_EQ(str1, str3), EXPECT_FATAL_FAILURE(ASSERT_EQ(str1, str3),
" str3\n" " str3\n Which is: \"A \\0 in the middle\"");
" Which is: \"A \\0 in the middle\"");
} }
#if GTEST_HAS_STD_WSTRING #if GTEST_HAS_STD_WSTRING
@ -4885,9 +4883,9 @@ TEST(EqAssertionTest, CharPointer) {
ASSERT_EQ(p1, p1); ASSERT_EQ(p1, p1);
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2), EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2),
"p2"); " p2\n Which is:");
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2), EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2),
"p2"); " p2\n Which is:");
EXPECT_FATAL_FAILURE(ASSERT_EQ(reinterpret_cast<char*>(0x1234), EXPECT_FATAL_FAILURE(ASSERT_EQ(reinterpret_cast<char*>(0x1234),
reinterpret_cast<char*>(0xABC0)), reinterpret_cast<char*>(0xABC0)),
"ABC0"); "ABC0");
@ -4907,9 +4905,9 @@ TEST(EqAssertionTest, WideCharPointer) {
EXPECT_EQ(p0, p0); EXPECT_EQ(p0, p0);
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2), EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2),
"p2"); " p2\n Which is:");
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2), EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2),
"p2"); " p2\n Which is:");
void* pv3 = (void*)0x1234; // NOLINT void* pv3 = (void*)0x1234; // NOLINT
void* pv4 = (void*)0xABC0; // NOLINT void* pv4 = (void*)0xABC0; // NOLINT
const wchar_t* p3 = reinterpret_cast<const wchar_t*>(pv3); const wchar_t* p3 = reinterpret_cast<const wchar_t*>(pv3);
@ -5454,7 +5452,8 @@ TEST_F(SetUpTestCaseTest, Test2) {
EXPECT_STREQ("123", shared_resource_); EXPECT_STREQ("123", shared_resource_);
} }
// The InitGoogleTestTest test case tests testing::InitGoogleTest().
// The ParseFlagsTest test case tests ParseGoogleTestFlagsOnly.
// The Flags struct stores a copy of all Google Test flags. // The Flags struct stores a copy of all Google Test flags.
struct Flags { struct Flags {
@ -5540,8 +5539,8 @@ struct Flags {
return flags; return flags;
} }
// Creates a Flags struct where the gtest_random_seed flag has // Creates a Flags struct where the gtest_random_seed flag has the given
// the given value. // value.
static Flags RandomSeed(Int32 random_seed) { static Flags RandomSeed(Int32 random_seed) {
Flags flags; Flags flags;
flags.random_seed = random_seed; flags.random_seed = random_seed;
@ -5556,8 +5555,8 @@ struct Flags {
return flags; return flags;
} }
// Creates a Flags struct where the gtest_shuffle flag has // Creates a Flags struct where the gtest_shuffle flag has the given
// the given value. // value.
static Flags Shuffle(bool shuffle) { static Flags Shuffle(bool shuffle) {
Flags flags; Flags flags;
flags.shuffle = shuffle; flags.shuffle = shuffle;
@ -5605,8 +5604,8 @@ struct Flags {
bool throw_on_failure; bool throw_on_failure;
}; };
// Fixture for testing InitGoogleTest(). // Fixture for testing ParseGoogleTestFlagsOnly().
class InitGoogleTestTest : public Test { class ParseFlagsTest : public Test {
protected: protected:
// Clears the flags before each test. // Clears the flags before each test.
virtual void SetUp() { virtual void SetUp() {
@ -5713,7 +5712,7 @@ class InitGoogleTestTest : public Test {
}; };
// Tests parsing an empty command line. // Tests parsing an empty command line.
TEST_F(InitGoogleTestTest, Empty) { TEST_F(ParseFlagsTest, Empty) {
const char* argv[] = { const char* argv[] = {
NULL NULL
}; };
@ -5726,7 +5725,7 @@ TEST_F(InitGoogleTestTest, Empty) {
} }
// Tests parsing a command line that has no flag. // Tests parsing a command line that has no flag.
TEST_F(InitGoogleTestTest, NoFlag) { TEST_F(ParseFlagsTest, NoFlag) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
NULL NULL
@ -5741,7 +5740,7 @@ TEST_F(InitGoogleTestTest, NoFlag) {
} }
// Tests parsing a bad --gtest_filter flag. // Tests parsing a bad --gtest_filter flag.
TEST_F(InitGoogleTestTest, FilterBad) { TEST_F(ParseFlagsTest, FilterBad) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_filter", "--gtest_filter",
@ -5758,7 +5757,7 @@ TEST_F(InitGoogleTestTest, FilterBad) {
} }
// Tests parsing an empty --gtest_filter flag. // Tests parsing an empty --gtest_filter flag.
TEST_F(InitGoogleTestTest, FilterEmpty) { TEST_F(ParseFlagsTest, FilterEmpty) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_filter=", "--gtest_filter=",
@ -5774,7 +5773,7 @@ TEST_F(InitGoogleTestTest, FilterEmpty) {
} }
// Tests parsing a non-empty --gtest_filter flag. // Tests parsing a non-empty --gtest_filter flag.
TEST_F(InitGoogleTestTest, FilterNonEmpty) { TEST_F(ParseFlagsTest, FilterNonEmpty) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_filter=abc", "--gtest_filter=abc",
@ -5790,7 +5789,7 @@ TEST_F(InitGoogleTestTest, FilterNonEmpty) {
} }
// Tests parsing --gtest_break_on_failure. // Tests parsing --gtest_break_on_failure.
TEST_F(InitGoogleTestTest, BreakOnFailureWithoutValue) { TEST_F(ParseFlagsTest, BreakOnFailureWithoutValue) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_break_on_failure", "--gtest_break_on_failure",
@ -5806,7 +5805,7 @@ TEST_F(InitGoogleTestTest, BreakOnFailureWithoutValue) {
} }
// Tests parsing --gtest_break_on_failure=0. // Tests parsing --gtest_break_on_failure=0.
TEST_F(InitGoogleTestTest, BreakOnFailureFalse_0) { TEST_F(ParseFlagsTest, BreakOnFailureFalse_0) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_break_on_failure=0", "--gtest_break_on_failure=0",
@ -5822,7 +5821,7 @@ TEST_F(InitGoogleTestTest, BreakOnFailureFalse_0) {
} }
// Tests parsing --gtest_break_on_failure=f. // Tests parsing --gtest_break_on_failure=f.
TEST_F(InitGoogleTestTest, BreakOnFailureFalse_f) { TEST_F(ParseFlagsTest, BreakOnFailureFalse_f) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_break_on_failure=f", "--gtest_break_on_failure=f",
@ -5838,7 +5837,7 @@ TEST_F(InitGoogleTestTest, BreakOnFailureFalse_f) {
} }
// Tests parsing --gtest_break_on_failure=F. // Tests parsing --gtest_break_on_failure=F.
TEST_F(InitGoogleTestTest, BreakOnFailureFalse_F) { TEST_F(ParseFlagsTest, BreakOnFailureFalse_F) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_break_on_failure=F", "--gtest_break_on_failure=F",
@ -5855,7 +5854,7 @@ TEST_F(InitGoogleTestTest, BreakOnFailureFalse_F) {
// Tests parsing a --gtest_break_on_failure flag that has a "true" // Tests parsing a --gtest_break_on_failure flag that has a "true"
// definition. // definition.
TEST_F(InitGoogleTestTest, BreakOnFailureTrue) { TEST_F(ParseFlagsTest, BreakOnFailureTrue) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_break_on_failure=1", "--gtest_break_on_failure=1",
@ -5871,7 +5870,7 @@ TEST_F(InitGoogleTestTest, BreakOnFailureTrue) {
} }
// Tests parsing --gtest_catch_exceptions. // Tests parsing --gtest_catch_exceptions.
TEST_F(InitGoogleTestTest, CatchExceptions) { TEST_F(ParseFlagsTest, CatchExceptions) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_catch_exceptions", "--gtest_catch_exceptions",
@ -5887,7 +5886,7 @@ TEST_F(InitGoogleTestTest, CatchExceptions) {
} }
// Tests parsing --gtest_death_test_use_fork. // Tests parsing --gtest_death_test_use_fork.
TEST_F(InitGoogleTestTest, DeathTestUseFork) { TEST_F(ParseFlagsTest, DeathTestUseFork) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_death_test_use_fork", "--gtest_death_test_use_fork",
@ -5904,7 +5903,7 @@ TEST_F(InitGoogleTestTest, DeathTestUseFork) {
// Tests having the same flag twice with different values. The // Tests having the same flag twice with different values. The
// expected behavior is that the one coming last takes precedence. // expected behavior is that the one coming last takes precedence.
TEST_F(InitGoogleTestTest, DuplicatedFlags) { TEST_F(ParseFlagsTest, DuplicatedFlags) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_filter=a", "--gtest_filter=a",
@ -5921,7 +5920,7 @@ TEST_F(InitGoogleTestTest, DuplicatedFlags) {
} }
// Tests having an unrecognized flag on the command line. // Tests having an unrecognized flag on the command line.
TEST_F(InitGoogleTestTest, UnrecognizedFlag) { TEST_F(ParseFlagsTest, UnrecognizedFlag) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_break_on_failure", "--gtest_break_on_failure",
@ -5943,7 +5942,7 @@ TEST_F(InitGoogleTestTest, UnrecognizedFlag) {
} }
// Tests having a --gtest_list_tests flag // Tests having a --gtest_list_tests flag
TEST_F(InitGoogleTestTest, ListTestsFlag) { TEST_F(ParseFlagsTest, ListTestsFlag) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_list_tests", "--gtest_list_tests",
@ -5959,7 +5958,7 @@ TEST_F(InitGoogleTestTest, ListTestsFlag) {
} }
// Tests having a --gtest_list_tests flag with a "true" value // Tests having a --gtest_list_tests flag with a "true" value
TEST_F(InitGoogleTestTest, ListTestsTrue) { TEST_F(ParseFlagsTest, ListTestsTrue) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_list_tests=1", "--gtest_list_tests=1",
@ -5975,7 +5974,7 @@ TEST_F(InitGoogleTestTest, ListTestsTrue) {
} }
// Tests having a --gtest_list_tests flag with a "false" value // Tests having a --gtest_list_tests flag with a "false" value
TEST_F(InitGoogleTestTest, ListTestsFalse) { TEST_F(ParseFlagsTest, ListTestsFalse) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_list_tests=0", "--gtest_list_tests=0",
@ -5991,7 +5990,7 @@ TEST_F(InitGoogleTestTest, ListTestsFalse) {
} }
// Tests parsing --gtest_list_tests=f. // Tests parsing --gtest_list_tests=f.
TEST_F(InitGoogleTestTest, ListTestsFalse_f) { TEST_F(ParseFlagsTest, ListTestsFalse_f) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_list_tests=f", "--gtest_list_tests=f",
@ -6007,7 +6006,7 @@ TEST_F(InitGoogleTestTest, ListTestsFalse_f) {
} }
// Tests parsing --gtest_list_tests=F. // Tests parsing --gtest_list_tests=F.
TEST_F(InitGoogleTestTest, ListTestsFalse_F) { TEST_F(ParseFlagsTest, ListTestsFalse_F) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_list_tests=F", "--gtest_list_tests=F",
@ -6023,7 +6022,7 @@ TEST_F(InitGoogleTestTest, ListTestsFalse_F) {
} }
// Tests parsing --gtest_output (invalid). // Tests parsing --gtest_output (invalid).
TEST_F(InitGoogleTestTest, OutputEmpty) { TEST_F(ParseFlagsTest, OutputEmpty) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_output", "--gtest_output",
@ -6040,7 +6039,7 @@ TEST_F(InitGoogleTestTest, OutputEmpty) {
} }
// Tests parsing --gtest_output=xml // Tests parsing --gtest_output=xml
TEST_F(InitGoogleTestTest, OutputXml) { TEST_F(ParseFlagsTest, OutputXml) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_output=xml", "--gtest_output=xml",
@ -6056,7 +6055,7 @@ TEST_F(InitGoogleTestTest, OutputXml) {
} }
// Tests parsing --gtest_output=xml:file // Tests parsing --gtest_output=xml:file
TEST_F(InitGoogleTestTest, OutputXmlFile) { TEST_F(ParseFlagsTest, OutputXmlFile) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_output=xml:file", "--gtest_output=xml:file",
@ -6072,7 +6071,7 @@ TEST_F(InitGoogleTestTest, OutputXmlFile) {
} }
// Tests parsing --gtest_output=xml:directory/path/ // Tests parsing --gtest_output=xml:directory/path/
TEST_F(InitGoogleTestTest, OutputXmlDirectory) { TEST_F(ParseFlagsTest, OutputXmlDirectory) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_output=xml:directory/path/", "--gtest_output=xml:directory/path/",
@ -6089,7 +6088,7 @@ TEST_F(InitGoogleTestTest, OutputXmlDirectory) {
} }
// Tests having a --gtest_print_time flag // Tests having a --gtest_print_time flag
TEST_F(InitGoogleTestTest, PrintTimeFlag) { TEST_F(ParseFlagsTest, PrintTimeFlag) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_print_time", "--gtest_print_time",
@ -6105,7 +6104,7 @@ TEST_F(InitGoogleTestTest, PrintTimeFlag) {
} }
// Tests having a --gtest_print_time flag with a "true" value // Tests having a --gtest_print_time flag with a "true" value
TEST_F(InitGoogleTestTest, PrintTimeTrue) { TEST_F(ParseFlagsTest, PrintTimeTrue) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_print_time=1", "--gtest_print_time=1",
@ -6121,7 +6120,7 @@ TEST_F(InitGoogleTestTest, PrintTimeTrue) {
} }
// Tests having a --gtest_print_time flag with a "false" value // Tests having a --gtest_print_time flag with a "false" value
TEST_F(InitGoogleTestTest, PrintTimeFalse) { TEST_F(ParseFlagsTest, PrintTimeFalse) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_print_time=0", "--gtest_print_time=0",
@ -6137,7 +6136,7 @@ TEST_F(InitGoogleTestTest, PrintTimeFalse) {
} }
// Tests parsing --gtest_print_time=f. // Tests parsing --gtest_print_time=f.
TEST_F(InitGoogleTestTest, PrintTimeFalse_f) { TEST_F(ParseFlagsTest, PrintTimeFalse_f) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_print_time=f", "--gtest_print_time=f",
@ -6153,7 +6152,7 @@ TEST_F(InitGoogleTestTest, PrintTimeFalse_f) {
} }
// Tests parsing --gtest_print_time=F. // Tests parsing --gtest_print_time=F.
TEST_F(InitGoogleTestTest, PrintTimeFalse_F) { TEST_F(ParseFlagsTest, PrintTimeFalse_F) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_print_time=F", "--gtest_print_time=F",
@ -6169,7 +6168,7 @@ TEST_F(InitGoogleTestTest, PrintTimeFalse_F) {
} }
// Tests parsing --gtest_random_seed=number // Tests parsing --gtest_random_seed=number
TEST_F(InitGoogleTestTest, RandomSeed) { TEST_F(ParseFlagsTest, RandomSeed) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_random_seed=1000", "--gtest_random_seed=1000",
@ -6185,7 +6184,7 @@ TEST_F(InitGoogleTestTest, RandomSeed) {
} }
// Tests parsing --gtest_repeat=number // Tests parsing --gtest_repeat=number
TEST_F(InitGoogleTestTest, Repeat) { TEST_F(ParseFlagsTest, Repeat) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_repeat=1000", "--gtest_repeat=1000",
@ -6201,7 +6200,7 @@ TEST_F(InitGoogleTestTest, Repeat) {
} }
// Tests having a --gtest_also_run_disabled_tests flag // Tests having a --gtest_also_run_disabled_tests flag
TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsFlag) { TEST_F(ParseFlagsTest, AlsoRunDisabledTestsFlag) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_also_run_disabled_tests", "--gtest_also_run_disabled_tests",
@ -6218,7 +6217,7 @@ TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsFlag) {
} }
// Tests having a --gtest_also_run_disabled_tests flag with a "true" value // Tests having a --gtest_also_run_disabled_tests flag with a "true" value
TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsTrue) { TEST_F(ParseFlagsTest, AlsoRunDisabledTestsTrue) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_also_run_disabled_tests=1", "--gtest_also_run_disabled_tests=1",
@ -6235,7 +6234,7 @@ TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsTrue) {
} }
// Tests having a --gtest_also_run_disabled_tests flag with a "false" value // Tests having a --gtest_also_run_disabled_tests flag with a "false" value
TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsFalse) { TEST_F(ParseFlagsTest, AlsoRunDisabledTestsFalse) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_also_run_disabled_tests=0", "--gtest_also_run_disabled_tests=0",
@ -6252,7 +6251,7 @@ TEST_F(InitGoogleTestTest, AlsoRunDisabledTestsFalse) {
} }
// Tests parsing --gtest_shuffle. // Tests parsing --gtest_shuffle.
TEST_F(InitGoogleTestTest, ShuffleWithoutValue) { TEST_F(ParseFlagsTest, ShuffleWithoutValue) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_shuffle", "--gtest_shuffle",
@ -6268,7 +6267,7 @@ TEST_F(InitGoogleTestTest, ShuffleWithoutValue) {
} }
// Tests parsing --gtest_shuffle=0. // Tests parsing --gtest_shuffle=0.
TEST_F(InitGoogleTestTest, ShuffleFalse_0) { TEST_F(ParseFlagsTest, ShuffleFalse_0) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_shuffle=0", "--gtest_shuffle=0",
@ -6283,9 +6282,8 @@ TEST_F(InitGoogleTestTest, ShuffleFalse_0) {
GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(false), false); GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(false), false);
} }
// Tests parsing a --gtest_shuffle flag that has a "true" // Tests parsing a --gtest_shuffle flag that has a "true" definition.
// definition. TEST_F(ParseFlagsTest, ShuffleTrue) {
TEST_F(InitGoogleTestTest, ShuffleTrue) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_shuffle=1", "--gtest_shuffle=1",
@ -6301,7 +6299,7 @@ TEST_F(InitGoogleTestTest, ShuffleTrue) {
} }
// Tests parsing --gtest_stack_trace_depth=number. // Tests parsing --gtest_stack_trace_depth=number.
TEST_F(InitGoogleTestTest, StackTraceDepth) { TEST_F(ParseFlagsTest, StackTraceDepth) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_stack_trace_depth=5", "--gtest_stack_trace_depth=5",
@ -6316,7 +6314,7 @@ TEST_F(InitGoogleTestTest, StackTraceDepth) {
GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::StackTraceDepth(5), false); GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::StackTraceDepth(5), false);
} }
TEST_F(InitGoogleTestTest, StreamResultTo) { TEST_F(ParseFlagsTest, StreamResultTo) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_stream_result_to=localhost:1234", "--gtest_stream_result_to=localhost:1234",
@ -6333,7 +6331,7 @@ TEST_F(InitGoogleTestTest, StreamResultTo) {
} }
// Tests parsing --gtest_throw_on_failure. // Tests parsing --gtest_throw_on_failure.
TEST_F(InitGoogleTestTest, ThrowOnFailureWithoutValue) { TEST_F(ParseFlagsTest, ThrowOnFailureWithoutValue) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_throw_on_failure", "--gtest_throw_on_failure",
@ -6349,7 +6347,7 @@ TEST_F(InitGoogleTestTest, ThrowOnFailureWithoutValue) {
} }
// Tests parsing --gtest_throw_on_failure=0. // Tests parsing --gtest_throw_on_failure=0.
TEST_F(InitGoogleTestTest, ThrowOnFailureFalse_0) { TEST_F(ParseFlagsTest, ThrowOnFailureFalse_0) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_throw_on_failure=0", "--gtest_throw_on_failure=0",
@ -6366,7 +6364,7 @@ TEST_F(InitGoogleTestTest, ThrowOnFailureFalse_0) {
// Tests parsing a --gtest_throw_on_failure flag that has a "true" // Tests parsing a --gtest_throw_on_failure flag that has a "true"
// definition. // definition.
TEST_F(InitGoogleTestTest, ThrowOnFailureTrue) { TEST_F(ParseFlagsTest, ThrowOnFailureTrue) {
const char* argv[] = { const char* argv[] = {
"foo.exe", "foo.exe",
"--gtest_throw_on_failure=1", "--gtest_throw_on_failure=1",
@ -6383,7 +6381,7 @@ TEST_F(InitGoogleTestTest, ThrowOnFailureTrue) {
# if GTEST_OS_WINDOWS # if GTEST_OS_WINDOWS
// Tests parsing wide strings. // Tests parsing wide strings.
TEST_F(InitGoogleTestTest, WideStrings) { TEST_F(ParseFlagsTest, WideStrings) {
const wchar_t* argv[] = { const wchar_t* argv[] = {
L"foo.exe", L"foo.exe",
L"--gtest_filter=Foo*", L"--gtest_filter=Foo*",
@ -6409,10 +6407,10 @@ TEST_F(InitGoogleTestTest, WideStrings) {
# endif // GTEST_OS_WINDOWS # endif // GTEST_OS_WINDOWS
#if GTEST_USE_OWN_FLAGFILE_FLAG_ #if GTEST_USE_OWN_FLAGFILE_FLAG_
class FlagfileTest : public InitGoogleTestTest { class FlagfileTest : public ParseFlagsTest {
public: public:
virtual void SetUp() { virtual void SetUp() {
InitGoogleTestTest::SetUp(); ParseFlagsTest::SetUp();
testdata_path_.Set(internal::FilePath( testdata_path_.Set(internal::FilePath(
testing::TempDir() + internal::GetCurrentExecutableName().string() + testing::TempDir() + internal::GetCurrentExecutableName().string() +
@ -6423,7 +6421,7 @@ class FlagfileTest : public InitGoogleTestTest {
virtual void TearDown() { virtual void TearDown() {
testing::internal::posix::RmDir(testdata_path_.c_str()); testing::internal::posix::RmDir(testdata_path_.c_str());
InitGoogleTestTest::TearDown(); ParseFlagsTest::TearDown();
} }
internal::FilePath CreateFlagfile(const char* contents) { internal::FilePath CreateFlagfile(const char* contents) {
@ -6562,6 +6560,7 @@ TEST_F(CurrentTestInfoTest, WorksForSecondTestInATestCase) {
} // namespace testing } // namespace testing
// These two lines test that we can define tests in a namespace that // These two lines test that we can define tests in a namespace that
// has the name "testing" and is nested in another namespace. // has the name "testing" and is nested in another namespace.
namespace my_namespace { namespace my_namespace {
@ -6642,7 +6641,7 @@ TEST(StreamingAssertionsTest, Truth2) {
} }
#ifdef __BORLANDC__ #ifdef __BORLANDC__
// Restores warnings after previous "#pragma option push" supressed them // Restores warnings after previous "#pragma option push" suppressed them
# pragma option pop # pragma option pop
#endif #endif
@ -6892,14 +6891,6 @@ TEST(StaticAssertTypeEqTest, CompilesForEqualTypes) {
StaticAssertTypeEq<int*, IntAlias*>(); StaticAssertTypeEq<int*, IntAlias*>();
} }
TEST(GetCurrentOsStackTraceExceptTopTest, ReturnsTheStackTrace) {
testing::UnitTest* const unit_test = testing::UnitTest::GetInstance();
// We don't have a stack walker in Google Test yet.
EXPECT_STREQ("", GetCurrentOsStackTraceExceptTop(unit_test, 0).c_str());
EXPECT_STREQ("", GetCurrentOsStackTraceExceptTop(unit_test, 1).c_str());
}
TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsNoFailure) { TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsNoFailure) {
EXPECT_FALSE(HasNonfatalFailure()); EXPECT_FALSE(HasNonfatalFailure());
} }
@ -7659,7 +7650,7 @@ TEST(NativeArrayTest, MethodsWork) {
EXPECT_EQ(0, *it); EXPECT_EQ(0, *it);
++it; ++it;
EXPECT_EQ(1, *it); EXPECT_EQ(1, *it);
++it; it++;
EXPECT_EQ(2, *it); EXPECT_EQ(2, *it);
++it; ++it;
EXPECT_EQ(na.end(), it); EXPECT_EQ(na.end(), it);

View File

@ -43,7 +43,13 @@ GTEST_OUTPUT_2_TEST = "gtest_xml_outfile2_test_"
EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?> EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests"> <testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
<testsuite name="PropertyOne" tests="1" failures="0" disabled="0" errors="0" time="*"> <testsuite name="PropertyOne" tests="1" failures="0" disabled="0" errors="0" time="*">
<testcase name="TestSomeProperties" status="run" time="*" classname="PropertyOne" SetUpProp="1" TestSomeProperty="1" TearDownProp="1" /> <testcase name="TestSomeProperties" status="run" time="*" classname="PropertyOne">
<properties>
<property name="SetUpProp" value="1"/>
<property name="TestSomeProperty" value="1"/>
<property name="TearDownProp" value="1"/>
</properties>
</testcase>
</testsuite> </testsuite>
</testsuites> </testsuites>
""" """
@ -51,7 +57,13 @@ EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?>
EXPECTED_XML_2 = """<?xml version="1.0" encoding="UTF-8"?> EXPECTED_XML_2 = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests"> <testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
<testsuite name="PropertyTwo" tests="1" failures="0" disabled="0" errors="0" time="*"> <testsuite name="PropertyTwo" tests="1" failures="0" disabled="0" errors="0" time="*">
<testcase name="TestSomeProperties" status="run" time="*" classname="PropertyTwo" SetUpProp="2" TestSomeProperty="2" TearDownProp="2" /> <testcase name="TestSomeProperties" status="run" time="*" classname="PropertyTwo">
<properties>
<property name="SetUpProp" value="2"/>
<property name="TestSomeProperty" value="2"/>
<property name="TearDownProp" value="2"/>
</properties>
</testcase>
</testsuite> </testsuite>
</testsuites> </testsuites>
""" """

View File

@ -104,15 +104,45 @@ Invalid characters in brackets []%(stack)s]]></failure>
<testcase name="DISABLED_test_not_run" status="notrun" time="*" classname="DisabledTest"/> <testcase name="DISABLED_test_not_run" status="notrun" time="*" classname="DisabledTest"/>
</testsuite> </testsuite>
<testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" errors="0" time="*" SetUpTestCase="yes" TearDownTestCase="aye"> <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" errors="0" time="*" SetUpTestCase="yes" TearDownTestCase="aye">
<testcase name="OneProperty" status="run" time="*" classname="PropertyRecordingTest" key_1="1"/> <testcase name="OneProperty" status="run" time="*" classname="PropertyRecordingTest">
<testcase name="IntValuedProperty" status="run" time="*" classname="PropertyRecordingTest" key_int="1"/> <properties>
<testcase name="ThreeProperties" status="run" time="*" classname="PropertyRecordingTest" key_1="1" key_2="2" key_3="3"/> <property name="key_1" value="1"/>
<testcase name="TwoValuesForOneKeyUsesLastValue" status="run" time="*" classname="PropertyRecordingTest" key_1="2"/> </properties>
</testcase>
<testcase name="IntValuedProperty" status="run" time="*" classname="PropertyRecordingTest">
<properties>
<property name="key_int" value="1"/>
</properties>
</testcase>
<testcase name="ThreeProperties" status="run" time="*" classname="PropertyRecordingTest">
<properties>
<property name="key_1" value="1"/>
<property name="key_2" value="2"/>
<property name="key_3" value="3"/>
</properties>
</testcase>
<testcase name="TwoValuesForOneKeyUsesLastValue" status="run" time="*" classname="PropertyRecordingTest">
<properties>
<property name="key_1" value="2"/>
</properties>
</testcase>
</testsuite> </testsuite>
<testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" errors="0" time="*"> <testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" errors="0" time="*">
<testcase name="RecordProperty" status="run" time="*" classname="NoFixtureTest" key="1"/> <testcase name="RecordProperty" status="run" time="*" classname="NoFixtureTest">
<testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" status="run" time="*" classname="NoFixtureTest" key_for_utility_int="1"/> <properties>
<testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" status="run" time="*" classname="NoFixtureTest" key_for_utility_string="1"/> <property name="key" value="1"/>
</properties>
</testcase>
<testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" status="run" time="*" classname="NoFixtureTest">
<properties>
<property name="key_for_utility_int" value="1"/>
</properties>
</testcase>
<testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" status="run" time="*" classname="NoFixtureTest">
<properties>
<property name="key_for_utility_string" value="1"/>
</properties>
</testcase>
</testsuite> </testsuite>
<testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" errors="0" time="*"> <testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" errors="0" time="*">
<testcase name="HasValueParamAttribute/0" value_param="33" status="run" time="*" classname="Single/ValueParamTest" /> <testcase name="HasValueParamAttribute/0" value_param="33" status="run" time="*" classname="Single/ValueParamTest" />
@ -149,7 +179,11 @@ EXPECTED_SHARDED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/> <testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/>
</testsuite> </testsuite>
<testsuite name="NoFixtureTest" tests="1" failures="0" disabled="0" errors="0" time="*"> <testsuite name="NoFixtureTest" tests="1" failures="0" disabled="0" errors="0" time="*">
<testcase name="RecordProperty" status="run" time="*" classname="NoFixtureTest" key="1"/> <testcase name="RecordProperty" status="run" time="*" classname="NoFixtureTest">
<properties>
<property name="key" value="1"/>
</properties>
</testcase>
</testsuite> </testsuite>
<testsuite name="Single/ValueParamTest" tests="1" failures="0" disabled="0" errors="0" time="*"> <testsuite name="Single/ValueParamTest" tests="1" failures="0" disabled="0" errors="0" time="*">
<testcase name="AnotherTestThatHasValueParamAttribute/1" value_param="42" status="run" time="*" classname="Single/ValueParamTest" /> <testcase name="AnotherTestThatHasValueParamAttribute/1" value_param="42" status="run" time="*" classname="Single/ValueParamTest" />

View File

@ -105,15 +105,18 @@ class GTestXMLTestCase(gtest_test_utils.TestCase):
'testsuite': 'name', 'testsuite': 'name',
'testcase': 'name', 'testcase': 'name',
'failure': 'message', 'failure': 'message',
'property': 'name',
} }
def _GetChildren(self, element): def _GetChildren(self, element):
""" """
Fetches all of the child nodes of element, a DOM Element object. Fetches all of the child nodes of element, a DOM Element object.
Returns them as the values of a dictionary keyed by the IDs of the Returns them as the values of a dictionary keyed by the IDs of the
children. For <testsuites>, <testsuite> and <testcase> elements, the ID children. For <testsuites>, <testsuite>, <testcase>, and <property>
is the value of their "name" attribute; for <failure> elements, it is elements, the ID is the value of their "name" attribute; for <failure>
the value of the "message" attribute; CDATA sections and non-whitespace elements, it is the value of the "message" attribute; for <properties>
elements, it is the value of their parent's "name" attribute plus the
literal string "properties"; CDATA sections and non-whitespace
text nodes are concatenated into a single CDATA section with ID text nodes are concatenated into a single CDATA section with ID
"detail". An exception is raised if any element other than the above "detail". An exception is raised if any element other than the above
four is encountered, if two child elements with the same identifying four is encountered, if two child elements with the same identifying
@ -123,11 +126,17 @@ class GTestXMLTestCase(gtest_test_utils.TestCase):
children = {} children = {}
for child in element.childNodes: for child in element.childNodes:
if child.nodeType == Node.ELEMENT_NODE: if child.nodeType == Node.ELEMENT_NODE:
if child.tagName == 'properties':
self.assert_(child.parentNode is not None,
'Encountered <properties> element without a parent')
child_id = child.parentNode.getAttribute('name') + '-properties'
else:
self.assert_(child.tagName in self.identifying_attribute, self.assert_(child.tagName in self.identifying_attribute,
'Encountered unknown element <%s>' % child.tagName) 'Encountered unknown element <%s>' % child.tagName)
childID = child.getAttribute(self.identifying_attribute[child.tagName]) child_id = child.getAttribute(
self.assert_(childID not in children) self.identifying_attribute[child.tagName])
children[childID] = child self.assert_(child_id not in children)
children[child_id] = child
elif child.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]: elif child.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]:
if 'detail' not in children: if 'detail' not in children:
if (child.nodeType == Node.CDATA_SECTION_NODE or if (child.nodeType == Node.CDATA_SECTION_NODE or

View File

@ -29,7 +29,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""A script to prepare version informtion for use the gtest Info.plist file. """A script to prepare version information for use the gtest Info.plist file.
This script extracts the version information from the configure.ac file and This script extracts the version information from the configure.ac file and
uses it to generate a header file containing the same information. The uses it to generate a header file containing the same information. The