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

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: Remove silly comment + address tommi@s comments 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
« no previous file with comments | « 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..7a621dce2cb37c8e4301dc47bb3501da0b26976d 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* has_died) : has_died_(has_died), is_ok_to_die_(false) {}
+ ~LifeTimeCheck() {
+ EXPECT_TRUE(is_ok_to_die_);
+ *has_died_ = true;
+ }
+ void PrepareToDie() { is_ok_to_die_ = true; }
+ void NullaryVoid() {}
+
+ private:
+ bool* const has_died_;
+ bool is_ok_to_die_;
+};
+
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,49 @@ 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 object_has_died = false;
+ scoped_refptr<LifeTimeCheck> object =
+ new RefCountedObject<LifeTimeCheck>(&object_has_died);
+ {
+ auto functor = Bind(&LifeTimeCheck::PrepareToDie, object.get());
+ object = nullptr;
+ EXPECT_FALSE(object_has_died);
+ // Run prepare to die via functor.
+ functor();
+ }
+ EXPECT_TRUE(object_has_died);
+}
+
+// Test Bind where method object implements RefCountInterface and is passed as a
+// scoped_refptr<>.
+TEST(BindTest, CaptureScopedRefPtrAsScopedRefPtr) {
+ bool object_has_died = false;
+ scoped_refptr<LifeTimeCheck> object =
+ new RefCountedObject<LifeTimeCheck>(&object_has_died);
+ {
+ auto functor = Bind(&LifeTimeCheck::PrepareToDie, object);
+ object = nullptr;
+ EXPECT_FALSE(object_has_died);
+ // Run prepare to die via functor.
+ functor();
+ }
+ EXPECT_TRUE(object_has_died);
+}
+
+// Test Bind where method object is captured as scoped_refptr<> and the functor
+// dies while there are references left.
+TEST(BindTest, FunctorReleasesObjectOnDestruction) {
+ bool object_has_died = false;
+ scoped_refptr<LifeTimeCheck> object =
+ new RefCountedObject<LifeTimeCheck>(&object_has_died);
+ Bind(&LifeTimeCheck::NullaryVoid, object.get())();
+ EXPECT_FALSE(object_has_died);
+ object->PrepareToDie();
+ object = nullptr;
+ EXPECT_TRUE(object_has_died);
+}
+
} // namespace rtc
« no previous file with comments | « webrtc/base/bind.h.pump ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698