1 // Copyright 2018 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/fxcrt/autorestorer.h"
6 #include "core/fxcrt/retain_ptr.h"
7 #include "core/fxcrt/unowned_ptr.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "testing/pseudo_retainable.h"
10
TEST(fxcrt,AutoRestorer)11 TEST(fxcrt, AutoRestorer) {
12 int x = 5;
13 {
14 AutoRestorer<int> restorer(&x);
15 x = 6;
16 EXPECT_EQ(6, x);
17 }
18 EXPECT_EQ(5, x);
19 }
20
TEST(fxcrt,AutoRestorerNoOp)21 TEST(fxcrt, AutoRestorerNoOp) {
22 int x = 5;
23 {
24 AutoRestorer<int> restorer(&x);
25 EXPECT_EQ(5, x);
26 }
27 EXPECT_EQ(5, x);
28 }
29
TEST(fxcrt,AutoRestorerAbandon)30 TEST(fxcrt, AutoRestorerAbandon) {
31 int x = 5;
32 {
33 AutoRestorer<int> restorer(&x);
34 x = 6;
35 EXPECT_EQ(6, x);
36 restorer.AbandonRestoration();
37 }
38 EXPECT_EQ(6, x);
39 }
40
TEST(fxcrt,AutoRestorerUnownedPtr)41 TEST(fxcrt, AutoRestorerUnownedPtr) {
42 int x = 5;
43 int y = 6;
44 UnownedPtr<int> ptr(&x);
45 {
46 AutoRestorer<UnownedPtr<int>> restorer(&ptr);
47 ptr = &y;
48 EXPECT_EQ(&y, ptr);
49 }
50 EXPECT_EQ(&x, ptr);
51 }
52
TEST(fxcrt,AutoRestorerUnownedNoOp)53 TEST(fxcrt, AutoRestorerUnownedNoOp) {
54 int x = 5;
55 UnownedPtr<int> ptr(&x);
56 {
57 AutoRestorer<UnownedPtr<int>> restorer(&ptr);
58 EXPECT_EQ(&x, ptr);
59 }
60 EXPECT_EQ(&x, ptr);
61 }
62
TEST(fxcrt,AutoRestorerUnownedPtrAbandon)63 TEST(fxcrt, AutoRestorerUnownedPtrAbandon) {
64 int x = 5;
65 int y = 6;
66 UnownedPtr<int> ptr(&x);
67 {
68 AutoRestorer<UnownedPtr<int>> restorer(&ptr);
69 ptr = &y;
70 EXPECT_EQ(&y, ptr);
71 restorer.AbandonRestoration();
72 }
73 EXPECT_EQ(&y, ptr);
74 }
75
TEST(fxcrt,AutoRestorerRetainPtr)76 TEST(fxcrt, AutoRestorerRetainPtr) {
77 PseudoRetainable obj1;
78 PseudoRetainable obj2;
79 RetainPtr<PseudoRetainable> ptr(&obj1);
80 EXPECT_EQ(1, obj1.retain_count());
81 EXPECT_EQ(0, obj1.release_count());
82 {
83 AutoRestorer<RetainPtr<PseudoRetainable>> restorer(&ptr);
84 // |obj1| is kept alive by restorer in case it need to be restored.
85 EXPECT_EQ(2, obj1.retain_count());
86 EXPECT_EQ(0, obj1.release_count());
87 ptr.Reset(&obj2);
88 EXPECT_EQ(&obj2, ptr.Get());
89
90 // |obj1| released by |ptr| assignment.
91 EXPECT_TRUE(obj1.alive());
92 EXPECT_EQ(2, obj1.retain_count());
93 EXPECT_EQ(1, obj1.release_count());
94
95 // |obj2| now kept alive by |ptr|.
96 EXPECT_TRUE(obj1.alive());
97 EXPECT_EQ(1, obj2.retain_count());
98 EXPECT_EQ(0, obj2.release_count());
99 }
100 EXPECT_EQ(&obj1, ptr.Get());
101
102 // |obj1| now kept alive again by |ptr|.
103 EXPECT_TRUE(obj1.alive());
104 EXPECT_EQ(3, obj1.retain_count());
105 EXPECT_EQ(2, obj1.release_count());
106
107 // |obj2| dead.
108 EXPECT_FALSE(obj2.alive());
109 EXPECT_EQ(1, obj2.retain_count());
110 EXPECT_EQ(1, obj2.release_count());
111 }
112
TEST(fxcrt,AutoRestorerRetainPtrNoOp)113 TEST(fxcrt, AutoRestorerRetainPtrNoOp) {
114 PseudoRetainable obj1;
115 RetainPtr<PseudoRetainable> ptr(&obj1);
116 EXPECT_EQ(1, obj1.retain_count());
117 EXPECT_EQ(0, obj1.release_count());
118 {
119 AutoRestorer<RetainPtr<PseudoRetainable>> restorer(&ptr);
120 EXPECT_EQ(2, obj1.retain_count());
121 EXPECT_EQ(0, obj1.release_count());
122 }
123 EXPECT_EQ(&obj1, ptr.Get());
124
125 // Self-reassignement avoided ref churn.
126 EXPECT_TRUE(obj1.alive());
127 EXPECT_EQ(2, obj1.retain_count());
128 EXPECT_EQ(1, obj1.release_count());
129 }
130
TEST(fxcrt,AutoRestorerRetainPtrAbandon)131 TEST(fxcrt, AutoRestorerRetainPtrAbandon) {
132 PseudoRetainable obj1;
133 PseudoRetainable obj2;
134 RetainPtr<PseudoRetainable> ptr(&obj1);
135 EXPECT_EQ(1, obj1.retain_count());
136 EXPECT_EQ(0, obj1.release_count());
137 {
138 AutoRestorer<RetainPtr<PseudoRetainable>> restorer(&ptr);
139 // |obj1| is kept alive by restorer in case it need to be restored.
140 EXPECT_EQ(2, obj1.retain_count());
141 EXPECT_EQ(0, obj1.release_count());
142 ptr.Reset(&obj2);
143 EXPECT_EQ(&obj2, ptr.Get());
144
145 // |obj1| released by |ptr| assignment.
146 EXPECT_EQ(2, obj1.retain_count());
147 EXPECT_EQ(1, obj1.release_count());
148
149 // |obj2| now kept alive by |ptr|.
150 EXPECT_EQ(1, obj2.retain_count());
151 EXPECT_EQ(0, obj2.release_count());
152
153 restorer.AbandonRestoration();
154 }
155 EXPECT_EQ(&obj2, ptr.Get());
156
157 // |obj1| now dead as a result of abandonment.
158 EXPECT_FALSE(obj1.alive());
159 EXPECT_EQ(2, obj1.retain_count());
160 EXPECT_EQ(2, obj1.release_count());
161
162 // |obj2| kept alive by |ptr|.
163 EXPECT_TRUE(obj2.alive());
164 EXPECT_EQ(1, obj2.retain_count());
165 EXPECT_EQ(0, obj2.release_count());
166 }
167