|  | // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/debug/leak_tracker.h" | 
|  | #include "base/memory/scoped_ptr.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | namespace base { | 
|  | namespace debug { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | class ClassA { | 
|  | private: | 
|  | LeakTracker<ClassA> leak_tracker_; | 
|  | }; | 
|  |  | 
|  | class ClassB { | 
|  | private: | 
|  | LeakTracker<ClassB> leak_tracker_; | 
|  | }; | 
|  |  | 
|  | #ifndef ENABLE_LEAK_TRACKER | 
|  |  | 
|  | // If leak tracking is disabled, we should do nothing. | 
|  | TEST(LeakTrackerTest, NotEnabled) { | 
|  | EXPECT_EQ(-1, LeakTracker<ClassA>::NumLiveInstances()); | 
|  | EXPECT_EQ(-1, LeakTracker<ClassB>::NumLiveInstances()); | 
|  |  | 
|  | // Use scoped_ptr so compiler doesn't complain about unused variables. | 
|  | scoped_ptr<ClassA> a1(new ClassA); | 
|  | scoped_ptr<ClassB> b1(new ClassB); | 
|  | scoped_ptr<ClassB> b2(new ClassB); | 
|  |  | 
|  | EXPECT_EQ(-1, LeakTracker<ClassA>::NumLiveInstances()); | 
|  | EXPECT_EQ(-1, LeakTracker<ClassB>::NumLiveInstances()); | 
|  | } | 
|  |  | 
|  | #else | 
|  |  | 
|  | TEST(LeakTrackerTest, Basic) { | 
|  | { | 
|  | ClassA a1; | 
|  |  | 
|  | EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances()); | 
|  | EXPECT_EQ(0, LeakTracker<ClassB>::NumLiveInstances()); | 
|  |  | 
|  | ClassB b1; | 
|  | ClassB b2; | 
|  |  | 
|  | EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances()); | 
|  | EXPECT_EQ(2, LeakTracker<ClassB>::NumLiveInstances()); | 
|  |  | 
|  | scoped_ptr<ClassA> a2(new ClassA); | 
|  |  | 
|  | EXPECT_EQ(2, LeakTracker<ClassA>::NumLiveInstances()); | 
|  | EXPECT_EQ(2, LeakTracker<ClassB>::NumLiveInstances()); | 
|  |  | 
|  | a2.reset(); | 
|  |  | 
|  | EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances()); | 
|  | EXPECT_EQ(2, LeakTracker<ClassB>::NumLiveInstances()); | 
|  | } | 
|  |  | 
|  | EXPECT_EQ(0, LeakTracker<ClassA>::NumLiveInstances()); | 
|  | EXPECT_EQ(0, LeakTracker<ClassB>::NumLiveInstances()); | 
|  | } | 
|  |  | 
|  | // Try some orderings of create/remove to hit different cases in the linked-list | 
|  | // assembly. | 
|  | TEST(LeakTrackerTest, LinkedList) { | 
|  | EXPECT_EQ(0, LeakTracker<ClassB>::NumLiveInstances()); | 
|  |  | 
|  | scoped_ptr<ClassA> a1(new ClassA); | 
|  | scoped_ptr<ClassA> a2(new ClassA); | 
|  | scoped_ptr<ClassA> a3(new ClassA); | 
|  | scoped_ptr<ClassA> a4(new ClassA); | 
|  |  | 
|  | EXPECT_EQ(4, LeakTracker<ClassA>::NumLiveInstances()); | 
|  |  | 
|  | // Remove the head of the list (a1). | 
|  | a1.reset(); | 
|  | EXPECT_EQ(3, LeakTracker<ClassA>::NumLiveInstances()); | 
|  |  | 
|  | // Remove the tail of the list (a4). | 
|  | a4.reset(); | 
|  | EXPECT_EQ(2, LeakTracker<ClassA>::NumLiveInstances()); | 
|  |  | 
|  | // Append to the new tail of the list (a3). | 
|  | scoped_ptr<ClassA> a5(new ClassA); | 
|  | EXPECT_EQ(3, LeakTracker<ClassA>::NumLiveInstances()); | 
|  |  | 
|  | a2.reset(); | 
|  | a3.reset(); | 
|  |  | 
|  | EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances()); | 
|  |  | 
|  | a5.reset(); | 
|  | EXPECT_EQ(0, LeakTracker<ClassA>::NumLiveInstances()); | 
|  | } | 
|  |  | 
|  | TEST(LeakTrackerTest, NoOpCheckForLeaks) { | 
|  | // There are no live instances of ClassA, so this should do nothing. | 
|  | LeakTracker<ClassA>::CheckForLeaks(); | 
|  | } | 
|  |  | 
|  | #endif  // ENABLE_LEAK_TRACKER | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | }  // namespace debug | 
|  | }  // namespace base |