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/cfx_observable.h"
6
7#include <utility>
8#include <vector>
9
10#include "testing/fx_string_testhelpers.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace {
14
15class PseudoObservable : public CFX_Observable<PseudoObservable> {
16 public:
17  PseudoObservable() {}
18  int SomeMethod() { return 42; }
19  size_t ActiveObservedPtrs() const { return ActiveObservedPtrsForTesting(); }
20};
21
22}  // namespace
23
24TEST(fxcrt, ObservePtrNull) {
25  PseudoObservable::ObservedPtr ptr;
26  EXPECT_EQ(nullptr, ptr.Get());
27}
28
29TEST(fxcrt, ObservePtrLivesLonger) {
30  PseudoObservable* pObs = new PseudoObservable;
31  PseudoObservable::ObservedPtr ptr(pObs);
32  EXPECT_NE(nullptr, ptr.Get());
33  EXPECT_EQ(1u, pObs->ActiveObservedPtrs());
34  delete pObs;
35  EXPECT_EQ(nullptr, ptr.Get());
36}
37
38TEST(fxcrt, ObservePtrLivesShorter) {
39  PseudoObservable obs;
40  {
41    PseudoObservable::ObservedPtr ptr(&obs);
42    EXPECT_NE(nullptr, ptr.Get());
43    EXPECT_EQ(1u, obs.ActiveObservedPtrs());
44  }
45  EXPECT_EQ(0u, obs.ActiveObservedPtrs());
46}
47
48TEST(fxcrt, ObserveCopyConstruct) {
49  PseudoObservable obs;
50  {
51    PseudoObservable::ObservedPtr ptr(&obs);
52    EXPECT_NE(nullptr, ptr.Get());
53    EXPECT_EQ(1u, obs.ActiveObservedPtrs());
54    {
55      PseudoObservable::ObservedPtr ptr2(ptr);
56      EXPECT_NE(nullptr, ptr2.Get());
57      EXPECT_EQ(2u, obs.ActiveObservedPtrs());
58    }
59    EXPECT_EQ(1u, obs.ActiveObservedPtrs());
60  }
61  EXPECT_EQ(0u, obs.ActiveObservedPtrs());
62}
63
64TEST(fxcrt, ObserveCopyAssign) {
65  PseudoObservable obs;
66  {
67    PseudoObservable::ObservedPtr ptr(&obs);
68    EXPECT_NE(nullptr, ptr.Get());
69    EXPECT_EQ(1u, obs.ActiveObservedPtrs());
70    {
71      PseudoObservable::ObservedPtr ptr2;
72      ptr2 = ptr;
73      EXPECT_NE(nullptr, ptr2.Get());
74      EXPECT_EQ(2u, obs.ActiveObservedPtrs());
75    }
76    EXPECT_EQ(1u, obs.ActiveObservedPtrs());
77  }
78  EXPECT_EQ(0u, obs.ActiveObservedPtrs());
79}
80
81TEST(fxcrt, ObserveVector) {
82  PseudoObservable obs;
83  {
84    std::vector<PseudoObservable::ObservedPtr> vec1;
85    std::vector<PseudoObservable::ObservedPtr> vec2;
86    vec1.emplace_back(&obs);
87    vec1.emplace_back(&obs);
88    EXPECT_NE(nullptr, vec1[0].Get());
89    EXPECT_NE(nullptr, vec1[1].Get());
90    EXPECT_EQ(2u, obs.ActiveObservedPtrs());
91    vec2 = vec1;
92    EXPECT_NE(nullptr, vec2[0].Get());
93    EXPECT_NE(nullptr, vec2[1].Get());
94    EXPECT_EQ(4u, obs.ActiveObservedPtrs());
95    vec1.clear();
96    EXPECT_EQ(2u, obs.ActiveObservedPtrs());
97    vec2.resize(10000);
98    EXPECT_EQ(2u, obs.ActiveObservedPtrs());
99    vec2.resize(0);
100    EXPECT_EQ(0u, obs.ActiveObservedPtrs());
101  }
102  EXPECT_EQ(0u, obs.ActiveObservedPtrs());
103}
104
105TEST(fxcrt, ObserveVectorAutoClear) {
106  std::vector<PseudoObservable::ObservedPtr> vec1;
107  {
108    PseudoObservable obs;
109    vec1.emplace_back(&obs);
110    vec1.emplace_back(&obs);
111    EXPECT_NE(nullptr, vec1[0].Get());
112    EXPECT_NE(nullptr, vec1[1].Get());
113    EXPECT_EQ(2u, obs.ActiveObservedPtrs());
114  }
115  EXPECT_EQ(nullptr, vec1[0].Get());
116  EXPECT_EQ(nullptr, vec1[1].Get());
117}
118
119TEST(fxcrt, ObservePtrResetNull) {
120  PseudoObservable obs;
121  PseudoObservable::ObservedPtr ptr(&obs);
122  EXPECT_EQ(1u, obs.ActiveObservedPtrs());
123  ptr.Reset();
124  EXPECT_EQ(0u, obs.ActiveObservedPtrs());
125}
126
127TEST(fxcrt, ObservePtrReset) {
128  PseudoObservable obs1;
129  PseudoObservable obs2;
130  PseudoObservable::ObservedPtr ptr(&obs1);
131  EXPECT_EQ(1u, obs1.ActiveObservedPtrs());
132  EXPECT_EQ(0u, obs2.ActiveObservedPtrs());
133  ptr.Reset(&obs2);
134  EXPECT_EQ(0u, obs1.ActiveObservedPtrs());
135  EXPECT_EQ(1u, obs2.ActiveObservedPtrs());
136}
137
138TEST(fxcrt, ObservePtrEquals) {
139  PseudoObservable obj1;
140  PseudoObservable obj2;
141  PseudoObservable::ObservedPtr null_ptr1;
142  PseudoObservable::ObservedPtr obj1_ptr1(&obj1);
143  PseudoObservable::ObservedPtr obj2_ptr1(&obj2);
144  {
145    PseudoObservable::ObservedPtr null_ptr2;
146    EXPECT_TRUE(null_ptr1 == null_ptr2);
147
148    PseudoObservable::ObservedPtr obj1_ptr2(&obj1);
149    EXPECT_TRUE(obj1_ptr1 == obj1_ptr2);
150
151    PseudoObservable::ObservedPtr obj2_ptr2(&obj2);
152    EXPECT_TRUE(obj2_ptr1 == obj2_ptr2);
153  }
154  EXPECT_FALSE(null_ptr1 == obj1_ptr1);
155  EXPECT_FALSE(null_ptr1 == obj2_ptr1);
156  EXPECT_FALSE(obj1_ptr1 == obj2_ptr1);
157}
158
159TEST(fxcrt, ObservePtrNotEquals) {
160  PseudoObservable obj1;
161  PseudoObservable obj2;
162  PseudoObservable::ObservedPtr null_ptr1;
163  PseudoObservable::ObservedPtr obj1_ptr1(&obj1);
164  PseudoObservable::ObservedPtr obj2_ptr1(&obj2);
165  {
166    PseudoObservable::ObservedPtr null_ptr2;
167    PseudoObservable::ObservedPtr obj1_ptr2(&obj1);
168    PseudoObservable::ObservedPtr obj2_ptr2(&obj2);
169    EXPECT_FALSE(null_ptr1 != null_ptr2);
170    EXPECT_FALSE(obj1_ptr1 != obj1_ptr2);
171    EXPECT_FALSE(obj2_ptr1 != obj2_ptr2);
172  }
173  EXPECT_TRUE(null_ptr1 != obj1_ptr1);
174  EXPECT_TRUE(null_ptr1 != obj2_ptr1);
175  EXPECT_TRUE(obj1_ptr1 != obj2_ptr1);
176}
177
178TEST(fxcrt, ObservePtrBool) {
179  PseudoObservable obj1;
180  PseudoObservable::ObservedPtr null_ptr;
181  PseudoObservable::ObservedPtr obj1_ptr(&obj1);
182  bool null_bool = !!null_ptr;
183  bool obj1_bool = !!obj1_ptr;
184  EXPECT_FALSE(null_bool);
185  EXPECT_TRUE(obj1_bool);
186}
187