summaryrefslogtreecommitdiffstats
path: root/dom/indexedDB/test/gtest/TestSafeRefPtr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/indexedDB/test/gtest/TestSafeRefPtr.cpp')
-rw-r--r--dom/indexedDB/test/gtest/TestSafeRefPtr.cpp279
1 files changed, 279 insertions, 0 deletions
diff --git a/dom/indexedDB/test/gtest/TestSafeRefPtr.cpp b/dom/indexedDB/test/gtest/TestSafeRefPtr.cpp
new file mode 100644
index 0000000000..f3536db278
--- /dev/null
+++ b/dom/indexedDB/test/gtest/TestSafeRefPtr.cpp
@@ -0,0 +1,279 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gtest/gtest.h"
+
+#include "mozilla/dom/SafeRefPtr.h"
+#include "mozilla/RefCounted.h"
+
+using namespace mozilla;
+
+class SafeBase : public SafeRefCounted<SafeBase> {
+ public:
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(SafeBase)
+
+ SafeBase() : mDead(false) {}
+
+ static inline int sNumDestroyed;
+
+ ~SafeBase() {
+ MOZ_RELEASE_ASSERT(!mDead);
+ mDead = true;
+ sNumDestroyed++;
+ }
+
+ private:
+ bool mDead;
+};
+struct SafeDerived : public SafeBase {};
+
+class Base : public RefCounted<Base> {
+ public:
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(Base)
+
+ Base() : mDead(false) {}
+
+ static inline int sNumDestroyed;
+
+ ~Base() {
+ MOZ_RELEASE_ASSERT(!mDead);
+ mDead = true;
+ sNumDestroyed++;
+ }
+
+ private:
+ bool mDead;
+};
+
+struct Derived : public Base {};
+
+already_AddRefed<Base> NewFoo() {
+ RefPtr<Base> ptr(new Base());
+ return ptr.forget();
+}
+
+already_AddRefed<Base> NewBar() {
+ RefPtr<Derived> bar = new Derived();
+ return bar.forget();
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_Default)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr;
+ ASSERT_FALSE(ptr);
+ ASSERT_EQ(0, Base::sNumDestroyed);
+ }
+ ASSERT_EQ(0, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromNullPtr)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr = nullptr;
+ ASSERT_FALSE(ptr);
+ ASSERT_EQ(0, Base::sNumDestroyed);
+ }
+ ASSERT_EQ(0, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromMakeSafeRefPtr_SafeRefCounted)
+{
+ SafeBase::sNumDestroyed = 0;
+ {
+ SafeRefPtr<SafeBase> ptr = MakeSafeRefPtr<SafeBase>();
+ ASSERT_TRUE(ptr);
+ ASSERT_EQ(1u, ptr->refCount());
+ }
+ ASSERT_EQ(1, SafeBase::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr,
+ Construct_FromMakeSafeRefPtr_SafeRefCounted_DerivedType)
+{
+ SafeBase::sNumDestroyed = 0;
+ {
+ SafeRefPtr<SafeBase> ptr = MakeSafeRefPtr<SafeDerived>();
+ ASSERT_TRUE(ptr);
+ ASSERT_EQ(1u, ptr->refCount());
+ }
+ ASSERT_EQ(1, SafeBase::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromMakeSafeRefPtr_RefCounted)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr = MakeSafeRefPtr<Base>();
+ ASSERT_TRUE(ptr);
+ ASSERT_EQ(1u, ptr->refCount());
+ }
+ ASSERT_EQ(1, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromRefPtr)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr = SafeRefPtr{MakeRefPtr<Base>()};
+ ASSERT_TRUE(ptr);
+ ASSERT_EQ(1u, ptr->refCount());
+ }
+ ASSERT_EQ(1, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromRefPtr_DerivedType)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr = SafeRefPtr{MakeRefPtr<Derived>()};
+ ASSERT_TRUE(ptr);
+ ASSERT_EQ(1u, ptr->refCount());
+ }
+ ASSERT_EQ(1, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromAlreadyAddRefed)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr1 = SafeRefPtr{NewFoo()};
+ SafeRefPtr<Base> ptr2(NewFoo());
+ ASSERT_TRUE(ptr1);
+ ASSERT_TRUE(ptr2);
+ ASSERT_EQ(0, Base::sNumDestroyed);
+ }
+ ASSERT_EQ(2, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromAlreadyAddRefed_DerivedType)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr = SafeRefPtr{NewBar()};
+ ASSERT_TRUE(ptr);
+ ASSERT_EQ(1u, ptr->refCount());
+ ASSERT_EQ(0, Base::sNumDestroyed);
+ }
+ ASSERT_EQ(1, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromRawPtr)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr = SafeRefPtr{new Base(), AcquireStrongRefFromRawPtr{}};
+ ASSERT_TRUE(ptr);
+ ASSERT_EQ(1u, ptr->refCount());
+ ASSERT_EQ(0, Base::sNumDestroyed);
+ }
+ ASSERT_EQ(1, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Construct_FromRawPtr_Dervied)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr =
+ SafeRefPtr{new Derived(), AcquireStrongRefFromRawPtr{}};
+ ASSERT_TRUE(ptr);
+ ASSERT_EQ(1u, ptr->refCount());
+ ASSERT_EQ(0, Base::sNumDestroyed);
+ }
+ ASSERT_EQ(1, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, ClonePtr)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr1;
+ {
+ ptr1 = MakeSafeRefPtr<Base>();
+ const SafeRefPtr<Base> ptr2 = ptr1.clonePtr();
+ SafeRefPtr<Base> f3 = ptr2.clonePtr();
+
+ ASSERT_EQ(3u, ptr1->refCount());
+ ASSERT_EQ(0, Base::sNumDestroyed);
+ }
+ ASSERT_EQ(1u, ptr1->refCount());
+ ASSERT_EQ(0, Base::sNumDestroyed);
+ }
+ ASSERT_EQ(1, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Forget)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr1 = MakeSafeRefPtr<Base>();
+ SafeRefPtr<Base> ptr2 = SafeRefPtr{ptr1.forget()};
+
+ ASSERT_FALSE(ptr1);
+ ASSERT_TRUE(ptr2);
+ ASSERT_EQ(1u, ptr2->refCount());
+ }
+ ASSERT_EQ(1, Base::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, Downcast)
+{
+ Base::sNumDestroyed = 0;
+ {
+ SafeRefPtr<Base> ptr1 = MakeSafeRefPtr<Derived>();
+ SafeRefPtr<Derived> ptr2 = std::move(ptr1).downcast<Derived>();
+
+ ASSERT_FALSE(ptr1);
+ ASSERT_TRUE(ptr2);
+ ASSERT_EQ(1u, ptr2->refCount());
+ }
+ ASSERT_EQ(1, Base::sNumDestroyed);
+}
+
+struct SafeTest final : SafeBase {
+ template <typename Func>
+ explicit SafeTest(Func aCallback) {
+ aCallback(SafeRefPtrFromThis());
+ }
+};
+
+TEST(DOM_IndexedDB_SafeRefPtr, SafeRefPtrFromThis_StoreFromCtor)
+{
+ SafeBase::sNumDestroyed = 0;
+ {
+ SafeRefPtr<SafeBase> ptr1;
+ {
+ SafeRefPtr<SafeTest> ptr2 =
+ MakeSafeRefPtr<SafeTest>([&ptr1](SafeRefPtr<SafeBase> ptr) {
+ ptr1 = std::move(ptr);
+ EXPECT_EQ(2u, ptr1->refCount());
+ });
+ ASSERT_EQ(2u, ptr2->refCount());
+ }
+ ASSERT_EQ(0, SafeBase::sNumDestroyed);
+ ASSERT_EQ(1u, ptr1->refCount());
+ }
+ ASSERT_EQ(1, SafeBase::sNumDestroyed);
+}
+
+TEST(DOM_IndexedDB_SafeRefPtr, SafeRefPtrFromThis_DiscardInCtor)
+{
+ SafeBase::sNumDestroyed = 0;
+ {
+ SafeRefPtr<SafeTest> ptr = MakeSafeRefPtr<SafeTest>(
+ [](SafeRefPtr<SafeBase> ptr) { EXPECT_EQ(2u, ptr->refCount()); });
+ ASSERT_EQ(1u, ptr->refCount());
+ ASSERT_EQ(0, SafeBase::sNumDestroyed);
+ }
+ ASSERT_EQ(1, SafeBase::sNumDestroyed);
+}
+
+static_assert(
+ std::is_same_v<SafeRefPtr<Base>,
+ decltype(std::declval<bool>() ? MakeSafeRefPtr<Derived>()
+ : MakeSafeRefPtr<Base>())>);