blob: c748f1447d66ab7b8cd9ee17bc283a5f5357ffa3 [file] [log] [blame]
// Copyright 2016 The PDFium Authors
// 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 <memory>
#include <utility>
#include <vector>
#include "testing/gtest/include/gtest/gtest.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<SelfObservable> m_pOther;
};
} // namespace
TEST(ObservePtr, Null) {
ObservedPtr<PseudoObservable> ptr;
EXPECT_FALSE(ptr.Get());
}
TEST(ObservePtr, LivesLonger) {
ObservedPtr<PseudoObservable> ptr;
{
auto pObs = std::make_unique<PseudoObservable>();
ptr.Reset(pObs.get());
EXPECT_TRUE(ptr.Get());
EXPECT_EQ(1u, pObs->ActiveObservedPtrs());
}
EXPECT_FALSE(ptr.Get());
}
TEST(ObservePtr, LivesShorter) {
PseudoObservable obs;
{
ObservedPtr<PseudoObservable> ptr(&obs);
EXPECT_TRUE(ptr.Get());
EXPECT_EQ(1u, obs.ActiveObservedPtrs());
}
EXPECT_EQ(0u, obs.ActiveObservedPtrs());
}
TEST(ObservePtr, CopyConstruct) {
PseudoObservable obs;
{
ObservedPtr<PseudoObservable> ptr(&obs);
EXPECT_TRUE(ptr.Get());
EXPECT_EQ(1u, obs.ActiveObservedPtrs());
{
ObservedPtr<PseudoObservable> ptr2(ptr);
EXPECT_TRUE(ptr2.Get());
EXPECT_EQ(2u, obs.ActiveObservedPtrs());
}
EXPECT_EQ(1u, obs.ActiveObservedPtrs());
}
EXPECT_EQ(0u, obs.ActiveObservedPtrs());
}
TEST(ObservePtr, CopyAssign) {
PseudoObservable obs;
{
ObservedPtr<PseudoObservable> ptr(&obs);
EXPECT_TRUE(ptr.Get());
EXPECT_EQ(1u, obs.ActiveObservedPtrs());
{
ObservedPtr<PseudoObservable> ptr2;
ptr2 = ptr;
EXPECT_TRUE(ptr2.Get());
EXPECT_EQ(2u, obs.ActiveObservedPtrs());
}
EXPECT_EQ(1u, obs.ActiveObservedPtrs());
}
EXPECT_EQ(0u, obs.ActiveObservedPtrs());
}
TEST(ObservePtr, Vector) {
PseudoObservable obs;
{
std::vector<ObservedPtr<PseudoObservable>> vec1;
std::vector<ObservedPtr<PseudoObservable>> vec2;
vec1.emplace_back(&obs);
vec1.emplace_back(&obs);
EXPECT_TRUE(vec1[0].Get());
EXPECT_TRUE(vec1[1].Get());
EXPECT_EQ(2u, obs.ActiveObservedPtrs());
vec2 = vec1;
EXPECT_TRUE(vec2[0].Get());
EXPECT_TRUE(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<ObservedPtr<PseudoObservable>> vec1;
{
PseudoObservable obs;
vec1.emplace_back(&obs);
vec1.emplace_back(&obs);
EXPECT_TRUE(vec1[0].Get());
EXPECT_TRUE(vec1[1].Get());
EXPECT_EQ(2u, obs.ActiveObservedPtrs());
}
EXPECT_FALSE(vec1[0].Get());
EXPECT_FALSE(vec1[1].Get());
}
TEST(ObservePtr, ResetNull) {
PseudoObservable obs;
ObservedPtr<PseudoObservable> ptr(&obs);
EXPECT_EQ(1u, obs.ActiveObservedPtrs());
ptr.Reset();
EXPECT_EQ(0u, obs.ActiveObservedPtrs());
}
TEST(ObservePtr, Reset) {
PseudoObservable obs1;
PseudoObservable obs2;
ObservedPtr<PseudoObservable> 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<PseudoObservable> null_ptr1;
ObservedPtr<PseudoObservable> obj1_ptr1(&obj1);
ObservedPtr<PseudoObservable> obj2_ptr1(&obj2);
EXPECT_TRUE(&obj1 == obj1_ptr1);
EXPECT_TRUE(obj1_ptr1 == &obj1);
EXPECT_TRUE(&obj2 == obj2_ptr1);
EXPECT_TRUE(obj2_ptr1 == &obj2);
{
ObservedPtr<PseudoObservable> null_ptr2;
EXPECT_TRUE(null_ptr1 == null_ptr2);
ObservedPtr<PseudoObservable> obj1_ptr2(&obj1);
EXPECT_TRUE(obj1_ptr1 == obj1_ptr2);
ObservedPtr<PseudoObservable> 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<PseudoObservable> null_ptr1;
ObservedPtr<PseudoObservable> obj1_ptr1(&obj1);
ObservedPtr<PseudoObservable> obj2_ptr1(&obj2);
EXPECT_FALSE(&obj1 != obj1_ptr1);
EXPECT_FALSE(obj1_ptr1 != &obj1);
EXPECT_FALSE(&obj2 != obj2_ptr1);
EXPECT_FALSE(obj2_ptr1 != &obj2);
{
ObservedPtr<PseudoObservable> null_ptr2;
ObservedPtr<PseudoObservable> obj1_ptr2(&obj1);
ObservedPtr<PseudoObservable> 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<PseudoObservable> null_ptr;
ObservedPtr<PseudoObservable> 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_FALSE(thing1.m_pOther.Get());
// Must be no ASAN violations upon cleanup here.
}
} // namespace fxcrt