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