// 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/weak_ptr.h"
|
|
#include <memory>
|
#include <utility>
|
|
#include "core/fxcrt/fx_memory.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
namespace fxcrt {
|
namespace {
|
|
class PseudoDeletable;
|
using WeakTestPtr = WeakPtr<PseudoDeletable, ReleaseDeleter<PseudoDeletable>>;
|
using UniqueTestPtr =
|
std::unique_ptr<PseudoDeletable, ReleaseDeleter<PseudoDeletable>>;
|
|
class PseudoDeletable {
|
public:
|
PseudoDeletable() : delete_count_(0) {}
|
void Release() {
|
++delete_count_;
|
next_.Reset();
|
}
|
void SetNext(const WeakTestPtr& next) { next_ = next; }
|
int delete_count() const { return delete_count_; }
|
|
private:
|
int delete_count_;
|
WeakTestPtr next_;
|
};
|
|
} // namespace
|
|
TEST(WeakPtr, Null) {
|
WeakTestPtr ptr1;
|
EXPECT_FALSE(ptr1);
|
|
WeakTestPtr ptr2;
|
EXPECT_TRUE(ptr1 == ptr2);
|
EXPECT_FALSE(ptr1 != ptr2);
|
|
WeakTestPtr ptr3(ptr1);
|
EXPECT_TRUE(ptr1 == ptr3);
|
EXPECT_FALSE(ptr1 != ptr3);
|
|
WeakTestPtr ptr4 = ptr1;
|
EXPECT_TRUE(ptr1 == ptr4);
|
EXPECT_FALSE(ptr1 != ptr4);
|
}
|
|
TEST(WeakPtr, NonNull) {
|
PseudoDeletable thing;
|
EXPECT_EQ(0, thing.delete_count());
|
{
|
UniqueTestPtr unique(&thing);
|
WeakTestPtr ptr1(std::move(unique));
|
EXPECT_TRUE(ptr1);
|
EXPECT_EQ(&thing, ptr1.Get());
|
|
WeakTestPtr ptr2;
|
EXPECT_FALSE(ptr1 == ptr2);
|
EXPECT_TRUE(ptr1 != ptr2);
|
{
|
WeakTestPtr ptr3(ptr1);
|
EXPECT_TRUE(ptr1 == ptr3);
|
EXPECT_FALSE(ptr1 != ptr3);
|
EXPECT_EQ(&thing, ptr3.Get());
|
{
|
WeakTestPtr ptr4 = ptr1;
|
EXPECT_TRUE(ptr1 == ptr4);
|
EXPECT_FALSE(ptr1 != ptr4);
|
EXPECT_EQ(&thing, ptr4.Get());
|
}
|
}
|
EXPECT_EQ(0, thing.delete_count());
|
}
|
EXPECT_EQ(1, thing.delete_count());
|
}
|
|
TEST(WeakPtr, ResetNull) {
|
PseudoDeletable thing;
|
{
|
UniqueTestPtr unique(&thing);
|
WeakTestPtr ptr1(std::move(unique));
|
WeakTestPtr ptr2 = ptr1;
|
ptr1.Reset();
|
EXPECT_FALSE(ptr1);
|
EXPECT_EQ(nullptr, ptr1.Get());
|
EXPECT_TRUE(ptr2);
|
EXPECT_EQ(&thing, ptr2.Get());
|
EXPECT_FALSE(ptr1 == ptr2);
|
EXPECT_TRUE(ptr1 != ptr2);
|
EXPECT_EQ(0, thing.delete_count());
|
}
|
EXPECT_EQ(1, thing.delete_count());
|
}
|
|
TEST(WeakPtr, ResetNonNull) {
|
PseudoDeletable thing1;
|
PseudoDeletable thing2;
|
{
|
UniqueTestPtr unique1(&thing1);
|
WeakTestPtr ptr1(std::move(unique1));
|
WeakTestPtr ptr2 = ptr1;
|
UniqueTestPtr unique2(&thing2);
|
ptr2.Reset(std::move(unique2));
|
EXPECT_TRUE(ptr1);
|
EXPECT_EQ(&thing1, ptr1.Get());
|
EXPECT_TRUE(ptr2);
|
EXPECT_EQ(&thing2, ptr2.Get());
|
EXPECT_FALSE(ptr1 == ptr2);
|
EXPECT_TRUE(ptr1 != ptr2);
|
EXPECT_EQ(0, thing1.delete_count());
|
EXPECT_EQ(0, thing2.delete_count());
|
}
|
EXPECT_EQ(1, thing1.delete_count());
|
EXPECT_EQ(1, thing2.delete_count());
|
}
|
|
TEST(WeakPtr, DeleteObject) {
|
PseudoDeletable thing;
|
{
|
UniqueTestPtr unique(&thing);
|
WeakTestPtr ptr1(std::move(unique));
|
WeakTestPtr ptr2 = ptr1;
|
ptr1.DeleteObject();
|
EXPECT_FALSE(ptr1);
|
EXPECT_EQ(nullptr, ptr1.Get());
|
EXPECT_FALSE(ptr2);
|
EXPECT_EQ(nullptr, ptr2.Get());
|
EXPECT_FALSE(ptr1 == ptr2);
|
EXPECT_TRUE(ptr1 != ptr2);
|
EXPECT_EQ(1, thing.delete_count());
|
}
|
EXPECT_EQ(1, thing.delete_count());
|
}
|
|
TEST(WeakPtr, Cyclic) {
|
PseudoDeletable thing1;
|
PseudoDeletable thing2;
|
{
|
UniqueTestPtr unique1(&thing1);
|
UniqueTestPtr unique2(&thing2);
|
WeakTestPtr ptr1(std::move(unique1));
|
WeakTestPtr ptr2(std::move(unique2));
|
ptr1->SetNext(ptr2);
|
ptr2->SetNext(ptr1);
|
}
|
// Leaks without explicit clear.
|
EXPECT_EQ(0, thing1.delete_count());
|
EXPECT_EQ(0, thing2.delete_count());
|
}
|
|
TEST(WeakPtr, CyclicDeleteObject) {
|
PseudoDeletable thing1;
|
PseudoDeletable thing2;
|
{
|
UniqueTestPtr unique1(&thing1);
|
UniqueTestPtr unique2(&thing2);
|
WeakTestPtr ptr1(std::move(unique1));
|
WeakTestPtr ptr2(std::move(unique2));
|
ptr1->SetNext(ptr2);
|
ptr2->SetNext(ptr1);
|
ptr1.DeleteObject();
|
EXPECT_EQ(1, thing1.delete_count());
|
EXPECT_EQ(0, thing2.delete_count());
|
}
|
EXPECT_EQ(1, thing1.delete_count());
|
EXPECT_EQ(1, thing2.delete_count());
|
}
|
|
} // namespace fxcrt
|