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

Side by Side 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, 3 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 unified diff | Download patch
« no previous file with comments | « webrtc/base/bind.h.pump ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/base/bind.h" 11 #include "webrtc/base/bind.h"
12 #include "webrtc/base/gunit.h" 12 #include "webrtc/base/gunit.h"
13 13
14 #include "webrtc/base/refcount.h" 14 #include "webrtc/base/refcount.h"
15 15
16 namespace rtc { 16 namespace rtc {
17 17
18 namespace { 18 namespace {
19 19
20 struct LifeTimeCheck;
21
20 struct MethodBindTester { 22 struct MethodBindTester {
21 void NullaryVoid() { ++call_count; } 23 void NullaryVoid() { ++call_count; }
22 int NullaryInt() { ++call_count; return 1; } 24 int NullaryInt() { ++call_count; return 1; }
23 int NullaryConst() const { ++call_count; return 2; } 25 int NullaryConst() const { ++call_count; return 2; }
24 void UnaryVoid(int dummy) { ++call_count; } 26 void UnaryVoid(int dummy) { ++call_count; }
25 template <class T> T Identity(T value) { ++call_count; return value; } 27 template <class T> T Identity(T value) { ++call_count; return value; }
26 int UnaryByRef(int& value) const { ++call_count; return ++value; } // NOLINT 28 int UnaryByRef(int& value) const { ++call_count; return ++value; } // NOLINT
27 int Multiply(int a, int b) const { ++call_count; return a * b; } 29 int Multiply(int a, int b) const { ++call_count; return a * b; }
30 void RefArgument(const scoped_refptr<LifeTimeCheck>& object) {
31 EXPECT_TRUE(object.get() != nullptr);
32 }
33
28 mutable int call_count; 34 mutable int call_count;
29 }; 35 };
30 36
31 struct A { int dummy; }; 37 struct A { int dummy; };
32 struct B: public RefCountInterface { int dummy; }; 38 struct B: public RefCountInterface { int dummy; };
33 struct C: public A, B {}; 39 struct C: public A, B {};
34 struct D { 40 struct D {
35 int AddRef(); 41 int AddRef();
36 }; 42 };
37 struct E: public D { 43 struct E: public D {
38 int Release(); 44 int Release();
39 }; 45 };
40 struct F { 46 struct F {
41 void AddRef(); 47 void AddRef();
42 void Release(); 48 void Release();
43 }; 49 };
44 50
45 class LifeTimeCheck : public RefCountInterface { 51 struct LifeTimeCheck {
46 public: 52 LifeTimeCheck() : ref_count_(0) {}
47 LifeTimeCheck(bool* has_died) : has_died_(has_died), is_ok_to_die_(false) {} 53 void AddRef() { ++ref_count_; }
48 ~LifeTimeCheck() { 54 void Release() { --ref_count_; }
49 EXPECT_TRUE(is_ok_to_die_);
50 *has_died_ = true;
51 }
52 void PrepareToDie() { is_ok_to_die_ = true; }
53 void NullaryVoid() {} 55 void NullaryVoid() {}
54 56 int ref_count_;
55 private:
56 bool* const has_died_;
57 bool is_ok_to_die_;
58 }; 57 };
59 58
60 int Return42() { return 42; } 59 int Return42() { return 42; }
61 int Negate(int a) { return -a; } 60 int Negate(int a) { return -a; }
62 int Multiply(int a, int b) { return a * b; } 61 int Multiply(int a, int b) { return a * b; }
63 62
64 } // namespace 63 } // namespace
65 64
66 // Try to catch any problem with scoped_refptr type deduction in rtc::Bind at 65 // Try to catch any problem with scoped_refptr type deduction in rtc::Bind at
67 // compile time. 66 // compile time.
67 static_assert(is_same<detail::RemoveScopedPtrRef<
tommi 2015/08/24 15:43:31 these are nice
68 const scoped_refptr<RefCountInterface>&>::type,
69 scoped_refptr<RefCountInterface>>::value,
70 "const scoped_refptr& should be captured by value");
71
72 static_assert(is_same<detail::RemoveScopedPtrRef<const scoped_refptr<F>&>::type,
73 scoped_refptr<F>>::value,
74 "const scoped_refptr& should be captured by value");
75
76 static_assert(
77 is_same<detail::RemoveScopedPtrRef<const int&>::type, const int&>::value,
78 "const int& should be captured as const int&");
79
80 static_assert(
81 is_same<detail::RemoveScopedPtrRef<const F&>::type, const F&>::value,
82 "const F& should be captured as const F&");
83
84 static_assert(
85 is_same<detail::RemoveScopedPtrRef<F&>::type, F&>::value,
86 "F& should be captured as F&");
87
68 #define EXPECT_IS_CAPTURED_AS_PTR(T) \ 88 #define EXPECT_IS_CAPTURED_AS_PTR(T) \
69 static_assert(is_same<detail::PointerType<T>::type, T*>::value, \ 89 static_assert(is_same<detail::PointerType<T>::type, T*>::value, \
70 "PointerType") 90 "PointerType")
71 #define EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(T) \ 91 #define EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(T) \
72 static_assert( \ 92 static_assert( \
73 is_same<detail::PointerType<T>::type, scoped_refptr<T>>::value, \ 93 is_same<detail::PointerType<T>::type, scoped_refptr<T>>::value, \
74 "PointerType") 94 "PointerType")
75 95
76 EXPECT_IS_CAPTURED_AS_PTR(void); 96 EXPECT_IS_CAPTURED_AS_PTR(void);
77 EXPECT_IS_CAPTURED_AS_PTR(int); 97 EXPECT_IS_CAPTURED_AS_PTR(int);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 137
118 TEST(BindTest, BindToFunction) { 138 TEST(BindTest, BindToFunction) {
119 EXPECT_EQ(42, Bind(&Return42)()); 139 EXPECT_EQ(42, Bind(&Return42)());
120 EXPECT_EQ(3, Bind(&Negate, -3)()); 140 EXPECT_EQ(3, Bind(&Negate, -3)());
121 EXPECT_EQ(56, Bind(&Multiply, 8, 7)()); 141 EXPECT_EQ(56, Bind(&Multiply, 8, 7)());
122 } 142 }
123 143
124 // Test Bind where method object implements RefCountInterface and is passed as a 144 // Test Bind where method object implements RefCountInterface and is passed as a
125 // pointer. 145 // pointer.
126 TEST(BindTest, CapturePointerAsScopedRefPtr) { 146 TEST(BindTest, CapturePointerAsScopedRefPtr) {
127 bool object_has_died = false; 147 LifeTimeCheck object;
128 scoped_refptr<LifeTimeCheck> object = 148 EXPECT_EQ(object.ref_count_, 0);
129 new RefCountedObject<LifeTimeCheck>(&object_has_died); 149 scoped_refptr<LifeTimeCheck> scoped_object(&object);
150 EXPECT_EQ(object.ref_count_, 1);
130 { 151 {
131 auto functor = Bind(&LifeTimeCheck::PrepareToDie, object.get()); 152 auto functor = Bind(&LifeTimeCheck::NullaryVoid, &object);
132 object = nullptr; 153 EXPECT_EQ(object.ref_count_, 2);
133 EXPECT_FALSE(object_has_died); 154 scoped_object = nullptr;
134 // Run prepare to die via functor. 155 EXPECT_EQ(object.ref_count_, 1);
135 functor();
136 } 156 }
137 EXPECT_TRUE(object_has_died); 157 EXPECT_EQ(object.ref_count_, 0);
138 } 158 }
139 159
140 // Test Bind where method object implements RefCountInterface and is passed as a 160 // Test Bind where method object implements RefCountInterface and is passed as a
141 // scoped_refptr<>. 161 // scoped_refptr<>.
142 TEST(BindTest, CaptureScopedRefPtrAsScopedRefPtr) { 162 TEST(BindTest, CaptureScopedRefPtrAsScopedRefPtr) {
143 bool object_has_died = false; 163 LifeTimeCheck object;
144 scoped_refptr<LifeTimeCheck> object = 164 EXPECT_EQ(object.ref_count_, 0);
145 new RefCountedObject<LifeTimeCheck>(&object_has_died); 165 scoped_refptr<LifeTimeCheck> scoped_object(&object);
166 EXPECT_EQ(object.ref_count_, 1);
146 { 167 {
147 auto functor = Bind(&LifeTimeCheck::PrepareToDie, object); 168 auto functor = Bind(&LifeTimeCheck::NullaryVoid, scoped_object);
148 object = nullptr; 169 EXPECT_EQ(object.ref_count_, 2);
149 EXPECT_FALSE(object_has_died); 170 scoped_object = nullptr;
150 // Run prepare to die via functor. 171 EXPECT_EQ(object.ref_count_, 1);
151 functor();
152 } 172 }
153 EXPECT_TRUE(object_has_died); 173 EXPECT_EQ(object.ref_count_, 0);
154 } 174 }
155 175
156 // Test Bind where method object is captured as scoped_refptr<> and the functor 176 // Test Bind where method object is captured as scoped_refptr<> and the functor
157 // dies while there are references left. 177 // dies while there are references left.
158 TEST(BindTest, FunctorReleasesObjectOnDestruction) { 178 TEST(BindTest, FunctorReleasesObjectOnDestruction) {
159 bool object_has_died = false; 179 LifeTimeCheck object;
160 scoped_refptr<LifeTimeCheck> object = 180 EXPECT_EQ(object.ref_count_, 0);
161 new RefCountedObject<LifeTimeCheck>(&object_has_died); 181 scoped_refptr<LifeTimeCheck> scoped_object(&object);
162 Bind(&LifeTimeCheck::NullaryVoid, object.get())(); 182 EXPECT_EQ(object.ref_count_, 1);
163 EXPECT_FALSE(object_has_died); 183 Bind(&LifeTimeCheck::NullaryVoid, &object)();
164 object->PrepareToDie(); 184 EXPECT_EQ(object.ref_count_, 1);
165 object = nullptr; 185 scoped_object = nullptr;
166 EXPECT_TRUE(object_has_died); 186 EXPECT_EQ(object.ref_count_, 0);
187 }
188
189 // Test Bind with scoped_refptr<> argument.
190 TEST(BindTest, ScopedRefPointerArgument) {
191 LifeTimeCheck object;
192 EXPECT_EQ(object.ref_count_, 0);
193 scoped_refptr<LifeTimeCheck> scoped_object(&object);
194 EXPECT_EQ(object.ref_count_, 1);
195 {
196 MethodBindTester bind_tester;
197 auto functor =
198 Bind(&MethodBindTester::RefArgument, &bind_tester, scoped_object);
199 EXPECT_EQ(object.ref_count_, 2);
200 }
201 EXPECT_EQ(object.ref_count_, 1);
202 scoped_object = nullptr;
203 EXPECT_EQ(object.ref_count_, 0);
204 }
205
206 namespace {
207
208 const int* Ref(const int& a) { return &a; }
209
210 } // anonymous namespace
211
212 // Test Bind with non-scoped_refptr<> reference argument.
213 TEST(BindTest, RefArgument) {
214 const int x = 42;
215 EXPECT_TRUE(Ref(x) == &x);
216 // Bind() should not make a copy of |x|, i.e. the pointers should be the same.
217 auto functor = Bind(&Ref, x);
218 EXPECT_TRUE(functor() == &x);
167 } 219 }
168 220
169 } // namespace rtc 221 } // namespace rtc
OLDNEW
« 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