// 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"
namespace fxcrt {
namespace {
class PseudoObservable : public Observable<PseudoObservable> {
public:
PseudoObservable() {}
int SomeMethod() { return 42; }
size_t ActiveObservedPtrs() const { return ActiveObservedPtrsForTesting(); }
};
} // namespace
TEST(ObservePtr, Null) {
PseudoObservable::ObservedPtr ptr;
EXPECT_EQ(nullptr, ptr.Get());
}
TEST(ObservePtr, LivesLonger) {
PseudoObservable* pObs = new PseudoObservable;
PseudoObservable::ObservedPtr ptr(pObs);
EXPECT_NE(nullptr, ptr.Get());
EXPECT_EQ(1u, pObs->ActiveObservedPtrs());
delete pObs;
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);
}
} // namespace fxcrt