OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Note: This file tests both binding.h (mojo::Binding) and strong_binding.h | 5 // Note: This file tests both binding.h (mojo::Binding) and strong_binding.h |
6 // (mojo::StrongBinding). | 6 // (mojo::StrongBinding). |
7 | 7 |
8 #include "mojo/public/cpp/bindings/binding.h" | 8 #include "mojo/public/cpp/bindings/binding.h" |
9 | 9 |
10 #include <stdint.h> | 10 #include <stdint.h> |
11 #include <utility> | 11 #include <utility> |
12 | 12 |
13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/run_loop.h" |
14 #include "mojo/message_pump/message_pump_mojo.h" | 15 #include "mojo/message_pump/message_pump_mojo.h" |
15 #include "mojo/public/cpp/bindings/strong_binding.h" | 16 #include "mojo/public/cpp/bindings/strong_binding.h" |
16 #include "mojo/public/cpp/system/macros.h" | 17 #include "mojo/public/cpp/system/macros.h" |
17 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" | 18 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" |
18 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" | 19 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
20 | 21 |
21 namespace mojo { | 22 namespace mojo { |
22 namespace { | 23 namespace { |
23 | 24 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 }; | 60 }; |
60 | 61 |
61 // BindingTest ----------------------------------------------------------------- | 62 // BindingTest ----------------------------------------------------------------- |
62 | 63 |
63 using BindingTest = BindingTestBase; | 64 using BindingTest = BindingTestBase; |
64 | 65 |
65 TEST_F(BindingTest, Close) { | 66 TEST_F(BindingTest, Close) { |
66 bool called = false; | 67 bool called = false; |
67 sample::ServicePtr ptr; | 68 sample::ServicePtr ptr; |
68 auto request = GetProxy(&ptr); | 69 auto request = GetProxy(&ptr); |
69 ptr.set_connection_error_handler([&called]() { called = true; }); | 70 base::RunLoop run_loop; |
| 71 ptr.set_connection_error_handler([&called, &run_loop]() { |
| 72 called = true; |
| 73 run_loop.Quit(); |
| 74 }); |
70 ServiceImpl impl; | 75 ServiceImpl impl; |
71 Binding<sample::Service> binding(&impl, std::move(request)); | 76 Binding<sample::Service> binding(&impl, std::move(request)); |
72 | 77 |
73 binding.Close(); | 78 binding.Close(); |
74 EXPECT_FALSE(called); | 79 EXPECT_FALSE(called); |
75 loop().RunUntilIdle(); | 80 run_loop.Run(); |
76 EXPECT_TRUE(called); | 81 EXPECT_TRUE(called); |
77 } | 82 } |
78 | 83 |
79 // Tests that destroying a mojo::Binding closes the bound message pipe handle. | 84 // Tests that destroying a mojo::Binding closes the bound message pipe handle. |
80 TEST_F(BindingTest, DestroyClosesMessagePipe) { | 85 TEST_F(BindingTest, DestroyClosesMessagePipe) { |
81 bool encountered_error = false; | 86 bool encountered_error = false; |
82 ServiceImpl impl; | 87 ServiceImpl impl; |
83 sample::ServicePtr ptr; | 88 sample::ServicePtr ptr; |
84 auto request = GetProxy(&ptr); | 89 auto request = GetProxy(&ptr); |
| 90 base::RunLoop run_loop; |
85 ptr.set_connection_error_handler( | 91 ptr.set_connection_error_handler( |
86 [&encountered_error]() { encountered_error = true; }); | 92 [&encountered_error, &run_loop]() { |
| 93 encountered_error = true; |
| 94 run_loop.Quit(); |
| 95 }); |
87 bool called = false; | 96 bool called = false; |
88 auto called_cb = [&called](int32_t result) { called = true; }; | 97 base::RunLoop run_loop2; |
| 98 auto called_cb = [&called, &run_loop2](int32_t result) { |
| 99 called = true; |
| 100 run_loop2.Quit(); |
| 101 }; |
89 { | 102 { |
90 Binding<sample::Service> binding(&impl, std::move(request)); | 103 Binding<sample::Service> binding(&impl, std::move(request)); |
91 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 104 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
92 called_cb); | 105 called_cb); |
93 loop().RunUntilIdle(); | 106 run_loop2.Run(); |
94 EXPECT_TRUE(called); | 107 EXPECT_TRUE(called); |
95 EXPECT_FALSE(encountered_error); | 108 EXPECT_FALSE(encountered_error); |
96 } | 109 } |
97 // Now that the Binding is out of scope we should detect an error on the other | 110 // Now that the Binding is out of scope we should detect an error on the other |
98 // end of the pipe. | 111 // end of the pipe. |
99 loop().RunUntilIdle(); | 112 run_loop.Run(); |
100 EXPECT_TRUE(encountered_error); | 113 EXPECT_TRUE(encountered_error); |
101 | 114 |
102 // And calls should fail. | 115 // And calls should fail. |
103 called = false; | 116 called = false; |
104 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 117 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
105 called_cb); | 118 called_cb); |
106 loop().RunUntilIdle(); | 119 loop().RunUntilIdle(); |
107 EXPECT_FALSE(called); | 120 EXPECT_FALSE(called); |
108 } | 121 } |
109 | 122 |
110 // Tests that the binding's connection error handler gets called when the other | 123 // Tests that the binding's connection error handler gets called when the other |
111 // end is closed. | 124 // end is closed. |
112 TEST_F(BindingTest, ConnectionError) { | 125 TEST_F(BindingTest, ConnectionError) { |
113 bool called = false; | 126 bool called = false; |
114 { | 127 { |
115 ServiceImpl impl; | 128 ServiceImpl impl; |
116 sample::ServicePtr ptr; | 129 sample::ServicePtr ptr; |
117 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); | 130 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); |
118 binding.set_connection_error_handler([&called]() { called = true; }); | 131 base::RunLoop run_loop; |
| 132 binding.set_connection_error_handler([&called, &run_loop]() { |
| 133 called = true; |
| 134 run_loop.Quit(); |
| 135 }); |
119 ptr.reset(); | 136 ptr.reset(); |
120 EXPECT_FALSE(called); | 137 EXPECT_FALSE(called); |
121 loop().RunUntilIdle(); | 138 run_loop.Run(); |
122 EXPECT_TRUE(called); | 139 EXPECT_TRUE(called); |
123 // We want to make sure that it isn't called again during destruction. | 140 // We want to make sure that it isn't called again during destruction. |
124 called = false; | 141 called = false; |
125 } | 142 } |
126 EXPECT_FALSE(called); | 143 EXPECT_FALSE(called); |
127 } | 144 } |
128 | 145 |
129 // Tests that calling Close doesn't result in the connection error handler being | 146 // Tests that calling Close doesn't result in the connection error handler being |
130 // called. | 147 // called. |
131 TEST_F(BindingTest, CloseDoesntCallConnectionErrorHandler) { | 148 TEST_F(BindingTest, CloseDoesntCallConnectionErrorHandler) { |
132 ServiceImpl impl; | 149 ServiceImpl impl; |
133 sample::ServicePtr ptr; | 150 sample::ServicePtr ptr; |
134 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); | 151 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); |
135 bool called = false; | 152 bool called = false; |
136 binding.set_connection_error_handler([&called]() { called = true; }); | 153 binding.set_connection_error_handler([&called]() { called = true; }); |
137 binding.Close(); | 154 binding.Close(); |
138 loop().RunUntilIdle(); | 155 loop().RunUntilIdle(); |
139 EXPECT_FALSE(called); | 156 EXPECT_FALSE(called); |
140 | 157 |
141 // We can also close the other end, and the error handler still won't be | 158 // We can also close the other end, and the error handler still won't be |
142 // called. | 159 // called. |
143 ptr.reset(); | 160 ptr.reset(); |
144 loop().RunUntilIdle(); | 161 loop().RunUntilIdle(); |
145 EXPECT_FALSE(called); | 162 EXPECT_FALSE(called); |
146 } | 163 } |
147 | 164 |
148 class ServiceImplWithBinding : public ServiceImpl { | 165 class ServiceImplWithBinding : public ServiceImpl { |
149 public: | 166 public: |
150 ServiceImplWithBinding(bool* was_deleted, | 167 ServiceImplWithBinding(bool* was_deleted, |
| 168 const base::Closure& closure, |
151 InterfaceRequest<sample::Service> request) | 169 InterfaceRequest<sample::Service> request) |
152 : ServiceImpl(was_deleted), binding_(this, std::move(request)) { | 170 : ServiceImpl(was_deleted), |
| 171 binding_(this, std::move(request)), |
| 172 closure_(closure) { |
153 binding_.set_connection_error_handler([this]() { delete this; }); | 173 binding_.set_connection_error_handler([this]() { delete this; }); |
154 } | 174 } |
155 | 175 |
156 private: | 176 private: |
| 177 ~ServiceImplWithBinding() override{ |
| 178 closure_.Run(); |
| 179 } |
| 180 |
157 Binding<sample::Service> binding_; | 181 Binding<sample::Service> binding_; |
| 182 base::Closure closure_; |
158 | 183 |
159 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithBinding); | 184 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithBinding); |
160 }; | 185 }; |
161 | 186 |
162 // Tests that the binding may be deleted in the connection error handler. | 187 // Tests that the binding may be deleted in the connection error handler. |
163 TEST_F(BindingTest, SelfDeleteOnConnectionError) { | 188 TEST_F(BindingTest, SelfDeleteOnConnectionError) { |
164 bool was_deleted = false; | 189 bool was_deleted = false; |
165 sample::ServicePtr ptr; | 190 sample::ServicePtr ptr; |
166 // This should delete itself on connection error. | 191 // This should delete itself on connection error. |
167 new ServiceImplWithBinding(&was_deleted, GetProxy(&ptr)); | 192 base::RunLoop run_loop; |
| 193 new ServiceImplWithBinding(&was_deleted, run_loop.QuitClosure(), |
| 194 GetProxy(&ptr)); |
168 ptr.reset(); | 195 ptr.reset(); |
169 EXPECT_FALSE(was_deleted); | 196 EXPECT_FALSE(was_deleted); |
170 loop().RunUntilIdle(); | 197 run_loop.Run(); |
171 EXPECT_TRUE(was_deleted); | 198 EXPECT_TRUE(was_deleted); |
172 } | 199 } |
173 | 200 |
174 // Tests that explicitly calling Unbind followed by rebinding works. | 201 // Tests that explicitly calling Unbind followed by rebinding works. |
175 TEST_F(BindingTest, Unbind) { | 202 TEST_F(BindingTest, Unbind) { |
176 ServiceImpl impl; | 203 ServiceImpl impl; |
177 sample::ServicePtr ptr; | 204 sample::ServicePtr ptr; |
178 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); | 205 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); |
179 | 206 |
180 bool called = false; | 207 bool called = false; |
181 auto called_cb = [&called](int32_t result) { called = true; }; | 208 base::RunLoop run_loop; |
| 209 auto called_cb = [&called, &run_loop](int32_t result) { |
| 210 called = true; |
| 211 run_loop.Quit(); |
| 212 }; |
182 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 213 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
183 called_cb); | 214 called_cb); |
184 loop().RunUntilIdle(); | 215 run_loop.Run(); |
185 EXPECT_TRUE(called); | 216 EXPECT_TRUE(called); |
186 | 217 |
187 called = false; | 218 called = false; |
188 auto request = binding.Unbind(); | 219 auto request = binding.Unbind(); |
189 EXPECT_FALSE(binding.is_bound()); | 220 EXPECT_FALSE(binding.is_bound()); |
190 // All calls should fail when not bound... | 221 // All calls should fail when not bound... |
191 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 222 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
192 called_cb); | 223 called_cb); |
193 loop().RunUntilIdle(); | 224 loop().RunUntilIdle(); |
194 EXPECT_FALSE(called); | 225 EXPECT_FALSE(called); |
195 | 226 |
196 called = false; | 227 called = false; |
197 binding.Bind(std::move(request)); | 228 binding.Bind(std::move(request)); |
198 EXPECT_TRUE(binding.is_bound()); | 229 EXPECT_TRUE(binding.is_bound()); |
199 // ...and should succeed again when the rebound. | 230 // ...and should succeed again when the rebound. |
| 231 base::RunLoop run_loop2; |
| 232 auto called_cb2 = [&called, &run_loop2](int32_t result) { |
| 233 called = true; |
| 234 run_loop2.Quit(); |
| 235 }; |
200 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 236 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
201 called_cb); | 237 called_cb2); |
202 loop().RunUntilIdle(); | 238 run_loop2.Run(); |
203 EXPECT_TRUE(called); | 239 EXPECT_TRUE(called); |
204 } | 240 } |
205 | 241 |
206 class IntegerAccessorImpl : public sample::IntegerAccessor { | 242 class IntegerAccessorImpl : public sample::IntegerAccessor { |
207 public: | 243 public: |
208 IntegerAccessorImpl() {} | 244 IntegerAccessorImpl() {} |
209 ~IntegerAccessorImpl() override {} | 245 ~IntegerAccessorImpl() override {} |
210 | 246 |
211 private: | 247 private: |
212 // sample::IntegerAccessor implementation. | 248 // sample::IntegerAccessor implementation. |
213 void GetInteger(const GetIntegerCallback& callback) override { | 249 void GetInteger(const GetIntegerCallback& callback) override { |
214 callback.Run(1, sample::ENUM_VALUE); | 250 callback.Run(1, sample::ENUM_VALUE); |
215 } | 251 } |
216 void SetInteger(int64_t data, sample::Enum type) override {} | 252 void SetInteger(int64_t data, sample::Enum type) override {} |
217 | 253 |
218 MOJO_DISALLOW_COPY_AND_ASSIGN(IntegerAccessorImpl); | 254 MOJO_DISALLOW_COPY_AND_ASSIGN(IntegerAccessorImpl); |
219 }; | 255 }; |
220 | 256 |
221 TEST_F(BindingTest, SetInterfacePtrVersion) { | 257 TEST_F(BindingTest, SetInterfacePtrVersion) { |
222 IntegerAccessorImpl impl; | 258 IntegerAccessorImpl impl; |
223 sample::IntegerAccessorPtr ptr; | 259 sample::IntegerAccessorPtr ptr; |
224 Binding<sample::IntegerAccessor> binding(&impl, &ptr); | 260 Binding<sample::IntegerAccessor> binding(&impl, &ptr); |
225 EXPECT_EQ(3u, ptr.version()); | 261 EXPECT_EQ(3u, ptr.version()); |
226 } | 262 } |
227 | 263 |
228 TEST_F(BindingTest, PauseResume) { | 264 TEST_F(BindingTest, PauseResume) { |
229 bool called = false; | 265 bool called = false; |
230 auto called_cb = [&called](int32_t result) { called = true; }; | 266 base::RunLoop run_loop; |
| 267 auto called_cb = [&called, &run_loop](int32_t result) { |
| 268 called = true; |
| 269 run_loop.Quit(); |
| 270 }; |
231 sample::ServicePtr ptr; | 271 sample::ServicePtr ptr; |
232 auto request = GetProxy(&ptr); | 272 auto request = GetProxy(&ptr); |
233 ServiceImpl impl; | 273 ServiceImpl impl; |
234 Binding<sample::Service> binding(&impl, std::move(request)); | 274 Binding<sample::Service> binding(&impl, std::move(request)); |
235 binding.PauseIncomingMethodCallProcessing(); | 275 binding.PauseIncomingMethodCallProcessing(); |
236 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 276 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
237 called_cb); | 277 called_cb); |
238 EXPECT_FALSE(called); | 278 EXPECT_FALSE(called); |
239 loop().RunUntilIdle(); | 279 loop().RunUntilIdle(); |
240 // Frobinate() should not be called as the binding is paused. | 280 // Frobinate() should not be called as the binding is paused. |
241 EXPECT_FALSE(called); | 281 EXPECT_FALSE(called); |
242 | 282 |
243 // Resume the binding, which should trigger processing. | 283 // Resume the binding, which should trigger processing. |
244 binding.ResumeIncomingMethodCallProcessing(); | 284 binding.ResumeIncomingMethodCallProcessing(); |
245 loop().RunUntilIdle(); | 285 run_loop.Run(); |
246 EXPECT_TRUE(called); | 286 EXPECT_TRUE(called); |
247 } | 287 } |
248 | 288 |
249 // Verifies the connection error handler is not run while a binding is paused. | 289 // Verifies the connection error handler is not run while a binding is paused. |
250 TEST_F(BindingTest, ErrorHandleNotRunWhilePaused) { | 290 TEST_F(BindingTest, ErrorHandleNotRunWhilePaused) { |
251 bool called = false; | 291 bool called = false; |
| 292 base::RunLoop run_loop; |
252 sample::ServicePtr ptr; | 293 sample::ServicePtr ptr; |
253 auto request = GetProxy(&ptr); | 294 auto request = GetProxy(&ptr); |
254 ServiceImpl impl; | 295 ServiceImpl impl; |
255 Binding<sample::Service> binding(&impl, std::move(request)); | 296 Binding<sample::Service> binding(&impl, std::move(request)); |
256 binding.set_connection_error_handler([&called]() { called = true; }); | 297 binding.set_connection_error_handler([&called, &run_loop]() { |
| 298 called = true; |
| 299 run_loop.Quit(); |
| 300 }); |
257 binding.PauseIncomingMethodCallProcessing(); | 301 binding.PauseIncomingMethodCallProcessing(); |
258 | 302 |
259 ptr.reset(); | 303 ptr.reset(); |
260 loop().RunUntilIdle(); | 304 loop().RunUntilIdle(); |
261 // The connection error handle should not be called as the binding is paused. | 305 // The connection error handle should not be called as the binding is paused. |
262 EXPECT_FALSE(called); | 306 EXPECT_FALSE(called); |
263 | 307 |
264 // Resume the binding, which should trigger the error handler. | 308 // Resume the binding, which should trigger the error handler. |
265 binding.ResumeIncomingMethodCallProcessing(); | 309 binding.ResumeIncomingMethodCallProcessing(); |
266 loop().RunUntilIdle(); | 310 run_loop.Run(); |
267 EXPECT_TRUE(called); | 311 EXPECT_TRUE(called); |
268 } | 312 } |
269 | 313 |
270 // StrongBindingTest ----------------------------------------------------------- | 314 // StrongBindingTest ----------------------------------------------------------- |
271 | 315 |
272 using StrongBindingTest = BindingTestBase; | 316 using StrongBindingTest = BindingTestBase; |
273 | 317 |
274 // Tests that destroying a mojo::StrongBinding closes the bound message pipe | 318 // Tests that destroying a mojo::StrongBinding closes the bound message pipe |
275 // handle but does *not* destroy the implementation object. | 319 // handle but does *not* destroy the implementation object. |
276 TEST_F(StrongBindingTest, DestroyClosesMessagePipe) { | 320 TEST_F(StrongBindingTest, DestroyClosesMessagePipe) { |
| 321 base::RunLoop run_loop; |
277 bool encountered_error = false; | 322 bool encountered_error = false; |
278 bool was_deleted = false; | 323 bool was_deleted = false; |
279 ServiceImpl impl(&was_deleted); | 324 ServiceImpl impl(&was_deleted); |
280 sample::ServicePtr ptr; | 325 sample::ServicePtr ptr; |
281 auto request = GetProxy(&ptr); | 326 auto request = GetProxy(&ptr); |
282 ptr.set_connection_error_handler( | 327 ptr.set_connection_error_handler( |
283 [&encountered_error]() { encountered_error = true; }); | 328 [&encountered_error, &run_loop]() { |
| 329 encountered_error = true; |
| 330 run_loop.Quit(); |
| 331 }); |
284 bool called = false; | 332 bool called = false; |
285 auto called_cb = [&called](int32_t result) { called = true; }; | 333 base::RunLoop run_loop2; |
| 334 auto called_cb = [&called, &run_loop2](int32_t result) { |
| 335 called = true; |
| 336 run_loop2.Quit(); |
| 337 }; |
286 { | 338 { |
287 StrongBinding<sample::Service> binding(&impl, std::move(request)); | 339 StrongBinding<sample::Service> binding(&impl, std::move(request)); |
288 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 340 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
289 called_cb); | 341 called_cb); |
290 loop().RunUntilIdle(); | 342 run_loop2.Run(); |
291 EXPECT_TRUE(called); | 343 EXPECT_TRUE(called); |
292 EXPECT_FALSE(encountered_error); | 344 EXPECT_FALSE(encountered_error); |
293 } | 345 } |
294 // Now that the StrongBinding is out of scope we should detect an error on the | 346 // Now that the StrongBinding is out of scope we should detect an error on the |
295 // other end of the pipe. | 347 // other end of the pipe. |
296 loop().RunUntilIdle(); | 348 run_loop.Run(); |
297 EXPECT_TRUE(encountered_error); | 349 EXPECT_TRUE(encountered_error); |
298 // But destroying the StrongBinding doesn't destroy the object. | 350 // But destroying the StrongBinding doesn't destroy the object. |
299 ASSERT_FALSE(was_deleted); | 351 ASSERT_FALSE(was_deleted); |
300 } | 352 } |
301 | 353 |
302 class ServiceImplWithStrongBinding : public ServiceImpl { | 354 class ServiceImplWithStrongBinding : public ServiceImpl { |
303 public: | 355 public: |
304 ServiceImplWithStrongBinding(bool* was_deleted, | 356 ServiceImplWithStrongBinding(bool* was_deleted, |
305 InterfaceRequest<sample::Service> request) | 357 InterfaceRequest<sample::Service> request) |
306 : ServiceImpl(was_deleted), binding_(this, std::move(request)) {} | 358 : ServiceImpl(was_deleted), binding_(this, std::move(request)) {} |
307 | 359 |
308 StrongBinding<sample::Service>& binding() { return binding_; } | 360 StrongBinding<sample::Service>& binding() { return binding_; } |
309 | 361 |
310 private: | 362 private: |
311 StrongBinding<sample::Service> binding_; | 363 StrongBinding<sample::Service> binding_; |
312 | 364 |
313 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithStrongBinding); | 365 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithStrongBinding); |
314 }; | 366 }; |
315 | 367 |
316 // Tests the typical case, where the implementation object owns the | 368 // Tests the typical case, where the implementation object owns the |
317 // StrongBinding (and should be destroyed on connection error). | 369 // StrongBinding (and should be destroyed on connection error). |
318 TEST_F(StrongBindingTest, ConnectionErrorDestroysImpl) { | 370 TEST_F(StrongBindingTest, ConnectionErrorDestroysImpl) { |
319 sample::ServicePtr ptr; | 371 sample::ServicePtr ptr; |
320 bool was_deleted = false; | 372 bool was_deleted = false; |
321 // Will delete itself. | 373 // Will delete itself. |
322 new ServiceImplWithBinding(&was_deleted, GetProxy(&ptr)); | 374 base::RunLoop run_loop; |
| 375 new ServiceImplWithBinding(&was_deleted, run_loop.QuitClosure(), |
| 376 GetProxy(&ptr)); |
323 | 377 |
324 loop().RunUntilIdle(); | 378 loop().RunUntilIdle(); |
325 EXPECT_FALSE(was_deleted); | 379 EXPECT_FALSE(was_deleted); |
326 | 380 |
327 ptr.reset(); | 381 ptr.reset(); |
328 EXPECT_FALSE(was_deleted); | 382 EXPECT_FALSE(was_deleted); |
329 loop().RunUntilIdle(); | 383 run_loop.Run(); |
330 EXPECT_TRUE(was_deleted); | 384 EXPECT_TRUE(was_deleted); |
331 } | 385 } |
332 | 386 |
333 // Tests that even when the implementation object owns the StrongBinding, that | 387 // Tests that even when the implementation object owns the StrongBinding, that |
334 // the implementation can still be deleted (which should result in the message | 388 // the implementation can still be deleted (which should result in the message |
335 // pipe being closed). Also checks that the connection error handler doesn't get | 389 // pipe being closed). Also checks that the connection error handler doesn't get |
336 // called. | 390 // called. |
337 TEST_F(StrongBindingTest, ExplicitDeleteImpl) { | 391 TEST_F(StrongBindingTest, ExplicitDeleteImpl) { |
338 bool ptr_error_handler_called = false; | 392 bool ptr_error_handler_called = false; |
339 sample::ServicePtr ptr; | 393 sample::ServicePtr ptr; |
340 auto request = GetProxy(&ptr); | 394 auto request = GetProxy(&ptr); |
| 395 base::RunLoop run_loop; |
341 ptr.set_connection_error_handler( | 396 ptr.set_connection_error_handler( |
342 [&ptr_error_handler_called]() { ptr_error_handler_called = true; }); | 397 [&ptr_error_handler_called, &run_loop]() { |
| 398 ptr_error_handler_called = true; |
| 399 run_loop.Quit(); |
| 400 }); |
343 bool was_deleted = false; | 401 bool was_deleted = false; |
344 ServiceImplWithStrongBinding* impl = | 402 ServiceImplWithStrongBinding* impl = |
345 new ServiceImplWithStrongBinding(&was_deleted, std::move(request)); | 403 new ServiceImplWithStrongBinding(&was_deleted, std::move(request)); |
346 bool binding_error_handler_called = false; | 404 bool binding_error_handler_called = false; |
347 impl->binding().set_connection_error_handler( | 405 impl->binding().set_connection_error_handler( |
348 [&binding_error_handler_called]() { | 406 [&binding_error_handler_called]() { |
349 binding_error_handler_called = true; | 407 binding_error_handler_called = true; |
350 }); | 408 }); |
351 | 409 |
352 loop().RunUntilIdle(); | 410 loop().RunUntilIdle(); |
353 EXPECT_FALSE(ptr_error_handler_called); | 411 EXPECT_FALSE(ptr_error_handler_called); |
354 EXPECT_FALSE(was_deleted); | 412 EXPECT_FALSE(was_deleted); |
355 | 413 |
356 delete impl; | 414 delete impl; |
357 EXPECT_FALSE(ptr_error_handler_called); | 415 EXPECT_FALSE(ptr_error_handler_called); |
358 EXPECT_TRUE(was_deleted); | 416 EXPECT_TRUE(was_deleted); |
359 was_deleted = false; // It shouldn't be double-deleted! | 417 was_deleted = false; // It shouldn't be double-deleted! |
360 loop().RunUntilIdle(); | 418 run_loop.Run(); |
361 EXPECT_TRUE(ptr_error_handler_called); | 419 EXPECT_TRUE(ptr_error_handler_called); |
362 EXPECT_FALSE(was_deleted); | 420 EXPECT_FALSE(was_deleted); |
363 | 421 |
364 EXPECT_FALSE(binding_error_handler_called); | 422 EXPECT_FALSE(binding_error_handler_called); |
365 } | 423 } |
366 | 424 |
367 } // namespace | 425 } // namespace |
368 } // mojo | 426 } // mojo |
OLD | NEW |