1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/weak_ptr.h"
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
93f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <class T>
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass OffThreadObjectCreator {
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static T* NewObject() {
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    T* result;
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Thread creator_thread("creator_thread");
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      creator_thread.Start();
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      creator_thread.message_loop()->PostTask(
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          FROM_HERE,
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          NewRunnableFunction(OffThreadObjectCreator::CreateObject, &result));
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(result);  // We synchronized on thread destruction above.
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void CreateObject(T** result) {
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *result = new T;
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct Base {};
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct Derived : Base {};
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct Producer : SupportsWeakPtr<Producer> {};
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct Consumer { WeakPtr<Producer> producer; };
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, Basic) {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int data;
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtrFactory<int> factory(&data);
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtr<int> ptr = factory.GetWeakPtr();
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(&data, ptr.get());
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, Comparison) {
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int data;
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtrFactory<int> factory(&data);
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtr<int> ptr = factory.GetWeakPtr();
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtr<int> ptr2 = ptr;
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(ptr == ptr2);
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, OutOfScope) {
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtr<int> ptr;
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(ptr.get() == NULL);
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  {
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int data;
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    WeakPtrFactory<int> factory(&data);
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ptr = factory.GetWeakPtr();
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(ptr.get() == NULL);
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, Multiple) {
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtr<int> a, b;
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  {
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int data;
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    WeakPtrFactory<int> factory(&data);
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    a = factory.GetWeakPtr();
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    b = factory.GetWeakPtr();
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(&data, a.get());
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(&data, b.get());
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(a.get() == NULL);
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(b.get() == NULL);
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, UpCast) {
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Derived data;
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtrFactory<Derived> factory(&data);
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtr<Base> ptr = factory.GetWeakPtr();
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ptr = factory.GetWeakPtr();
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(ptr.get(), &data);
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, SupportsWeakPtr) {
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Producer f;
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtr<Producer> ptr = f.AsWeakPtr();
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(&f, ptr.get());
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, InvalidateWeakPtrs) {
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int data;
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtrFactory<int> factory(&data);
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtr<int> ptr = factory.GetWeakPtr();
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(&data, ptr.get());
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(factory.HasWeakPtrs());
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  factory.InvalidateWeakPtrs();
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(ptr.get() == NULL);
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(factory.HasWeakPtrs());
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, HasWeakPtrs) {
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int data;
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtrFactory<int> factory(&data);
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  {
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    WeakPtr<int> ptr = factory.GetWeakPtr();
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(factory.HasWeakPtrs());
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(factory.HasWeakPtrs());
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, SingleThreaded1) {
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Test that it is OK to create a class that supports weak references on one
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // thread, but use it on another.  This tests that we do not trip runtime
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // checks that ensure that a weak reference is not used by multiple threads.
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<Producer> producer(OffThreadObjectCreator<Producer>::NewObject());
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WeakPtr<Producer> weak_producer = producer->AsWeakPtr();
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(producer.get(), weak_producer.get());
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(WeakPtrTest, SingleThreaded2) {
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Test that it is OK to create a class that has a WeakPtr member on one
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // thread, but use it on another.  This tests that we do not trip runtime
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // checks that ensure that a weak reference is not used by multiple threads.
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject());
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Producer producer;
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  consumer->producer = producer.AsWeakPtr();
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(&producer, consumer->producer.get());
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
138