diff options
| -rw-r--r-- | CONTRIBUTING.md | 3 | ||||
| -rw-r--r-- | googlemock/include/gmock/gmock-matchers.h | 69 | ||||
| -rw-r--r-- | googlemock/test/gmock-matchers_test.cc | 18 | ||||
| -rw-r--r-- | googletest/src/gtest.cc | 210 | ||||
| -rw-r--r-- | googletest/test/gtest_list_output_unittest.py | 141 | ||||
| -rw-r--r-- | googletest/test/gtest_list_output_unittest_.cc | 51 | ||||
| -rw-r--r-- | googletest/test/gtest_unittest.cc | 4 | 
7 files changed, 387 insertions, 109 deletions
| diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4dfdd95c..846dd8ab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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.  ## Are you a Googler? -If you are a Googler, please create an internal change and -have it reviewed and submitted. The maintainers will normally be in position to upstream the changes. +If you are a Googler, you can either create an internal change or work on GitHub directly.  ## Contributing A Patch diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 3336eff2..3975cd07 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -2602,16 +2602,20 @@ class PropertyMatcher {  // Type traits specifying various features of different functors for ResultOf.  // 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>  struct CallableTraits { -  typedef typename Functor::result_type ResultType;    typedef Functor StorageType;    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>    static ResultType Invoke(Functor f, T arg) { return f(arg); } +#endif  };  // Specialization for function pointers. @@ -2632,13 +2636,11 @@ struct CallableTraits<ResType(*)(ArgType)> {  // Implements the ResultOf() matcher for matching a return value of a  // unary function of an object. -template <typename Callable> +template <typename Callable, typename InnerMatcher>  class ResultOfMatcher {   public: -  typedef typename CallableTraits<Callable>::ResultType ResultType; - -  ResultOfMatcher(Callable callable, const Matcher<ResultType>& matcher) -      : callable_(callable), matcher_(matcher) { +  ResultOfMatcher(Callable callable, InnerMatcher matcher) +      : callable_(internal::move(callable)), matcher_(internal::move(matcher)) {      CallableTraits<Callable>::CheckIsValid(callable_);    } @@ -2652,9 +2654,17 @@ class ResultOfMatcher {    template <typename 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: -    Impl(CallableStorageType callable, const Matcher<ResultType>& matcher) -        : callable_(callable), matcher_(matcher) {} +    template <typename M> +    Impl(const CallableStorageType& callable, const M& matcher) +        : callable_(callable), matcher_(MatcherCast<ResultType>(matcher)) {}      virtual void DescribeTo(::std::ostream* os) const {        *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 {        *listener << "which is mapped by the given callable to "; -      // Cannot pass the return value (for example, int) to -      // MatchPrintAndExplain, which takes a non-const reference as argument. +      // Cannot pass the return value directly to MatchPrintAndExplain, which +      // 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 =            CallableTraits<Callable>::template Invoke<T>(callable_, obj);        return MatchPrintAndExplain(result, matcher_, listener); @@ -2679,7 +2691,7 @@ class ResultOfMatcher {      // Functors often define operator() as non-const method even though      // 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 -    // 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.      mutable CallableStorageType callable_;      const Matcher<ResultType> matcher_; @@ -2688,7 +2700,7 @@ class ResultOfMatcher {    };  // class Impl    const CallableStorageType callable_; -  const Matcher<ResultType> matcher_; +  const InnerMatcher matcher_;    GTEST_DISALLOW_ASSIGN_(ResultOfMatcher);  }; @@ -4554,26 +4566,15 @@ Property(const std::string& property_name,  // For example,  //   ResultOf(f, StartsWith("hi"))  // matches a Foo object x iff f(x) starts with "hi". -// callable parameter can be a function, function pointer, or a functor. -// Callable has to satisfy the following conditions: -//   * It is required to keep no state affecting the results of -//     the calls on it and make no assumptions about how many calls -//     will be made. Any state it keeps must be protected from the -//     concurrent access. -//   * If it is a function object, it has to define type result_type. -//     We recommend deriving your functor classes from std::unary_function. -// -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. +// `callable` parameter can be a function, function pointer, or a functor. It is +// required to keep no state affecting the results of the calls on it and make +// no assumptions about how many calls will be made. Any state it keeps must be +// protected from the concurrent access. +template <typename Callable, typename InnerMatcher> +internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf( +    Callable callable, InnerMatcher matcher) { +  return internal::ResultOfMatcher<Callable, InnerMatcher>( +      internal::move(callable), internal::move(matcher));  }  // String matchers. diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc index d08f08f7..4697f0bf 100644 --- a/googlemock/test/gmock-matchers_test.cc +++ b/googlemock/test/gmock-matchers_test.cc @@ -4597,6 +4597,7 @@ struct PolymorphicFunctor {    typedef int result_type;    int operator()(int n) { return n; }    int operator()(const char* s) { return static_cast<int>(strlen(s)); } +  std::string operator()(int *p) { return p ? "good ptr" : "null"; }  };  TEST(ResultOfTest, WorksForPolymorphicFunctors) { @@ -4611,6 +4612,23 @@ TEST(ResultOfTest, WorksForPolymorphicFunctors) {    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; }  struct ReferencingFunctor { diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index e9127a11..f476044b 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -194,6 +194,21 @@ const char kStackTraceMarker[] = "\nStack trace:\n";  // specified on the command line.  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  // 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  // was explicitly specified. +// FIXME Remove GetAbsolutePathToOutputFile checking gtest_output_flag == NULL  std::string UnitTestOptions::GetAbsolutePathToOutputFile() {    const char* const gtest_output_flag = GTEST_FLAG(output).c_str();    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.  static const char* const kReservedTestCaseAttributes[] = { -  "classname", -  "name", -  "status", -  "time", -  "type_param", -  "value_param" -}; +    "classname",  "name",        "status", "time", +    "type_param", "value_param", "file",   "line"};  template <int 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);    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:    // 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.  void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,                                                    int /*iteration*/) { -  FILE* xmlout = NULL; -  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_ << "\""; -  } +  FILE* xmlout = OpenFileForWriting(output_file_);    std::stringstream stream;    PrintXmlUnitTest(&stream, unit_test);    fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());    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  // is true, the text is meant to appear as an attribute value, and  // 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) {      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",                       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, "tests",                       StreamableToString(test_case.reportable_test_count())); -  OutputXmlAttribute(stream, kTestsuite, "failures", -                     StreamableToString(test_case.failed_test_count())); -  OutputXmlAttribute( -      stream, kTestsuite, "disabled", -      StreamableToString(test_case.reportable_disabled_test_count())); -  OutputXmlAttribute(stream, kTestsuite, "errors", "0"); -  OutputXmlAttribute(stream, kTestsuite, "time", -                     FormatTimeInMillisAsSeconds(test_case.elapsed_time())); -  *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()) -          << ">\n"; - +  if (!GTEST_FLAG(list_tests)) { +    OutputXmlAttribute(stream, kTestsuite, "failures", +                       StreamableToString(test_case.failed_test_count())); +    OutputXmlAttribute( +        stream, kTestsuite, "disabled", +        StreamableToString(test_case.reportable_disabled_test_count())); +    OutputXmlAttribute(stream, kTestsuite, "errors", "0"); +    OutputXmlAttribute(stream, kTestsuite, "time", +                       FormatTimeInMillisAsSeconds(test_case.elapsed_time())); +    *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()); +  } +  *stream << ">\n";    for (int i = 0; i < test_case.total_test_count(); ++i) {      if (test_case.GetTestInfo(i)->is_reportable())        OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i)); @@ -3808,6 +3821,28 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,    *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  // delimited XML attributes based on the property key="value" pairs.  std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( @@ -3843,7 +3878,6 @@ void XmlUnitTestResultPrinter::OutputXmlTestProperties(  // End XmlUnitTestResultPrinter -  // This class generates an JSON output file.  class JsonUnitTestResultPrinter : public EmptyTestEventListener {   public: @@ -3851,6 +3885,10 @@ class JsonUnitTestResultPrinter : public EmptyTestEventListener {    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:    // Returns an JSON-escaped copy of the input 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,                                                    int /*iteration*/) { -  FILE* jsonout = NULL; -  FilePath output_file(output_file_); -  FilePath output_dir(output_file.RemoveFileName()); - -  if (output_dir.CreateDirectoriesRecursively()) { -    jsonout = posix::FOpen(output_file_.c_str(), "w"); -  } -  if (jsonout == NULL) { -    // 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_ << "\""; -  } +  FILE* jsonout = OpenFileForWriting(output_file_);    std::stringstream stream;    PrintJsonUnitTest(&stream, unit_test);    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(),                    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",                  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, "tests", test_case.reportable_test_count(),                  kIndent); -  OutputJsonKey(stream, kTestsuite, "failures", test_case.failed_test_count(), -                kIndent); -  OutputJsonKey(stream, kTestsuite, "disabled", -                test_case.reportable_disabled_test_count(), kIndent); -  OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent); -  OutputJsonKey(stream, kTestsuite, "time", -                FormatTimeInMillisAsDuration(test_case.elapsed_time()), kIndent, -                false); -  *stream << TestPropertiesAsJson(test_case.ad_hoc_test_result(), kIndent) -          << ",\n"; +  if (!GTEST_FLAG(list_tests)) { +    OutputJsonKey(stream, kTestsuite, "failures", test_case.failed_test_count(), +                  kIndent); +    OutputJsonKey(stream, kTestsuite, "disabled", +                  test_case.reportable_disabled_test_count(), kIndent); +    OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent); +    OutputJsonKey(stream, kTestsuite, "time", +                  FormatTimeInMillisAsDuration(test_case.elapsed_time()), +                  kIndent, false); +    *stream << TestPropertiesAsJson(test_case.ad_hoc_test_result(), kIndent) +            << ",\n"; +  }    *stream << kIndent << "\"" << kTestsuite << "\": [\n"; @@ -4174,6 +4200,31 @@ void JsonUnitTestResultPrinter::PrintJsonUnitTest(std::ostream* stream,    *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  // a JSON dictionary.  std::string JsonUnitTestResultPrinter::TestPropertiesAsJson( @@ -5394,6 +5445,23 @@ void UnitTestImpl::ListTestsMatchingFilter() {      }    }    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. diff --git a/googletest/test/gtest_list_output_unittest.py b/googletest/test/gtest_list_output_unittest.py new file mode 100644 index 00000000..3bba7ea2 --- /dev/null +++ b/googletest/test/gtest_list_output_unittest.py @@ -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() diff --git a/googletest/test/gtest_list_output_unittest_.cc b/googletest/test/gtest_list_output_unittest_.cc new file mode 100644 index 00000000..b1c7b4de --- /dev/null +++ b/googletest/test/gtest_list_output_unittest_.cc @@ -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(); +} diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index e1c30f39..f7213fbf 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -2090,8 +2090,8 @@ TEST_F(UnitTestRecordPropertyTest,         AddRecordWithReservedKeysGeneratesCorrectPropertyList) {    EXPECT_NONFATAL_FAILURE(        Test::RecordProperty("name", "1"), -      "'classname', 'name', 'status', 'time', 'type_param', and 'value_param'" -      " are reserved"); +      "'classname', 'name', 'status', 'time', 'type_param', 'value_param'," +      " 'file', and 'line' are reserved");  }  class UnitTestRecordPropertyTestEnvironment : public Environment { | 
