diff options
-rw-r--r-- | googletest/docs/advanced.md | 72 | ||||
-rw-r--r-- | googletest/include/gtest/gtest-printers.h | 7 | ||||
-rw-r--r-- | googletest/test/googletest-printers-test.cc | 59 |
3 files changed, 63 insertions, 75 deletions
diff --git a/googletest/docs/advanced.md b/googletest/docs/advanced.md index 16ff081..b1a4815 100644 --- a/googletest/docs/advanced.md +++ b/googletest/docs/advanced.md @@ -1817,78 +1817,6 @@ For technical reasons, there are some caveats: 1. `statement` in `EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}()()` cannot return a value. -## Registering tests programmatically - -The `TEST` macros handle the vast majority of all use cases, but there are few -were runtime registration logic is required. For those cases, the framework -provides the `::testing::RegisterTest` that allows callers to register arbitrary -tests dynamically. - -This is an advanced API only to be used when the `TEST` macros are insufficient. -The macros should be preferred when possible, as they avoid most of the -complexity of calling this function. - -It provides the following signature: - -```c++ -template <typename Factory> -TestInfo* RegisterTest(const char* test_case_name, const char* test_name, - const char* type_param, const char* value_param, - const char* file, int line, Factory factory); -``` - -The `factory` argument is a factory callable (move-constructible) object or -function pointer that creates a new instance of the Test object. It handles -ownership to the caller. The signature of the callable is `Fixture*()`, where -`Fixture` is the test fixture class for the test. All tests registered with the -same `test_case_name` must return the same fixture type. This is checked at -runtime. - -The framework will infer the fixture class from the factory and will call the -`SetUpTestCase` and `TearDownTestCase` for it. - -Must be called before `RUN_ALL_TESTS()` is invoked, otherwise behavior is -undefined. - -Use case example: - -```c++ -class MyFixture : public ::testing::Test { - public: - // All of these optional, just like in regular macro usage. - static void SetUpTestCase() { ... } - static void TearDownTestCase() { ... } - void SetUp() override { ... } - void TearDown() override { ... } -}; - -class MyTest : public MyFixture { - public: - explicit MyTest(int data) : data_(data) {} - void TestBody() override { ... } - - private: - int data_; -}; - -void RegisterMyTests(const std::vector<int>& values) { - for (int v : values) { - ::testing::RegisterTest( - "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr, - std::to_string(v).c_str(), - __FILE__, __LINE__, - // Important to use the fixture type as the return type here. - [=]() -> MyFixture* { return new MyTest(v); }); - } -} -... -int main(int argc, char** argv) { - std::vector<int> values_to_test = LoadValuesFromConfig(); - RegisterMyTests(values_to_test); - ... - return RUN_ALL_TESTS(); -} -``` ## Getting the Current Test's Name diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h index 97cdb2a..56a0545 100644 --- a/googletest/include/gtest/gtest-printers.h +++ b/googletest/include/gtest/gtest-printers.h @@ -151,9 +151,10 @@ class TypeWithoutFormatter { public: // This default version is called when kTypeKind is kOtherType. static void PrintValue(const T& value, ::std::ostream* os) { - PrintBytesInObjectTo(static_cast<const unsigned char*>( - reinterpret_cast<const void*>(&value)), - sizeof(value), os); + PrintBytesInObjectTo( + static_cast<const unsigned char*>( + reinterpret_cast<const void*>(std::addressof(value))), + sizeof(value), os); } }; diff --git a/googletest/test/googletest-printers-test.cc b/googletest/test/googletest-printers-test.cc index d896c24..4bdc9ad 100644 --- a/googletest/test/googletest-printers-test.cc +++ b/googletest/test/googletest-printers-test.cc @@ -1556,6 +1556,65 @@ TEST(PrintOneofTest, Basic) { PrintToString(Type(NonPrintable{}))); } #endif // GTEST_HAS_ABSL +namespace { +class string_ref; + +/** + * This is a synthetic pointer to a fixed size string. + */ +class string_ptr { + public: + string_ptr(const char* data, size_t size) : data_(data), size_(size) {} + + string_ptr& operator++() noexcept { + data_ += size_; + return *this; + } + + string_ref operator*() const noexcept; + + private: + const char* data_; + size_t size_; +}; + +/** + * This is a synthetic reference of a fixed size string. + */ +class string_ref { + public: + string_ref(const char* data, size_t size) : data_(data), size_(size) {} + + string_ptr operator&() const noexcept { return {data_, size_}; } // NOLINT + + bool operator==(const char* s) const noexcept { + if (size_ > 0 && data_[size_ - 1] != 0) { + return std::string(data_, size_) == std::string(s); + } else { + return std::string(data_) == std::string(s); + } + } + + private: + const char* data_; + size_t size_; +}; + +string_ref string_ptr::operator*() const noexcept { return {data_, size_}; } + +TEST(string_ref, compare) { + const char* s = "alex\0davidjohn\0"; + string_ptr ptr(s, 5); + EXPECT_EQ(*ptr, "alex"); + EXPECT_TRUE(*ptr == "alex"); + ++ptr; + EXPECT_EQ(*ptr, "david"); + EXPECT_TRUE(*ptr == "david"); + ++ptr; + EXPECT_EQ(*ptr, "john"); +} + +} // namespace } // namespace gtest_printers_test } // namespace testing |