1 // Copyright 2016 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/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:
Object(Observer * observer,const std::string & name)34 Object(Observer* observer, const std::string& name)
35 : name_(name), observer_(observer) {
36 observer->OnConstruct(name_);
37 }
Object(const Object & that)38 Object(const Object& that) : name_(that.name_), observer_(that.observer_) {
39 observer_->OnConstruct(name_);
40 }
~Object()41 ~Object() override { observer_->OnDestruct(name_); }
42
Clone() const43 RetainPtr<Object> Clone() const { return pdfium::MakeRetain<Object>(*this); }
44
45 private:
46 std::string name_;
47 Observer* observer_;
48 };
49
50 } // namespace
51
TEST(SharedCopyOnWrite,Null)52 TEST(SharedCopyOnWrite, Null) {
53 Observer observer;
54 {
55 SharedCopyOnWrite<Object> ptr;
56 EXPECT_EQ(nullptr, ptr.GetObject());
57 }
58 }
59
TEST(SharedCopyOnWrite,Copy)60 TEST(SharedCopyOnWrite, Copy) {
61 Observer observer;
62 {
63 SharedCopyOnWrite<Object> ptr1;
64 ptr1.Emplace(&observer, std::string("one"));
65 {
66 SharedCopyOnWrite<Object> ptr2 = ptr1;
67 EXPECT_EQ(1, observer.GetConstructionCount("one"));
68 EXPECT_EQ(0, observer.GetDestructionCount("one"));
69 }
70 {
71 SharedCopyOnWrite<Object> ptr3(ptr1);
72 EXPECT_EQ(1, observer.GetConstructionCount("one"));
73 EXPECT_EQ(0, observer.GetDestructionCount("one"));
74 }
75 EXPECT_EQ(1, observer.GetConstructionCount("one"));
76 EXPECT_EQ(0, observer.GetDestructionCount("one"));
77 }
78 EXPECT_EQ(1, observer.GetDestructionCount("one"));
79 }
80
TEST(SharedCopyOnWrite,AssignOverOld)81 TEST(SharedCopyOnWrite, AssignOverOld) {
82 Observer observer;
83 {
84 SharedCopyOnWrite<Object> ptr1;
85 ptr1.Emplace(&observer, std::string("one"));
86 ptr1.Emplace(&observer, std::string("two"));
87 EXPECT_EQ(1, observer.GetConstructionCount("one"));
88 EXPECT_EQ(1, observer.GetConstructionCount("two"));
89 EXPECT_EQ(1, observer.GetDestructionCount("one"));
90 EXPECT_EQ(0, observer.GetDestructionCount("two"));
91 }
92 EXPECT_EQ(1, observer.GetDestructionCount("two"));
93 }
94
TEST(SharedCopyOnWrite,AssignOverRetained)95 TEST(SharedCopyOnWrite, AssignOverRetained) {
96 Observer observer;
97 {
98 SharedCopyOnWrite<Object> ptr1;
99 ptr1.Emplace(&observer, std::string("one"));
100 SharedCopyOnWrite<Object> ptr2(ptr1);
101 ptr1.Emplace(&observer, std::string("two"));
102 EXPECT_EQ(1, observer.GetConstructionCount("one"));
103 EXPECT_EQ(1, observer.GetConstructionCount("two"));
104 EXPECT_EQ(0, observer.GetDestructionCount("one"));
105 EXPECT_EQ(0, observer.GetDestructionCount("two"));
106 }
107 EXPECT_EQ(1, observer.GetDestructionCount("one"));
108 EXPECT_EQ(1, observer.GetDestructionCount("two"));
109 }
110
TEST(SharedCopyOnWrite,GetModify)111 TEST(SharedCopyOnWrite, GetModify) {
112 Observer observer;
113 {
114 SharedCopyOnWrite<Object> ptr;
115 EXPECT_NE(nullptr, ptr.GetPrivateCopy(&observer, std::string("one")));
116 EXPECT_EQ(1, observer.GetConstructionCount("one"));
117 EXPECT_EQ(0, observer.GetDestructionCount("one"));
118
119 EXPECT_NE(nullptr, ptr.GetPrivateCopy(&observer, std::string("one")));
120 EXPECT_EQ(1, observer.GetConstructionCount("one"));
121 EXPECT_EQ(0, observer.GetDestructionCount("one"));
122 {
123 SharedCopyOnWrite<Object> other(ptr);
124 EXPECT_NE(nullptr, ptr.GetPrivateCopy(&observer, std::string("one")));
125 EXPECT_EQ(2, observer.GetConstructionCount("one"));
126 EXPECT_EQ(0, observer.GetDestructionCount("one"));
127 }
128 EXPECT_EQ(2, observer.GetConstructionCount("one"));
129 EXPECT_EQ(1, observer.GetDestructionCount("one"));
130 }
131 EXPECT_EQ(2, observer.GetDestructionCount("one"));
132 }
133
134 } // namespace fxcrt
135