Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(535)

Unified Diff: base/memory/weak_ptr_unittest.cc

Issue 10690080: Rename/re-comment tests and added new death tests for WeakPtr (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« base/memory/weak_ptr.h ('K') | « base/memory/weak_ptr.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/memory/weak_ptr_unittest.cc
===================================================================
--- base/memory/weak_ptr_unittest.cc (revision 145398)
+++ base/memory/weak_ptr_unittest.cc (working copy)
@@ -40,9 +40,9 @@
struct Base { std::string member; };
struct Derived : Base {};
-struct Producer : SupportsWeakPtr<Producer> {};
-struct DerivedProducer : Producer {};
-struct Consumer { WeakPtr<Producer> producer; };
+struct Target : SupportsWeakPtr<Target> {};
+struct DerivedTarget : Target {};
+struct Arrow { WeakPtr<Target> target; };
Ryan Sleevi 2012/07/10 00:06:44 style nit: struct Arrow { WeakPtr<Target> targe
kaiwang 2012/07/10 22:21:19 Done.
// Helper class to create and destroy weak pointer copies
// and delete objects on a background thread.
@@ -54,80 +54,80 @@
Stop();
}
- void CreateConsumerFromProducer(Consumer** consumer, Producer* producer) {
+ void CreateArrowFromTarget(Arrow** arrow, Target* target) {
WaitableEvent completion(true, false);
message_loop()->PostTask(
FROM_HERE,
- base::Bind(&BackgroundThread::DoCreateFromProducer, consumer, producer,
+ base::Bind(&BackgroundThread::DoCreateFromTarget, arrow, target,
&completion));
completion.Wait();
}
- void CreateConsumerFromConsumer(Consumer** consumer, const Consumer* other) {
+ void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
WaitableEvent completion(true, false);
message_loop()->PostTask(
FROM_HERE,
- base::Bind(&BackgroundThread::DoCreateFromConsumer, consumer, other,
+ base::Bind(&BackgroundThread::DoCreateFromArrow, arrow, other,
&completion));
completion.Wait();
}
- void DeleteProducer(Producer* object) {
+ void DeleteTarget(Target* object) {
WaitableEvent completion(true, false);
message_loop()->PostTask(
FROM_HERE,
- base::Bind(&BackgroundThread::DoDeleteProducer, object, &completion));
+ base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion));
completion.Wait();
}
- void DeleteConsumer(Consumer* object) {
+ void DeleteArrow(Arrow* object) {
WaitableEvent completion(true, false);
message_loop()->PostTask(
FROM_HERE,
- base::Bind(&BackgroundThread::DoDeleteConsumer, object, &completion));
+ base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion));
completion.Wait();
}
- Producer* DeRef(const Consumer* consumer) {
+ Target* DeRef(const Arrow* arrow) {
WaitableEvent completion(true, false);
- Producer* result = NULL;
+ Target* result = NULL;
message_loop()->PostTask(
FROM_HERE,
- base::Bind(&BackgroundThread::DoDeRef, consumer, &result, &completion));
+ base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion));
completion.Wait();
return result;
}
protected:
- static void DoCreateFromConsumer(Consumer** consumer,
- const Consumer* other,
- WaitableEvent* completion) {
- *consumer = new Consumer;
- **consumer = *other;
+ static void DoCreateFromArrow(Arrow** arrow,
+ const Arrow* other,
+ WaitableEvent* completion) {
+ *arrow = new Arrow;
+ **arrow = *other;
completion->Signal();
}
- static void DoCreateFromProducer(Consumer** consumer,
- Producer* producer,
- WaitableEvent* completion) {
- *consumer = new Consumer;
- (*consumer)->producer = producer->AsWeakPtr();
+ static void DoCreateFromTarget(Arrow** arrow,
+ Target* target,
+ WaitableEvent* completion) {
+ *arrow = new Arrow;
+ (*arrow)->target = target->AsWeakPtr();
completion->Signal();
}
- static void DoDeRef(const Consumer* consumer,
- Producer** result,
+ static void DoDeRef(const Arrow* arrow,
+ Target** result,
WaitableEvent* completion) {
- *result = consumer->producer.get();
+ *result = arrow->target.get();
completion->Signal();
}
- static void DoDeleteProducer(Producer* object, WaitableEvent* completion) {
+ static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
delete object;
completion->Signal();
}
- static void DoDeleteConsumer(Consumer* object, WaitableEvent* completion) {
+ static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
delete object;
completion->Signal();
}
@@ -135,14 +135,14 @@
} // namespace
-TEST(WeakPtrTest, Basic) {
+TEST(WeakPtrFactoryTest, Basic) {
int data;
WeakPtrFactory<int> factory(&data);
WeakPtr<int> ptr = factory.GetWeakPtr();
EXPECT_EQ(&data, ptr.get());
}
-TEST(WeakPtrTest, Comparison) {
+TEST(WeakPtrFactoryTest, Comparison) {
int data;
WeakPtrFactory<int> factory(&data);
WeakPtr<int> ptr = factory.GetWeakPtr();
@@ -150,7 +150,7 @@
EXPECT_TRUE(ptr == ptr2);
}
-TEST(WeakPtrTest, OutOfScope) {
+TEST(WeakPtrFactoryTest, OutOfScope) {
WeakPtr<int> ptr;
EXPECT_TRUE(ptr.get() == NULL);
{
@@ -161,7 +161,7 @@
EXPECT_TRUE(ptr.get() == NULL);
}
-TEST(WeakPtrTest, Multiple) {
+TEST(WeakPtrFactoryTest, Multiple) {
WeakPtr<int> a, b;
{
int data;
@@ -175,7 +175,7 @@
EXPECT_TRUE(b.get() == NULL);
}
-TEST(WeakPtrTest, MultipleStaged) {
+TEST(WeakPtrFactoryTest, MultipleStaged) {
WeakPtr<int> a;
{
int data;
@@ -189,7 +189,17 @@
EXPECT_TRUE(a.get() == NULL);
}
-TEST(WeakPtrTest, UpCast) {
+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();
@@ -198,14 +208,14 @@
}
TEST(WeakPtrTest, SupportsWeakPtr) {
- Producer f;
- WeakPtr<Producer> ptr = f.AsWeakPtr();
+ Target f;
+ WeakPtr<Target> ptr = f.AsWeakPtr();
EXPECT_EQ(&f, ptr.get());
}
-TEST(WeakPtrTest, DerivedProducer) {
- DerivedProducer f;
- WeakPtr<DerivedProducer> ptr = AsWeakPtr(&f);
+TEST(WeakPtrTest, DerivedTarget) {
+ DerivedTarget f;
+ WeakPtr<DerivedTarget> ptr = AsWeakPtr(&f);
EXPECT_EQ(&f, ptr.get());
}
@@ -230,127 +240,192 @@
EXPECT_FALSE(factory.HasWeakPtrs());
}
-TEST(WeakPtrTest, SingleThreaded1) {
- // Test that it is OK to create a class that supports weak references on one
- // thread, but use it on another. This tests that we do not trip runtime
- // checks that ensure that a weak reference is not used by multiple threads.
- scoped_ptr<Producer> producer(OffThreadObjectCreator<Producer>::NewObject());
- WeakPtr<Producer> weak_producer = producer->AsWeakPtr();
- EXPECT_EQ(producer.get(), weak_producer.get());
+TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
+ // Test that it is OK to create an object that supports WeakPtr on one thread,
+ // but uses it on another. This tests that we do not trip runtime checks that
Ryan Sleevi 2012/07/10 00:06:44 nit: uses -> use (since this is an active statemen
kaiwang 2012/07/10 22:21:19 Done.
+ // ensure that a WeakPtr is not used by multiple threads.
+ scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
+ WeakPtr<Target> weak_ptr = target->AsWeakPtr();
+ EXPECT_EQ(target.get(), weak_ptr.get());
}
-TEST(WeakPtrTest, SingleThreaded2) {
- // Test that it is OK to create a class that has a WeakPtr member on one
+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 weak reference is not used by multiple threads.
- scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject());
- Producer producer;
- consumer->producer = producer.AsWeakPtr();
- EXPECT_EQ(&producer, consumer->producer.get());
+ // checks that ensure that a WeakPtr is not used by multiple threads.
+ scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
+ Target target;
+ arrow->target = target.AsWeakPtr();
+ EXPECT_EQ(&target, arrow->target.get());
}
-TEST(WeakPtrTest, MoveOwnershipImplicit) {
+TEST(WeakPtrTest, MoveOwnershipImplicitly) {
// Move object ownership to other thread by releasing all weak pointers
// on the original thread first. Establishing weak pointers on a different
// thread after previous pointers have been destroyed implicitly reattaches
// the thread checks.
- // - Thread A creates object and weak pointer
- // - Thread A deletes the weak pointer
- // - Thread B creates weak pointer
- // - Thread B derefs weak pointer
- // - Thread B deletes object
- BackgroundThread thread;
- thread.Start();
- Producer* producer = new Producer();
+ // - Main thread creates object and weak pointer
+ // - Main thread deletes the weak pointer, then the thread ownership of the
+ // object can be implicitly moved.
+ // - Background thread creates weak pointer(and implicitly owns the object)
+ // - Background thread derefs weak pointer
+ // - Background thread deletes object
+ // - Background thread deletes weak pointer
+ BackgroundThread background;
+ background.Start();
+ Target* target = new Target();
{
- WeakPtr<Producer> weak_ptr = producer->AsWeakPtr();
+ WeakPtr<Target> weak_ptr = target->AsWeakPtr();
}
- Consumer* consumer;
- thread.CreateConsumerFromProducer(&consumer, producer);
- EXPECT_EQ(thread.DeRef(consumer), producer);
- thread.DeleteProducer(producer);
- thread.DeleteConsumer(consumer);
+ Arrow* arrow;
+ background.CreateArrowFromTarget(&arrow, target);
+ EXPECT_EQ(background.DeRef(arrow), target);
+ background.DeleteTarget(target);
+ background.DeleteArrow(arrow);
}
-TEST(WeakPtrTest, MoveOwnershipExplicit) {
- // Test that we do not trip any checks if we establish weak references
- // on one thread and delete the object on another thread after explicit
- // detachment.
- // - Thread A creates object
- // - Thread B creates weak pointer
- // - Thread B releases weak pointer
- // - Detach owner from Thread B
- // - Thread A destroys object
- BackgroundThread thread;
- thread.Start();
- Producer producer;
- Consumer* consumer;
- thread.CreateConsumerFromProducer(&consumer, &producer);
- EXPECT_EQ(thread.DeRef(consumer), &producer);
- thread.DeleteConsumer(consumer);
- producer.DetachFromThread();
+TEST(WeakPtrTest, MoveOwnershipExplicitlyObjectNotReferenced) {
+ // Case 1: The target is not bound to any thread yet. So calling
+ // DetachFromThread() is a no-op.
+ Target target;
+ target.DetachFromThread();
+
+ // Case 2: The target is bound to main thread but no WeakPtr is pointing to
+ // it. In this case, it will be re-bound to any thread trying to get a
+ // WeakPtr pointing to it. So detach function call is again no-op.
+ {
+ WeakPtr<Target> weak_ptr = target.AsWeakPtr();
+ }
+ target.DetachFromThread();
}
+TEST(WeakPtrTest, MoveOwnershipExplicitly) {
+ // Test that we do not trip any checks if we establish WeakPtr on one thread
+ // and delete the object on another thread after explicit detachment.
+ // - Main thread creates object
+ // - Background thread creates weak pointer(and implicitly owns the object)
+ // - Object detach from background thread
+ // - Main thread destroys object
+ BackgroundThread background;
+ background.Start();
+ Target target;
+ Arrow* arrow;
+
+ background.CreateArrowFromTarget(&arrow, &target);
+ EXPECT_EQ(background.DeRef(arrow), &target);
+ target.DetachFromThread();
+ // Detached target getting destructed will not cause thread ownership
+ // violation.
+}
+
TEST(WeakPtrTest, ThreadARefOutlivesThreadBRef) {
// Originating thread has a WeakPtr that outlives others.
- // - Thread A creates WeakPtr<> and passes copy to Thread B
- // - Destruct the pointer on Thread B
- // - Destruct the pointer on Thread A
- BackgroundThread thread;
- thread.Start();
- Producer producer;
- Consumer consumer;
- consumer.producer = producer.AsWeakPtr();
- Consumer* consumer_copy;
- thread.CreateConsumerFromConsumer(&consumer_copy, &consumer);
- EXPECT_EQ(consumer_copy->producer, &producer);
- thread.DeleteConsumer(consumer_copy);
+ // - Main thread creates a WeakPtr
+ // - Background thread creates a WeakPtr copy from the one in main thread
+ // - Destruct the WeakPtr on background thread
+ // - Destruct the WeakPtr on main thread
+
+ BackgroundThread background;
+ background.Start();
+
+ Target target;
+ Arrow arrow;
+ arrow.target = target.AsWeakPtr();
+
+ Arrow* arrow_copy;
+ background.CreateArrowFromArrow(&arrow_copy, &arrow);
+ EXPECT_EQ(arrow_copy->target, &target);
+ background.DeleteArrow(arrow_copy);
}
TEST(WeakPtrTest, ThreadBRefOutlivesThreadARef) {
// Originating thread drops all references before another thread.
- // - Thread A creates WeakPtr<> and passes copy to Thread B
- // - Destruct the pointer on Thread A
- // - Destruct the pointer on Thread B
- BackgroundThread thread;
- thread.Start();
- Producer producer;
- Consumer* consumer_copy;
+ // - Main thread creates a WeakPtr and passes copy to background thread
+ // - Destruct the pointer on main thread
+ // - Destruct the pointer on background thread
+ BackgroundThread background;
+ background.Start();
+ Target target;
+ Arrow* arrow_copy;
{
- Consumer consumer;
- consumer.producer = producer.AsWeakPtr();
- thread.CreateConsumerFromConsumer(&consumer_copy, &consumer);
+ Arrow arrow;
+ arrow.target = target.AsWeakPtr();
+ background.CreateArrowFromArrow(&arrow_copy, &arrow);
}
- EXPECT_EQ(consumer_copy->producer, &producer);
- thread.DeleteConsumer(consumer_copy);
+ EXPECT_EQ(arrow_copy->target, &target);
+ background.DeleteArrow(arrow_copy);
}
TEST(WeakPtrTest, OwnerThreadDeletesObject) {
// Originating thread invalidates WeakPtrs while its held by other thread.
- // - Thread A creates WeakPtr<> and passes Copy to Thread B
- // - WeakReferenceOwner gets destroyed on Thread A
+ // - Main thread creates WeakPtr and passes Copy to background thread
+ // - Object gets destroyed on main thread
+ // (invalidates WeakPtr on background thread)
// - WeakPtr gets destroyed on Thread B
- BackgroundThread thread;
- thread.Start();
- Consumer* consumer_copy;
+ BackgroundThread background;
+ background.Start();
+ Arrow* arrow_copy;
{
- Producer producer;
- Consumer consumer;
- consumer.producer = producer.AsWeakPtr();
- thread.CreateConsumerFromConsumer(&consumer_copy, &consumer);
+ Target target;
+ Arrow arrow;
+ arrow.target = target.AsWeakPtr();
+ background.CreateArrowFromArrow(&arrow_copy, &arrow);
}
- EXPECT_TRUE(consumer_copy->producer == NULL);
- thread.DeleteConsumer(consumer_copy);
+ EXPECT_TRUE(arrow_copy->target == NULL);
+ background.DeleteArrow(arrow_copy);
}
-TEST(WeakPtrTest, 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(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
+ // Main thread creates a Target object.
+ Target target;
+ // Main thread creates a arrow referencing the Target.
+ Arrow* arrow = new Arrow();
+ arrow->target = target.AsWeakPtr();
+
+ // Background can delete arrow (as well as the WeakPtr inside).
+ BackgroundThread background;
+ background.Start();
+ background.DeleteArrow(arrow);
}
+#ifndef NDEBUG // Thread ownership is only checked in debug version.
Ryan Sleevi 2012/07/10 00:06:44 This isn't correct It should be #if !defined(NDE
kaiwang 2012/07/10 22:21:19 Done.
+
+TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtr) {
+ // The default value "fast" can not well support multi-threaded tests.
+ // May introduce deadlock on linux.
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+
+ // Main thread creates a Target object.
+ Target target;
+ // Main thread creates a arrow referencing the Target (so target's
+ // thread ownership can not be implicitly moved).
+ Arrow arrow;
+ arrow.target = target.AsWeakPtr();
+
+ // Background thread tries to delete target, which violates thread
+ // ownership.
Ryan Sleevi 2012/07/10 00:06:44 the comments here and on 423 are backwards (this o
kaiwang 2012/07/10 22:21:19 Done.
+ BackgroundThread background;
+ background.Start();
+ ASSERT_DEATH(background.DeRef(&arrow), "");
+}
+
+TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObject) {
+ // The default value "fast" can not well support multi-threaded tests.
+ // May introduce deadlock on linux.
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+
+ Target* target = new Target();
Ryan Sleevi 2012/07/10 00:06:44 Pretty sure this object will show up in the valgri
kaiwang 2012/07/10 22:21:19 Done.
+ // Main thread creates a arrow referencing the Target (so target's thread
+ // ownership can not be implicitly moved).
+ Arrow arrow;
+ arrow.target = target->AsWeakPtr();
+
+ // Background thread tries to deref target, which violates thread ownership.
+ BackgroundThread background;
+ background.Start();
+ ASSERT_DEATH(background.DeleteTarget(target), "");
+}
+
+#endif
+
} // namespace base
« base/memory/weak_ptr.h ('K') | « base/memory/weak_ptr.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698