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

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

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

Powered by Google App Engine
This is Rietveld 408576698