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