| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include "perfetto/trace_processor/ref_counted.h" |
| |
| #include "test/gtest_and_gmock.h" |
| |
| namespace perfetto { |
| namespace trace_processor { |
| namespace { |
| |
| int g_instances = 0; |
| |
| class RObj : public RefCounted { |
| public: |
| RObj() { ++g_instances; } |
| ~RObj() { --g_instances; } |
| }; |
| |
| TEST(RefCountedTest, CreateAndReset) { |
| RefPtr<RObj> ptr; |
| EXPECT_FALSE(ptr); |
| EXPECT_EQ(ptr.get(), nullptr); |
| |
| g_instances = 0; |
| |
| for (int i = 0; i < 3; i++) { |
| ptr.reset(new RObj()); |
| EXPECT_TRUE(ptr); |
| EXPECT_NE(ptr.get(), nullptr); |
| EXPECT_EQ(g_instances, 1); |
| } |
| |
| ptr.reset(); |
| EXPECT_EQ(g_instances, 0); |
| EXPECT_FALSE(ptr); |
| |
| ptr.reset(new RObj()); |
| ptr.reset(nullptr); |
| EXPECT_EQ(g_instances, 0); |
| EXPECT_FALSE(ptr); |
| |
| // Test RAII. |
| { |
| RefPtr<RObj> ptr1(new RObj()); |
| EXPECT_EQ(g_instances, 1); |
| { |
| RefPtr<RObj> ptr2(new RObj()); |
| EXPECT_EQ(g_instances, 2); |
| } |
| EXPECT_EQ(g_instances, 1); |
| } |
| EXPECT_EQ(g_instances, 0); |
| } |
| |
| TEST(RefCountedTest, CopyOperators) { |
| g_instances = 0; |
| |
| RefPtr<RObj> x1(new RObj()); |
| RefPtr<RObj> y1(new RObj()); |
| EXPECT_EQ(g_instances, 2); |
| |
| auto x2 = x1; |
| EXPECT_EQ(g_instances, 2); |
| |
| auto y2 = y1; |
| EXPECT_EQ(g_instances, 2); |
| |
| EXPECT_EQ(x1.get(), x2.get()); |
| EXPECT_EQ(&*y1, &*y2); |
| |
| x1.reset(); |
| y2.reset(); |
| EXPECT_EQ(g_instances, 2); |
| |
| x2.reset(); |
| EXPECT_EQ(g_instances, 1); |
| |
| y1 = x2; |
| EXPECT_EQ(g_instances, 0); |
| |
| { |
| RefPtr<RObj> nested1(new RObj()); |
| EXPECT_EQ(g_instances, 1); |
| { |
| RefPtr<RObj> nested2(new RObj()); |
| EXPECT_EQ(g_instances, 2); |
| nested1 = nested2; |
| EXPECT_EQ(g_instances, 1); |
| } |
| EXPECT_EQ(g_instances, 1); |
| } |
| EXPECT_EQ(g_instances, 0); |
| } |
| |
| TEST(RefCountedTest, MoveOperators) { |
| g_instances = 0; |
| |
| RefPtr<RObj> x1(new RObj()); |
| RefPtr<RObj> y1(new RObj()); |
| EXPECT_EQ(g_instances, 2); |
| |
| auto x2 = std::move(x1); |
| EXPECT_EQ(g_instances, 2); |
| EXPECT_FALSE(x1); |
| |
| auto y2 = std::move(y1); |
| EXPECT_EQ(g_instances, 2); |
| EXPECT_FALSE(y1); |
| |
| // Test recycling. |
| x1 = RefPtr<RObj>(new RObj()); |
| EXPECT_EQ(g_instances, 3); |
| |
| // y1 is still null; |
| y2 = std::move(y1); |
| EXPECT_FALSE(y1); |
| EXPECT_FALSE(y2); |
| EXPECT_EQ(g_instances, 2); // y2 goes away. |
| |
| // We are left with x1 and x2. |
| EXPECT_TRUE(x1); |
| EXPECT_TRUE(x2); |
| EXPECT_NE(&*x1, &*x2); |
| |
| x1 = std::move(x2); // Now only x1 is left. |
| EXPECT_EQ(g_instances, 1); |
| EXPECT_FALSE(x2); |
| |
| x1 = std::move(x2); |
| EXPECT_EQ(g_instances, 0); |
| |
| { |
| RefPtr<RObj> nested1(new RObj()); |
| EXPECT_EQ(g_instances, 1); |
| { |
| RefPtr<RObj> nested2(new RObj()); |
| EXPECT_EQ(g_instances, 2); |
| nested1 = std::move(nested2); |
| EXPECT_EQ(g_instances, 1); |
| } |
| EXPECT_EQ(g_instances, 1); |
| } |
| EXPECT_EQ(g_instances, 0); |
| } |
| |
| } // namespace |
| } // namespace trace_processor |
| } // namespace perfetto |