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