| // Copyright 2016 PDFium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "core/fxcrt/weak_ptr.h" | |
| #include <memory> | |
| #include <utility> | |
| #include "core/fxcrt/fx_memory.h" | |
| #include "testing/gtest/include/gtest/gtest.h" | |
| namespace fxcrt { | |
| namespace { | |
| class PseudoDeletable; | |
| using WeakTestPtr = WeakPtr<PseudoDeletable, ReleaseDeleter<PseudoDeletable>>; | |
| using UniqueTestPtr = | |
| std::unique_ptr<PseudoDeletable, ReleaseDeleter<PseudoDeletable>>; | |
| class PseudoDeletable { | |
| public: | |
| PseudoDeletable() : delete_count_(0) {} | |
| void Release() { | |
| ++delete_count_; | |
| next_.Reset(); | |
| } | |
| void SetNext(const WeakTestPtr& next) { next_ = next; } | |
| int delete_count() const { return delete_count_; } | |
| private: | |
| int delete_count_; | |
| WeakTestPtr next_; | |
| }; | |
| } // namespace | |
| TEST(WeakPtr, Null) { | |
| WeakTestPtr ptr1; | |
| EXPECT_FALSE(ptr1); | |
| WeakTestPtr ptr2; | |
| EXPECT_TRUE(ptr1 == ptr2); | |
| EXPECT_FALSE(ptr1 != ptr2); | |
| WeakTestPtr ptr3(ptr1); | |
| EXPECT_TRUE(ptr1 == ptr3); | |
| EXPECT_FALSE(ptr1 != ptr3); | |
| WeakTestPtr ptr4 = ptr1; | |
| EXPECT_TRUE(ptr1 == ptr4); | |
| EXPECT_FALSE(ptr1 != ptr4); | |
| } | |
| TEST(WeakPtr, NonNull) { | |
| PseudoDeletable thing; | |
| EXPECT_EQ(0, thing.delete_count()); | |
| { | |
| UniqueTestPtr unique(&thing); | |
| WeakTestPtr ptr1(std::move(unique)); | |
| EXPECT_TRUE(ptr1); | |
| EXPECT_EQ(&thing, ptr1.Get()); | |
| WeakTestPtr ptr2; | |
| EXPECT_FALSE(ptr1 == ptr2); | |
| EXPECT_TRUE(ptr1 != ptr2); | |
| { | |
| WeakTestPtr ptr3(ptr1); | |
| EXPECT_TRUE(ptr1 == ptr3); | |
| EXPECT_FALSE(ptr1 != ptr3); | |
| EXPECT_EQ(&thing, ptr3.Get()); | |
| { | |
| WeakTestPtr ptr4 = ptr1; | |
| EXPECT_TRUE(ptr1 == ptr4); | |
| EXPECT_FALSE(ptr1 != ptr4); | |
| EXPECT_EQ(&thing, ptr4.Get()); | |
| } | |
| } | |
| EXPECT_EQ(0, thing.delete_count()); | |
| } | |
| EXPECT_EQ(1, thing.delete_count()); | |
| } | |
| TEST(WeakPtr, ResetNull) { | |
| PseudoDeletable thing; | |
| { | |
| UniqueTestPtr unique(&thing); | |
| WeakTestPtr ptr1(std::move(unique)); | |
| WeakTestPtr ptr2 = ptr1; | |
| ptr1.Reset(); | |
| EXPECT_FALSE(ptr1); | |
| EXPECT_EQ(nullptr, ptr1.Get()); | |
| EXPECT_TRUE(ptr2); | |
| EXPECT_EQ(&thing, ptr2.Get()); | |
| EXPECT_FALSE(ptr1 == ptr2); | |
| EXPECT_TRUE(ptr1 != ptr2); | |
| EXPECT_EQ(0, thing.delete_count()); | |
| } | |
| EXPECT_EQ(1, thing.delete_count()); | |
| } | |
| TEST(WeakPtr, ResetNonNull) { | |
| PseudoDeletable thing1; | |
| PseudoDeletable thing2; | |
| { | |
| UniqueTestPtr unique1(&thing1); | |
| WeakTestPtr ptr1(std::move(unique1)); | |
| WeakTestPtr ptr2 = ptr1; | |
| UniqueTestPtr unique2(&thing2); | |
| ptr2.Reset(std::move(unique2)); | |
| EXPECT_TRUE(ptr1); | |
| EXPECT_EQ(&thing1, ptr1.Get()); | |
| EXPECT_TRUE(ptr2); | |
| EXPECT_EQ(&thing2, ptr2.Get()); | |
| EXPECT_FALSE(ptr1 == ptr2); | |
| EXPECT_TRUE(ptr1 != ptr2); | |
| EXPECT_EQ(0, thing1.delete_count()); | |
| EXPECT_EQ(0, thing2.delete_count()); | |
| } | |
| EXPECT_EQ(1, thing1.delete_count()); | |
| EXPECT_EQ(1, thing2.delete_count()); | |
| } | |
| TEST(WeakPtr, DeleteObject) { | |
| PseudoDeletable thing; | |
| { | |
| UniqueTestPtr unique(&thing); | |
| WeakTestPtr ptr1(std::move(unique)); | |
| WeakTestPtr ptr2 = ptr1; | |
| ptr1.DeleteObject(); | |
| EXPECT_FALSE(ptr1); | |
| EXPECT_EQ(nullptr, ptr1.Get()); | |
| EXPECT_FALSE(ptr2); | |
| EXPECT_EQ(nullptr, ptr2.Get()); | |
| EXPECT_FALSE(ptr1 == ptr2); | |
| EXPECT_TRUE(ptr1 != ptr2); | |
| EXPECT_EQ(1, thing.delete_count()); | |
| } | |
| EXPECT_EQ(1, thing.delete_count()); | |
| } | |
| TEST(WeakPtr, Cyclic) { | |
| PseudoDeletable thing1; | |
| PseudoDeletable thing2; | |
| { | |
| UniqueTestPtr unique1(&thing1); | |
| UniqueTestPtr unique2(&thing2); | |
| WeakTestPtr ptr1(std::move(unique1)); | |
| WeakTestPtr ptr2(std::move(unique2)); | |
| ptr1->SetNext(ptr2); | |
| ptr2->SetNext(ptr1); | |
| } | |
| // Leaks without explicit clear. | |
| EXPECT_EQ(0, thing1.delete_count()); | |
| EXPECT_EQ(0, thing2.delete_count()); | |
| } | |
| TEST(WeakPtr, CyclicDeleteObject) { | |
| PseudoDeletable thing1; | |
| PseudoDeletable thing2; | |
| { | |
| UniqueTestPtr unique1(&thing1); | |
| UniqueTestPtr unique2(&thing2); | |
| WeakTestPtr ptr1(std::move(unique1)); | |
| WeakTestPtr ptr2(std::move(unique2)); | |
| ptr1->SetNext(ptr2); | |
| ptr2->SetNext(ptr1); | |
| ptr1.DeleteObject(); | |
| EXPECT_EQ(1, thing1.delete_count()); | |
| EXPECT_EQ(0, thing2.delete_count()); | |
| } | |
| EXPECT_EQ(1, thing1.delete_count()); | |
| EXPECT_EQ(1, thing2.delete_count()); | |
| } | |
| } // namespace fxcrt |