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

Unified Diff: webrtc/base/bind_unittest.cc

Issue 1308563004: rtc::Bind: Capture scoped_refptr reference arguments by value (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Capture scoped_refptr references by-value instead 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 7a621dce2cb37c8e4301dc47bb3501da0b26976d..d38729d9df20b64eb06484d94ffbece584321ec0 100644
--- a/webrtc/base/bind_unittest.cc
+++ b/webrtc/base/bind_unittest.cc
@@ -17,6 +17,8 @@ namespace rtc {
namespace {
+struct LifeTimeCheck;
+
struct MethodBindTester {
void NullaryVoid() { ++call_count; }
int NullaryInt() { ++call_count; return 1; }
@@ -25,6 +27,10 @@ struct MethodBindTester {
template <class T> T Identity(T value) { ++call_count; return value; }
int UnaryByRef(int& value) const { ++call_count; return ++value; } // NOLINT
int Multiply(int a, int b) const { ++call_count; return a * b; }
+ void RefArgument(const scoped_refptr<LifeTimeCheck>& object) {
+ EXPECT_TRUE(object.get() != nullptr);
+ }
+
mutable int call_count;
};
@@ -42,19 +48,12 @@ struct F {
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; }
+struct LifeTimeCheck {
+ LifeTimeCheck() : ref_count_(0) {}
+ void AddRef() { ++ref_count_; }
+ void Release() { --ref_count_; }
void NullaryVoid() {}
-
- private:
- bool* const has_died_;
- bool is_ok_to_die_;
+ int ref_count_;
};
int Return42() { return 42; }
@@ -65,6 +64,27 @@ int Multiply(int a, int b) { return a * b; }
// Try to catch any problem with scoped_refptr type deduction in rtc::Bind at
// compile time.
+static_assert(is_same<detail::RemoveScopedPtrRef<
tommi 2015/08/24 15:43:31 these are nice
+ const scoped_refptr<RefCountInterface>&>::type,
+ scoped_refptr<RefCountInterface>>::value,
+ "const scoped_refptr& should be captured by value");
+
+static_assert(is_same<detail::RemoveScopedPtrRef<const scoped_refptr<F>&>::type,
+ scoped_refptr<F>>::value,
+ "const scoped_refptr& should be captured by value");
+
+static_assert(
+ is_same<detail::RemoveScopedPtrRef<const int&>::type, const int&>::value,
+ "const int& should be captured as const int&");
+
+static_assert(
+ is_same<detail::RemoveScopedPtrRef<const F&>::type, const F&>::value,
+ "const F& should be captured as const F&");
+
+static_assert(
+ is_same<detail::RemoveScopedPtrRef<F&>::type, F&>::value,
+ "F& should be captured as F&");
+
#define EXPECT_IS_CAPTURED_AS_PTR(T) \
static_assert(is_same<detail::PointerType<T>::type, T*>::value, \
"PointerType")
@@ -124,46 +144,78 @@ TEST(BindTest, BindToFunction) {
// 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);
+ LifeTimeCheck object;
+ EXPECT_EQ(object.ref_count_, 0);
+ scoped_refptr<LifeTimeCheck> scoped_object(&object);
+ EXPECT_EQ(object.ref_count_, 1);
{
- auto functor = Bind(&LifeTimeCheck::PrepareToDie, object.get());
- object = nullptr;
- EXPECT_FALSE(object_has_died);
- // Run prepare to die via functor.
- functor();
+ auto functor = Bind(&LifeTimeCheck::NullaryVoid, &object);
+ EXPECT_EQ(object.ref_count_, 2);
+ scoped_object = nullptr;
+ EXPECT_EQ(object.ref_count_, 1);
}
- EXPECT_TRUE(object_has_died);
+ EXPECT_EQ(object.ref_count_, 0);
}
// 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);
+ LifeTimeCheck object;
+ EXPECT_EQ(object.ref_count_, 0);
+ scoped_refptr<LifeTimeCheck> scoped_object(&object);
+ EXPECT_EQ(object.ref_count_, 1);
{
- auto functor = Bind(&LifeTimeCheck::PrepareToDie, object);
- object = nullptr;
- EXPECT_FALSE(object_has_died);
- // Run prepare to die via functor.
- functor();
+ auto functor = Bind(&LifeTimeCheck::NullaryVoid, scoped_object);
+ EXPECT_EQ(object.ref_count_, 2);
+ scoped_object = nullptr;
+ EXPECT_EQ(object.ref_count_, 1);
}
- EXPECT_TRUE(object_has_died);
+ EXPECT_EQ(object.ref_count_, 0);
}
// 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);
+ LifeTimeCheck object;
+ EXPECT_EQ(object.ref_count_, 0);
+ scoped_refptr<LifeTimeCheck> scoped_object(&object);
+ EXPECT_EQ(object.ref_count_, 1);
+ Bind(&LifeTimeCheck::NullaryVoid, &object)();
+ EXPECT_EQ(object.ref_count_, 1);
+ scoped_object = nullptr;
+ EXPECT_EQ(object.ref_count_, 0);
+}
+
+// Test Bind with scoped_refptr<> argument.
+TEST(BindTest, ScopedRefPointerArgument) {
+ LifeTimeCheck object;
+ EXPECT_EQ(object.ref_count_, 0);
+ scoped_refptr<LifeTimeCheck> scoped_object(&object);
+ EXPECT_EQ(object.ref_count_, 1);
+ {
+ MethodBindTester bind_tester;
+ auto functor =
+ Bind(&MethodBindTester::RefArgument, &bind_tester, scoped_object);
+ EXPECT_EQ(object.ref_count_, 2);
+ }
+ EXPECT_EQ(object.ref_count_, 1);
+ scoped_object = nullptr;
+ EXPECT_EQ(object.ref_count_, 0);
+}
+
+namespace {
+
+const int* Ref(const int& a) { return &a; }
+
+} // anonymous namespace
+
+// Test Bind with non-scoped_refptr<> reference argument.
+TEST(BindTest, RefArgument) {
+ const int x = 42;
+ EXPECT_TRUE(Ref(x) == &x);
+ // Bind() should not make a copy of |x|, i.e. the pointers should be the same.
+ auto functor = Bind(&Ref, x);
+ EXPECT_TRUE(functor() == &x);
}
} // 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