| // 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/observable.h" |
| |
| #include <utility> |
| #include <vector> |
| |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/base/ptr_util.h" |
| |
| namespace fxcrt { |
| namespace { |
| |
| class PseudoObservable final : public Observable<PseudoObservable> { |
| public: |
| int SomeMethod() { return 42; } |
| size_t ActiveObservedPtrs() const { return ActiveObserversForTesting(); } |
| }; |
| |
| class SelfObservable final : public Observable<SelfObservable> { |
| public: |
| ObservedPtr m_pOther; |
| }; |
| |
| } // namespace |
| |
| TEST(ObservePtr, Null) { |
| PseudoObservable::ObservedPtr ptr; |
| EXPECT_EQ(nullptr, ptr.Get()); |
| } |
| |
| TEST(ObservePtr, LivesLonger) { |
| PseudoObservable::ObservedPtr ptr; |
| { |
| auto pObs = pdfium::MakeUnique<PseudoObservable>(); |
| ptr.Reset(pObs.get()); |
| EXPECT_NE(nullptr, ptr.Get()); |
| EXPECT_EQ(1u, pObs->ActiveObservedPtrs()); |
| } |
| EXPECT_EQ(nullptr, ptr.Get()); |
| } |
| |
| TEST(ObservePtr, LivesShorter) { |
| PseudoObservable obs; |
| { |
| PseudoObservable::ObservedPtr ptr(&obs); |
| EXPECT_NE(nullptr, ptr.Get()); |
| EXPECT_EQ(1u, obs.ActiveObservedPtrs()); |
| } |
| EXPECT_EQ(0u, obs.ActiveObservedPtrs()); |
| } |
| |
| TEST(ObservePtr, CopyConstruct) { |
| PseudoObservable obs; |
| { |
| PseudoObservable::ObservedPtr ptr(&obs); |
| EXPECT_NE(nullptr, ptr.Get()); |
| EXPECT_EQ(1u, obs.ActiveObservedPtrs()); |
| { |
| PseudoObservable::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; |
| { |
| PseudoObservable::ObservedPtr ptr(&obs); |
| EXPECT_NE(nullptr, ptr.Get()); |
| EXPECT_EQ(1u, obs.ActiveObservedPtrs()); |
| { |
| PseudoObservable::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<PseudoObservable::ObservedPtr> vec1; |
| std::vector<PseudoObservable::ObservedPtr> 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<PseudoObservable::ObservedPtr> 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; |
| PseudoObservable::ObservedPtr ptr(&obs); |
| EXPECT_EQ(1u, obs.ActiveObservedPtrs()); |
| ptr.Reset(); |
| EXPECT_EQ(0u, obs.ActiveObservedPtrs()); |
| } |
| |
| TEST(ObservePtr, Reset) { |
| PseudoObservable obs1; |
| PseudoObservable obs2; |
| PseudoObservable::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; |
| PseudoObservable::ObservedPtr null_ptr1; |
| PseudoObservable::ObservedPtr obj1_ptr1(&obj1); |
| PseudoObservable::ObservedPtr obj2_ptr1(&obj2); |
| { |
| PseudoObservable::ObservedPtr null_ptr2; |
| EXPECT_TRUE(null_ptr1 == null_ptr2); |
| |
| PseudoObservable::ObservedPtr obj1_ptr2(&obj1); |
| EXPECT_TRUE(obj1_ptr1 == obj1_ptr2); |
| |
| PseudoObservable::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; |
| PseudoObservable::ObservedPtr null_ptr1; |
| PseudoObservable::ObservedPtr obj1_ptr1(&obj1); |
| PseudoObservable::ObservedPtr obj2_ptr1(&obj2); |
| { |
| PseudoObservable::ObservedPtr null_ptr2; |
| PseudoObservable::ObservedPtr obj1_ptr2(&obj1); |
| PseudoObservable::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; |
| PseudoObservable::ObservedPtr null_ptr; |
| PseudoObservable::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 |