// 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/retain_ptr.h" #include #include #include "testing/gtest/include/gtest/gtest.h" #include "testing/pseudo_retainable.h" namespace fxcrt { TEST(RetainPtr, Null) { RetainPtr ptr; EXPECT_EQ(nullptr, ptr.Get()); } TEST(RetainPtr, Normal) { PseudoRetainable obj; { RetainPtr ptr(&obj); EXPECT_EQ(&obj, ptr.Get()); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); } EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } TEST(RetainPtr, CopyCtor) { PseudoRetainable obj; { RetainPtr ptr1(&obj); { RetainPtr ptr2(ptr1); EXPECT_EQ(2, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); } EXPECT_EQ(2, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } EXPECT_EQ(2, obj.retain_count()); EXPECT_EQ(2, obj.release_count()); } TEST(RetainPtr, MoveCtor) { PseudoRetainable obj; { RetainPtr ptr1(&obj); { RetainPtr ptr2(std::move(ptr1)); EXPECT_EQ(nullptr, ptr1.Get()); EXPECT_EQ(&obj, ptr2.Get()); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); } EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } TEST(RetainPtr, ResetNull) { PseudoRetainable obj; { RetainPtr ptr(&obj); ptr.Reset(); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } TEST(RetainPtr, Reset) { PseudoRetainable obj1; PseudoRetainable obj2; { RetainPtr ptr(&obj1); ptr.Reset(&obj2); EXPECT_EQ(1, obj1.retain_count()); EXPECT_EQ(1, obj1.release_count()); EXPECT_EQ(1, obj2.retain_count()); EXPECT_EQ(0, obj2.release_count()); } EXPECT_EQ(1, obj1.retain_count()); EXPECT_EQ(1, obj1.release_count()); EXPECT_EQ(1, obj2.retain_count()); EXPECT_EQ(1, obj2.release_count()); } TEST(RetainPtr, Swap) { PseudoRetainable obj1; PseudoRetainable obj2; { RetainPtr ptr1(&obj1); { RetainPtr ptr2(&obj2); ptr1.Swap(ptr2); EXPECT_EQ(1, obj1.retain_count()); EXPECT_EQ(0, obj1.release_count()); EXPECT_EQ(1, obj2.retain_count()); EXPECT_EQ(0, obj2.release_count()); } EXPECT_EQ(1, obj1.retain_count()); EXPECT_EQ(1, obj1.release_count()); EXPECT_EQ(1, obj2.retain_count()); EXPECT_EQ(0, obj2.release_count()); } EXPECT_EQ(1, obj1.retain_count()); EXPECT_EQ(1, obj1.release_count()); EXPECT_EQ(1, obj2.retain_count()); EXPECT_EQ(1, obj2.release_count()); } TEST(RetainPtr, Leak) { PseudoRetainable obj; PseudoRetainable* leak; { RetainPtr ptr(&obj); leak = ptr.Leak(); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); } EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); { RetainPtr ptr; ptr.Unleak(leak); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); } EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } TEST(RetainPtr, SwapNull) { PseudoRetainable obj1; { RetainPtr ptr1(&obj1); { RetainPtr ptr2; ptr1.Swap(ptr2); EXPECT_FALSE(ptr1); EXPECT_TRUE(ptr2); EXPECT_EQ(1, obj1.retain_count()); EXPECT_EQ(0, obj1.release_count()); } EXPECT_EQ(1, obj1.retain_count()); EXPECT_EQ(1, obj1.release_count()); } EXPECT_EQ(1, obj1.retain_count()); EXPECT_EQ(1, obj1.release_count()); } TEST(RetainPtr, Assign) { PseudoRetainable obj; { RetainPtr ptr(&obj); { RetainPtr ptr2; ptr2 = ptr; EXPECT_EQ(2, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); } EXPECT_EQ(2, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } EXPECT_EQ(2, obj.retain_count()); EXPECT_EQ(2, obj.release_count()); } TEST(RetainPtr, MoveAssign) { PseudoRetainable obj; { RetainPtr ptr1(&obj); { RetainPtr ptr2; EXPECT_EQ(&obj, ptr1.Get()); EXPECT_EQ(nullptr, ptr2.Get()); ptr2 = std::move(ptr1); EXPECT_EQ(nullptr, ptr1.Get()); EXPECT_EQ(&obj, ptr2.Get()); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); } EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } TEST(RetainPtr, Equals) { PseudoRetainable obj1; PseudoRetainable obj2; RetainPtr null_ptr1; RetainPtr obj1_ptr1(&obj1); RetainPtr obj2_ptr1(&obj2); { RetainPtr null_ptr2; EXPECT_TRUE(null_ptr1 == null_ptr2); RetainPtr obj1_ptr2(&obj1); EXPECT_TRUE(obj1_ptr1 == obj1_ptr2); RetainPtr obj2_ptr2(&obj2); EXPECT_TRUE(obj2_ptr1 == obj2_ptr2); } EXPECT_FALSE(null_ptr1 == obj1_ptr1); EXPECT_FALSE(null_ptr1 == obj2_ptr1); EXPECT_FALSE(obj1_ptr1 == obj2_ptr1); } TEST(RetainPtr, NotEquals) { PseudoRetainable obj1; PseudoRetainable obj2; RetainPtr null_ptr1; RetainPtr obj1_ptr1(&obj1); RetainPtr obj2_ptr1(&obj2); { RetainPtr null_ptr2; RetainPtr obj1_ptr2(&obj1); RetainPtr obj2_ptr2(&obj2); EXPECT_FALSE(null_ptr1 != null_ptr2); EXPECT_FALSE(obj1_ptr1 != obj1_ptr2); EXPECT_FALSE(obj2_ptr1 != obj2_ptr2); } EXPECT_TRUE(null_ptr1 != obj1_ptr1); EXPECT_TRUE(null_ptr1 != obj2_ptr1); EXPECT_TRUE(obj1_ptr1 != obj2_ptr1); } TEST(RetainPtr, LessThan) { PseudoRetainable objs[2]; RetainPtr obj1_ptr(&objs[0]); RetainPtr obj2_ptr(&objs[1]); EXPECT_TRUE(obj1_ptr < obj2_ptr); EXPECT_FALSE(obj2_ptr < obj1_ptr); } TEST(RetainPtr, Bool) { PseudoRetainable obj1; RetainPtr null_ptr; RetainPtr obj1_ptr(&obj1); bool null_bool = !!null_ptr; bool obj1_bool = !!obj1_ptr; EXPECT_FALSE(null_bool); EXPECT_TRUE(obj1_bool); } TEST(RetainPtr, MakeRetained) { auto ptr = pdfium::MakeRetain(); EXPECT_TRUE(ptr->HasOneRef()); { RetainPtr other = ptr; EXPECT_FALSE(ptr->HasOneRef()); } EXPECT_TRUE(ptr->HasOneRef()); } TEST(RetainPtr, VectorMove) { // Proves move ctor is selected by std::vector over copy/delete, this // may require the ctor to be marked "noexcept". PseudoRetainable obj; { RetainPtr ptr(&obj); std::vector> vec1; vec1.push_back(std::move(ptr)); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); std::vector> vec2 = std::move(vec1); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); vec2.resize(4096); EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(0, obj.release_count()); } EXPECT_EQ(1, obj.retain_count()); EXPECT_EQ(1, obj.release_count()); } } // namespace fxcrt