/* * Copyright (c) 2018-2023, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include struct Object : public RefCounted { int x; }; TEST_CASE(basics) { auto object = adopt_ref(*new Object); EXPECT_EQ(object->ref_count(), 1u); object->ref(); EXPECT_EQ(object->ref_count(), 2u); object->unref(); EXPECT_EQ(object->ref_count(), 1u); { NonnullRefPtr another = object; EXPECT_EQ(object->ref_count(), 2u); } EXPECT_EQ(object->ref_count(), 1u); } TEST_CASE(assign_reference) { auto object = adopt_ref(*new Object); EXPECT_EQ(object->ref_count(), 1u); object = *object; EXPECT_EQ(object->ref_count(), 1u); } TEST_CASE(assign_owner_of_self) { struct Object : public RefCounted { RefPtr parent; }; auto parent = adopt_ref(*new Object); auto child = adopt_ref(*new Object); child->parent = move(parent); child = *child->parent; EXPECT_EQ(child->ref_count(), 1u); } TEST_CASE(swap_with_self) { auto object = adopt_ref(*new Object); swap(object, object); EXPECT_EQ(object->ref_count(), 1u); } TEST_CASE(destroy_self_owning_refcounted_object) { // This test is a little convoluted because SelfOwningRefCounted can't own itself // through a NonnullRefPtr directly. We have to use an intermediate object ("Inner"). struct SelfOwningRefCounted : public RefCounted { SelfOwningRefCounted() : inner(make(*this)) { } struct Inner { explicit Inner(SelfOwningRefCounted& self) : self(self) { } NonnullRefPtr self; }; OwnPtr inner; }; RefPtr object = make_ref_counted(); auto* object_ptr = object.ptr(); object = nullptr; object_ptr->inner = nullptr; }