blob: e2a2337c924ee9192f60ce6fc6e7899aa15bd492 [file] [log] [blame]
// 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 "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() = default;
void Release() {
++delete_count_;
next_.Reset();
}
void SetNext(const WeakTestPtr& next) { next_ = next; }
int delete_count() const { return delete_count_; }
private:
int delete_count_ = 0;
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