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

Unified Diff: webrtc/base/bind_unittest.cc

Issue 1300523004: rtc::Bind: Capture method objects as scoped_refptr if they are ref counted (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Update bind.h.pump Created 5 years, 4 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
« webrtc/base/bind.h ('K') | « webrtc/base/bind.h.pump ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/base/bind_unittest.cc
diff --git a/webrtc/base/bind_unittest.cc b/webrtc/base/bind_unittest.cc
index ed8dd5cf2d226a93b24512069bc9324aa9c91619..fae3d1ff0a0b899f076f3a1ca42f2d7536acf681 100644
--- a/webrtc/base/bind_unittest.cc
+++ b/webrtc/base/bind_unittest.cc
@@ -11,6 +11,8 @@
#include "webrtc/base/bind.h"
#include "webrtc/base/gunit.h"
+#include "webrtc/base/refcount.h"
+
namespace rtc {
namespace {
@@ -26,12 +28,67 @@ struct MethodBindTester {
mutable int call_count;
};
+struct A { int dummy; };
+struct B: public RefCountInterface { int dummy; };
+struct C: public A, B {};
+struct D {
+ int AddRef();
+};
+struct E: public D {
+ int Release();
+};
+struct F {
+ void AddRef();
+ void Release();
+};
+
+class LifeTimeCheck : public RefCountInterface {
+ public:
+ LifeTimeCheck(bool* hasDied) : hasDied_(hasDied), isOkToDie(false) {}
tommi 2015/08/20 12:35:41 has_died
magjed_webrtc 2015/08/20 13:05:34 Done.
+ ~LifeTimeCheck() {
+ EXPECT_TRUE(isOkToDie);
+ *hasDied_ = true;
+ }
+ void PrepareToDie() { isOkToDie = true; }
+ void NullaryVoid() {}
+
+ private:
+ bool* const hasDied_;
tommi 2015/08/20 12:35:41 has_died_
magjed_webrtc 2015/08/20 13:05:33 Done.
+ bool isOkToDie;
tommi 2015/08/20 12:35:41 is_ok_to_die_ (or ok_to_die_?)
magjed_webrtc 2015/08/20 13:05:33 Done.
+};
+
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(D);
+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(E);
+EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(F);
+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 +121,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
« webrtc/base/bind.h ('K') | « webrtc/base/bind.h.pump ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698