Index: webrtc/base/bind_unittest.cc |
diff --git a/webrtc/base/bind_unittest.cc b/webrtc/base/bind_unittest.cc |
index ed8dd5cf2d226a93b24512069bc9324aa9c91619..707b8d4935dc6922711a5cbebcd709e56f212a7b 100644 |
--- a/webrtc/base/bind_unittest.cc |
+++ b/webrtc/base/bind_unittest.cc |
@@ -26,12 +26,54 @@ struct MethodBindTester { |
mutable int call_count; |
}; |
+struct A { int dummy; }; |
+struct B: public RefCountInterface { int dummy; }; |
+struct C: public A, B {}; |
+ |
+class LifeTimeCheck : public RefCountInterface { |
+ public: |
+ LifeTimeCheck(bool* hasDied) : hasDied_(hasDied), isOkToDie(false) {} |
+ ~LifeTimeCheck() { |
+ EXPECT_TRUE(isOkToDie); |
+ *hasDied_ = true; |
+ } |
+ void PrepareToDie() { isOkToDie = true; } |
+ void NullaryVoid() {} |
+ |
+ private: |
+ bool* const hasDied_; |
+ bool isOkToDie; |
+}; |
+ |
int Return42() { return 42; } |
int Negate(int a) { return -a; } |
int Multiply(int a, int b) { return a * b; } |
} // namespace |
+// Try to catch any problem with scoped_refptr type deduction in rtc::Bind at |
+// compile time. |
+#define EXPECT_IS_CAPTURED_AS_PTR(T) \ |
+ static_assert(is_same<detail::PointerType<T>::type, T*>::value, \ |
+ "PointerType") |
+#define EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(T) \ |
+ static_assert( \ |
+ is_same<detail::PointerType<T>::type, scoped_refptr<T>>::value, \ |
+ "PointerType") |
+ |
+EXPECT_IS_CAPTURED_AS_PTR(void); |
+EXPECT_IS_CAPTURED_AS_PTR(int); |
+EXPECT_IS_CAPTURED_AS_PTR(double); |
+EXPECT_IS_CAPTURED_AS_PTR(A); |
+EXPECT_IS_CAPTURED_AS_PTR(RefCountInterface*); |
+ |
+EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountInterface); |
+EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(B); |
+EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(C); |
+EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountedObject<RefCountInterface>); |
+EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountedObject<B>); |
+EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountedObject<C>); |
+ |
TEST(BindTest, BindToMethod) { |
MethodBindTester object = {0}; |
EXPECT_EQ(0, object.call_count); |
@@ -64,4 +106,51 @@ TEST(BindTest, BindToFunction) { |
EXPECT_EQ(56, Bind(&Multiply, 8, 7)()); |
} |
+// Test Bind where method object implements RefCountInterface and is passed as a |
+// pointer. |
+TEST(BindTest, CapturePointerAsScopedRefPtr) { |
+ bool objectHasDied = false; |
+ scoped_refptr<LifeTimeCheck> object = |
+ new RefCountedObject<LifeTimeCheck>(&objectHasDied); |
+ { |
+ MethodFunctor0<LifeTimeCheck, void (LifeTimeCheck::*)(), void> functor = |
+ Bind(&LifeTimeCheck::PrepareToDie, object.get()); |
+ object = nullptr; |
+ EXPECT_FALSE(objectHasDied); |
+ // Run prepare to die via functor. |
+ functor(); |
+ } |
+ EXPECT_TRUE(objectHasDied); |
+} |
+ |
+// Test Bind where method object implements RefCountInterface and is passed as a |
+// scoped_refptr<>. |
+TEST(BindTest, CaptureScopedRefPtrAsScopedRefPtr) { |
+ bool objectHasDied = false; |
+ scoped_refptr<LifeTimeCheck> object = |
+ new RefCountedObject<LifeTimeCheck>(&objectHasDied); |
+ { |
+ MethodFunctor0<LifeTimeCheck, void (LifeTimeCheck::*)(), void> functor = |
+ Bind(&LifeTimeCheck::PrepareToDie, object); |
+ object = nullptr; |
+ EXPECT_FALSE(objectHasDied); |
+ // Run prepare to die via functor. |
+ functor(); |
+ } |
+ EXPECT_TRUE(objectHasDied); |
+} |
+ |
+// Test Bind where method object is captured as scoped_refptr<> and the functor |
+// dies while there are references left. |
+TEST(BindTest, FunctorReleasesObjectOnDestruction) { |
+ bool objectHasDied = false; |
+ scoped_refptr<LifeTimeCheck> object = |
+ new RefCountedObject<LifeTimeCheck>(&objectHasDied); |
+ Bind(&LifeTimeCheck::NullaryVoid, object.get())(); |
+ EXPECT_FALSE(objectHasDied); |
+ object->PrepareToDie(); |
+ object = nullptr; |
+ EXPECT_TRUE(objectHasDied); |
+} |
+ |
} // namespace rtc |