Merge branch 'master' into fix-1764_CMake-errors-in-googlemock

This commit is contained in:
Gennadiy Civil 2018-08-27 13:25:45 -04:00 committed by GitHub
commit ebb2fca51a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 387 additions and 109 deletions

View File

@ -20,8 +20,7 @@ instructions for how to sign and return it. Once we receive it, we'll be able to
accept your pull requests. accept your pull requests.
## Are you a Googler? ## Are you a Googler?
If you are a Googler, please create an internal change and If you are a Googler, you can either create an internal change or work on GitHub directly.
have it reviewed and submitted. The maintainers will normally be in position to upstream the changes.
## Contributing A Patch ## Contributing A Patch

View File

@ -2602,16 +2602,20 @@ class PropertyMatcher {
// Type traits specifying various features of different functors for ResultOf. // Type traits specifying various features of different functors for ResultOf.
// The default template specifies features for functor objects. // The default template specifies features for functor objects.
// Functor classes have to typedef argument_type and result_type
// to be compatible with ResultOf.
template <typename Functor> template <typename Functor>
struct CallableTraits { struct CallableTraits {
typedef typename Functor::result_type ResultType;
typedef Functor StorageType; typedef Functor StorageType;
static void CheckIsValid(Functor /* functor */) {} static void CheckIsValid(Functor /* functor */) {}
#if GTEST_LANG_CXX11
template <typename T>
static auto Invoke(Functor f, T arg) -> decltype(f(arg)) { return f(arg); }
#else
typedef typename Functor::result_type ResultType;
template <typename T> template <typename T>
static ResultType Invoke(Functor f, T arg) { return f(arg); } static ResultType Invoke(Functor f, T arg) { return f(arg); }
#endif
}; };
// Specialization for function pointers. // Specialization for function pointers.
@ -2632,13 +2636,11 @@ struct CallableTraits<ResType(*)(ArgType)> {
// Implements the ResultOf() matcher for matching a return value of a // Implements the ResultOf() matcher for matching a return value of a
// unary function of an object. // unary function of an object.
template <typename Callable> template <typename Callable, typename InnerMatcher>
class ResultOfMatcher { class ResultOfMatcher {
public: public:
typedef typename CallableTraits<Callable>::ResultType ResultType; ResultOfMatcher(Callable callable, InnerMatcher matcher)
: callable_(internal::move(callable)), matcher_(internal::move(matcher)) {
ResultOfMatcher(Callable callable, const Matcher<ResultType>& matcher)
: callable_(callable), matcher_(matcher) {
CallableTraits<Callable>::CheckIsValid(callable_); CallableTraits<Callable>::CheckIsValid(callable_);
} }
@ -2652,9 +2654,17 @@ class ResultOfMatcher {
template <typename T> template <typename T>
class Impl : public MatcherInterface<T> { class Impl : public MatcherInterface<T> {
#if GTEST_LANG_CXX11
using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>(
std::declval<CallableStorageType>(), std::declval<T>()));
#else
typedef typename CallableTraits<Callable>::ResultType ResultType;
#endif
public: public:
Impl(CallableStorageType callable, const Matcher<ResultType>& matcher) template <typename M>
: callable_(callable), matcher_(matcher) {} Impl(const CallableStorageType& callable, const M& matcher)
: callable_(callable), matcher_(MatcherCast<ResultType>(matcher)) {}
virtual void DescribeTo(::std::ostream* os) const { virtual void DescribeTo(::std::ostream* os) const {
*os << "is mapped by the given callable to a value that "; *os << "is mapped by the given callable to a value that ";
@ -2668,8 +2678,10 @@ class ResultOfMatcher {
virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const { virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
*listener << "which is mapped by the given callable to "; *listener << "which is mapped by the given callable to ";
// Cannot pass the return value (for example, int) to // Cannot pass the return value directly to MatchPrintAndExplain, which
// MatchPrintAndExplain, which takes a non-const reference as argument. // takes a non-const reference as argument.
// Also, specifying template argument explicitly is needed because T could
// be a non-const reference (e.g. Matcher<Uncopyable&>).
ResultType result = ResultType result =
CallableTraits<Callable>::template Invoke<T>(callable_, obj); CallableTraits<Callable>::template Invoke<T>(callable_, obj);
return MatchPrintAndExplain(result, matcher_, listener); return MatchPrintAndExplain(result, matcher_, listener);
@ -2679,7 +2691,7 @@ class ResultOfMatcher {
// Functors often define operator() as non-const method even though // Functors often define operator() as non-const method even though
// they are actually 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 doesn't guarantee
// how many times the callable will be invoked. // how many times the callable will be invoked.
mutable CallableStorageType callable_; mutable CallableStorageType callable_;
const Matcher<ResultType> matcher_; const Matcher<ResultType> matcher_;
@ -2688,7 +2700,7 @@ class ResultOfMatcher {
}; // class Impl }; // class Impl
const CallableStorageType callable_; const CallableStorageType callable_;
const Matcher<ResultType> matcher_; const InnerMatcher matcher_;
GTEST_DISALLOW_ASSIGN_(ResultOfMatcher); GTEST_DISALLOW_ASSIGN_(ResultOfMatcher);
}; };
@ -4554,26 +4566,15 @@ Property(const std::string& property_name,
// For example, // For example,
// ResultOf(f, StartsWith("hi")) // ResultOf(f, StartsWith("hi"))
// matches a Foo object x iff f(x) starts with "hi". // matches a Foo object x iff f(x) starts with "hi".
// callable parameter can be a function, function pointer, or a functor. // `callable` parameter can be a function, function pointer, or a functor. It is
// Callable has to satisfy the following conditions: // required to keep no state affecting the results of the calls on it and make
// * It is required to keep no state affecting the results of // no assumptions about how many calls will be made. Any state it keeps must be
// the calls on it and make no assumptions about how many calls // protected from the concurrent access.
// will be made. Any state it keeps must be protected from the template <typename Callable, typename InnerMatcher>
// concurrent access. internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
// * If it is a function object, it has to define type result_type. Callable callable, InnerMatcher matcher) {
// We recommend deriving your functor classes from std::unary_function. return internal::ResultOfMatcher<Callable, InnerMatcher>(
// internal::move(callable), internal::move(matcher));
template <typename Callable, typename ResultOfMatcher>
internal::ResultOfMatcher<Callable> ResultOf(
Callable callable, const ResultOfMatcher& matcher) {
return internal::ResultOfMatcher<Callable>(
callable,
MatcherCast<typename internal::CallableTraits<Callable>::ResultType>(
matcher));
// The call to MatcherCast() is required for supporting inner
// matchers of compatible types. For example, it allows
// ResultOf(Function, m)
// to compile where Function() returns an int32 and m is a matcher for int64.
} }
// String matchers. // String matchers.

View File

@ -4597,6 +4597,7 @@ struct PolymorphicFunctor {
typedef int result_type; typedef int result_type;
int operator()(int n) { return n; } int operator()(int n) { return n; }
int operator()(const char* s) { return static_cast<int>(strlen(s)); } int operator()(const char* s) { return static_cast<int>(strlen(s)); }
std::string operator()(int *p) { return p ? "good ptr" : "null"; }
}; };
TEST(ResultOfTest, WorksForPolymorphicFunctors) { TEST(ResultOfTest, WorksForPolymorphicFunctors) {
@ -4611,6 +4612,23 @@ TEST(ResultOfTest, WorksForPolymorphicFunctors) {
EXPECT_FALSE(matcher_string.Matches("shrt")); EXPECT_FALSE(matcher_string.Matches("shrt"));
} }
#if GTEST_LANG_CXX11
TEST(ResultOfTest, WorksForPolymorphicFunctorsIgnoringResultType) {
Matcher<int*> matcher = ResultOf(PolymorphicFunctor(), "good ptr");
int n = 0;
EXPECT_TRUE(matcher.Matches(&n));
EXPECT_FALSE(matcher.Matches(nullptr));
}
TEST(ResultOfTest, WorksForLambdas) {
Matcher<int> matcher =
ResultOf([](int str_len) { return std::string(str_len, 'x'); }, "xxx");
EXPECT_TRUE(matcher.Matches(3));
EXPECT_FALSE(matcher.Matches(1));
}
#endif
const int* ReferencingFunction(const int& n) { return &n; } const int* ReferencingFunction(const int& n) { return &n; }
struct ReferencingFunctor { struct ReferencingFunctor {

View File

@ -194,6 +194,21 @@ const char kStackTraceMarker[] = "\nStack trace:\n";
// specified on the command line. // specified on the command line.
bool g_help_flag = false; bool g_help_flag = false;
// Utilty function to Open File for Writing
static FILE* OpenFileForWriting(const std::string& output_file) {
FILE* fileout = NULL;
FilePath output_file_path(output_file);
FilePath output_dir(output_file_path.RemoveFileName());
if (output_dir.CreateDirectoriesRecursively()) {
fileout = posix::FOpen(output_file.c_str(), "w");
}
if (fileout == NULL) {
GTEST_LOG_(FATAL) << "Unable to open file \"" << output_file << "\"";
}
return fileout;
}
} // namespace internal } // namespace internal
// Bazel passes in the argument to '--test_filter' via the TESTBRIDGE_TEST_ONLY // Bazel passes in the argument to '--test_filter' via the TESTBRIDGE_TEST_ONLY
@ -454,6 +469,7 @@ std::string UnitTestOptions::GetOutputFormat() {
// Returns the name of the requested output file, or the default if none // Returns the name of the requested output file, or the default if none
// was explicitly specified. // was explicitly specified.
// FIXME Remove GetAbsolutePathToOutputFile checking gtest_output_flag == NULL
std::string UnitTestOptions::GetAbsolutePathToOutputFile() { std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
if (gtest_output_flag == NULL) if (gtest_output_flag == NULL)
@ -2130,13 +2146,8 @@ static const char* const kReservedTestSuiteAttributes[] = {
// The list of reserved attributes used in the <testcase> element of XML output. // The list of reserved attributes used in the <testcase> element of XML output.
static const char* const kReservedTestCaseAttributes[] = { static const char* const kReservedTestCaseAttributes[] = {
"classname", "classname", "name", "status", "time",
"name", "type_param", "value_param", "file", "line"};
"status",
"time",
"type_param",
"value_param"
};
template <int kSize> template <int kSize>
std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) { std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
@ -3414,6 +3425,11 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
explicit XmlUnitTestResultPrinter(const char* output_file); explicit XmlUnitTestResultPrinter(const char* output_file);
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
void ListTestsMatchingFilter(const std::vector<TestCase*>& test_cases);
// Prints an XML summary of all unit tests.
static void PrintXmlTestsList(std::ostream* stream,
const std::vector<TestCase*>& test_cases);
private: private:
// Is c a whitespace character that is normalized to a space character // Is c a whitespace character that is normalized to a space character
@ -3497,33 +3513,22 @@ XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
// Called after the unit test ends. // Called after the unit test ends.
void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
int /*iteration*/) { int /*iteration*/) {
FILE* xmlout = NULL; FILE* xmlout = OpenFileForWriting(output_file_);
FilePath output_file(output_file_);
FilePath output_dir(output_file.RemoveFileName());
if (output_dir.CreateDirectoriesRecursively()) {
xmlout = posix::FOpen(output_file_.c_str(), "w");
}
if (xmlout == NULL) {
// FIXME: 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; std::stringstream stream;
PrintXmlUnitTest(&stream, unit_test); PrintXmlUnitTest(&stream, unit_test);
fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
fclose(xmlout); fclose(xmlout);
} }
void XmlUnitTestResultPrinter::ListTestsMatchingFilter(
const std::vector<TestCase*>& test_cases) {
FILE* xmlout = OpenFileForWriting(output_file_);
std::stringstream stream;
PrintXmlTestsList(&stream, test_cases);
fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
fclose(xmlout);
}
// Returns an XML-escaped copy of the input string str. If is_attribute // Returns an XML-escaped copy of the input string str. If is_attribute
// is true, the text is meant to appear as an attribute value, and // is true, the text is meant to appear as an attribute value, and
// normalizable whitespace is preserved by replacing it with character // normalizable whitespace is preserved by replacing it with character
@ -3706,6 +3711,13 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
if (test_info.type_param() != NULL) { if (test_info.type_param() != NULL) {
OutputXmlAttribute(stream, kTestcase, "type_param", test_info.type_param()); OutputXmlAttribute(stream, kTestcase, "type_param", test_info.type_param());
} }
if (GTEST_FLAG(list_tests)) {
OutputXmlAttribute(stream, kTestcase, "file", test_info.file());
OutputXmlAttribute(stream, kTestcase, "line",
StreamableToString(test_info.line()));
*stream << " />\n";
return;
}
OutputXmlAttribute(stream, kTestcase, "status", OutputXmlAttribute(stream, kTestcase, "status",
test_info.should_run() ? "run" : "notrun"); test_info.should_run() ? "run" : "notrun");
@ -3752,17 +3764,18 @@ void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream,
OutputXmlAttribute(stream, kTestsuite, "name", test_case.name()); OutputXmlAttribute(stream, kTestsuite, "name", test_case.name());
OutputXmlAttribute(stream, kTestsuite, "tests", OutputXmlAttribute(stream, kTestsuite, "tests",
StreamableToString(test_case.reportable_test_count())); StreamableToString(test_case.reportable_test_count()));
OutputXmlAttribute(stream, kTestsuite, "failures", if (!GTEST_FLAG(list_tests)) {
StreamableToString(test_case.failed_test_count())); OutputXmlAttribute(stream, kTestsuite, "failures",
OutputXmlAttribute( StreamableToString(test_case.failed_test_count()));
stream, kTestsuite, "disabled", OutputXmlAttribute(
StreamableToString(test_case.reportable_disabled_test_count())); stream, kTestsuite, "disabled",
OutputXmlAttribute(stream, kTestsuite, "errors", "0"); StreamableToString(test_case.reportable_disabled_test_count()));
OutputXmlAttribute(stream, kTestsuite, "time", OutputXmlAttribute(stream, kTestsuite, "errors", "0");
FormatTimeInMillisAsSeconds(test_case.elapsed_time())); OutputXmlAttribute(stream, kTestsuite, "time",
*stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()) FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
<< ">\n"; *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result());
}
*stream << ">\n";
for (int i = 0; i < test_case.total_test_count(); ++i) { for (int i = 0; i < test_case.total_test_count(); ++i) {
if (test_case.GetTestInfo(i)->is_reportable()) if (test_case.GetTestInfo(i)->is_reportable())
OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i)); OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i));
@ -3808,6 +3821,28 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
*stream << "</" << kTestsuites << ">\n"; *stream << "</" << kTestsuites << ">\n";
} }
void XmlUnitTestResultPrinter::PrintXmlTestsList(
std::ostream* stream, const std::vector<TestCase*>& test_cases) {
const std::string kTestsuites = "testsuites";
*stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
*stream << "<" << kTestsuites;
int total_tests = 0;
for (size_t i = 0; i < test_cases.size(); ++i) {
total_tests += test_cases[i]->total_test_count();
}
OutputXmlAttribute(stream, kTestsuites, "tests",
StreamableToString(total_tests));
OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
*stream << ">\n";
for (size_t i = 0; i < test_cases.size(); ++i) {
PrintXmlTestCase(stream, *test_cases[i]);
}
*stream << "</" << kTestsuites << ">\n";
}
// Produces a string representing the test properties in a result as space // Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs. // delimited XML attributes based on the property key="value" pairs.
std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
@ -3843,7 +3878,6 @@ void XmlUnitTestResultPrinter::OutputXmlTestProperties(
// End XmlUnitTestResultPrinter // End XmlUnitTestResultPrinter
// This class generates an JSON output file. // This class generates an JSON output file.
class JsonUnitTestResultPrinter : public EmptyTestEventListener { class JsonUnitTestResultPrinter : public EmptyTestEventListener {
public: public:
@ -3851,6 +3885,10 @@ class JsonUnitTestResultPrinter : public EmptyTestEventListener {
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
// Prints an JSON summary of all unit tests.
static void PrintJsonTestList(::std::ostream* stream,
const std::vector<TestCase*>& test_cases);
private: private:
// Returns an JSON-escaped copy of the input string str. // Returns an JSON-escaped copy of the input string str.
static std::string EscapeJson(const std::string& str); static std::string EscapeJson(const std::string& str);
@ -3904,27 +3942,7 @@ JsonUnitTestResultPrinter::JsonUnitTestResultPrinter(const char* output_file)
void JsonUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, void JsonUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
int /*iteration*/) { int /*iteration*/) {
FILE* jsonout = NULL; FILE* jsonout = OpenFileForWriting(output_file_);
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) {
// FIXME: 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; std::stringstream stream;
PrintJsonUnitTest(&stream, unit_test); PrintJsonUnitTest(&stream, unit_test);
fprintf(jsonout, "%s", StringStreamToString(&stream).c_str()); fprintf(jsonout, "%s", StringStreamToString(&stream).c_str());
@ -4059,6 +4077,12 @@ void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream,
OutputJsonKey(stream, kTestcase, "type_param", test_info.type_param(), OutputJsonKey(stream, kTestcase, "type_param", test_info.type_param(),
kIndent); kIndent);
} }
if (GTEST_FLAG(list_tests)) {
OutputJsonKey(stream, kTestcase, "file", test_info.file(), kIndent);
OutputJsonKey(stream, kTestcase, "line", test_info.line(), kIndent, false);
*stream << "\n" << Indent(8) << "}";
return;
}
OutputJsonKey(stream, kTestcase, "status", OutputJsonKey(stream, kTestcase, "status",
test_info.should_run() ? "RUN" : "NOTRUN", kIndent); test_info.should_run() ? "RUN" : "NOTRUN", kIndent);
@ -4101,16 +4125,18 @@ void JsonUnitTestResultPrinter::PrintJsonTestCase(std::ostream* stream,
OutputJsonKey(stream, kTestsuite, "name", test_case.name(), kIndent); OutputJsonKey(stream, kTestsuite, "name", test_case.name(), kIndent);
OutputJsonKey(stream, kTestsuite, "tests", test_case.reportable_test_count(), OutputJsonKey(stream, kTestsuite, "tests", test_case.reportable_test_count(),
kIndent); kIndent);
OutputJsonKey(stream, kTestsuite, "failures", test_case.failed_test_count(), if (!GTEST_FLAG(list_tests)) {
kIndent); OutputJsonKey(stream, kTestsuite, "failures", test_case.failed_test_count(),
OutputJsonKey(stream, kTestsuite, "disabled", kIndent);
test_case.reportable_disabled_test_count(), kIndent); OutputJsonKey(stream, kTestsuite, "disabled",
OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent); test_case.reportable_disabled_test_count(), kIndent);
OutputJsonKey(stream, kTestsuite, "time", OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent);
FormatTimeInMillisAsDuration(test_case.elapsed_time()), kIndent, OutputJsonKey(stream, kTestsuite, "time",
false); FormatTimeInMillisAsDuration(test_case.elapsed_time()),
*stream << TestPropertiesAsJson(test_case.ad_hoc_test_result(), kIndent) kIndent, false);
<< ",\n"; *stream << TestPropertiesAsJson(test_case.ad_hoc_test_result(), kIndent)
<< ",\n";
}
*stream << kIndent << "\"" << kTestsuite << "\": [\n"; *stream << kIndent << "\"" << kTestsuite << "\": [\n";
@ -4174,6 +4200,31 @@ void JsonUnitTestResultPrinter::PrintJsonUnitTest(std::ostream* stream,
*stream << "\n" << kIndent << "]\n" << "}\n"; *stream << "\n" << kIndent << "]\n" << "}\n";
} }
void JsonUnitTestResultPrinter::PrintJsonTestList(
std::ostream* stream, const std::vector<TestCase*>& test_cases) {
const std::string kTestsuites = "testsuites";
const std::string kIndent = Indent(2);
*stream << "{\n";
int total_tests = 0;
for (size_t i = 0; i < test_cases.size(); ++i) {
total_tests += test_cases[i]->total_test_count();
}
OutputJsonKey(stream, kTestsuites, "tests", total_tests, kIndent);
OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent);
*stream << kIndent << "\"" << kTestsuites << "\": [\n";
for (size_t i = 0; i < test_cases.size(); ++i) {
if (i != 0) {
*stream << ",\n";
}
PrintJsonTestCase(stream, *test_cases[i]);
}
*stream << "\n"
<< kIndent << "]\n"
<< "}\n";
}
// Produces a string representing the test properties in a result as // Produces a string representing the test properties in a result as
// a JSON dictionary. // a JSON dictionary.
std::string JsonUnitTestResultPrinter::TestPropertiesAsJson( std::string JsonUnitTestResultPrinter::TestPropertiesAsJson(
@ -5394,6 +5445,23 @@ void UnitTestImpl::ListTestsMatchingFilter() {
} }
} }
fflush(stdout); fflush(stdout);
const std::string& output_format = UnitTestOptions::GetOutputFormat();
if (output_format == "xml" || output_format == "json") {
FILE* fileout = OpenFileForWriting(
UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
std::stringstream stream;
if (output_format == "xml") {
XmlUnitTestResultPrinter(
UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
.PrintXmlTestsList(&stream, test_cases_);
} else if (output_format == "json") {
JsonUnitTestResultPrinter(
UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
.PrintJsonTestList(&stream, test_cases_);
}
fprintf(fileout, "%s", StringStreamToString(&stream).c_str());
fclose(fileout);
}
} }
// Sets the OS stack trace getter. // Sets the OS stack trace getter.

View File

@ -0,0 +1,141 @@
#!/usr/bin/env python
#
# Copyright 2006, 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 Google Test's --gtest_list_tests flag.
A user can ask Google Test to list all tests by specifying the
--gtest_list_tests flag. If output is requested, via --gtest_output=xml
or --gtest_output=json, the tests are listed, with extra information in the
output file.
This script tests such functionality by invoking gtest_list_output_unittest_
(a program written with Google Test) the command line flags.
"""
import os
import re
import gtest_test_utils
GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
GTEST_OUTPUT_FLAG = '--gtest_output'
EXPECTED_XML = """<\?xml version="1.0" encoding="UTF-8"\?>
<testsuites tests="2" name="AllTests">
<testsuite name="FooTest" tests="2">
<testcase name="Test1" file=".*gtest_list_output_unittest_.cc" line="43" />
<testcase name="Test2" file=".*gtest_list_output_unittest_.cc" line="45" />
</testsuite>
</testsuites>
"""
EXPECTED_JSON = """{
"tests": 2,
"name": "AllTests",
"testsuites": \[
{
"name": "FooTest",
"tests": 2,
"testsuite": \[
{
"name": "Test1",
"file": ".*gtest_list_output_unittest_.cc",
"line": 43
},
{
"name": "Test2",
"file": ".*gtest_list_output_unittest_.cc",
"line": 45
}
\]
}
\]
}
"""
class GTestListTestsOutputUnitTest(gtest_test_utils.TestCase):
"""Unit test for Google Test's list tests with output to file functionality.
"""
def testXml(self):
"""Verifies XML output for listing tests in a Google Test binary.
Runs a test program that generates an empty XML output, and
tests that the XML output is expected.
"""
self._TestOutput('xml', EXPECTED_XML)
def testJSON(self):
"""Verifies XML output for listing tests in a Google Test binary.
Runs a test program that generates an empty XML output, and
tests that the XML output is expected.
"""
self._TestOutput('json', EXPECTED_JSON)
def _GetOutput(self, out_format):
file_path = os.path.join(gtest_test_utils.GetTempDir(),
'test_out.' + out_format)
gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
'gtest_list_output_unittest_')
command = ([
gtest_prog_path,
'%s=%s:%s' % (GTEST_OUTPUT_FLAG, out_format, file_path),
'--gtest_list_tests'
])
environ_copy = os.environ.copy()
p = gtest_test_utils.Subprocess(
command, env=environ_copy, working_dir=gtest_test_utils.GetTempDir())
self.assert_(p.exited)
self.assertEquals(0, p.exit_code)
with open(file_path) as f:
result = f.read()
return result
def _TestOutput(self, test_format, expected_output):
actual = self._GetOutput(test_format)
actual_lines = actual.splitlines()
expected_lines = expected_output.splitlines()
line_count = 0
for actual_line in actual_lines:
expected_line = expected_lines[line_count]
expected_line_re = re.compile(expected_line.strip())
self.assert_(
expected_line_re.match(actual_line.strip()),
('actual output of "%s",\n'
'which does not match expected regex of "%s"\n'
'on line %d' % (actual, expected_output, line_count)))
line_count = line_count + 1
if __name__ == '__main__':
os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
gtest_test_utils.Main()

View File

@ -0,0 +1,51 @@
// 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.
//
// Author: david.schuldenfrei@gmail.com (David Schuldenfrei)
// Unit test for Google Test's --gtest_list_tests and --gtest_output flag.
//
// A user can ask Google Test to list all tests that will run,
// and have the output saved in a Json/Xml file.
// The tests will not be run after listing.
//
// This program will be invoked from a Python unit test.
// Don't run it directly.
#include "gtest/gtest.h"
TEST(FooTest, Test1) {}
TEST(FooTest, Test2) {}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -2090,8 +2090,8 @@ TEST_F(UnitTestRecordPropertyTest,
AddRecordWithReservedKeysGeneratesCorrectPropertyList) { AddRecordWithReservedKeysGeneratesCorrectPropertyList) {
EXPECT_NONFATAL_FAILURE( EXPECT_NONFATAL_FAILURE(
Test::RecordProperty("name", "1"), Test::RecordProperty("name", "1"),
"'classname', 'name', 'status', 'time', 'type_param', and 'value_param'" "'classname', 'name', 'status', 'time', 'type_param', 'value_param',"
" are reserved"); " 'file', and 'line' are reserved");
} }
class UnitTestRecordPropertyTestEnvironment : public Environment { class UnitTestRecordPropertyTestEnvironment : public Environment {