// 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/observed_ptr.h" #include #include #include "testing/gtest/include/gtest/gtest.h" #include "third_party/base/ptr_util.h" namespace fxcrt { namespace { class PseudoObservable final : public Observable { public: int SomeMethod() { return 42; } size_t ActiveObservedPtrs() const { return ActiveObserversForTesting(); } }; class SelfObservable final : public Observable { public: ObservedPtr m_pOther; }; } // namespace TEST(ObservePtr, Null) { ObservedPtr ptr; EXPECT_EQ(nullptr, ptr.Get()); } TEST(ObservePtr, LivesLonger) { ObservedPtr ptr; { auto pObs = pdfium::MakeUnique(); ptr.Reset(pObs.get()); EXPECT_NE(nullptr, ptr.Get()); EXPECT_EQ(1u, pObs->ActiveObservedPtrs()); } EXPECT_EQ(nullptr, ptr.Get()); } TEST(ObservePtr, LivesShorter) { PseudoObservable obs; { ObservedPtr ptr(&obs); EXPECT_NE(nullptr, ptr.Get()); EXPECT_EQ(1u, obs.ActiveObservedPtrs()); } EXPECT_EQ(0u, obs.ActiveObservedPtrs()); } TEST(ObservePtr, CopyConstruct) { PseudoObservable obs; { ObservedPtr ptr(&obs); EXPECT_NE(nullptr, ptr.Get()); EXPECT_EQ(1u, obs.ActiveObservedPtrs()); { ObservedPtr ptr2(ptr); EXPECT_NE(nullptr, ptr2.Get()); EXPECT_EQ(2u, obs.ActiveObservedPtrs()); } EXPECT_EQ(1u, obs.ActiveObservedPtrs()); } EXPECT_EQ(0u, obs.ActiveObservedPtrs()); } TEST(ObservePtr, CopyAssign) { PseudoObservable obs; { ObservedPtr ptr(&obs); EXPECT_NE(nullptr, ptr.Get()); EXPECT_EQ(1u, obs.ActiveObservedPtrs()); { ObservedPtr ptr2; ptr2 = ptr; EXPECT_NE(nullptr, ptr2.Get()); EXPECT_EQ(2u, obs.ActiveObservedPtrs()); } EXPECT_EQ(1u, obs.ActiveObservedPtrs()); } EXPECT_EQ(0u, obs.ActiveObservedPtrs()); } TEST(ObservePtr, Vector) { PseudoObservable obs; { std::vector> vec1; std::vector> vec2; vec1.emplace_back(&obs); vec1.emplace_back(&obs); EXPECT_NE(nullptr, vec1[0].Get()); EXPECT_NE(nullptr, vec1[1].Get()); EXPECT_EQ(2u, obs.ActiveObservedPtrs()); vec2 = vec1; EXPECT_NE(nullptr, vec2[0].Get()); EXPECT_NE(nullptr, vec2[1].Get()); EXPECT_EQ(4u, obs.ActiveObservedPtrs()); vec1.clear(); EXPECT_EQ(2u, obs.ActiveObservedPtrs()); vec2.resize(10000); EXPECT_EQ(2u, obs.ActiveObservedPtrs()); vec2.resize(0); EXPECT_EQ(0u, obs.ActiveObservedPtrs()); } EXPECT_EQ(0u, obs.ActiveObservedPtrs()); } TEST(ObservePtr, VectorAutoClear) { std::vector> vec1; { PseudoObservable obs; vec1.emplace_back(&obs); vec1.emplace_back(&obs); EXPECT_NE(nullptr, vec1[0].Get()); EXPECT_NE(nullptr, vec1[1].Get()); EXPECT_EQ(2u, obs.ActiveObservedPtrs()); } EXPECT_EQ(nullptr, vec1[0].Get()); EXPECT_EQ(nullptr, vec1[1].Get()); } TEST(ObservePtr, ResetNull) { PseudoObservable obs; ObservedPtr ptr(&obs); EXPECT_EQ(1u, obs.ActiveObservedPtrs()); ptr.Reset(); EXPECT_EQ(0u, obs.ActiveObservedPtrs()); } TEST(ObservePtr, Reset) { PseudoObservable obs1; PseudoObservable obs2; ObservedPtr ptr(&obs1); EXPECT_EQ(1u, obs1.ActiveObservedPtrs()); EXPECT_EQ(0u, obs2.ActiveObservedPtrs()); ptr.Reset(&obs2); EXPECT_EQ(0u, obs1.ActiveObservedPtrs()); EXPECT_EQ(1u, obs2.ActiveObservedPtrs()); } TEST(ObservePtr, Equals) { PseudoObservable obj1; PseudoObservable obj2; ObservedPtr null_ptr1; ObservedPtr obj1_ptr1(&obj1); ObservedPtr obj2_ptr1(&obj2); EXPECT_TRUE(&obj1 == obj1_ptr1); EXPECT_TRUE(obj1_ptr1 == &obj1); EXPECT_TRUE(&obj2 == obj2_ptr1); EXPECT_TRUE(obj2_ptr1 == &obj2); { ObservedPtr null_ptr2; EXPECT_TRUE(null_ptr1 == null_ptr2); ObservedPtr obj1_ptr2(&obj1); EXPECT_TRUE(obj1_ptr1 == obj1_ptr2); ObservedPtr 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(ObservePtr, NotEquals) { PseudoObservable obj1; PseudoObservable obj2; ObservedPtr null_ptr1; ObservedPtr obj1_ptr1(&obj1); ObservedPtr obj2_ptr1(&obj2); EXPECT_FALSE(&obj1 != obj1_ptr1); EXPECT_FALSE(obj1_ptr1 != &obj1); EXPECT_FALSE(&obj2 != obj2_ptr1); EXPECT_FALSE(obj2_ptr1 != &obj2); { ObservedPtr null_ptr2; ObservedPtr obj1_ptr2(&obj1); ObservedPtr 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(ObservePtr, Bool) { PseudoObservable obj1; ObservedPtr null_ptr; ObservedPtr obj1_ptr(&obj1); bool null_bool = !!null_ptr; bool obj1_bool = !!obj1_ptr; EXPECT_FALSE(null_bool); EXPECT_TRUE(obj1_bool); } TEST(ObservePtr, SelfObservable) { SelfObservable thing; thing.m_pOther.Reset(&thing); EXPECT_EQ(&thing, thing.m_pOther.Get()); // Must be no ASAN violations upon cleanup here. } TEST(ObservePtr, PairwiseObservable) { SelfObservable thing1; { SelfObservable thing2; thing1.m_pOther.Reset(&thing2); thing2.m_pOther.Reset(&thing1); EXPECT_EQ(&thing2, thing1.m_pOther.Get()); EXPECT_EQ(&thing1, thing2.m_pOther.Get()); } EXPECT_EQ(nullptr, thing1.m_pOther.Get()); // Must be no ASAN violations upon cleanup here. } } // namespace fxcrt