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

Side by Side Diff: mojo/public/cpp/bindings/tests/binding_unittest.cc

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 // Note: This file tests both binding.h (mojo::Binding) and strong_binding.h
6 // (mojo::StrongBinding).
7
8 #include "gtest/gtest.h"
9 #include "mojo/public/cpp/bindings/binding.h"
10 #include "mojo/public/cpp/bindings/strong_binding.h"
11 #include "mojo/public/cpp/system/macros.h"
12 #include "mojo/public/cpp/utility/run_loop.h"
13 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h"
14 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h"
15
16 namespace mojo {
17 namespace {
18
19 class BindingTestBase : public testing::Test {
20 public:
21 BindingTestBase() {}
22 ~BindingTestBase() override {}
23
24 RunLoop& loop() { return loop_; }
25
26 private:
27 RunLoop loop_;
28
29 MOJO_DISALLOW_COPY_AND_ASSIGN(BindingTestBase);
30 };
31
32 class ServiceImpl : public sample::Service {
33 public:
34 explicit ServiceImpl(bool* was_deleted = nullptr)
35 : was_deleted_(was_deleted) {}
36 ~ServiceImpl() override {
37 if (was_deleted_)
38 *was_deleted_ = true;
39 }
40
41 private:
42 // sample::Service implementation
43 void Frobinate(sample::FooPtr foo,
44 BazOptions options,
45 mojo::InterfaceHandle<sample::Port> port,
46 const FrobinateCallback& callback) override {
47 callback.Run(1);
48 }
49 void GetPort(InterfaceRequest<sample::Port> port) override {}
50
51 bool* const was_deleted_;
52
53 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImpl);
54 };
55
56 // BindingTest -----------------------------------------------------------------
57
58 using BindingTest = BindingTestBase;
59
60 TEST_F(BindingTest, Close) {
61 bool called = false;
62 sample::ServicePtr ptr;
63 auto request = GetProxy(&ptr);
64 ptr.set_connection_error_handler([&called]() { called = true; });
65 ServiceImpl impl;
66 Binding<sample::Service> binding(&impl, request.Pass());
67
68 binding.Close();
69 EXPECT_FALSE(called);
70 loop().RunUntilIdle();
71 EXPECT_TRUE(called);
72 }
73
74 // Tests that destroying a mojo::Binding closes the bound message pipe handle.
75 TEST_F(BindingTest, DestroyClosesMessagePipe) {
76 bool encountered_error = false;
77 ServiceImpl impl;
78 sample::ServicePtr ptr;
79 auto request = GetProxy(&ptr);
80 ptr.set_connection_error_handler(
81 [&encountered_error]() { encountered_error = true; });
82 bool called = false;
83 auto called_cb = [&called](int32_t result) { called = true; };
84 {
85 Binding<sample::Service> binding(&impl, request.Pass());
86 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
87 called_cb);
88 loop().RunUntilIdle();
89 EXPECT_TRUE(called);
90 EXPECT_FALSE(encountered_error);
91 }
92 // Now that the Binding is out of scope we should detect an error on the other
93 // end of the pipe.
94 loop().RunUntilIdle();
95 EXPECT_TRUE(encountered_error);
96
97 // And calls should fail.
98 called = false;
99 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
100 called_cb);
101 loop().RunUntilIdle();
102 EXPECT_FALSE(called);
103 }
104
105 // Tests that the binding's connection error handler gets called when the other
106 // end is closed.
107 TEST_F(BindingTest, ConnectionError) {
108 bool called = false;
109 {
110 ServiceImpl impl;
111 sample::ServicePtr ptr;
112 Binding<sample::Service> binding(&impl, GetProxy(&ptr));
113 binding.set_connection_error_handler([&called]() { called = true; });
114 ptr.reset();
115 EXPECT_FALSE(called);
116 loop().RunUntilIdle();
117 EXPECT_TRUE(called);
118 // We want to make sure that it isn't called again during destruction.
119 called = false;
120 }
121 EXPECT_FALSE(called);
122 }
123
124 // Tests that calling Close doesn't result in the connection error handler being
125 // called.
126 TEST_F(BindingTest, CloseDoesntCallConnectionErrorHandler) {
127 ServiceImpl impl;
128 sample::ServicePtr ptr;
129 Binding<sample::Service> binding(&impl, GetProxy(&ptr));
130 bool called = false;
131 binding.set_connection_error_handler([&called]() { called = true; });
132 binding.Close();
133 loop().RunUntilIdle();
134 EXPECT_FALSE(called);
135
136 // We can also close the other end, and the error handler still won't be
137 // called.
138 ptr.reset();
139 loop().RunUntilIdle();
140 EXPECT_FALSE(called);
141 }
142
143 class ServiceImplWithBinding : public ServiceImpl {
144 public:
145 ServiceImplWithBinding(bool* was_deleted,
146 InterfaceRequest<sample::Service> request)
147 : ServiceImpl(was_deleted), binding_(this, request.Pass()) {
148 binding_.set_connection_error_handler([this]() { delete this; });
149 }
150
151 private:
152 Binding<sample::Service> binding_;
153
154 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithBinding);
155 };
156
157 // Tests that the binding may be deleted in the connection error handler.
158 TEST_F(BindingTest, SelfDeleteOnConnectionError) {
159 bool was_deleted = false;
160 sample::ServicePtr ptr;
161 // This should delete itself on connection error.
162 new ServiceImplWithBinding(&was_deleted, GetProxy(&ptr));
163 ptr.reset();
164 EXPECT_FALSE(was_deleted);
165 loop().RunUntilIdle();
166 EXPECT_TRUE(was_deleted);
167 }
168
169 // Tests that explicitly calling Unbind followed by rebinding works.
170 TEST_F(BindingTest, Unbind) {
171 ServiceImpl impl;
172 sample::ServicePtr ptr;
173 Binding<sample::Service> binding(&impl, GetProxy(&ptr));
174
175 bool called = false;
176 auto called_cb = [&called](int32_t result) { called = true; };
177 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
178 called_cb);
179 loop().RunUntilIdle();
180 EXPECT_TRUE(called);
181
182 called = false;
183 auto request = binding.Unbind();
184 EXPECT_FALSE(binding.is_bound());
185 // All calls should fail when not bound...
186 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
187 called_cb);
188 loop().RunUntilIdle();
189 EXPECT_FALSE(called);
190
191 called = false;
192 binding.Bind(request.Pass());
193 EXPECT_TRUE(binding.is_bound());
194 // ...and should succeed again when the rebound.
195 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
196 called_cb);
197 loop().RunUntilIdle();
198 EXPECT_TRUE(called);
199 }
200
201 class IntegerAccessorImpl : public sample::IntegerAccessor {
202 public:
203 IntegerAccessorImpl() {}
204 ~IntegerAccessorImpl() override {}
205
206 private:
207 // sample::IntegerAccessor implementation.
208 void GetInteger(const GetIntegerCallback& callback) override {
209 callback.Run(1, sample::Enum::VALUE);
210 }
211 void SetInteger(int64_t data, sample::Enum type) override {}
212
213 MOJO_DISALLOW_COPY_AND_ASSIGN(IntegerAccessorImpl);
214 };
215
216 TEST_F(BindingTest, SetInterfaceHandleVersion) {
217 IntegerAccessorImpl impl;
218 mojo::InterfaceHandle<sample::IntegerAccessor> handle;
219 Binding<sample::IntegerAccessor> binding(&impl, &handle);
220 EXPECT_EQ(3u, handle.version());
221 }
222
223 // StrongBindingTest -----------------------------------------------------------
224
225 using StrongBindingTest = BindingTestBase;
226
227 // Tests that destroying a mojo::StrongBinding closes the bound message pipe
228 // handle but does *not* destroy the implementation object.
229 TEST_F(StrongBindingTest, DestroyClosesMessagePipe) {
230 bool encountered_error = false;
231 bool was_deleted = false;
232 ServiceImpl impl(&was_deleted);
233 sample::ServicePtr ptr;
234 auto request = GetProxy(&ptr);
235 ptr.set_connection_error_handler(
236 [&encountered_error]() { encountered_error = true; });
237 bool called = false;
238 auto called_cb = [&called](int32_t result) { called = true; };
239 {
240 StrongBinding<sample::Service> binding(&impl, request.Pass());
241 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
242 called_cb);
243 loop().RunUntilIdle();
244 EXPECT_TRUE(called);
245 EXPECT_FALSE(encountered_error);
246 }
247 // Now that the StrongBinding is out of scope we should detect an error on the
248 // other end of the pipe.
249 loop().RunUntilIdle();
250 EXPECT_TRUE(encountered_error);
251 // But destroying the StrongBinding doesn't destroy the object.
252 ASSERT_FALSE(was_deleted);
253 }
254
255 class ServiceImplWithStrongBinding : public ServiceImpl {
256 public:
257 ServiceImplWithStrongBinding(bool* was_deleted,
258 InterfaceRequest<sample::Service> request)
259 : ServiceImpl(was_deleted), binding_(this, request.Pass()) {}
260
261 StrongBinding<sample::Service>& binding() { return binding_; }
262
263 private:
264 StrongBinding<sample::Service> binding_;
265
266 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithStrongBinding);
267 };
268
269 // Tests the typical case, where the implementation object owns the
270 // StrongBinding (and should be destroyed on connection error).
271 TEST_F(StrongBindingTest, ConnectionErrorDestroysImpl) {
272 sample::ServicePtr ptr;
273 bool was_deleted = false;
274 // Will delete itself.
275 new ServiceImplWithBinding(&was_deleted, GetProxy(&ptr));
276
277 loop().RunUntilIdle();
278 EXPECT_FALSE(was_deleted);
279
280 ptr.reset();
281 EXPECT_FALSE(was_deleted);
282 loop().RunUntilIdle();
283 EXPECT_TRUE(was_deleted);
284 }
285
286 // Tests that even when the implementation object owns the StrongBinding, that
287 // the implementation can still be deleted (which should result in the message
288 // pipe being closed). Also checks that the connection error handler doesn't get
289 // called.
290 TEST_F(StrongBindingTest, ExplicitDeleteImpl) {
291 bool ptr_error_handler_called = false;
292 sample::ServicePtr ptr;
293 auto request = GetProxy(&ptr);
294 ptr.set_connection_error_handler(
295 [&ptr_error_handler_called]() { ptr_error_handler_called = true; });
296 bool was_deleted = false;
297 ServiceImplWithStrongBinding* impl =
298 new ServiceImplWithStrongBinding(&was_deleted, request.Pass());
299 bool binding_error_handler_called = false;
300 impl->binding().set_connection_error_handler(
301 [&binding_error_handler_called]() {
302 binding_error_handler_called = true;
303 });
304
305 loop().RunUntilIdle();
306 EXPECT_FALSE(ptr_error_handler_called);
307 EXPECT_FALSE(was_deleted);
308
309 delete impl;
310 EXPECT_FALSE(ptr_error_handler_called);
311 EXPECT_TRUE(was_deleted);
312 was_deleted = false; // It shouldn't be double-deleted!
313 loop().RunUntilIdle();
314 EXPECT_TRUE(ptr_error_handler_called);
315 EXPECT_FALSE(was_deleted);
316
317 EXPECT_FALSE(binding_error_handler_called);
318 }
319
320 // Tests that StrongBinding::Close() compiles.
321 TEST_F(BindingTest, StrongBindingCloseCompile) {
322 ServiceImpl impl;
323 sample::ServicePtr ptr;
324 StrongBinding<sample::Service> binding(&impl, GetProxy(&ptr));
325 binding.Close();
326 }
327
328 // Tests that StrongBinding::Unbind() compiles.
329 TEST_F(BindingTest, StrongBindingUnbindCompile) {
330 ServiceImpl impl;
331 sample::ServicePtr ptr;
332 StrongBinding<sample::Service> binding(&impl, GetProxy(&ptr));
333 binding.Unbind();
334 }
335
336 } // namespace
337 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/tests/binding_set_unittest.cc ('k') | mojo/public/cpp/bindings/tests/bindings_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698