1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "perfetto/trace_processor/ref_counted.h"
17
18 #include "test/gtest_and_gmock.h"
19
20 namespace perfetto {
21 namespace trace_processor {
22 namespace {
23
24 int g_instances = 0;
25
26 class RObj : public RefCounted {
27 public:
RObj()28 RObj() { ++g_instances; }
~RObj()29 ~RObj() { --g_instances; }
30 };
31
TEST(RefCountedTest,CreateAndReset)32 TEST(RefCountedTest, CreateAndReset) {
33 RefPtr<RObj> ptr;
34 EXPECT_FALSE(ptr);
35 EXPECT_EQ(ptr.get(), nullptr);
36
37 g_instances = 0;
38
39 for (int i = 0; i < 3; i++) {
40 ptr.reset(new RObj());
41 EXPECT_TRUE(ptr);
42 EXPECT_NE(ptr.get(), nullptr);
43 EXPECT_EQ(g_instances, 1);
44 }
45
46 ptr.reset();
47 EXPECT_EQ(g_instances, 0);
48 EXPECT_FALSE(ptr);
49
50 ptr.reset(new RObj());
51 ptr.reset(nullptr);
52 EXPECT_EQ(g_instances, 0);
53 EXPECT_FALSE(ptr);
54
55 // Test RAII.
56 {
57 RefPtr<RObj> ptr1(new RObj());
58 EXPECT_EQ(g_instances, 1);
59 {
60 RefPtr<RObj> ptr2(new RObj());
61 EXPECT_EQ(g_instances, 2);
62 }
63 EXPECT_EQ(g_instances, 1);
64 }
65 EXPECT_EQ(g_instances, 0);
66 }
67
TEST(RefCountedTest,CopyOperators)68 TEST(RefCountedTest, CopyOperators) {
69 g_instances = 0;
70
71 RefPtr<RObj> x1(new RObj());
72 RefPtr<RObj> y1(new RObj());
73 EXPECT_EQ(g_instances, 2);
74
75 auto x2 = x1;
76 EXPECT_EQ(g_instances, 2);
77
78 auto y2 = y1;
79 EXPECT_EQ(g_instances, 2);
80
81 EXPECT_EQ(x1.get(), x2.get());
82 EXPECT_EQ(&*y1, &*y2);
83
84 x1.reset();
85 y2.reset();
86 EXPECT_EQ(g_instances, 2);
87
88 x2.reset();
89 EXPECT_EQ(g_instances, 1);
90
91 y1 = x2;
92 EXPECT_EQ(g_instances, 0);
93
94 {
95 RefPtr<RObj> nested1(new RObj());
96 EXPECT_EQ(g_instances, 1);
97 {
98 RefPtr<RObj> nested2(new RObj());
99 EXPECT_EQ(g_instances, 2);
100 nested1 = nested2;
101 EXPECT_EQ(g_instances, 1);
102 }
103 EXPECT_EQ(g_instances, 1);
104 }
105 EXPECT_EQ(g_instances, 0);
106 }
107
TEST(RefCountedTest,MoveOperators)108 TEST(RefCountedTest, MoveOperators) {
109 g_instances = 0;
110
111 RefPtr<RObj> x1(new RObj());
112 RefPtr<RObj> y1(new RObj());
113 EXPECT_EQ(g_instances, 2);
114
115 auto x2 = std::move(x1);
116 EXPECT_EQ(g_instances, 2);
117 EXPECT_FALSE(x1);
118
119 auto y2 = std::move(y1);
120 EXPECT_EQ(g_instances, 2);
121 EXPECT_FALSE(y1);
122
123 // Test recycling.
124 x1 = RefPtr<RObj>(new RObj());
125 EXPECT_EQ(g_instances, 3);
126
127 // y1 is still null;
128 y2 = std::move(y1);
129 EXPECT_FALSE(y1);
130 EXPECT_FALSE(y2);
131 EXPECT_EQ(g_instances, 2); // y2 goes away.
132
133 // We are left with x1 and x2.
134 EXPECT_TRUE(x1);
135 EXPECT_TRUE(x2);
136 EXPECT_NE(&*x1, &*x2);
137
138 x1 = std::move(x2); // Now only x1 is left.
139 EXPECT_EQ(g_instances, 1);
140 EXPECT_FALSE(x2);
141
142 x1 = std::move(x2);
143 EXPECT_EQ(g_instances, 0);
144
145 {
146 RefPtr<RObj> nested1(new RObj());
147 EXPECT_EQ(g_instances, 1);
148 {
149 RefPtr<RObj> nested2(new RObj());
150 EXPECT_EQ(g_instances, 2);
151 nested1 = std::move(nested2);
152 EXPECT_EQ(g_instances, 1);
153 }
154 EXPECT_EQ(g_instances, 1);
155 }
156 EXPECT_EQ(g_instances, 0);
157 }
158
159 } // namespace
160 } // namespace trace_processor
161 } // namespace perfetto
162