/* * 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 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 ptr1(new RObj()); EXPECT_EQ(g_instances, 1); { RefPtr 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 x1(new RObj()); RefPtr 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 nested1(new RObj()); EXPECT_EQ(g_instances, 1); { RefPtr 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 x1(new RObj()); RefPtr 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(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 nested1(new RObj()); EXPECT_EQ(g_instances, 1); { RefPtr 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