OLD | NEW |
---|---|
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" | |
15 | |
14 namespace rtc { | 16 namespace rtc { |
15 | 17 |
16 namespace { | 18 namespace { |
17 | 19 |
18 struct MethodBindTester { | 20 struct MethodBindTester { |
19 void NullaryVoid() { ++call_count; } | 21 void NullaryVoid() { ++call_count; } |
20 int NullaryInt() { ++call_count; return 1; } | 22 int NullaryInt() { ++call_count; return 1; } |
21 int NullaryConst() const { ++call_count; return 2; } | 23 int NullaryConst() const { ++call_count; return 2; } |
22 void UnaryVoid(int dummy) { ++call_count; } | 24 void UnaryVoid(int dummy) { ++call_count; } |
23 template <class T> T Identity(T value) { ++call_count; return value; } | 25 template <class T> T Identity(T value) { ++call_count; return value; } |
24 int UnaryByRef(int& value) const { ++call_count; return ++value; } // NOLINT | 26 int UnaryByRef(int& value) const { ++call_count; return ++value; } // NOLINT |
25 int Multiply(int a, int b) const { ++call_count; return a * b; } | 27 int Multiply(int a, int b) const { ++call_count; return a * b; } |
26 mutable int call_count; | 28 mutable int call_count; |
27 }; | 29 }; |
28 | 30 |
31 struct A { int dummy; }; | |
32 struct B: public RefCountInterface { int dummy; }; | |
33 struct C: public A, B {}; | |
34 struct D { | |
35 int AddRef(); | |
36 }; | |
37 struct E: public D { | |
38 int Release(); | |
39 }; | |
40 struct F { | |
41 void AddRef(); | |
42 void Release(); | |
43 }; | |
44 | |
45 class LifeTimeCheck : public RefCountInterface { | |
46 public: | |
47 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.
| |
48 ~LifeTimeCheck() { | |
49 EXPECT_TRUE(isOkToDie); | |
50 *hasDied_ = true; | |
51 } | |
52 void PrepareToDie() { isOkToDie = true; } | |
53 void NullaryVoid() {} | |
54 | |
55 private: | |
56 bool* const hasDied_; | |
tommi
2015/08/20 12:35:41
has_died_
magjed_webrtc
2015/08/20 13:05:33
Done.
| |
57 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.
| |
58 }; | |
59 | |
29 int Return42() { return 42; } | 60 int Return42() { return 42; } |
30 int Negate(int a) { return -a; } | 61 int Negate(int a) { return -a; } |
31 int Multiply(int a, int b) { return a * b; } | 62 int Multiply(int a, int b) { return a * b; } |
32 | 63 |
33 } // namespace | 64 } // namespace |
34 | 65 |
66 // Try to catch any problem with scoped_refptr type deduction in rtc::Bind at | |
67 // compile time. | |
68 #define EXPECT_IS_CAPTURED_AS_PTR(T) \ | |
69 static_assert(is_same<detail::PointerType<T>::type, T*>::value, \ | |
70 "PointerType") | |
71 #define EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(T) \ | |
72 static_assert( \ | |
73 is_same<detail::PointerType<T>::type, scoped_refptr<T>>::value, \ | |
74 "PointerType") | |
75 | |
76 EXPECT_IS_CAPTURED_AS_PTR(void); | |
77 EXPECT_IS_CAPTURED_AS_PTR(int); | |
78 EXPECT_IS_CAPTURED_AS_PTR(double); | |
79 EXPECT_IS_CAPTURED_AS_PTR(A); | |
80 EXPECT_IS_CAPTURED_AS_PTR(D); | |
81 EXPECT_IS_CAPTURED_AS_PTR(RefCountInterface*); | |
82 | |
83 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountInterface); | |
84 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(B); | |
85 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(C); | |
86 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(E); | |
87 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(F); | |
88 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountedObject<RefCountInterface>); | |
89 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountedObject<B>); | |
90 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountedObject<C>); | |
91 | |
35 TEST(BindTest, BindToMethod) { | 92 TEST(BindTest, BindToMethod) { |
36 MethodBindTester object = {0}; | 93 MethodBindTester object = {0}; |
37 EXPECT_EQ(0, object.call_count); | 94 EXPECT_EQ(0, object.call_count); |
38 Bind(&MethodBindTester::NullaryVoid, &object)(); | 95 Bind(&MethodBindTester::NullaryVoid, &object)(); |
39 EXPECT_EQ(1, object.call_count); | 96 EXPECT_EQ(1, object.call_count); |
40 EXPECT_EQ(1, Bind(&MethodBindTester::NullaryInt, &object)()); | 97 EXPECT_EQ(1, Bind(&MethodBindTester::NullaryInt, &object)()); |
41 EXPECT_EQ(2, object.call_count); | 98 EXPECT_EQ(2, object.call_count); |
42 EXPECT_EQ(2, Bind(&MethodBindTester::NullaryConst, | 99 EXPECT_EQ(2, Bind(&MethodBindTester::NullaryConst, |
43 static_cast<const MethodBindTester*>(&object))()); | 100 static_cast<const MethodBindTester*>(&object))()); |
44 EXPECT_EQ(3, object.call_count); | 101 EXPECT_EQ(3, object.call_count); |
(...skipping 12 matching lines...) Expand all Loading... | |
57 EXPECT_EQ(56, Bind(&MethodBindTester::Multiply, &object, 7, 8)()); | 114 EXPECT_EQ(56, Bind(&MethodBindTester::Multiply, &object, 7, 8)()); |
58 EXPECT_EQ(8, object.call_count); | 115 EXPECT_EQ(8, object.call_count); |
59 } | 116 } |
60 | 117 |
61 TEST(BindTest, BindToFunction) { | 118 TEST(BindTest, BindToFunction) { |
62 EXPECT_EQ(42, Bind(&Return42)()); | 119 EXPECT_EQ(42, Bind(&Return42)()); |
63 EXPECT_EQ(3, Bind(&Negate, -3)()); | 120 EXPECT_EQ(3, Bind(&Negate, -3)()); |
64 EXPECT_EQ(56, Bind(&Multiply, 8, 7)()); | 121 EXPECT_EQ(56, Bind(&Multiply, 8, 7)()); |
65 } | 122 } |
66 | 123 |
124 // Test Bind where method object implements RefCountInterface and is passed as a | |
125 // pointer. | |
126 TEST(BindTest, CapturePointerAsScopedRefPtr) { | |
127 bool objectHasDied = false; | |
128 scoped_refptr<LifeTimeCheck> object = | |
129 new RefCountedObject<LifeTimeCheck>(&objectHasDied); | |
130 { | |
131 MethodFunctor0<LifeTimeCheck, void (LifeTimeCheck::*)(), void> functor = | |
132 Bind(&LifeTimeCheck::PrepareToDie, object.get()); | |
133 object = nullptr; | |
134 EXPECT_FALSE(objectHasDied); | |
135 // Run prepare to die via functor. | |
136 functor(); | |
137 } | |
138 EXPECT_TRUE(objectHasDied); | |
139 } | |
140 | |
141 // Test Bind where method object implements RefCountInterface and is passed as a | |
142 // scoped_refptr<>. | |
143 TEST(BindTest, CaptureScopedRefPtrAsScopedRefPtr) { | |
144 bool objectHasDied = false; | |
145 scoped_refptr<LifeTimeCheck> object = | |
146 new RefCountedObject<LifeTimeCheck>(&objectHasDied); | |
147 { | |
148 MethodFunctor0<LifeTimeCheck, void (LifeTimeCheck::*)(), void> functor = | |
149 Bind(&LifeTimeCheck::PrepareToDie, object); | |
150 object = nullptr; | |
151 EXPECT_FALSE(objectHasDied); | |
152 // Run prepare to die via functor. | |
153 functor(); | |
154 } | |
155 EXPECT_TRUE(objectHasDied); | |
156 } | |
157 | |
158 // Test Bind where method object is captured as scoped_refptr<> and the functor | |
159 // dies while there are references left. | |
160 TEST(BindTest, FunctorReleasesObjectOnDestruction) { | |
161 bool objectHasDied = false; | |
162 scoped_refptr<LifeTimeCheck> object = | |
163 new RefCountedObject<LifeTimeCheck>(&objectHasDied); | |
164 Bind(&LifeTimeCheck::NullaryVoid, object.get())(); | |
165 EXPECT_FALSE(objectHasDied); | |
166 object->PrepareToDie(); | |
167 object = nullptr; | |
168 EXPECT_TRUE(objectHasDied); | |
169 } | |
170 | |
67 } // namespace rtc | 171 } // namespace rtc |
OLD | NEW |