xref: /aosp_15_r20/external/pdfium/core/fxcrt/maybe_owned_unittest.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2016 The PDFium Authors
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/maybe_owned.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "core/fxcrt/unowned_ptr.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 
13 namespace fxcrt {
14 namespace {
15 
16 class PseudoDeletable {
17  public:
PseudoDeletable(int id,int * count_location)18   explicit PseudoDeletable(int id, int* count_location)
19       : id_(id), count_location_(count_location) {}
~PseudoDeletable()20   ~PseudoDeletable() { ++(*count_location_); }
GetID() const21   int GetID() const { return id_; }
22 
23  private:
24   int id_;
25   int* count_location_;
26 };
27 
28 }  // namespace
29 
TEST(MaybeOwned,Null)30 TEST(MaybeOwned, Null) {
31   MaybeOwned<PseudoDeletable> ptr1;
32   EXPECT_FALSE(ptr1.IsOwned());
33   EXPECT_FALSE(ptr1);
34   EXPECT_FALSE(ptr1.Get());
35 
36   MaybeOwned<PseudoDeletable> ptr2;
37   EXPECT_TRUE(ptr1 == ptr2);
38   EXPECT_FALSE(ptr1 != ptr2);
39 }
40 
TEST(MaybeOwned,NotOwned)41 TEST(MaybeOwned, NotOwned) {
42   int delete_count = 0;
43   PseudoDeletable thing1(100, &delete_count);
44   {
45     MaybeOwned<PseudoDeletable> ptr(&thing1);
46     EXPECT_FALSE(ptr.IsOwned());
47     EXPECT_EQ(ptr.Get(), &thing1);
48     EXPECT_EQ(100, ptr->GetID());
49     EXPECT_TRUE(ptr == &thing1);
50     EXPECT_FALSE(ptr != &thing1);
51 
52     MaybeOwned<PseudoDeletable> empty;
53     EXPECT_FALSE(ptr == empty);
54     EXPECT_TRUE(ptr != empty);
55   }
56   EXPECT_EQ(0, delete_count);
57 
58   delete_count = 0;
59   PseudoDeletable thing2(200, &delete_count);
60   {
61     MaybeOwned<PseudoDeletable> ptr(&thing1);
62     ptr = &thing2;
63     EXPECT_FALSE(ptr.IsOwned());
64     EXPECT_EQ(ptr.Get(), &thing2);
65     EXPECT_EQ(200, ptr->GetID());
66   }
67   EXPECT_EQ(0, delete_count);
68 
69   delete_count = 0;
70   int owned_delete_count = 0;
71   {
72     MaybeOwned<PseudoDeletable> ptr(&thing1);
73     EXPECT_EQ(100, ptr->GetID());
74     ptr = std::make_unique<PseudoDeletable>(300, &owned_delete_count);
75     EXPECT_TRUE(ptr.IsOwned());
76     EXPECT_EQ(300, ptr->GetID());
77   }
78   EXPECT_EQ(0, delete_count);
79   EXPECT_EQ(1, owned_delete_count);
80 }
81 
TEST(MaybeOwned,UnownedPtr)82 TEST(MaybeOwned, UnownedPtr) {
83   int delete_count = 0;
84   PseudoDeletable thing1(100, &delete_count);
85   PseudoDeletable thing2(200, &delete_count);
86   UnownedPtr<PseudoDeletable> unowned1(&thing1);
87   UnownedPtr<PseudoDeletable> unowned2(&thing2);
88   {
89     MaybeOwned<PseudoDeletable> ptr1(unowned1);
90     MaybeOwned<PseudoDeletable> ptr2(unowned2);
91     ptr2 = unowned1;
92     ptr1 = unowned2;
93   }
94   EXPECT_EQ(0, delete_count);
95 }
96 
TEST(MaybeOwned,Owned)97 TEST(MaybeOwned, Owned) {
98   int delete_count = 0;
99   {
100     MaybeOwned<PseudoDeletable> ptr(
101         std::make_unique<PseudoDeletable>(100, &delete_count));
102     EXPECT_TRUE(ptr.IsOwned());
103     EXPECT_EQ(100, ptr->GetID());
104 
105     MaybeOwned<PseudoDeletable> empty;
106     EXPECT_FALSE(ptr == empty);
107     EXPECT_TRUE(ptr != empty);
108   }
109   EXPECT_EQ(1, delete_count);
110 
111   delete_count = 0;
112   {
113     MaybeOwned<PseudoDeletable> ptr(
114         std::make_unique<PseudoDeletable>(200, &delete_count));
115     ptr = std::make_unique<PseudoDeletable>(300, &delete_count);
116     EXPECT_TRUE(ptr.IsOwned());
117     EXPECT_EQ(300, ptr->GetID());
118     EXPECT_EQ(1, delete_count);
119   }
120   EXPECT_EQ(2, delete_count);
121 
122   delete_count = 0;
123   int unowned_delete_count = 0;
124   PseudoDeletable thing2(400, &unowned_delete_count);
125   {
126     MaybeOwned<PseudoDeletable> ptr(
127         std::make_unique<PseudoDeletable>(500, &delete_count));
128     ptr = &thing2;
129     EXPECT_FALSE(ptr.IsOwned());
130     EXPECT_EQ(400, ptr->GetID());
131     EXPECT_EQ(1, delete_count);
132     EXPECT_EQ(0, unowned_delete_count);
133   }
134   EXPECT_EQ(1, delete_count);
135   EXPECT_EQ(0, unowned_delete_count);
136 }
137 
TEST(MaybeOwned,Release)138 TEST(MaybeOwned, Release) {
139   int delete_count = 0;
140   {
141     std::unique_ptr<PseudoDeletable> stolen;
142     {
143       MaybeOwned<PseudoDeletable> ptr(
144           std::make_unique<PseudoDeletable>(100, &delete_count));
145       EXPECT_TRUE(ptr.IsOwned());
146       stolen = ptr.Release();
147       EXPECT_FALSE(ptr.IsOwned());
148       EXPECT_EQ(ptr, stolen);
149       EXPECT_EQ(0, delete_count);
150     }
151     EXPECT_EQ(0, delete_count);
152   }
153   EXPECT_EQ(1, delete_count);
154 }
155 
TEST(MaybeOwned,Move)156 TEST(MaybeOwned, Move) {
157   int delete_count = 0;
158   PseudoDeletable thing1(100, &delete_count);
159   {
160     MaybeOwned<PseudoDeletable> ptr1(&thing1);
161     MaybeOwned<PseudoDeletable> ptr2(
162         std::make_unique<PseudoDeletable>(200, &delete_count));
163     EXPECT_FALSE(ptr1.IsOwned());
164     EXPECT_TRUE(ptr2.IsOwned());
165 
166     MaybeOwned<PseudoDeletable> ptr3(std::move(ptr1));
167     MaybeOwned<PseudoDeletable> ptr4(std::move(ptr2));
168     EXPECT_FALSE(ptr1.IsOwned());  // Unowned and null.
169     EXPECT_FALSE(ptr1.Get());
170     EXPECT_TRUE(ptr2.IsOwned());  // Owned but null.
171     EXPECT_FALSE(ptr2.Get());
172     EXPECT_FALSE(ptr3.IsOwned());
173     EXPECT_TRUE(ptr4.IsOwned());
174     EXPECT_EQ(0, delete_count);
175     EXPECT_EQ(100, ptr3->GetID());
176     EXPECT_EQ(200, ptr4->GetID());
177 
178     MaybeOwned<PseudoDeletable> ptr5;
179     MaybeOwned<PseudoDeletable> ptr6;
180     ptr5 = std::move(ptr3);
181     ptr6 = std::move(ptr4);
182     EXPECT_FALSE(ptr3.IsOwned());  // Unowned and null.
183     EXPECT_FALSE(ptr3.Get());
184     EXPECT_TRUE(ptr4.IsOwned());  // Owned but null.
185     EXPECT_FALSE(ptr4.Get());
186     EXPECT_FALSE(ptr5.IsOwned());
187     EXPECT_TRUE(ptr6.IsOwned());
188     EXPECT_EQ(0, delete_count);
189     EXPECT_EQ(100, ptr5->GetID());
190     EXPECT_EQ(200, ptr6->GetID());
191   }
192   EXPECT_EQ(1, delete_count);
193 }
194 
195 namespace {
196 
197 class Thing {
198  public:
199   int x = 42;
200 };
201 
202 class Owner {
203  public:
Owner(std::unique_ptr<Thing> thing)204   explicit Owner(std::unique_ptr<Thing> thing) : thing_(std::move(thing)) {}
205 
206  private:
207   std::unique_ptr<Thing> thing_;
208 };
209 
210 class Manager {
211  public:
Manager()212   Manager()
213       : transient_(std::make_unique<Thing>()),
214         owner_(std::make_unique<Owner>(transient_.Release())),
215         thing_(std::move(transient_).Get()) {}
216 
has_transient() const217   bool has_transient() const { return !!transient_.Get(); }
218 
219  private:
220   MaybeOwned<Thing> transient_;         // For initializng next two members.
221   const std::unique_ptr<Owner> owner_;  // Must outlive thing_.
222   const UnownedPtr<Thing> thing_;
223 };
224 
225 }  // namespace
226 
TEST(MaybeOwned,MoveElisionThwarted)227 TEST(MaybeOwned, MoveElisionThwarted) {
228   // Test fails if the std::move() in Manager::Manager() is elided.
229   Manager manager;
230   EXPECT_FALSE(manager.has_transient());
231 }
232 
233 }  // namespace fxcrt
234