|  | /* | 
|  | *  Copyright 2016 The WebRTC Project Authors. All rights reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #include "rtc_base/weak_ptr.h" | 
|  |  | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <utility> | 
|  |  | 
|  | #include "rtc_base/task_queue_for_test.h" | 
|  | #include "test/gtest.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | struct Base { | 
|  | std::string member; | 
|  | }; | 
|  | struct Derived : public Base {}; | 
|  |  | 
|  | struct 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, Move) { | 
|  | int data; | 
|  | WeakPtrFactory<int> factory(&data); | 
|  | WeakPtr<int> ptr = factory.GetWeakPtr(); | 
|  | WeakPtr<int> ptr2 = factory.GetWeakPtr(); | 
|  | WeakPtr<int> ptr3 = std::move(ptr2); | 
|  | EXPECT_NE(ptr.get(), ptr2.get()); | 
|  | EXPECT_EQ(ptr.get(), ptr3.get()); | 
|  | } | 
|  |  | 
|  | TEST(WeakPtrFactoryTest, OutOfScope) { | 
|  | WeakPtr<int> ptr; | 
|  | EXPECT_EQ(nullptr, ptr.get()); | 
|  | { | 
|  | int data; | 
|  | WeakPtrFactory<int> factory(&data); | 
|  | ptr = factory.GetWeakPtr(); | 
|  | EXPECT_EQ(&data, ptr.get()); | 
|  | } | 
|  | EXPECT_EQ(nullptr, 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(nullptr, a.get()); | 
|  | EXPECT_EQ(nullptr, b.get()); | 
|  | } | 
|  |  | 
|  | TEST(WeakPtrFactoryTest, MultipleStaged) { | 
|  | WeakPtr<int> a; | 
|  | { | 
|  | int data; | 
|  | WeakPtrFactory<int> factory(&data); | 
|  | a = factory.GetWeakPtr(); | 
|  | { WeakPtr<int> b = factory.GetWeakPtr(); } | 
|  | EXPECT_NE(nullptr, a.get()); | 
|  | } | 
|  | EXPECT_EQ(nullptr, 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, DefaultConstructor) { | 
|  | WeakPtr<int> ptr; | 
|  | EXPECT_EQ(nullptr, ptr.get()); | 
|  | } | 
|  |  | 
|  | TEST(WeakPtrFactoryTest, BooleanTesting) { | 
|  | int data; | 
|  | WeakPtrFactory<int> factory(&data); | 
|  |  | 
|  | WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr(); | 
|  | EXPECT_TRUE(ptr_to_an_instance); | 
|  | EXPECT_FALSE(!ptr_to_an_instance); | 
|  |  | 
|  | if (ptr_to_an_instance) { | 
|  | } else { | 
|  | ADD_FAILURE() << "Pointer to an instance should result in true."; | 
|  | } | 
|  |  | 
|  | if (!ptr_to_an_instance) {  // check for operator!(). | 
|  | ADD_FAILURE() << "Pointer to an instance should result in !x being false."; | 
|  | } | 
|  |  | 
|  | WeakPtr<int> null_ptr; | 
|  | EXPECT_FALSE(null_ptr); | 
|  | EXPECT_TRUE(!null_ptr); | 
|  |  | 
|  | if (null_ptr) { | 
|  | ADD_FAILURE() << "Null pointer should result in false."; | 
|  | } | 
|  |  | 
|  | if (!null_ptr) {  // check for operator!(). | 
|  | } else { | 
|  | ADD_FAILURE() << "Null pointer should result in !x being true."; | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST(WeakPtrFactoryTest, ComparisonToNull) { | 
|  | int data; | 
|  | WeakPtrFactory<int> factory(&data); | 
|  |  | 
|  | WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr(); | 
|  | EXPECT_NE(nullptr, ptr_to_an_instance); | 
|  | EXPECT_NE(ptr_to_an_instance, nullptr); | 
|  |  | 
|  | WeakPtr<int> null_ptr; | 
|  | EXPECT_EQ(null_ptr, nullptr); | 
|  | EXPECT_EQ(nullptr, null_ptr); | 
|  | } | 
|  |  | 
|  | 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(nullptr, 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(nullptr, 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()); | 
|  | } | 
|  |  | 
|  | template <class T> | 
|  | std::unique_ptr<T> NewObjectCreatedOnTaskQueue() { | 
|  | std::unique_ptr<T> obj; | 
|  | TaskQueueForTest queue("NewObjectCreatedOnTaskQueue"); | 
|  | queue.SendTask([&] { obj = std::make_unique<T>(); }); | 
|  | return obj; | 
|  | } | 
|  |  | 
|  | TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) { | 
|  | // Test that it is OK to create an object with a WeakPtrFactory one thread, | 
|  | // but use it on another.  This tests that we do not trip runtime checks that | 
|  | // ensure that a WeakPtr is not used by multiple threads. | 
|  | std::unique_ptr<TargetWithFactory> target( | 
|  | NewObjectCreatedOnTaskQueue<TargetWithFactory>()); | 
|  | WeakPtr<Target> weak_ptr = target->factory.GetWeakPtr(); | 
|  | EXPECT_EQ(target.get(), weak_ptr.get()); | 
|  | } | 
|  |  | 
|  | TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) { | 
|  | // Test that it is OK to create a WeakPtr on one thread, but use it on | 
|  | // another. This tests that we do not trip runtime checks that ensure that a | 
|  | // WeakPtr is not used by multiple threads. | 
|  | auto target = std::make_unique<TargetWithFactory>(); | 
|  | // Create weak ptr on main thread | 
|  | WeakPtr<Target> weak_ptr = target->factory.GetWeakPtr(); | 
|  | TaskQueueForTest queue("queue"); | 
|  | queue.SendTask([&] { | 
|  | // Dereference and invalide weak_ptr on another thread. | 
|  | EXPECT_EQ(weak_ptr.get(), target.get()); | 
|  | target.reset(); | 
|  | }); | 
|  | } | 
|  |  | 
|  | }  // namespace webrtc |