Reputation: 2640
My question (for the inpatient)
Given a google-mock matcher, I would like to describe it to a string. For example:
std::string description = DescribeMatcher(Ge(0)) // puts "size is > 0" in the string
Does anybody know an easy way of doing that? Did not find anything in googlemock documentation. I did it myself like this:
template<typename T, typename S>
std::string DescribeMatcher(S matcher)
{
Matcher<T> matcherCast = matcher;
std::ostringstream os;
matcherCast.DescribeTo(&os);
return os.str();
}
Background
I want to write my own matcher that is based on a different one. My matcher matches a string that represents a name of a file having the specified size.
MATCHER_P(FileSizeIs, sizeMatcher, std::string("File size ") + DescribeMatcher(sizeMatcher))
{
auto fileSize = fs::file_size(arg);
return ExplainMatchResult(sizeMatcher, fileSize, result_listener);
}
Here is an example for its usage:
EXPECT_THAT(someFileName, FileSizeIs(Ge(100)); // the size of the file is at-least 100 bytes
EXPECT_THAT(someFileName, FileSizeIs(AllOf(Ge(200), Le(1000)); // the size of the file is between 200 and 1000 bytes
The problem is in the last argument of the MATCHER_P macro. I want the description of FileSizeIs
to be based on the description of sizeMatcher
. However, I did not find any such function inside googlemock and had to write it myself.
Upvotes: 3
Views: 2073
Reputation: 4267
I have had a similar issue creating nested matchers. My solution uses MatcherInterface instead of MATCHER_P. For your case this would be something like:
template <typename InternalMatcher>
class FileSizeIsMatcher : public MatcherInterface<fs::path> {
public:
FileSizeIsMatcher(InternalMatcher internalMatcher)
: mInternalMatcher(SafeMatcherCast<std::uintmax_t>(internalMatcher))
{
}
bool MatchAndExplain(fs::path arg, MatchResultListener* listener) const override {
auto fileSize = fs::file_size(arg);
*listener << "whose size is " << PrintToString(fileSize) << " ";
return mInternalMatcher.MatchAndExplain(fileSize, listener);
}
void DescribeTo(std::ostream* os) const override {
*os << "file whose size ";
mInternalMatcher.DescribeTo(os);
}
void DescribeNegationTo(std::ostream* os) const override {
*os << "file whose size ";
mInternalMatcher.DescribeNegationTo(os);
}
private:
Matcher<std::uintmax_t> mInternalMatcher;
};
template <typename InternalMatcher>
Matcher<fs::path> FileSizeIs(InternalMatcher m) {
return MakeMatcher(new FileSizeIsMatcher<InternalMatcher>(m));
};
Example:
TEST_F(DetectorPlacementControllerTests, TmpTest) {
EXPECT_THAT("myFile.txt", FileSizeIs(Lt(100ul)));
}
Gives output:
Value of: "myFile.txt"
Expected: file whose size is < 100
Actual: "myFile.txt" (of type char [11]), whose size is 123
Upvotes: 2