Unverified Commit fc437ef4 authored by Bernhard Bauer's avatar Bernhard Bauer Committed by GitHub
Browse files

Merge branch 'master' into upstream_188748737

parents 7b70413e abc6e943
...@@ -46,6 +46,12 @@ config_setting( ...@@ -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( ...@@ -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(
......
...@@ -103,7 +103,7 @@ package (as described below): ...@@ -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 ###
......
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",
)
...@@ -15,25 +15,11 @@ environment: ...@@ -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: ...@@ -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"
} }
......
...@@ -33,3 +33,4 @@ set -e ...@@ -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
...@@ -178,6 +178,8 @@ divided into several categories: ...@@ -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.|
......
...@@ -1231,7 +1231,7 @@ that references the implementation object dies, the implementation ...@@ -1231,7 +1231,7 @@ that references the implementation object dies, the implementation
object will be deleted. object will be deleted.
Therefore, if you have some complex matcher that you want to use again Therefore, if you have some complex matcher that you want to use again
and again, there is no need to build it everytime. Just assign it to a and again, there is no need to build it every time. Just assign it to a
matcher variable and use that variable repeatedly! For example, matcher variable and use that variable repeatedly! For example,
``` ```
...@@ -1403,7 +1403,7 @@ edge from node A to node B wherever A must occur before B, we can get ...@@ -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
...@@ -2182,7 +2182,7 @@ the implementation object dies, the implementation object will be ...@@ -2182,7 +2182,7 @@ the implementation object dies, the implementation object will be
deleted. deleted.
If you have some complex action that you want to use again and again, If you have some complex action that you want to use again and again,
you may not have to build it from scratch everytime. If the action you may not have to build it from scratch every time. If the action
doesn't have an internal state (i.e. if it always does the same thing doesn't have an internal state (i.e. if it always does the same thing
no matter how many times it has been called), you can assign it to an no matter how many times it has been called), you can assign it to an
action variable and use that variable repeatedly. For example: action variable and use that variable repeatedly. For example:
......
...@@ -47,10 +47,9 @@ ...@@ -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> ...@@ -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> { ...@@ -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 { ...@@ -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; ...@@ -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 { ...@@ -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 { ...@@ -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 ...@@ -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 ...@@ -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()) {
// The element count doesn't match. If the container is empty, if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
// there's no need to explain anything as Google Mock already if (matrix.LhsSize() != matrix.RhsSize()) {
// prints the empty container. Otherwise we just need to show // The element count doesn't match. If the container is empty,
// how many elements there actually are. // there's no need to explain anything as Google Mock already
if (actual_count != 0 && listener->IsInterested()) { // prints the empty container. Otherwise we just need to show
*listener << "which has " << Elements(actual_count); // how many elements there actually are.
if (matrix.LhsSize() != 0 && listener->IsInterested()) {
*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 ...@@ -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 { ...@@ -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 { ...@@ -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( ...@@ -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, ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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,
......
...@@ -53,6 +53,22 @@ MATCHER(IsEmpty, negation ? "isn't empty" : "is empty") { ...@@ -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_
...@@ -65,11 +65,6 @@ ...@@ -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 @@ ...@@ -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.
......
...@@ -59,8 +59,8 @@ ...@@ -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"
......
...@@ -33,7 +33,6 @@ ...@@ -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_
...@@ -90,42 +90,48 @@ struct MatcherTuple< ::testing::tuple<A1, A2, A3> > { ...@@ -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, ...@@ -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
......
...@@ -41,7 +41,6 @@ ...@@ -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 @@ ...@@ -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 { ...@@ -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> > { ...@@ -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_
...@@ -50,15 +50,11 @@ ...@@ -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
...@@ -72,18 +68,18 @@ ...@@ -72,18 +68,18 @@
#if !defined(GMOCK_DECLARE_bool_) #if !defined(GMOCK_DECLARE_bool_)
// Macros for declaring flags. // Macros for declaring flags.
#define GMOCK_DECLARE_bool_(name) extern GTEST_API_ bool GMOCK_FLAG(name) # define GMOCK_DECLARE_bool_(name) extern GTEST_API_ bool GMOCK_FLAG(name)
#define GMOCK_DECLARE_int32_(name) \ # define GMOCK_DECLARE_int32_(name) \
extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name)
#define GMOCK_DECLARE_string_(name) \ # define GMOCK_DECLARE_string_(name) \
extern GTEST_API_ ::std::string GMOCK_FLAG(name) extern GTEST_API_ ::std::string GMOCK_FLAG(name)
// Macros for defining flags. // Macros for defining flags.
#define GMOCK_DEFINE_bool_(name, default_val, doc) \ # define GMOCK_DEFINE_bool_(name, default_val, doc) \
GTEST_API_ bool GMOCK_FLAG(name) = (default_val) GTEST_API_ bool GMOCK_FLAG(name) = (default_val)
#define GMOCK_DEFINE_int32_(name, default_val, doc) \ # define GMOCK_DEFINE_int32_(name, default_val, doc) \
GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val) GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val)
#define GMOCK_DEFINE_string_(name, default_val, doc) \ # define GMOCK_DEFINE_string_(name, default_val, doc) \
GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val) GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val)
#endif // !defined(GMOCK_DECLARE_bool_) #endif // !defined(GMOCK_DECLARE_bool_)
......
...@@ -338,7 +338,7 @@ class Class(_GenericDeclaration): ...@@ -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): ...@@ -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): ...@@ -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)
......
...@@ -47,12 +47,31 @@ ...@@ -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, ...@@ -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
...@@ -38,6 +38,7 @@ ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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();
} }
...@@ -314,7 +292,7 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs, ...@@ -314,7 +292,7 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
typedef ElementMatcherPairs::const_iterator Iter; typedef ElementMatcherPairs::const_iterator Iter;
::std::ostream& os = *stream; ::std::ostream& os = *stream;
os << "{"; os << "{";
const char *sep = ""; const char* sep = "";
for (Iter it = pairs.begin(); it != pairs.end(); ++it) { for (Iter it = pairs.begin(); it != pairs.end(); ++it) {
os << sep << "\n (" os << sep << "\n ("
<< "element #" << it->first << ", " << "element #" << it->first << ", "
...@@ -324,38 +302,6 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs, ...@@ -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) {
...@@ -381,7 +327,7 @@ void MatchMatrix::Randomize() { ...@@ -381,7 +327,7 @@ void MatchMatrix::Randomize() {
std::string MatchMatrix::DebugString() const { std::string MatchMatrix::DebugString() const {
::std::stringstream ss; ::std::stringstream ss;
const char *sep = ""; const char* sep = "";
for (size_t i = 0; i < LhsSize(); ++i) { for (size_t i = 0; i < LhsSize(); ++i) {
ss << sep; ss << sep;
for (size_t j = 0; j < RhsSize(); ++j) { for (size_t j = 0; j < RhsSize(); ++j) {
...@@ -394,44 +340,83 @@ std::string MatchMatrix::DebugString() const { ...@@ -394,44 +340,83 @@ std::string MatchMatrix::DebugString() const {
void UnorderedElementsAreMatcherImplBase::DescribeToImpl( void UnorderedElementsAreMatcherImplBase::DescribeToImpl(
::std::ostream* os) const { ::std::ostream* os) const {
if (matcher_describers_.empty()) { switch (match_flags()) {
*os << "is empty"; case UnorderedMatcherRequire::ExactMatch:
return; if (matcher_describers_.empty()) {
} *os << "is empty";
if (matcher_describers_.size() == 1) { return;
*os << "has " << Elements(1) << " and that element "; }
matcher_describers_[0]->DescribeTo(os); if (matcher_describers_.size() == 1) {
return; *os << "has " << Elements(1) << " and that element ";
matcher_describers_[0]->DescribeTo(os);
return;
}
*os << "has " << Elements(matcher_describers_.size())
<< " 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;
} }
*os << "has " << Elements(matcher_describers_.size())
<< " and there exists some permutation of elements such that:\n";
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);
sep = ", and\n"; if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
sep = ", and\n";
} else {
sep = "\n";
}
} }
} }
void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl( void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
::std::ostream* os) const { ::std::ostream* os) const {
if (matcher_describers_.empty()) { switch (match_flags()) {
*os << "isn't empty"; case UnorderedMatcherRequire::ExactMatch:
return; if (matcher_describers_.empty()) {
} *os << "isn't empty";
if (matcher_describers_.size() == 1) { return;
*os << "doesn't have " << Elements(1) }
<< ", or has " << Elements(1) << " that "; if (matcher_describers_.size() == 1) {
matcher_describers_[0]->DescribeNegationTo(os); *os << "doesn't have " << Elements(1) << ", or has " << Elements(1)
return; << " that ";
matcher_describers_[0]->DescribeNegationTo(os);
return;
}
*os << "doesn't have " << Elements(matcher_describers_.size())
<< ", 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;
} }
*os << "doesn't have " << Elements(matcher_describers_.size())
<< ", or there exists no permutation of elements such that:\n";
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);
sep = ", and\n"; if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
sep = ", and\n";
} else {
sep = "\n";
}
} }
} }
...@@ -440,10 +425,9 @@ void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl( ...@@ -440,10 +425,9 @@ 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;
::std::vector<char> element_matched(matrix.LhsSize(), 0); ::std::vector<char> element_matched(matrix.LhsSize(), 0);
::std::vector<char> matcher_matched(matrix.RhsSize(), 0); ::std::vector<char> matcher_matched(matrix.RhsSize(), 0);
...@@ -456,12 +440,11 @@ bool UnorderedElementsAreMatcherImplBase:: ...@@ -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:: ...@@ -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:: ...@@ -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:: ...@@ -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
...@@ -136,8 +136,8 @@ static bool ParseGoogleMockIntFlag(const char* str, const char* flag, ...@@ -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().
......
# Copyright 2017 Google Inc. # Copyright 2017 Google Inc.
# All Rights Reserved. # All Rights Reserved.
# #
# #
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
# Author: misterg@google.com (Gennadiy Civil) # Author: misterg@google.com (Gennadiy Civil)
# #
# Bazel Build for Google C++ Testing Framework(Google Test)-googlemock # Bazel Build for Google C++ Testing Framework(Google Test)-googlemock
licenses(["notice"]) licenses(["notice"])
...@@ -53,3 +53,71 @@ cc_test( ...@@ -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",
],
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment