diff options
author | Abseil Team <absl-team@google.com> | 2018-10-25 02:04:43 (GMT) |
---|---|---|
committer | Gennadiy Civil <misterg@google.com> | 2018-10-26 18:19:59 (GMT) |
commit | b57c703963be1ca9749b902c49083beac56648aa (patch) | |
tree | b7f5433fce3803d121c9963dc69bcdeec4d35f7c /googletest | |
parent | a50e4f05b3d84c6a014c59a24263328242cc8236 (diff) | |
download | googletest-b57c703963be1ca9749b902c49083beac56648aa.zip googletest-b57c703963be1ca9749b902c49083beac56648aa.tar.gz googletest-b57c703963be1ca9749b902c49083beac56648aa.tar.bz2 |
Googletest export
Remove linked_ptr and use std::shared_ptr instead
PiperOrigin-RevId: 218618184
Diffstat (limited to 'googletest')
-rw-r--r-- | googletest/CMakeLists.txt | 1 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-linked_ptr.h | 243 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-param-util-generated.h | 20 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-param-util-generated.h.pump | 4 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-param-util.h | 13 | ||||
-rw-r--r-- | googletest/src/gtest-port.cc | 12 | ||||
-rw-r--r-- | googletest/src/gtest.cc | 3 | ||||
-rw-r--r-- | googletest/test/googletest-linked-ptr-test.cc | 151 | ||||
-rw-r--r-- | googletest/test/gtest_all_test.cc | 1 |
9 files changed, 421 insertions, 27 deletions
diff --git a/googletest/CMakeLists.txt b/googletest/CMakeLists.txt index e33718b..4c0d648 100644 --- a/googletest/CMakeLists.txt +++ b/googletest/CMakeLists.txt @@ -195,6 +195,7 @@ $env:Path = \"$project_bin;$env:Path\" cxx_test(googletest-death-test-test gtest_main) cxx_test(gtest_environment_test gtest) cxx_test(googletest-filepath-test gtest_main) + cxx_test(googletest-linked-ptr-test gtest_main) cxx_test(googletest-listener-test gtest_main) cxx_test(gtest_main_unittest gtest_main) cxx_test(googletest-message-test gtest_main) diff --git a/googletest/include/gtest/internal/gtest-linked_ptr.h b/googletest/include/gtest/internal/gtest-linked_ptr.h new file mode 100644 index 0000000..d25f7e9 --- /dev/null +++ b/googletest/include/gtest/internal/gtest-linked_ptr.h @@ -0,0 +1,243 @@ +// Copyright 2003 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. +// +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). +// +// Bill Gibbons suggested we use something like this. +// +// Thread Safety: +// Unlike other linked_ptr implementations, in this implementation +// a linked_ptr object is thread-safe in the sense that: +// - it's safe to copy linked_ptr objects concurrently, +// - it's safe to copy *from* a linked_ptr and read its underlying +// raw pointer (e.g. via get()) concurrently, and +// - it's safe to write to two linked_ptrs that point to the same +// shared object concurrently. +// FIXME: rename this to safe_linked_ptr to avoid +// confusion with normal linked_ptr. + +// GOOGLETEST_CM0001 DO NOT DELETE + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ + +#include <stdlib.h> +#include <assert.h> + +#include "gtest/internal/gtest-port.h" + +namespace testing { +namespace internal { + +// Protects copying of all linked_ptr objects. +GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Many linked_ptr operations may change p.link_ for some linked_ptr + // variable p in the same circle as this object. Therefore we need + // to prevent two such operations from occurring concurrently. + // + // Note that different types of linked_ptr objects can coexist in a + // circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and + // linked_ptr<Derived2>). Therefore we must use a single mutex to + // protect all linked_ptr objects. This can create serious + // contention in production code, but is acceptable in a testing + // framework. + + // Join an existing circle. + void join(linked_ptr_internal const* ptr) + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) { + assert(p->next_ != this && + "Trying to join() a linked ring we are already in. " + "Is GMock thread safety enabled?"); + p = p->next_; + } + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true if we were the + // last member of the circle. Once this is done, you can join() another. + bool depart() + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) { + assert(p->next_ != next_ && + "Trying to depart() a linked ring we are not in. " + "Is GMock thread safety enabled?"); + p = p->next_; + } + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template <typename T> +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = nullptr) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { // NOLINT + assert(&ptr != this); + copy(&ptr); + } + + // Assignment releases the old value and acquires the new. + template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = nullptr) { + depart(); + capture(ptr); + } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template <typename U> + bool operator==(linked_ptr<U> const& ptr) const { + return value_ == ptr.get(); + } + template <typename U> + bool operator!=(linked_ptr<U> const& ptr) const { + return value_ != ptr.get(); + } + + private: + template <typename U> + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template <typename U> void copy(linked_ptr<U> const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template<typename T> inline +bool operator==(T* ptr, const linked_ptr<T>& x) { + return ptr == x.get(); +} + +template<typename T> inline +bool operator!=(T* ptr, const linked_ptr<T>& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr<T> +// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation +// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) +template <typename T> +linked_ptr<T> make_linked_ptr(T* ptr) { + return linked_ptr<T>(ptr); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ diff --git a/googletest/include/gtest/internal/gtest-param-util-generated.h b/googletest/include/gtest/internal/gtest-param-util-generated.h index f3c1e16..78bf65f 100644 --- a/googletest/include/gtest/internal/gtest-param-util-generated.h +++ b/googletest/include/gtest/internal/gtest-param-util-generated.h @@ -47,8 +47,6 @@ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ -#include <memory> - #include "gtest/internal/gtest-param-util.h" #include "gtest/internal/gtest-port.h" @@ -164,7 +162,7 @@ class CartesianProductGenerator2 const typename ParamGenerator<T2>::iterator begin2_; const typename ParamGenerator<T2>::iterator end2_; typename ParamGenerator<T2>::iterator current2_; - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator2::Iterator // No implementation - assignment is unsupported. @@ -295,7 +293,7 @@ class CartesianProductGenerator3 const typename ParamGenerator<T3>::iterator begin3_; const typename ParamGenerator<T3>::iterator end3_; typename ParamGenerator<T3>::iterator current3_; - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator3::Iterator // No implementation - assignment is unsupported. @@ -445,7 +443,7 @@ class CartesianProductGenerator4 const typename ParamGenerator<T4>::iterator begin4_; const typename ParamGenerator<T4>::iterator end4_; typename ParamGenerator<T4>::iterator current4_; - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator4::Iterator // No implementation - assignment is unsupported. @@ -611,7 +609,7 @@ class CartesianProductGenerator5 const typename ParamGenerator<T5>::iterator begin5_; const typename ParamGenerator<T5>::iterator end5_; typename ParamGenerator<T5>::iterator current5_; - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator5::Iterator // No implementation - assignment is unsupported. @@ -795,7 +793,7 @@ class CartesianProductGenerator6 const typename ParamGenerator<T6>::iterator begin6_; const typename ParamGenerator<T6>::iterator end6_; typename ParamGenerator<T6>::iterator current6_; - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator6::Iterator // No implementation - assignment is unsupported. @@ -997,7 +995,7 @@ class CartesianProductGenerator7 const typename ParamGenerator<T7>::iterator begin7_; const typename ParamGenerator<T7>::iterator end7_; typename ParamGenerator<T7>::iterator current7_; - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator7::Iterator // No implementation - assignment is unsupported. @@ -1218,7 +1216,7 @@ class CartesianProductGenerator8 const typename ParamGenerator<T8>::iterator begin8_; const typename ParamGenerator<T8>::iterator end8_; typename ParamGenerator<T8>::iterator current8_; - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator8::Iterator // No implementation - assignment is unsupported. @@ -1456,7 +1454,7 @@ class CartesianProductGenerator9 const typename ParamGenerator<T9>::iterator begin9_; const typename ParamGenerator<T9>::iterator end9_; typename ParamGenerator<T9>::iterator current9_; - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator9::Iterator // No implementation - assignment is unsupported. @@ -1711,7 +1709,7 @@ class CartesianProductGenerator10 const typename ParamGenerator<T10>::iterator begin10_; const typename ParamGenerator<T10>::iterator end10_; typename ParamGenerator<T10>::iterator current10_; - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator10::Iterator // No implementation - assignment is unsupported. diff --git a/googletest/include/gtest/internal/gtest-param-util-generated.h.pump b/googletest/include/gtest/internal/gtest-param-util-generated.h.pump index 5dea7b2..67d1b34 100644 --- a/googletest/include/gtest/internal/gtest-param-util-generated.h.pump +++ b/googletest/include/gtest/internal/gtest-param-util-generated.h.pump @@ -43,8 +43,6 @@ $var maxtuple = 10 $$ Maximum number of Combine arguments we want to support. // GOOGLETEST_CM0001 DO NOT DELETE -#include <memory> - #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ @@ -175,7 +173,7 @@ $for j [[ typename ParamGenerator<T$j>::iterator current$(j)_; ]] - std::shared_ptr<ParamType> current_value_; + linked_ptr<ParamType> current_value_; }; // class CartesianProductGenerator$i::Iterator // No implementation - assignment is unsupported. diff --git a/googletest/include/gtest/internal/gtest-param-util.h b/googletest/include/gtest/internal/gtest-param-util.h index 9eb98b1..d5d4da9 100644 --- a/googletest/include/gtest/internal/gtest-param-util.h +++ b/googletest/include/gtest/internal/gtest-param-util.h @@ -38,13 +38,13 @@ #include <ctype.h> #include <iterator> -#include <memory> #include <set> #include <tuple> #include <utility> #include <vector> #include "gtest/internal/gtest-internal.h" +#include "gtest/internal/gtest-linked_ptr.h" #include "gtest/internal/gtest-port.h" #include "gtest/gtest-printers.h" @@ -193,7 +193,7 @@ class ParamGenerator { iterator end() const { return iterator(impl_->End()); } private: - std::shared_ptr<const ParamGeneratorInterface<T> > impl_; + linked_ptr<const ParamGeneratorInterface<T> > impl_; }; // Generates values from a range of two comparable values. Can be used to @@ -519,8 +519,9 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { void AddTestPattern(const char* test_case_name, const char* test_base_name, TestMetaFactoryBase<ParamType>* meta_factory) { - tests_.push_back(std::shared_ptr<TestInfo>( - new TestInfo(test_case_name, test_base_name, meta_factory))); + tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name, + test_base_name, + meta_factory))); } // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information // about a generator. @@ -540,7 +541,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { virtual void RegisterTests() { for (typename TestInfoContainer::iterator test_it = tests_.begin(); test_it != tests_.end(); ++test_it) { - std::shared_ptr<TestInfo> test_info = *test_it; + linked_ptr<TestInfo> test_info = *test_it; for (typename InstantiationContainer::iterator gen_it = instantiations_.begin(); gen_it != instantiations_.end(); ++gen_it) { @@ -604,7 +605,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { const std::string test_base_name; const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory; }; - using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >; + typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer; // Records data received from INSTANTIATE_TEST_CASE_P macros: // <Instantiation name, Sequence generator creation function, // Name generator function, Source file, Source line> diff --git a/googletest/src/gtest-port.cc b/googletest/src/gtest-port.cc index 082aaff..aa98ddb 100644 --- a/googletest/src/gtest-port.cc +++ b/googletest/src/gtest-port.cc @@ -31,11 +31,10 @@ #include "gtest/internal/gtest-port.h" #include <limits.h> -#include <stdio.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> #include <fstream> -#include <memory> #if GTEST_OS_WINDOWS # include <windows.h> @@ -476,7 +475,7 @@ class ThreadLocalRegistryImpl { thread_local_values .insert(std::make_pair( thread_local_instance, - std::shared_ptr<ThreadLocalValueHolderBase>( + linked_ptr<ThreadLocalValueHolderBase>( thread_local_instance->NewValueForCurrentThread()))) .first; } @@ -485,7 +484,7 @@ class ThreadLocalRegistryImpl { static void OnThreadLocalDestroyed( const ThreadLocalBase* thread_local_instance) { - std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders; + std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders; // Clean up the ThreadLocalValues data structure while holding the lock, but // defer the destruction of the ThreadLocalValueHolderBases. { @@ -513,7 +512,7 @@ class ThreadLocalRegistryImpl { static void OnThreadExit(DWORD thread_id) { GTEST_CHECK_(thread_id != 0) << ::GetLastError(); - std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders; + std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders; // Clean up the ThreadIdToThreadLocals data structure while holding the // lock, but defer the destruction of the ThreadLocalValueHolderBases. { @@ -540,8 +539,7 @@ class ThreadLocalRegistryImpl { private: // In a particular thread, maps a ThreadLocal object to its value. typedef std::map<const ThreadLocalBase*, - std::shared_ptr<ThreadLocalValueHolderBase> > - ThreadLocalValues; + linked_ptr<ThreadLocalValueHolderBase> > ThreadLocalValues; // Stores all ThreadIdToThreadLocals having values in a thread, indexed by // thread's ID. typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals; diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index afd7d1b..332b3e9 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -423,6 +423,9 @@ void AssertHelper::operator=(const Message& message) const { ); // NOLINT } +// Mutex for linked pointers. +GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); + // A copy of all command line arguments. Set by InitGoogleTest(). static ::std::vector<std::string> g_argvs; diff --git a/googletest/test/googletest-linked-ptr-test.cc b/googletest/test/googletest-linked-ptr-test.cc new file mode 100644 index 0000000..f680253 --- /dev/null +++ b/googletest/test/googletest-linked-ptr-test.cc @@ -0,0 +1,151 @@ +// Copyright 2003, 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. + +#include <stdlib.h> + +#include "gtest/internal/gtest-linked_ptr.h" +#include "gtest/gtest.h" + +namespace { + +using testing::Message; +using testing::internal::linked_ptr; + +int num; +Message* history = nullptr; + +// Class which tracks allocation/deallocation +class A { + public: + A(): mynum(num++) { *history << "A" << mynum << " ctor\n"; } + virtual ~A() { *history << "A" << mynum << " dtor\n"; } + virtual void Use() { *history << "A" << mynum << " use\n"; } + protected: + int mynum; +}; + +// Subclass +class B : public A { + public: + B() { *history << "B" << mynum << " ctor\n"; } + ~B() { *history << "B" << mynum << " dtor\n"; } + virtual void Use() { *history << "B" << mynum << " use\n"; } +}; + +class LinkedPtrTest : public testing::Test { + public: + LinkedPtrTest() { + num = 0; + history = new Message; + } + + virtual ~LinkedPtrTest() { + delete history; + history = nullptr; + } +}; + +TEST_F(LinkedPtrTest, GeneralTest) { + { + linked_ptr<A> a0, a1, a2; + // Use explicit function call notation here to suppress self-assign warning. + a0.operator=(a0); + a1 = a2; + ASSERT_EQ(a0.get(), static_cast<A*>(nullptr)); + ASSERT_EQ(a1.get(), static_cast<A*>(nullptr)); + ASSERT_EQ(a2.get(), static_cast<A*>(nullptr)); + ASSERT_TRUE(a0 == nullptr); + ASSERT_TRUE(a1 == nullptr); + ASSERT_TRUE(a2 == nullptr); + + { + linked_ptr<A> a3(new A); + a0 = a3; + ASSERT_TRUE(a0 == a3); + ASSERT_TRUE(a0 != nullptr); + ASSERT_TRUE(a0.get() == a3); + ASSERT_TRUE(a0 == a3.get()); + linked_ptr<A> a4(a0); + a1 = a4; + linked_ptr<A> a5(new A); + ASSERT_TRUE(a5.get() != a3); + ASSERT_TRUE(a5 != a3.get()); + a2 = a5; + linked_ptr<B> b0(new B); + linked_ptr<A> a6(b0); + ASSERT_TRUE(b0 == a6); + ASSERT_TRUE(a6 == b0); + ASSERT_TRUE(b0 != nullptr); + a5 = b0; + a5 = b0; + a3->Use(); + a4->Use(); + a5->Use(); + a6->Use(); + b0->Use(); + (*b0).Use(); + b0.get()->Use(); + } + + a0->Use(); + a1->Use(); + a2->Use(); + + a1 = a2; + a2.reset(new A); + a0.reset(); + + linked_ptr<A> a7; + } + + ASSERT_STREQ( + "A0 ctor\n" + "A1 ctor\n" + "A2 ctor\n" + "B2 ctor\n" + "A0 use\n" + "A0 use\n" + "B2 use\n" + "B2 use\n" + "B2 use\n" + "B2 use\n" + "B2 use\n" + "B2 dtor\n" + "A2 dtor\n" + "A0 use\n" + "A0 use\n" + "A1 use\n" + "A3 ctor\n" + "A0 dtor\n" + "A3 dtor\n" + "A1 dtor\n", + history->GetString().c_str()); +} + +} // Unnamed namespace diff --git a/googletest/test/gtest_all_test.cc b/googletest/test/gtest_all_test.cc index 615b29b..f948a10 100644 --- a/googletest/test/gtest_all_test.cc +++ b/googletest/test/gtest_all_test.cc @@ -33,6 +33,7 @@ // Sometimes it's desirable to build most of Google Test's own tests // by compiling a single file. This file serves this purpose. #include "test/googletest-filepath-test.cc" +#include "test/googletest-linked-ptr-test.cc" #include "test/googletest-message-test.cc" #include "test/googletest-options-test.cc" #include "test/googletest-port-test.cc" |