summaryrefslogtreecommitdiff
path: root/core/fxcrt/autorestorer_unittest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxcrt/autorestorer_unittest.cpp')
-rw-r--r--core/fxcrt/autorestorer_unittest.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/core/fxcrt/autorestorer_unittest.cpp b/core/fxcrt/autorestorer_unittest.cpp
index ac1d613e7c..6430fb67f6 100644
--- a/core/fxcrt/autorestorer_unittest.cpp
+++ b/core/fxcrt/autorestorer_unittest.cpp
@@ -3,7 +3,10 @@
// found in the LICENSE file.
#include "core/fxcrt/autorestorer.h"
+#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/pseudo_retainable.h"
TEST(fxcrt, AutoRestorer) {
int x = 5;
@@ -13,6 +16,19 @@ TEST(fxcrt, AutoRestorer) {
EXPECT_EQ(6, x);
}
EXPECT_EQ(5, x);
+}
+
+TEST(fxcrt, AutoRestorerNoOp) {
+ int x = 5;
+ {
+ AutoRestorer<int> restorer(&x);
+ EXPECT_EQ(5, x);
+ }
+ EXPECT_EQ(5, x);
+}
+
+TEST(fxcrt, AutoRestorerAbandon) {
+ int x = 5;
{
AutoRestorer<int> restorer(&x);
x = 6;
@@ -21,3 +37,130 @@ TEST(fxcrt, AutoRestorer) {
}
EXPECT_EQ(6, x);
}
+
+TEST(fxcrt, AutoRestorerUnownedPtr) {
+ int x = 5;
+ int y = 6;
+ UnownedPtr<int> ptr(&x);
+ {
+ AutoRestorer<UnownedPtr<int>> restorer(&ptr);
+ ptr = &y;
+ EXPECT_EQ(&y, ptr);
+ }
+ EXPECT_EQ(&x, ptr);
+}
+
+TEST(fxcrt, AutoRestorerUnownedNoOp) {
+ int x = 5;
+ UnownedPtr<int> ptr(&x);
+ {
+ AutoRestorer<UnownedPtr<int>> restorer(&ptr);
+ EXPECT_EQ(&x, ptr);
+ }
+ EXPECT_EQ(&x, ptr);
+}
+
+TEST(fxcrt, AutoRestorerUnownedPtrAbandon) {
+ int x = 5;
+ int y = 6;
+ UnownedPtr<int> ptr(&x);
+ {
+ AutoRestorer<UnownedPtr<int>> restorer(&ptr);
+ ptr = &y;
+ EXPECT_EQ(&y, ptr);
+ restorer.AbandonRestoration();
+ }
+ EXPECT_EQ(&y, ptr);
+}
+
+TEST(fxcrt, AutoRestorerRetainPtr) {
+ PseudoRetainable obj1;
+ PseudoRetainable obj2;
+ RetainPtr<PseudoRetainable> ptr(&obj1);
+ EXPECT_EQ(1, obj1.retain_count());
+ EXPECT_EQ(0, obj1.release_count());
+ {
+ AutoRestorer<RetainPtr<PseudoRetainable>> restorer(&ptr);
+ // |obj1| is kept alive by restorer in case it need to be restored.
+ EXPECT_EQ(2, obj1.retain_count());
+ EXPECT_EQ(0, obj1.release_count());
+ ptr.Reset(&obj2);
+ EXPECT_EQ(&obj2, ptr.Get());
+
+ // |obj1| released by |ptr| assignment.
+ EXPECT_TRUE(obj1.alive());
+ EXPECT_EQ(2, obj1.retain_count());
+ EXPECT_EQ(1, obj1.release_count());
+
+ // |obj2| now kept alive by |ptr|.
+ EXPECT_TRUE(obj1.alive());
+ EXPECT_EQ(1, obj2.retain_count());
+ EXPECT_EQ(0, obj2.release_count());
+ }
+ EXPECT_EQ(&obj1, ptr.Get());
+
+ // |obj1| now kept alive again by |ptr|.
+ EXPECT_TRUE(obj1.alive());
+ EXPECT_EQ(3, obj1.retain_count());
+ EXPECT_EQ(2, obj1.release_count());
+
+ // |obj2| dead.
+ EXPECT_FALSE(obj2.alive());
+ EXPECT_EQ(1, obj2.retain_count());
+ EXPECT_EQ(1, obj2.release_count());
+}
+
+TEST(fxcrt, AutoRestorerRetainPtrNoOp) {
+ PseudoRetainable obj1;
+ RetainPtr<PseudoRetainable> ptr(&obj1);
+ EXPECT_EQ(1, obj1.retain_count());
+ EXPECT_EQ(0, obj1.release_count());
+ {
+ AutoRestorer<RetainPtr<PseudoRetainable>> restorer(&ptr);
+ EXPECT_EQ(2, obj1.retain_count());
+ EXPECT_EQ(0, obj1.release_count());
+ }
+ EXPECT_EQ(&obj1, ptr.Get());
+
+ // Self-reassignement avoided ref churn.
+ EXPECT_TRUE(obj1.alive());
+ EXPECT_EQ(2, obj1.retain_count());
+ EXPECT_EQ(1, obj1.release_count());
+}
+
+TEST(fxcrt, AutoRestorerRetainPtrAbandon) {
+ PseudoRetainable obj1;
+ PseudoRetainable obj2;
+ RetainPtr<PseudoRetainable> ptr(&obj1);
+ EXPECT_EQ(1, obj1.retain_count());
+ EXPECT_EQ(0, obj1.release_count());
+ {
+ AutoRestorer<RetainPtr<PseudoRetainable>> restorer(&ptr);
+ // |obj1| is kept alive by restorer in case it need to be restored.
+ EXPECT_EQ(2, obj1.retain_count());
+ EXPECT_EQ(0, obj1.release_count());
+ ptr.Reset(&obj2);
+ EXPECT_EQ(&obj2, ptr.Get());
+
+ // |obj1| released by |ptr| assignment.
+ EXPECT_EQ(2, obj1.retain_count());
+ EXPECT_EQ(1, obj1.release_count());
+
+ // |obj2| now kept alive by |ptr|.
+ EXPECT_EQ(1, obj2.retain_count());
+ EXPECT_EQ(0, obj2.release_count());
+
+ restorer.AbandonRestoration();
+ }
+ EXPECT_EQ(&obj2, ptr.Get());
+
+ // |obj1| now dead as a result of abandonment.
+ EXPECT_FALSE(obj1.alive());
+ EXPECT_EQ(2, obj1.retain_count());
+ EXPECT_EQ(2, obj1.release_count());
+
+ // |obj2| kept alive by |ptr|.
+ EXPECT_TRUE(obj2.alive());
+ EXPECT_EQ(1, obj2.retain_count());
+ EXPECT_EQ(0, obj2.release_count());
+}