// Copyright (c) 2012 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 "butil/memory/weak_ptr.h" #include <string> #include "butil/debug/leak_annotations.h" #include "butil/memory/scoped_ptr.h" #include "butil/synchronization/waitable_event.h" #include <gtest/gtest.h> namespace butil { namespace { struct Base { std::string member; }; struct Derived : public Base {}; struct TargetBase {}; struct Target : public TargetBase, public SupportsWeakPtr<Target> { virtual ~Target() {} }; struct DerivedTarget : public Target {}; struct Arrow { WeakPtr<Target> target; }; struct TargetWithFactory : public Target { TargetWithFactory() : factory(this) {} WeakPtrFactory<Target> factory; }; } // namespace TEST(WeakPtrFactoryTest, Basic) { int data; WeakPtrFactory<int> factory(&data); WeakPtr<int> ptr = factory.GetWeakPtr(); EXPECT_EQ(&data, ptr.get()); } TEST(WeakPtrFactoryTest, Comparison) { int data; WeakPtrFactory<int> factory(&data); WeakPtr<int> ptr = factory.GetWeakPtr(); WeakPtr<int> ptr2 = ptr; EXPECT_EQ(ptr.get(), ptr2.get()); } TEST(WeakPtrFactoryTest, OutOfScope) { WeakPtr<int> ptr; EXPECT_EQ(NULL, ptr.get()); { int data; WeakPtrFactory<int> factory(&data); ptr = factory.GetWeakPtr(); } EXPECT_EQ(NULL, ptr.get()); } TEST(WeakPtrFactoryTest, Multiple) { WeakPtr<int> a, b; { int data; WeakPtrFactory<int> factory(&data); a = factory.GetWeakPtr(); b = factory.GetWeakPtr(); EXPECT_EQ(&data, a.get()); EXPECT_EQ(&data, b.get()); } EXPECT_EQ(NULL, a.get()); EXPECT_EQ(NULL, b.get()); } TEST(WeakPtrFactoryTest, MultipleStaged) { WeakPtr<int> a; { int data; WeakPtrFactory<int> factory(&data); a = factory.GetWeakPtr(); { WeakPtr<int> b = factory.GetWeakPtr(); } EXPECT_TRUE(NULL != a.get()); } EXPECT_EQ(NULL, a.get()); } TEST(WeakPtrFactoryTest, Dereference) { Base data; data.member = "123456"; WeakPtrFactory<Base> factory(&data); WeakPtr<Base> ptr = factory.GetWeakPtr(); EXPECT_EQ(&data, ptr.get()); EXPECT_EQ(data.member, (*ptr).member); EXPECT_EQ(data.member, ptr->member); } TEST(WeakPtrFactoryTest, UpCast) { Derived data; WeakPtrFactory<Derived> factory(&data); WeakPtr<Base> ptr = factory.GetWeakPtr(); ptr = factory.GetWeakPtr(); EXPECT_EQ(ptr.get(), &data); } TEST(WeakPtrTest, SupportsWeakPtr) { Target target; WeakPtr<Target> ptr = target.AsWeakPtr(); EXPECT_EQ(&target, ptr.get()); } TEST(WeakPtrTest, DerivedTarget) { DerivedTarget target; WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target); EXPECT_EQ(&target, ptr.get()); } TEST(WeakPtrTest, InvalidateWeakPtrs) { int data; WeakPtrFactory<int> factory(&data); WeakPtr<int> ptr = factory.GetWeakPtr(); EXPECT_EQ(&data, ptr.get()); EXPECT_TRUE(factory.HasWeakPtrs()); factory.InvalidateWeakPtrs(); EXPECT_EQ(NULL, ptr.get()); EXPECT_FALSE(factory.HasWeakPtrs()); // Test that the factory can create new weak pointers after a // InvalidateWeakPtrs call, and they remain valid until the next // InvalidateWeakPtrs call. WeakPtr<int> ptr2 = factory.GetWeakPtr(); EXPECT_EQ(&data, ptr2.get()); EXPECT_TRUE(factory.HasWeakPtrs()); factory.InvalidateWeakPtrs(); EXPECT_EQ(NULL, ptr2.get()); EXPECT_FALSE(factory.HasWeakPtrs()); } TEST(WeakPtrTest, HasWeakPtrs) { int data; WeakPtrFactory<int> factory(&data); { WeakPtr<int> ptr = factory.GetWeakPtr(); EXPECT_TRUE(factory.HasWeakPtrs()); } EXPECT_FALSE(factory.HasWeakPtrs()); } } // namespace butil