Adds support for type-parameterized tests (by Zhanyong Wan); also adds case-insensitive wide string comparison to the String class (by Vlad Losev).
This commit is contained in:
		@@ -46,11 +46,15 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#endif  // GTEST_OS_LINUX
 | 
			
		||||
 | 
			
		||||
#include <iomanip>  // NOLINT
 | 
			
		||||
#include <limits>   // NOLINT
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
#include <limits>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
#include <gtest/internal/gtest-string.h>
 | 
			
		||||
#include <gtest/internal/gtest-filepath.h>
 | 
			
		||||
#include <gtest/internal/gtest-type-util.h>
 | 
			
		||||
 | 
			
		||||
// Due to C++ preprocessor weirdness, we need double indirection to
 | 
			
		||||
// concatenate two tokens when one of them is __LINE__.  Writing
 | 
			
		||||
@@ -521,6 +525,182 @@ AssertionResult IsHRESULTFailure(const char* expr, long hr);  // NOLINT
 | 
			
		||||
 | 
			
		||||
#endif  // GTEST_OS_WINDOWS
 | 
			
		||||
 | 
			
		||||
// Formats a source file path and a line number as they would appear
 | 
			
		||||
// in a compiler error message.
 | 
			
		||||
inline String FormatFileLocation(const char* file, int line) {
 | 
			
		||||
  const char* const file_name = file == NULL ? "unknown file" : file;
 | 
			
		||||
  if (line < 0) {
 | 
			
		||||
    return String::Format("%s:", file_name);
 | 
			
		||||
  }
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
  return String::Format("%s(%d):", file_name, line);
 | 
			
		||||
#else
 | 
			
		||||
  return String::Format("%s:%d:", file_name, line);
 | 
			
		||||
#endif  // _MSC_VER
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Types of SetUpTestCase() and TearDownTestCase() functions.
 | 
			
		||||
typedef void (*SetUpTestCaseFunc)();
 | 
			
		||||
typedef void (*TearDownTestCaseFunc)();
 | 
			
		||||
 | 
			
		||||
// Creates a new TestInfo object and registers it with Google Test;
 | 
			
		||||
// returns the created object.
 | 
			
		||||
//
 | 
			
		||||
// Arguments:
 | 
			
		||||
//
 | 
			
		||||
//   test_case_name:   name of the test case
 | 
			
		||||
//   name:             name of the test
 | 
			
		||||
//   test_case_comment: a comment on the test case that will be included in
 | 
			
		||||
//                      the test output
 | 
			
		||||
//   comment:          a comment on the test that will be included in the
 | 
			
		||||
//                     test output
 | 
			
		||||
//   fixture_class_id: ID of the test fixture class
 | 
			
		||||
//   set_up_tc:        pointer to the function that sets up the test case
 | 
			
		||||
//   tear_down_tc:     pointer to the function that tears down the test case
 | 
			
		||||
//   factory:          pointer to the factory that creates a test object.
 | 
			
		||||
//                     The newly created TestInfo instance will assume
 | 
			
		||||
//                     ownership of the factory object.
 | 
			
		||||
TestInfo* MakeAndRegisterTestInfo(
 | 
			
		||||
    const char* test_case_name, const char* name,
 | 
			
		||||
    const char* test_case_comment, const char* comment,
 | 
			
		||||
    TypeId fixture_class_id,
 | 
			
		||||
    SetUpTestCaseFunc set_up_tc,
 | 
			
		||||
    TearDownTestCaseFunc tear_down_tc,
 | 
			
		||||
    TestFactoryBase* factory);
 | 
			
		||||
 | 
			
		||||
#if defined(GTEST_HAS_TYPED_TEST) || defined(GTEST_HAS_TYPED_TEST_P)
 | 
			
		||||
 | 
			
		||||
// State of the definition of a type-parameterized test case.
 | 
			
		||||
class TypedTestCasePState {
 | 
			
		||||
 public:
 | 
			
		||||
  TypedTestCasePState() : registered_(false) {}
 | 
			
		||||
 | 
			
		||||
  // Adds the given test name to defined_test_names_ and return true
 | 
			
		||||
  // if the test case hasn't been registered; otherwise aborts the
 | 
			
		||||
  // program.
 | 
			
		||||
  bool AddTestName(const char* file, int line, const char* case_name,
 | 
			
		||||
                   const char* test_name) {
 | 
			
		||||
    if (registered_) {
 | 
			
		||||
      fprintf(stderr, "%s Test %s must be defined before "
 | 
			
		||||
              "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
 | 
			
		||||
              FormatFileLocation(file, line).c_str(), test_name, case_name);
 | 
			
		||||
      abort();
 | 
			
		||||
    }
 | 
			
		||||
    defined_test_names_.insert(test_name);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Verifies that registered_tests match the test names in
 | 
			
		||||
  // defined_test_names_; returns registered_tests if successful, or
 | 
			
		||||
  // aborts the program otherwise.
 | 
			
		||||
  const char* VerifyRegisteredTestNames(
 | 
			
		||||
      const char* file, int line, const char* registered_tests);
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  bool registered_;
 | 
			
		||||
  ::std::set<const char*> defined_test_names_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Skips to the first non-space char after the first comma in 'str';
 | 
			
		||||
// returns NULL if no comma is found in 'str'.
 | 
			
		||||
inline const char* SkipComma(const char* str) {
 | 
			
		||||
  const char* comma = strchr(str, ',');
 | 
			
		||||
  if (comma == NULL) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  while (isspace(*(++comma))) {}
 | 
			
		||||
  return comma;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns the prefix of 'str' before the first comma in it; returns
 | 
			
		||||
// the entire string if it contains no comma.
 | 
			
		||||
inline String GetPrefixUntilComma(const char* str) {
 | 
			
		||||
  const char* comma = strchr(str, ',');
 | 
			
		||||
  return comma == NULL ? String(str) : String(str, comma - str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
 | 
			
		||||
// registers a list of type-parameterized tests with Google Test.  The
 | 
			
		||||
// return value is insignificant - we just need to return something
 | 
			
		||||
// such that we can call this function in a namespace scope.
 | 
			
		||||
//
 | 
			
		||||
// Implementation note: The GTEST_TEMPLATE_ macro declares a template
 | 
			
		||||
// template parameter.  It's defined in gtest-type-util.h.
 | 
			
		||||
template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
 | 
			
		||||
class TypeParameterizedTest {
 | 
			
		||||
 public:
 | 
			
		||||
  // 'index' is the index of the test in the type list 'Types'
 | 
			
		||||
  // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
 | 
			
		||||
  // Types).  Valid values for 'index' are [0, N - 1] where N is the
 | 
			
		||||
  // length of Types.
 | 
			
		||||
  static bool Register(const char* prefix, const char* case_name,
 | 
			
		||||
                       const char* test_names, int index) {
 | 
			
		||||
    typedef typename Types::Head Type;
 | 
			
		||||
    typedef Fixture<Type> FixtureClass;
 | 
			
		||||
    typedef typename GTEST_BIND_(TestSel, Type) TestClass;
 | 
			
		||||
 | 
			
		||||
    // First, registers the first type-parameterized test in the type
 | 
			
		||||
    // list.
 | 
			
		||||
    MakeAndRegisterTestInfo(
 | 
			
		||||
        String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/",
 | 
			
		||||
                       case_name, index).c_str(),
 | 
			
		||||
        GetPrefixUntilComma(test_names).c_str(),
 | 
			
		||||
        String::Format("TypeParam = %s", GetTypeName<Type>().c_str()).c_str(),
 | 
			
		||||
        "",
 | 
			
		||||
        GetTypeId<FixtureClass>(),
 | 
			
		||||
        TestClass::SetUpTestCase,
 | 
			
		||||
        TestClass::TearDownTestCase,
 | 
			
		||||
        new TestFactoryImpl<TestClass>);
 | 
			
		||||
 | 
			
		||||
    // Next, recurses (at compile time) with the tail of the type list.
 | 
			
		||||
    return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
 | 
			
		||||
        ::Register(prefix, case_name, test_names, index + 1);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// The base case for the compile time recursion.
 | 
			
		||||
template <GTEST_TEMPLATE_ Fixture, class TestSel>
 | 
			
		||||
class TypeParameterizedTest<Fixture, TestSel, Types0> {
 | 
			
		||||
 public:
 | 
			
		||||
  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
 | 
			
		||||
                       const char* /*test_names*/, int /*index*/) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
 | 
			
		||||
// registers *all combinations* of 'Tests' and 'Types' with Google
 | 
			
		||||
// Test.  The return value is insignificant - we just need to return
 | 
			
		||||
// something such that we can call this function in a namespace scope.
 | 
			
		||||
template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
 | 
			
		||||
class TypeParameterizedTestCase {
 | 
			
		||||
 public:
 | 
			
		||||
  static bool Register(const char* prefix, const char* case_name,
 | 
			
		||||
                       const char* test_names) {
 | 
			
		||||
    typedef typename Tests::Head Head;
 | 
			
		||||
 | 
			
		||||
    // First, register the first test in 'Test' for each type in 'Types'.
 | 
			
		||||
    TypeParameterizedTest<Fixture, Head, Types>::Register(
 | 
			
		||||
        prefix, case_name, test_names, 0);
 | 
			
		||||
 | 
			
		||||
    // Next, recurses (at compile time) with the tail of the test list.
 | 
			
		||||
    return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
 | 
			
		||||
        ::Register(prefix, case_name, SkipComma(test_names));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// The base case for the compile time recursion.
 | 
			
		||||
template <GTEST_TEMPLATE_ Fixture, typename Types>
 | 
			
		||||
class TypeParameterizedTestCase<Fixture, Templates0, Types> {
 | 
			
		||||
 public:
 | 
			
		||||
  static bool Register(const char* prefix, const char* case_name,
 | 
			
		||||
                       const char* test_names) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
 | 
			
		||||
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
@@ -544,27 +724,32 @@ AssertionResult IsHRESULTFailure(const char* expr, long hr);  // NOLINT
 | 
			
		||||
  else \
 | 
			
		||||
    fail("Value of: " booltext "\n  Actual: " #actual "\nExpected: " #expected)
 | 
			
		||||
 | 
			
		||||
// Expands to the name of the class that implements the given test.
 | 
			
		||||
#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
 | 
			
		||||
  test_case_name##_##test_name##_Test
 | 
			
		||||
 | 
			
		||||
// Helper macro for defining tests.
 | 
			
		||||
#define GTEST_TEST(test_case_name, test_name, parent_class)\
 | 
			
		||||
class test_case_name##_##test_name##_Test : public parent_class {\
 | 
			
		||||
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
 | 
			
		||||
 public:\
 | 
			
		||||
  test_case_name##_##test_name##_Test() {}\
 | 
			
		||||
  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
 | 
			
		||||
 private:\
 | 
			
		||||
  virtual void TestBody();\
 | 
			
		||||
  static ::testing::TestInfo* const test_info_;\
 | 
			
		||||
  GTEST_DISALLOW_COPY_AND_ASSIGN(test_case_name##_##test_name##_Test);\
 | 
			
		||||
  GTEST_DISALLOW_COPY_AND_ASSIGN(\
 | 
			
		||||
      GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
 | 
			
		||||
};\
 | 
			
		||||
\
 | 
			
		||||
::testing::TestInfo* const test_case_name##_##test_name##_Test::test_info_ =\
 | 
			
		||||
    ::testing::TestInfo::MakeAndRegisterInstance(\
 | 
			
		||||
        #test_case_name, \
 | 
			
		||||
        #test_name, \
 | 
			
		||||
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
 | 
			
		||||
  ::test_info_ =\
 | 
			
		||||
    ::testing::internal::MakeAndRegisterTestInfo(\
 | 
			
		||||
        #test_case_name, #test_name, "", "", \
 | 
			
		||||
        ::testing::internal::GetTypeId< parent_class >(), \
 | 
			
		||||
        parent_class::SetUpTestCase, \
 | 
			
		||||
        parent_class::TearDownTestCase, \
 | 
			
		||||
        new ::testing::internal::TestFactoryImpl<\
 | 
			
		||||
            test_case_name##_##test_name##_Test>);\
 | 
			
		||||
void test_case_name##_##test_name##_Test::TestBody()
 | 
			
		||||
            GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
 | 
			
		||||
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,10 @@
 | 
			
		||||
// Note that it is possible that none of the GTEST_OS_ macros are defined.
 | 
			
		||||
//
 | 
			
		||||
// Macros indicating available Google Test features:
 | 
			
		||||
//   GTEST_HAS_DEATH_TEST  - defined iff death tests are supported.
 | 
			
		||||
//   GTEST_HAS_DEATH_TEST   - defined iff death tests are supported.
 | 
			
		||||
//   GTEST_HAS_TYPED_TEST   - defined iff typed tests are supported.
 | 
			
		||||
//   GTEST_HAS_TYPED_TEST_P - defined iff type-parameterized tests are
 | 
			
		||||
//                            supported.
 | 
			
		||||
//
 | 
			
		||||
// Macros for basic C++ coding:
 | 
			
		||||
//   GTEST_AMBIGUOUS_ELSE_BLOCKER - for disabling a gcc warning.
 | 
			
		||||
@@ -225,6 +228,15 @@
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#endif  // GTEST_HAS_STD_STRING && defined(GTEST_OS_LINUX)
 | 
			
		||||
 | 
			
		||||
// Determines whether to support type-driven tests.
 | 
			
		||||
 | 
			
		||||
// Typed tests need <typeinfo> and variadic macros, which gcc and VC
 | 
			
		||||
// 8.0+ support.
 | 
			
		||||
#if defined(__GNUC__) || (_MSC_VER >= 1400)
 | 
			
		||||
#define GTEST_HAS_TYPED_TEST
 | 
			
		||||
#define GTEST_HAS_TYPED_TEST_P
 | 
			
		||||
#endif  // defined(__GNUC__) || (_MSC_VER >= 1400)
 | 
			
		||||
 | 
			
		||||
// Determines whether the system compiler uses UTF-16 for encoding wide strings.
 | 
			
		||||
#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_CYGWIN) || \
 | 
			
		||||
        defined(__SYMBIAN32__)
 | 
			
		||||
 
 | 
			
		||||
@@ -167,6 +167,21 @@ class String {
 | 
			
		||||
  static bool CaseInsensitiveCStringEquals(const char* lhs,
 | 
			
		||||
                                           const char* rhs);
 | 
			
		||||
 | 
			
		||||
  // Compares two wide C strings, ignoring case.  Returns true iff they
 | 
			
		||||
  // have the same content.
 | 
			
		||||
  //
 | 
			
		||||
  // Unlike wcscasecmp(), this function can handle NULL argument(s).
 | 
			
		||||
  // A NULL C string is considered different to any non-NULL wide C string,
 | 
			
		||||
  // including the empty string.
 | 
			
		||||
  // NB: The implementations on different platforms slightly differ.
 | 
			
		||||
  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
 | 
			
		||||
  // environment variable. On GNU platform this method uses wcscasecmp
 | 
			
		||||
  // which compares according to LC_CTYPE category of the current locale.
 | 
			
		||||
  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
 | 
			
		||||
  // current locale.
 | 
			
		||||
  static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
 | 
			
		||||
                                               const wchar_t* rhs);
 | 
			
		||||
 | 
			
		||||
  // Formats a list of arguments to a String, using the same format
 | 
			
		||||
  // spec string as for printf.
 | 
			
		||||
  //
 | 
			
		||||
@@ -218,6 +233,10 @@ class String {
 | 
			
		||||
    return CStringEquals(c_str_, c_str);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Returns true iff this String is less than the given C string.  A NULL
 | 
			
		||||
  // string is considered less than "".
 | 
			
		||||
  bool operator<(const String& rhs) const { return Compare(rhs) < 0; }
 | 
			
		||||
 | 
			
		||||
  // Returns true iff this String doesn't equal the given C string.  A NULL
 | 
			
		||||
  // string and a non-NULL string are considered not equal.
 | 
			
		||||
  bool operator!=(const char* c_str) const {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user