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

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

Issue 814543006: Move //mojo/{public, edk} underneath //third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 11 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 2013 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 #include "mojo/public/cpp/bindings/binding.h"
6 #include "mojo/public/cpp/bindings/error_handler.h"
7 #include "mojo/public/cpp/bindings/strong_binding.h"
8 #include "mojo/public/cpp/environment/environment.h"
9 #include "mojo/public/cpp/utility/run_loop.h"
10 #include "mojo/public/interfaces/bindings/tests/math_calculator.mojom.h"
11 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace mojo {
15 namespace test {
16 namespace {
17
18 class ErrorObserver : public ErrorHandler {
19 public:
20 ErrorObserver() : encountered_error_(false) {}
21
22 bool encountered_error() const { return encountered_error_; }
23
24 void OnConnectionError() override { encountered_error_ = true; }
25
26 private:
27 bool encountered_error_;
28 };
29
30 class MathCalculatorImpl : public InterfaceImpl<math::Calculator> {
31 public:
32 ~MathCalculatorImpl() override {}
33
34 MathCalculatorImpl() : total_(0.0) {}
35
36 void Clear() override { client()->Output(total_); }
37
38 void Add(double value) override {
39 total_ += value;
40 client()->Output(total_);
41 }
42
43 void Multiply(double value) override {
44 total_ *= value;
45 client()->Output(total_);
46 }
47
48 private:
49 double total_;
50 };
51
52 class MathCalculatorUIImpl : public math::CalculatorUI {
53 public:
54 explicit MathCalculatorUIImpl(math::CalculatorPtr calculator)
55 : calculator_(calculator.Pass()), output_(0.0) {
56 calculator_.set_client(this);
57 }
58
59 bool WaitForIncomingMethodCall() {
60 return calculator_.WaitForIncomingMethodCall();
61 }
62
63 bool encountered_error() const { return calculator_.encountered_error(); }
64
65 void Add(double value) { calculator_->Add(value); }
66
67 void Subtract(double value) { calculator_->Add(-value); }
68
69 void Multiply(double value) { calculator_->Multiply(value); }
70
71 void Divide(double value) { calculator_->Multiply(1.0 / value); }
72
73 double GetOutput() const { return output_; }
74
75 private:
76 // math::CalculatorUI implementation:
77 void Output(double value) override { output_ = value; }
78
79 math::CalculatorPtr calculator_;
80 double output_;
81 };
82
83 class SelfDestructingMathCalculatorUIImpl : public math::CalculatorUI {
84 public:
85 explicit SelfDestructingMathCalculatorUIImpl(math::CalculatorPtr calculator)
86 : calculator_(calculator.Pass()), nesting_level_(0) {
87 ++num_instances_;
88 calculator_.set_client(this);
89 }
90
91 void BeginTest(bool nested) {
92 nesting_level_ = nested ? 2 : 1;
93 calculator_->Add(1.0);
94 }
95
96 static int num_instances() { return num_instances_; }
97
98 private:
99 ~SelfDestructingMathCalculatorUIImpl() override { --num_instances_; }
100
101 void Output(double value) override {
102 if (--nesting_level_ > 0) {
103 // Add some more and wait for re-entrant call to Output!
104 calculator_->Add(1.0);
105 RunLoop::current()->RunUntilIdle();
106 } else {
107 delete this;
108 }
109 }
110
111 math::CalculatorPtr calculator_;
112 int nesting_level_;
113 static int num_instances_;
114 };
115
116 // static
117 int SelfDestructingMathCalculatorUIImpl::num_instances_ = 0;
118
119 class ReentrantServiceImpl : public InterfaceImpl<sample::Service> {
120 public:
121 ~ReentrantServiceImpl() override {}
122
123 ReentrantServiceImpl() : call_depth_(0), max_call_depth_(0) {}
124
125 int max_call_depth() { return max_call_depth_; }
126
127 void Frobinate(sample::FooPtr foo,
128 sample::Service::BazOptions baz,
129 sample::PortPtr port) override {
130 max_call_depth_ = std::max(++call_depth_, max_call_depth_);
131 if (call_depth_ == 1) {
132 EXPECT_TRUE(WaitForIncomingMethodCall());
133 }
134 call_depth_--;
135 }
136
137 void GetPort(mojo::InterfaceRequest<sample::Port> port) override {}
138
139 private:
140 int call_depth_;
141 int max_call_depth_;
142 };
143
144 class InterfacePtrTest : public testing::Test {
145 public:
146 ~InterfacePtrTest() override { loop_.RunUntilIdle(); }
147
148 void PumpMessages() { loop_.RunUntilIdle(); }
149
150 private:
151 Environment env_;
152 RunLoop loop_;
153 };
154
155 TEST_F(InterfacePtrTest, EndToEnd) {
156 math::CalculatorPtr calc;
157 BindToProxy(new MathCalculatorImpl(), &calc);
158
159 // Suppose this is instantiated in a process that has pipe1_.
160 MathCalculatorUIImpl calculator_ui(calc.Pass());
161
162 calculator_ui.Add(2.0);
163 calculator_ui.Multiply(5.0);
164
165 PumpMessages();
166
167 EXPECT_EQ(10.0, calculator_ui.GetOutput());
168 }
169
170 TEST_F(InterfacePtrTest, EndToEnd_Synchronous) {
171 math::CalculatorPtr calc;
172 MathCalculatorImpl* impl = BindToProxy(new MathCalculatorImpl(), &calc);
173
174 // Suppose this is instantiated in a process that has pipe1_.
175 MathCalculatorUIImpl calculator_ui(calc.Pass());
176
177 EXPECT_EQ(0.0, calculator_ui.GetOutput());
178
179 calculator_ui.Add(2.0);
180 EXPECT_EQ(0.0, calculator_ui.GetOutput());
181 impl->WaitForIncomingMethodCall();
182 calculator_ui.WaitForIncomingMethodCall();
183 EXPECT_EQ(2.0, calculator_ui.GetOutput());
184
185 calculator_ui.Multiply(5.0);
186 EXPECT_EQ(2.0, calculator_ui.GetOutput());
187 impl->WaitForIncomingMethodCall();
188 calculator_ui.WaitForIncomingMethodCall();
189 EXPECT_EQ(10.0, calculator_ui.GetOutput());
190 }
191
192 TEST_F(InterfacePtrTest, Movable) {
193 math::CalculatorPtr a;
194 math::CalculatorPtr b;
195 BindToProxy(new MathCalculatorImpl(), &b);
196
197 EXPECT_TRUE(!a);
198 EXPECT_FALSE(!b);
199
200 a = b.Pass();
201
202 EXPECT_FALSE(!a);
203 EXPECT_TRUE(!b);
204 }
205
206 TEST_F(InterfacePtrTest, Resettable) {
207 math::CalculatorPtr a;
208
209 EXPECT_TRUE(!a);
210
211 MessagePipe pipe;
212
213 // Save this so we can test it later.
214 Handle handle = pipe.handle0.get();
215
216 a = MakeProxy<math::Calculator>(pipe.handle0.Pass());
217
218 EXPECT_FALSE(!a);
219
220 a.reset();
221
222 EXPECT_TRUE(!a);
223 EXPECT_FALSE(a.internal_state()->router_for_testing());
224
225 // Test that handle was closed.
226 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, CloseRaw(handle));
227 }
228
229 TEST_F(InterfacePtrTest, EncounteredError) {
230 math::CalculatorPtr proxy;
231 MathCalculatorImpl* server = BindToProxy(new MathCalculatorImpl(), &proxy);
232
233 MathCalculatorUIImpl calculator_ui(proxy.Pass());
234
235 calculator_ui.Add(2.0);
236 PumpMessages();
237 EXPECT_EQ(2.0, calculator_ui.GetOutput());
238 EXPECT_FALSE(calculator_ui.encountered_error());
239
240 calculator_ui.Multiply(5.0);
241 EXPECT_FALSE(calculator_ui.encountered_error());
242
243 // Close the server.
244 server->internal_router()->CloseMessagePipe();
245
246 // The state change isn't picked up locally yet.
247 EXPECT_FALSE(calculator_ui.encountered_error());
248
249 PumpMessages();
250
251 // OK, now we see the error.
252 EXPECT_TRUE(calculator_ui.encountered_error());
253 }
254
255 TEST_F(InterfacePtrTest, EncounteredErrorCallback) {
256 math::CalculatorPtr proxy;
257 MathCalculatorImpl* server = BindToProxy(new MathCalculatorImpl(), &proxy);
258
259 ErrorObserver error_observer;
260 proxy.set_error_handler(&error_observer);
261
262 MathCalculatorUIImpl calculator_ui(proxy.Pass());
263
264 calculator_ui.Add(2.0);
265 PumpMessages();
266 EXPECT_EQ(2.0, calculator_ui.GetOutput());
267 EXPECT_FALSE(calculator_ui.encountered_error());
268
269 calculator_ui.Multiply(5.0);
270 EXPECT_FALSE(calculator_ui.encountered_error());
271
272 // Close the server.
273 server->internal_router()->CloseMessagePipe();
274
275 // The state change isn't picked up locally yet.
276 EXPECT_FALSE(calculator_ui.encountered_error());
277
278 PumpMessages();
279
280 // OK, now we see the error.
281 EXPECT_TRUE(calculator_ui.encountered_error());
282
283 // We should have also been able to observe the error through the
284 // ErrorHandler interface.
285 EXPECT_TRUE(error_observer.encountered_error());
286 }
287
288 TEST_F(InterfacePtrTest, NoClientAttribute) {
289 // This is a test to ensure the following compiles. The sample::Port interface
290 // does not have an explicit Client attribute.
291 sample::PortPtr port;
292 MessagePipe pipe;
293 port.Bind(pipe.handle0.Pass());
294 }
295
296 TEST_F(InterfacePtrTest, DestroyInterfacePtrOnClientMethod) {
297 math::CalculatorPtr proxy;
298 BindToProxy(new MathCalculatorImpl(), &proxy);
299
300 EXPECT_EQ(0, SelfDestructingMathCalculatorUIImpl::num_instances());
301
302 SelfDestructingMathCalculatorUIImpl* impl =
303 new SelfDestructingMathCalculatorUIImpl(proxy.Pass());
304 impl->BeginTest(false);
305
306 PumpMessages();
307
308 EXPECT_EQ(0, SelfDestructingMathCalculatorUIImpl::num_instances());
309 }
310
311 TEST_F(InterfacePtrTest, NestedDestroyInterfacePtrOnClientMethod) {
312 math::CalculatorPtr proxy;
313 BindToProxy(new MathCalculatorImpl(), &proxy);
314
315 EXPECT_EQ(0, SelfDestructingMathCalculatorUIImpl::num_instances());
316
317 SelfDestructingMathCalculatorUIImpl* impl =
318 new SelfDestructingMathCalculatorUIImpl(proxy.Pass());
319 impl->BeginTest(true);
320
321 PumpMessages();
322
323 EXPECT_EQ(0, SelfDestructingMathCalculatorUIImpl::num_instances());
324 }
325
326 TEST_F(InterfacePtrTest, ReentrantWaitForIncomingMethodCall) {
327 sample::ServicePtr proxy;
328 ReentrantServiceImpl* impl = BindToProxy(new ReentrantServiceImpl(), &proxy);
329
330 proxy->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr);
331 proxy->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr);
332
333 PumpMessages();
334
335 EXPECT_EQ(2, impl->max_call_depth());
336 }
337
338 class StrongMathCalculatorImpl : public math::Calculator, public ErrorHandler {
339 public:
340 StrongMathCalculatorImpl(ScopedMessagePipeHandle handle,
341 bool* error_received,
342 bool* destroyed)
343 : error_received_(error_received),
344 destroyed_(destroyed),
345 binding_(this, handle.Pass()) {
346 binding_.set_error_handler(this);
347 }
348 ~StrongMathCalculatorImpl() override { *destroyed_ = true; }
349
350 // math::Calculator implementation.
351 void Clear() override { binding_.client()->Output(total_); }
352
353 void Add(double value) override {
354 total_ += value;
355 binding_.client()->Output(total_);
356 }
357
358 void Multiply(double value) override {
359 total_ *= value;
360 binding_.client()->Output(total_);
361 }
362
363 // ErrorHandler implementation.
364 void OnConnectionError() override { *error_received_ = true; }
365
366 private:
367 double total_ = 0.0;
368 bool* error_received_;
369 bool* destroyed_;
370
371 StrongBinding<math::Calculator> binding_;
372 };
373
374 TEST(StrongConnectorTest, Math) {
375 Environment env;
376 RunLoop loop;
377
378 bool error_received = false;
379 bool destroyed = false;
380 MessagePipe pipe;
381 new StrongMathCalculatorImpl(pipe.handle0.Pass(), &error_received,
382 &destroyed);
383
384 math::CalculatorPtr calc;
385 calc.Bind(pipe.handle1.Pass());
386
387 {
388 // Suppose this is instantiated in a process that has the other end of the
389 // message pipe.
390 MathCalculatorUIImpl calculator_ui(calc.Pass());
391
392 calculator_ui.Add(2.0);
393 calculator_ui.Multiply(5.0);
394
395 loop.RunUntilIdle();
396
397 EXPECT_EQ(10.0, calculator_ui.GetOutput());
398 EXPECT_FALSE(error_received);
399 EXPECT_FALSE(destroyed);
400 }
401 // Destroying calculator_ui should close the pipe and generate an error on the
402 // other
403 // end which will destroy the instance since it is strongly bound.
404
405 loop.RunUntilIdle();
406 EXPECT_TRUE(error_received);
407 EXPECT_TRUE(destroyed);
408 }
409
410 class WeakMathCalculatorImpl : public math::Calculator, public ErrorHandler {
411 public:
412 WeakMathCalculatorImpl(ScopedMessagePipeHandle handle,
413 bool* error_received,
414 bool* destroyed)
415 : error_received_(error_received),
416 destroyed_(destroyed),
417 binding_(this, handle.Pass()) {
418 binding_.set_error_handler(this);
419 }
420 ~WeakMathCalculatorImpl() override { *destroyed_ = true; }
421
422 void Clear() override { binding_.client()->Output(total_); }
423
424 void Add(double value) override {
425 total_ += value;
426 binding_.client()->Output(total_);
427 }
428
429 void Multiply(double value) override {
430 total_ *= value;
431 binding_.client()->Output(total_);
432 }
433
434 // ErrorHandler implementation.
435 void OnConnectionError() override { *error_received_ = true; }
436
437 private:
438 double total_ = 0.0;
439 bool* error_received_;
440 bool* destroyed_;
441
442 Binding<math::Calculator> binding_;
443 };
444
445 TEST(WeakConnectorTest, Math) {
446 Environment env;
447 RunLoop loop;
448
449 bool error_received = false;
450 bool destroyed = false;
451 MessagePipe pipe;
452 WeakMathCalculatorImpl impl(pipe.handle0.Pass(), &error_received, &destroyed);
453
454 math::CalculatorPtr calc;
455 calc.Bind(pipe.handle1.Pass());
456
457 {
458 // Suppose this is instantiated in a process that has the other end of the
459 // message pipe.
460 MathCalculatorUIImpl calculator_ui(calc.Pass());
461
462 calculator_ui.Add(2.0);
463 calculator_ui.Multiply(5.0);
464
465 loop.RunUntilIdle();
466
467 EXPECT_EQ(10.0, calculator_ui.GetOutput());
468 EXPECT_FALSE(error_received);
469 EXPECT_FALSE(destroyed);
470 // Destroying calculator_ui should close the pipe and generate an error on
471 // the other
472 // end which will destroy the instance since it is strongly bound.
473 }
474
475 loop.RunUntilIdle();
476 EXPECT_TRUE(error_received);
477 EXPECT_FALSE(destroyed);
478 }
479
480 } // namespace
481 } // namespace test
482 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/tests/handle_passing_unittest.cc ('k') | mojo/public/cpp/bindings/tests/map_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698