Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
yangql
googletest
Commits
6a896b5e
Commit
6a896b5e
authored
Jan 16, 2009
by
zhanyong.wan
Browse files
Implements ContainerEq.
parent
19e49afd
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
223 additions
and
1 deletion
+223
-1
include/gmock/gmock-matchers.h
include/gmock/gmock-matchers.h
+78
-0
test/gmock-matchers_test.cc
test/gmock-matchers_test.cc
+145
-1
No files found.
include/gmock/gmock-matchers.h
View file @
6a896b5e
...
...
@@ -38,6 +38,7 @@
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
#include <algorithm>
#include <ostream> // NOLINT
#include <sstream>
#include <string>
...
...
@@ -1635,6 +1636,73 @@ void ExplainMatchResultTo(const ResultOfMatcher<Callable>& matcher,
matcher
.
ExplainMatchResultTo
(
obj
,
os
);
}
// Implements an equality matcher for any STL-style container whose elements
// support ==. This matcher is like Eq(), but its failure explanations provide
// more detailed information that is useful when the container is used as a set.
// The failure message reports elements that are in one of the operands but not
// the other. The failure messages do not report duplicate or out-of-order
// elements in the containers (which don't properly matter to sets, but can
// occur if the containers are vectors or lists, for example).
//
// Uses the container's const_iterator, value_type, operator ==,
// begin(), and end().
template
<
typename
Container
>
class
ContainerEqMatcher
{
public:
explicit
ContainerEqMatcher
(
const
Container
&
rhs
)
:
rhs_
(
rhs
)
{}
bool
Matches
(
const
Container
&
lhs
)
const
{
return
lhs
==
rhs_
;
}
void
DescribeTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"equals "
;
UniversalPrinter
<
Container
>::
Print
(
rhs_
,
os
);
}
void
DescribeNegationTo
(
::
std
::
ostream
*
os
)
const
{
*
os
<<
"does not equal "
;
UniversalPrinter
<
Container
>::
Print
(
rhs_
,
os
);
}
void
ExplainMatchResultTo
(
const
Container
&
lhs
,
::
std
::
ostream
*
os
)
const
{
// Something is different. Check for missing values first.
bool
printed_header
=
false
;
for
(
typename
Container
::
const_iterator
it
=
lhs
.
begin
();
it
!=
lhs
.
end
();
++
it
)
{
if
(
std
::
find
(
rhs_
.
begin
(),
rhs_
.
end
(),
*
it
)
==
rhs_
.
end
())
{
if
(
printed_header
)
{
*
os
<<
", "
;
}
else
{
*
os
<<
"Only in actual: "
;
printed_header
=
true
;
}
UniversalPrinter
<
typename
Container
::
value_type
>::
Print
(
*
it
,
os
);
}
}
// Now check for extra values.
bool
printed_header2
=
false
;
for
(
typename
Container
::
const_iterator
it
=
rhs_
.
begin
();
it
!=
rhs_
.
end
();
++
it
)
{
if
(
std
::
find
(
lhs
.
begin
(),
lhs
.
end
(),
*
it
)
==
lhs
.
end
())
{
if
(
printed_header2
)
{
*
os
<<
", "
;
}
else
{
*
os
<<
(
printed_header
?
"; not"
:
"Not"
)
<<
" in actual: "
;
printed_header2
=
true
;
}
UniversalPrinter
<
typename
Container
::
value_type
>::
Print
(
*
it
,
os
);
}
}
}
private:
const
Container
rhs_
;
};
template
<
typename
Container
>
void
ExplainMatchResultTo
(
const
ContainerEqMatcher
<
Container
>&
matcher
,
const
Container
&
lhs
,
::
std
::
ostream
*
os
)
{
matcher
.
ExplainMatchResultTo
(
lhs
,
os
);
}
}
// namespace internal
// Implements MatcherCast().
...
...
@@ -2073,6 +2141,16 @@ Truly(Predicate pred) {
return
MakePolymorphicMatcher
(
internal
::
TrulyMatcher
<
Predicate
>
(
pred
));
}
// Returns a matcher that matches an equal container.
// This matcher behaves like Eq(), but in the event of mismatch lists the
// values that are included in one container but not the other. (Duplicate
// values and order differences are not explained.)
template
<
typename
Container
>
inline
PolymorphicMatcher
<
internal
::
ContainerEqMatcher
<
Container
>
>
ContainerEq
(
const
Container
&
rhs
)
{
return
MakePolymorphicMatcher
(
internal
::
ContainerEqMatcher
<
Container
>
(
rhs
));
}
// Returns a predicate that is satisfied by anything that matches the
// given matcher.
template
<
typename
M
>
...
...
test/gmock-matchers_test.cc
View file @
6a896b5e
...
...
@@ -37,8 +37,12 @@
#include <string.h>
#include <functional>
#include <string>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <gtest/gtest-spi.h>
...
...
@@ -2625,5 +2629,145 @@ TEST(ByRefTest, AllowsNotCopyableValueInMatchers) {
EXPECT_TRUE
(
m
.
Matches
(
n2
));
}
// Tests ContainerEq with different container types, and
// different element types.
template
<
typename
T
>
class
ContainerEqTest
:
public
testing
::
Test
{
public:
};
typedef
testing
::
Types
<
std
::
set
<
int
>
,
std
::
vector
<
size_t
>
,
std
::
multiset
<
size_t
>
,
std
::
list
<
int
>
>
ContainerEqTestTypes
;
TYPED_TEST_CASE
(
ContainerEqTest
,
ContainerEqTestTypes
);
// Tests that the filled container is equal to itself.
TYPED_TEST
(
ContainerEqTest
,
EqualsSelf
)
{
static
const
int
vals
[]
=
{
1
,
1
,
2
,
3
,
5
,
8
};
TypeParam
my_set
(
vals
,
vals
+
6
);
const
Matcher
<
TypeParam
>
m
=
ContainerEq
(
my_set
);
EXPECT_TRUE
(
m
.
Matches
(
my_set
));
EXPECT_EQ
(
""
,
Explain
(
m
,
my_set
));
}
// Tests that missing values are reported.
TYPED_TEST
(
ContainerEqTest
,
ValueMissing
)
{
static
const
int
vals
[]
=
{
1
,
1
,
2
,
3
,
5
,
8
};
static
const
int
test_vals
[]
=
{
2
,
1
,
8
,
5
};
TypeParam
my_set
(
vals
,
vals
+
6
);
TypeParam
test_set
(
test_vals
,
test_vals
+
4
);
const
Matcher
<
TypeParam
>
m
=
ContainerEq
(
my_set
);
EXPECT_FALSE
(
m
.
Matches
(
test_set
));
EXPECT_EQ
(
"Not in actual: 3"
,
Explain
(
m
,
test_set
));
}
// Tests that added values are reported.
TYPED_TEST
(
ContainerEqTest
,
ValueAdded
)
{
static
const
int
vals
[]
=
{
1
,
1
,
2
,
3
,
5
,
8
};
static
const
int
test_vals
[]
=
{
1
,
2
,
3
,
5
,
8
,
46
};
TypeParam
my_set
(
vals
,
vals
+
6
);
TypeParam
test_set
(
test_vals
,
test_vals
+
6
);
const
Matcher
<
const
TypeParam
&>
m
=
ContainerEq
(
my_set
);
EXPECT_FALSE
(
m
.
Matches
(
test_set
));
EXPECT_EQ
(
"Only in actual: 46"
,
Explain
(
m
,
test_set
));
}
// Tests that added and missing values are reported together.
TYPED_TEST
(
ContainerEqTest
,
ValueAddedAndRemoved
)
{
static
const
int
vals
[]
=
{
1
,
1
,
2
,
3
,
5
,
8
};
static
const
int
test_vals
[]
=
{
1
,
2
,
3
,
8
,
46
};
TypeParam
my_set
(
vals
,
vals
+
6
);
TypeParam
test_set
(
test_vals
,
test_vals
+
5
);
const
Matcher
<
TypeParam
>
m
=
ContainerEq
(
my_set
);
EXPECT_FALSE
(
m
.
Matches
(
test_set
));
EXPECT_EQ
(
"Only in actual: 46; not in actual: 5"
,
Explain
(
m
,
test_set
));
}
// Tests duplicated value -- expect no explanation.
TYPED_TEST
(
ContainerEqTest
,
DuplicateDifference
)
{
static
const
int
vals
[]
=
{
1
,
1
,
2
,
3
,
5
,
8
};
static
const
int
test_vals
[]
=
{
1
,
2
,
3
,
5
,
8
};
TypeParam
my_set
(
vals
,
vals
+
6
);
TypeParam
test_set
(
test_vals
,
test_vals
+
5
);
const
Matcher
<
const
TypeParam
&>
m
=
ContainerEq
(
my_set
);
// Depending on the container, match may be true or false
// But in any case there should be no explanation.
EXPECT_EQ
(
""
,
Explain
(
m
,
test_set
));
}
// Tests that mutliple missing values are reported.
// Using just vector here, so order is predicatble.
TEST
(
ContainerEqExtraTest
,
MultipleValuesMissing
)
{
static
const
int
vals
[]
=
{
1
,
1
,
2
,
3
,
5
,
8
};
static
const
int
test_vals
[]
=
{
2
,
1
,
5
};
std
::
vector
<
int
>
my_set
(
vals
,
vals
+
6
);
std
::
vector
<
int
>
test_set
(
test_vals
,
test_vals
+
3
);
const
Matcher
<
std
::
vector
<
int
>
>
m
=
ContainerEq
(
my_set
);
EXPECT_FALSE
(
m
.
Matches
(
test_set
));
EXPECT_EQ
(
"Not in actual: 3, 8"
,
Explain
(
m
,
test_set
));
}
// Tests that added values are reported.
// Using just vector here, so order is predicatble.
TEST
(
ContainerEqExtraTest
,
MultipleValuesAdded
)
{
static
const
int
vals
[]
=
{
1
,
1
,
2
,
3
,
5
,
8
};
static
const
int
test_vals
[]
=
{
1
,
2
,
92
,
3
,
5
,
8
,
46
};
std
::
list
<
size_t
>
my_set
(
vals
,
vals
+
6
);
std
::
list
<
size_t
>
test_set
(
test_vals
,
test_vals
+
7
);
const
Matcher
<
const
std
::
list
<
size_t
>&>
m
=
ContainerEq
(
my_set
);
EXPECT_FALSE
(
m
.
Matches
(
test_set
));
EXPECT_EQ
(
"Only in actual: 92, 46"
,
Explain
(
m
,
test_set
));
}
// Tests that added and missing values are reported together.
TEST
(
ContainerEqExtraTest
,
MultipleValuesAddedAndRemoved
)
{
static
const
int
vals
[]
=
{
1
,
1
,
2
,
3
,
5
,
8
};
static
const
int
test_vals
[]
=
{
1
,
2
,
3
,
92
,
46
};
std
::
list
<
size_t
>
my_set
(
vals
,
vals
+
6
);
std
::
list
<
size_t
>
test_set
(
test_vals
,
test_vals
+
5
);
const
Matcher
<
const
std
::
list
<
size_t
>
>
m
=
ContainerEq
(
my_set
);
EXPECT_FALSE
(
m
.
Matches
(
test_set
));
EXPECT_EQ
(
"Only in actual: 92, 46; not in actual: 5, 8"
,
Explain
(
m
,
test_set
));
}
// Tests to see that duplicate elements are detected,
// but (as above) not reported in the explanation.
TEST
(
ContainerEqExtraTest
,
MultiSetOfIntDuplicateDifference
)
{
static
const
int
vals
[]
=
{
1
,
1
,
2
,
3
,
5
,
8
};
static
const
int
test_vals
[]
=
{
1
,
2
,
3
,
5
,
8
};
std
::
vector
<
int
>
my_set
(
vals
,
vals
+
6
);
std
::
vector
<
int
>
test_set
(
test_vals
,
test_vals
+
5
);
const
Matcher
<
std
::
vector
<
int
>
>
m
=
ContainerEq
(
my_set
);
EXPECT_TRUE
(
m
.
Matches
(
my_set
));
EXPECT_FALSE
(
m
.
Matches
(
test_set
));
// There is nothing to report when both sets contain all the same values.
EXPECT_EQ
(
""
,
Explain
(
m
,
test_set
));
}
// Tests that ContainerEq works for non-trivial associative containers,
// like maps.
TEST
(
ContainerEqExtraTest
,
WorksForMaps
)
{
std
::
map
<
int
,
std
::
string
>
my_map
;
my_map
[
0
]
=
"a"
;
my_map
[
1
]
=
"b"
;
std
::
map
<
int
,
std
::
string
>
test_map
;
test_map
[
0
]
=
"aa"
;
test_map
[
1
]
=
"b"
;
const
Matcher
<
const
std
::
map
<
int
,
std
::
string
>&>
m
=
ContainerEq
(
my_map
);
EXPECT_TRUE
(
m
.
Matches
(
my_map
));
EXPECT_FALSE
(
m
.
Matches
(
test_map
));
EXPECT_EQ
(
"Only in actual: (0,
\"
aa
\"
); not in actual: (0,
\"
a
\"
)"
,
Explain
(
m
,
test_map
));
}
}
// namespace gmock_matchers_test
}
// namespace testing
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment