blob: d469ab3e47f9500a217510ca64ac09715795dd68 [file] [log] [blame]
// Copyright 2019 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/retained_tree_node.h"
#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/retain_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace fxcrt {
namespace {
class ObservableRetainedTreeNodeForTest
: public RetainedTreeNode<ObservableRetainedTreeNodeForTest>,
public Observable {
public:
template <typename T, typename... Args>
friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
private:
ObservableRetainedTreeNodeForTest() = default;
};
void AddClutterToFront(
const RetainPtr<ObservableRetainedTreeNodeForTest>& parent) {
for (int i = 0; i < 4; ++i) {
parent->AppendFirstChild(
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>());
}
}
void AddClutterToBack(
const RetainPtr<ObservableRetainedTreeNodeForTest>& parent) {
for (int i = 0; i < 4; ++i) {
parent->AppendLastChild(
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>());
}
}
} // namespace
TEST(RetainedTreeNode, NoParent) {
ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
{
RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
EXPECT_FALSE(ptr->HasChild(ptr.Get()));
watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
EXPECT_TRUE(watcher.Get());
}
EXPECT_FALSE(watcher.Get());
}
TEST(RetainedTreeNode, FirstHasParent) {
ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
RetainPtr<ObservableRetainedTreeNodeForTest> parent =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
{
RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
parent->AppendFirstChild(ptr);
EXPECT_FALSE(parent->HasChild(parent.Get()));
EXPECT_TRUE(parent->HasChild(ptr.Get()));
EXPECT_TRUE(watcher.Get());
}
EXPECT_TRUE(watcher.Get());
parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
EXPECT_FALSE(watcher.Get());
// Now add some clutter.
{
RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
parent->AppendFirstChild(ptr);
AddClutterToFront(parent);
AddClutterToBack(parent);
EXPECT_TRUE(watcher.Get());
}
EXPECT_TRUE(watcher.Get());
parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
EXPECT_FALSE(watcher.Get());
}
TEST(RetainedTreeNode, LastHasParent) {
ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
RetainPtr<ObservableRetainedTreeNodeForTest> parent =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
{
RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
parent->AppendLastChild(ptr);
EXPECT_FALSE(parent->HasChild(parent.Get()));
EXPECT_TRUE(parent->HasChild(ptr.Get()));
EXPECT_TRUE(watcher.Get());
}
{
// Now add some clutter.
RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
parent->AppendLastChild(ptr);
AddClutterToFront(parent);
AddClutterToBack(parent);
EXPECT_TRUE(watcher.Get());
}
EXPECT_TRUE(watcher.Get());
parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
EXPECT_FALSE(watcher.Get());
}
TEST(RetainedTreeNode, GrandChildCleanedUp) {
ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
RetainPtr<ObservableRetainedTreeNodeForTest> grandparent =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
{
RetainPtr<ObservableRetainedTreeNodeForTest> parent =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
grandparent->AppendFirstChild(parent);
{
RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
parent->AppendFirstChild(ptr);
EXPECT_TRUE(watcher.Get());
}
grandparent->RemoveChild(parent);
EXPECT_TRUE(watcher.Get());
}
EXPECT_FALSE(watcher.Get());
}
TEST(RetainedTreeNode, RemoveSelf) {
ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
auto parent = pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
{
auto child = pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(child.Get());
parent->AppendFirstChild(child);
}
EXPECT_TRUE(watcher.Get());
watcher->RemoveSelfIfParented();
EXPECT_FALSE(watcher.Get());
}
TEST(RetainedTreeNode, InsertBeforeAfter) {
ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
RetainPtr<ObservableRetainedTreeNodeForTest> parent =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
AddClutterToFront(parent);
{
RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
parent->AppendFirstChild(ptr);
parent->InsertBefore(pdfium::WrapRetain(parent->GetFirstChild()),
parent->GetLastChild());
parent->InsertAfter(pdfium::WrapRetain(parent->GetLastChild()),
parent->GetFirstChild());
EXPECT_TRUE(watcher.Get());
}
parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
EXPECT_FALSE(watcher.Get());
}
TEST(RetainedTreeNode, Traversal) {
RetainPtr<ObservableRetainedTreeNodeForTest> parent =
pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
AddClutterToFront(parent);
int count = 0;
for (ObservableRetainedTreeNodeForTest* pNode = parent->GetFirstChild();
pNode; pNode = pNode->GetNextSibling()) {
++count;
}
EXPECT_EQ(4, count);
count = 0;
for (ObservableRetainedTreeNodeForTest* pNode = parent->GetLastChild(); pNode;
pNode = pNode->GetPrevSibling()) {
++count;
}
EXPECT_EQ(4, count);
}
} // namespace fxcrt