Bug 1404742 - add test for ThreadSafeWeakPtr. r=nfroyd
authorLee Salzman <lsalzman@mozilla.com>
Wed, 18 Oct 2017 14:21:27 -0400
changeset 387006 efd9a7070a08bdcf2077f3b9cf230f6462ce671a
parent 387005 6b9e12aef734b162c29885bbfb8cadf69f5db244
child 387007 16a80fc4e1026d42d148e834f41237b35d0474b8
push id32705
push userryanvm@gmail.com
push dateThu, 19 Oct 2017 01:01:49 +0000
treeherdermozilla-central@a21099ce055f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd
bugs1404742
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1404742 - add test for ThreadSafeWeakPtr. r=nfroyd MozReview-Commit-ID: GkNXsTLcN7m
mfbt/tests/TestThreadSafeWeakPtr.cpp
mfbt/tests/moz.build
new file mode 100644
--- /dev/null
+++ b/mfbt/tests/TestThreadSafeWeakPtr.cpp
@@ -0,0 +1,104 @@
+/* -*- 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 "mozilla/RefPtr.h"
+#include "mozilla/ThreadSafeWeakPtr.h"
+
+using mozilla::SupportsThreadSafeWeakPtr;
+using mozilla::ThreadSafeWeakPtr;
+
+// To have a class C support weak pointers, inherit from SupportsThreadSafeWeakPtr<C>.
+class C : public SupportsThreadSafeWeakPtr<C>
+{
+public:
+  MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(C)
+  MOZ_DECLARE_REFCOUNTED_TYPENAME(C)
+
+  int mNum;
+
+  C()
+    : mNum(0)
+  {}
+
+  ~C()
+  {
+    // Setting mNum in the destructor allows us to test against use-after-free below
+    mNum = 0xDEAD;
+  }
+
+  void act() {}
+};
+
+int
+main()
+{
+  RefPtr<C> c1 = new C;
+  MOZ_RELEASE_ASSERT(c1->mNum == 0);
+
+  // Get weak pointers to c1. The first time,
+  // a reference-counted ThreadSafeWeakReference object is created that
+  // can live beyond the lifetime of 'c1'. The ThreadSafeWeakReference
+  // object will be notified of 'c1's destruction.
+  ThreadSafeWeakPtr<C> w1(c1);
+  {
+    RefPtr<C> s1(w1);
+    // Test a weak pointer for validity before using it.
+    MOZ_RELEASE_ASSERT(s1);
+    MOZ_RELEASE_ASSERT(s1 == c1);
+    s1->mNum = 1;
+    s1->act();
+  }
+
+  // Test taking another ThreadSafeWeakPtr<C> to c1
+  ThreadSafeWeakPtr<C> w2(c1);
+  {
+    RefPtr<C> s2(w2);
+    MOZ_RELEASE_ASSERT(s2);
+    MOZ_RELEASE_ASSERT(s2 == c1);
+    MOZ_RELEASE_ASSERT(w1 == s2);
+    MOZ_RELEASE_ASSERT(s2->mNum == 1);
+  }
+
+  // Test that when a ThreadSafeWeakPtr is destroyed, it does not destroy the object that it points to,
+  // and it does not affect other ThreadSafeWeakPtrs pointing to the same object (e.g. it does not
+  // destroy the ThreadSafeWeakReference object).
+  {
+    ThreadSafeWeakPtr<C> w4local(c1);
+    MOZ_RELEASE_ASSERT(w4local == c1);
+  }
+  // Now w4local has gone out of scope. If that had destroyed c1, then the following would fail
+  // for sure (see C::~C()).
+  MOZ_RELEASE_ASSERT(c1->mNum == 1);
+  // Check that w4local going out of scope hasn't affected other ThreadSafeWeakPtr's pointing to c1
+  MOZ_RELEASE_ASSERT(w1 == c1);
+  MOZ_RELEASE_ASSERT(w2 == c1);
+
+  // Now construct another C object and test changing what object a ThreadSafeWeakPtr points to
+  RefPtr<C> c2 = new C;
+  c2->mNum = 2;
+  {
+    RefPtr<C> s2(w2);
+    MOZ_RELEASE_ASSERT(s2->mNum == 1); // w2 was pointing to c1
+  }
+  w2 = c2;
+  {
+    RefPtr<C> s2(w2);
+    MOZ_RELEASE_ASSERT(s2);
+    MOZ_RELEASE_ASSERT(s2 == c2);
+    MOZ_RELEASE_ASSERT(s2 != c1);
+    MOZ_RELEASE_ASSERT(w1 != s2);
+    MOZ_RELEASE_ASSERT(s2->mNum == 2);
+  }
+
+  // Destroying the underlying object clears weak pointers to it.
+  // It should not affect pointers that are not currently pointing to it.
+  c1 = nullptr;
+  MOZ_RELEASE_ASSERT(!bool(w1), "Deleting an object should clear ThreadSafeWeakPtr's to it.");
+  MOZ_RELEASE_ASSERT(bool(w2), "Deleting an object should not clear ThreadSafeWeakPtr that are not pointing to it.");
+
+  c2 = nullptr;
+  MOZ_RELEASE_ASSERT(!bool(w2), "Deleting an object should clear ThreadSafeWeakPtr's to it.");
+}
--- a/mfbt/tests/moz.build
+++ b/mfbt/tests/moz.build
@@ -45,16 +45,17 @@ CppUnitTests([
     'TestRollingMean',
     'TestSaturate',
     'TestScopeExit',
     'TestSegmentedVector',
     'TestSHA1',
     'TestSmallPointerArray',
     'TestSplayTree',
     'TestTemplateLib',
+    'TestThreadSafeWeakPtr',
     'TestTuple',
     'TestTypedEnum',
     'TestTypeTraits',
     'TestUniquePtr',
     'TestVariant',
     'TestVector',
     'TestWeakPtr',
     'TestXorShift128PlusRNG',