| Index: webrtc/base/weak_ptr_unittest.cc
|
| diff --git a/webrtc/base/weak_ptr_unittest.cc b/webrtc/base/weak_ptr_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a3cd1f839c5b990767f6b671e7c0bffa980bf02a
|
| --- /dev/null
|
| +++ b/webrtc/base/weak_ptr_unittest.cc
|
| @@ -0,0 +1,233 @@
|
| +/*
|
| + * 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 <string>
|
| +
|
| +#include "webrtc/base/gunit.h"
|
| +#include "webrtc/base/task_queue.h"
|
| +#include "webrtc/base/weak_ptr.h"
|
| +
|
| +namespace rtc {
|
| +
|
| +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;
|
| + TaskQueue queue("NewObjectCreatedOnTaskQueue");
|
| + Event event(false, false);
|
| + queue.PostTask([&event, &obj] {
|
| + obj.reset(new T());
|
| + event.Set();
|
| + });
|
| + EXPECT_TRUE(event.Wait(1000));
|
| + 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 an object that has a WeakPtr member 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.
|
| + std::unique_ptr<Arrow> arrow(NewObjectCreatedOnTaskQueue<Arrow>());
|
| + TargetWithFactory target;
|
| + arrow->target = target.factory.GetWeakPtr();
|
| + EXPECT_EQ(&target, arrow->target.get());
|
| +}
|
| +
|
| +} // namespace rtc
|
|
|