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/shared_copy_on_write.h"
6
7 #include <map>
8 #include <string>
9
10 #include "core/fxcrt/retain_ptr.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace fxcrt {
14 namespace {
15
16 class Observer {
17 public:
OnConstruct(const std::string & name)18 void OnConstruct(const std::string& name) { construction_counts_[name]++; }
OnDestruct(const std::string & name)19 void OnDestruct(const std::string& name) { destruction_counts_[name]++; }
GetConstructionCount(const std::string & name)20 int GetConstructionCount(const std::string& name) {
21 return construction_counts_[name];
22 }
GetDestructionCount(const std::string & name)23 int GetDestructionCount(const std::string& name) {
24 return destruction_counts_[name];
25 }
26
27 private:
28 std::map<std::string, int> construction_counts_;
29 std::map<std::string, int> destruction_counts_;
30 };
31
32 class Object final : public Retainable {
33 public:
34 CONSTRUCT_VIA_MAKE_RETAIN;
35
Clone() const36 RetainPtr<Object> Clone() const { return pdfium::MakeRetain<Object>(*this); }
37
38 private:
Object(Observer * observer,const std::string & name)39 Object(Observer* observer, const std::string& name)
40 : name_(name), observer_(observer) {
41 observer->OnConstruct(name_);
42 }
Object(const Object & that)43 Object(const Object& that) : name_(that.name_), observer_(that.observer_) {
44 observer_->OnConstruct(name_);
45 }
~Object()46 ~Object() override { observer_->OnDestruct(name_); }
47
48 std::string name_;
49 Observer* observer_;
50 };
51
52 } // namespace
53
TEST(SharedCopyOnWrite,Null)54 TEST(SharedCopyOnWrite, Null) {
55 Observer observer;
56 {
57 SharedCopyOnWrite<Object> ptr;
58 EXPECT_FALSE(ptr.GetObject());
59 }
60 }
61
TEST(SharedCopyOnWrite,Copy)62 TEST(SharedCopyOnWrite, Copy) {
63 Observer observer;
64 {
65 SharedCopyOnWrite<Object> ptr1;
66 ptr1.Emplace(&observer, std::string("one"));
67 {
68 SharedCopyOnWrite<Object> ptr2 = ptr1;
69 EXPECT_EQ(1, observer.GetConstructionCount("one"));
70 EXPECT_EQ(0, observer.GetDestructionCount("one"));
71 }
72 {
73 SharedCopyOnWrite<Object> ptr3(ptr1);
74 EXPECT_EQ(1, observer.GetConstructionCount("one"));
75 EXPECT_EQ(0, observer.GetDestructionCount("one"));
76 }
77 EXPECT_EQ(1, observer.GetConstructionCount("one"));
78 EXPECT_EQ(0, observer.GetDestructionCount("one"));
79 }
80 EXPECT_EQ(1, observer.GetDestructionCount("one"));
81 }
82
TEST(SharedCopyOnWrite,AssignOverOld)83 TEST(SharedCopyOnWrite, AssignOverOld) {
84 Observer observer;
85 {
86 SharedCopyOnWrite<Object> ptr1;
87 ptr1.Emplace(&observer, std::string("one"));
88 ptr1.Emplace(&observer, std::string("two"));
89 EXPECT_EQ(1, observer.GetConstructionCount("one"));
90 EXPECT_EQ(1, observer.GetConstructionCount("two"));
91 EXPECT_EQ(1, observer.GetDestructionCount("one"));
92 EXPECT_EQ(0, observer.GetDestructionCount("two"));
93 }
94 EXPECT_EQ(1, observer.GetDestructionCount("two"));
95 }
96
TEST(SharedCopyOnWrite,AssignOverRetained)97 TEST(SharedCopyOnWrite, AssignOverRetained) {
98 Observer observer;
99 {
100 SharedCopyOnWrite<Object> ptr1;
101 ptr1.Emplace(&observer, std::string("one"));
102 SharedCopyOnWrite<Object> ptr2(ptr1);
103 ptr1.Emplace(&observer, std::string("two"));
104 EXPECT_EQ(1, observer.GetConstructionCount("one"));
105 EXPECT_EQ(1, observer.GetConstructionCount("two"));
106 EXPECT_EQ(0, observer.GetDestructionCount("one"));
107 EXPECT_EQ(0, observer.GetDestructionCount("two"));
108 }
109 EXPECT_EQ(1, observer.GetDestructionCount("one"));
110 EXPECT_EQ(1, observer.GetDestructionCount("two"));
111 }
112
TEST(SharedCopyOnWrite,GetModify)113 TEST(SharedCopyOnWrite, GetModify) {
114 Observer observer;
115 {
116 SharedCopyOnWrite<Object> ptr;
117 EXPECT_TRUE(ptr.GetPrivateCopy(&observer, std::string("one")));
118 EXPECT_EQ(1, observer.GetConstructionCount("one"));
119 EXPECT_EQ(0, observer.GetDestructionCount("one"));
120
121 EXPECT_TRUE(ptr.GetPrivateCopy(&observer, std::string("one")));
122 EXPECT_EQ(1, observer.GetConstructionCount("one"));
123 EXPECT_EQ(0, observer.GetDestructionCount("one"));
124 {
125 SharedCopyOnWrite<Object> other(ptr);
126 EXPECT_TRUE(ptr.GetPrivateCopy(&observer, std::string("one")));
127 EXPECT_EQ(2, observer.GetConstructionCount("one"));
128 EXPECT_EQ(0, observer.GetDestructionCount("one"));
129 }
130 EXPECT_EQ(2, observer.GetConstructionCount("one"));
131 EXPECT_EQ(1, observer.GetDestructionCount("one"));
132 }
133 EXPECT_EQ(2, observer.GetDestructionCount("one"));
134 }
135
136 } // namespace fxcrt
137