blob: 85cec97ae987608938d1a7b42c99536205725845 [file] [log] [blame]
yzshen37b7abd2015-11-25 01:43:17 +09001// 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
Avi Drissman20b0cb02015-12-22 03:14:57 +09005#include <stddef.h>
6#include <stdint.h>
yzshen37b7abd2015-11-25 01:43:17 +09007#include <algorithm>
dchengcb035232015-12-26 13:46:36 +09008#include <utility>
yzshen37b7abd2015-11-25 01:43:17 +09009
10#include "base/bind.h"
rockot7464c2f2016-06-20 02:08:36 +090011#include "base/callback.h"
rockotcffd1b22016-08-25 08:37:11 +090012#include "base/callback_helpers.h"
fdoray64ef1472016-12-24 04:51:48 +090013#include "base/memory/ptr_util.h"
yzshen37b7abd2015-11-25 01:43:17 +090014#include "base/run_loop.h"
fdorayc2783162016-07-05 06:56:42 +090015#include "base/single_thread_task_runner.h"
jcivelli3907bec2017-01-07 03:23:01 +090016#include "base/synchronization/waitable_event.h"
Sam McNally7854eed2017-06-20 08:34:45 +090017#include "base/task_scheduler/post_task.h"
18#include "base/test/scoped_task_environment.h"
jcivelli9027ad72016-11-18 12:22:41 +090019#include "base/threading/sequenced_task_runner_handle.h"
yzshen37b7abd2015-11-25 01:43:17 +090020#include "base/threading/thread.h"
gab1400a962016-05-12 03:11:16 +090021#include "base/threading/thread_task_runner_handle.h"
yzshen37b7abd2015-11-25 01:43:17 +090022#include "mojo/public/cpp/bindings/associated_binding.h"
yzshen37b7abd2015-11-25 01:43:17 +090023#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
24#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
25#include "mojo/public/cpp/bindings/associated_interface_request.h"
26#include "mojo/public/cpp/bindings/binding.h"
27#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
sammc70588902016-09-01 18:52:58 +090028#include "mojo/public/cpp/bindings/strong_binding.h"
jcivelli9027ad72016-11-18 12:22:41 +090029#include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h"
rockotcffd1b22016-08-25 08:37:11 +090030#include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h"
yzshen37b7abd2015-11-25 01:43:17 +090031#include "mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.h"
32#include "testing/gtest/include/gtest/gtest.h"
33
34namespace mojo {
35namespace test {
36namespace {
37
yzshen37b7abd2015-11-25 01:43:17 +090038using mojo::internal::MultiplexRouter;
yzshen37b7abd2015-11-25 01:43:17 +090039
40class IntegerSenderImpl : public IntegerSender {
41 public:
42 explicit IntegerSenderImpl(AssociatedInterfaceRequest<IntegerSender> request)
dchengcb035232015-12-26 13:46:36 +090043 : binding_(this, std::move(request)) {}
yzshen37b7abd2015-11-25 01:43:17 +090044
45 ~IntegerSenderImpl() override {}
46
47 void set_notify_send_method_called(
48 const base::Callback<void(int32_t)>& callback) {
49 notify_send_method_called_ = callback;
50 }
51
52 void Echo(int32_t value, const EchoCallback& callback) override {
53 callback.Run(value);
54 }
55 void Send(int32_t value) override { notify_send_method_called_.Run(value); }
56
57 AssociatedBinding<IntegerSender>* binding() { return &binding_; }
58
rockot7464c2f2016-06-20 02:08:36 +090059 void set_connection_error_handler(const base::Closure& handler) {
yzshen37b7abd2015-11-25 01:43:17 +090060 binding_.set_connection_error_handler(handler);
61 }
62
63 private:
64 AssociatedBinding<IntegerSender> binding_;
65 base::Callback<void(int32_t)> notify_send_method_called_;
66};
67
yzshen50269ab2015-11-26 09:31:56 +090068class IntegerSenderConnectionImpl : public IntegerSenderConnection {
69 public:
70 explicit IntegerSenderConnectionImpl(
71 InterfaceRequest<IntegerSenderConnection> request)
dchengcb035232015-12-26 13:46:36 +090072 : binding_(this, std::move(request)) {}
yzshen50269ab2015-11-26 09:31:56 +090073
74 ~IntegerSenderConnectionImpl() override {}
75
76 void GetSender(AssociatedInterfaceRequest<IntegerSender> sender) override {
dchengcb035232015-12-26 13:46:36 +090077 IntegerSenderImpl* sender_impl = new IntegerSenderImpl(std::move(sender));
yzshen50269ab2015-11-26 09:31:56 +090078 sender_impl->set_connection_error_handler(
rockot453673f2016-06-19 05:15:51 +090079 base::Bind(&DeleteSender, sender_impl));
yzshen50269ab2015-11-26 09:31:56 +090080 }
81
82 void AsyncGetSender(const AsyncGetSenderCallback& callback) override {
yzshen9ce81092016-01-20 09:42:42 +090083 IntegerSenderAssociatedPtrInfo ptr_info;
yzshene968d282017-02-16 08:22:41 +090084 auto request = MakeRequest(&ptr_info);
dchengcb035232015-12-26 13:46:36 +090085 GetSender(std::move(request));
86 callback.Run(std::move(ptr_info));
yzshen50269ab2015-11-26 09:31:56 +090087 }
88
yzshen09b12282015-12-11 10:37:50 +090089 Binding<IntegerSenderConnection>* binding() { return &binding_; }
90
yzshen50269ab2015-11-26 09:31:56 +090091 private:
rockot453673f2016-06-19 05:15:51 +090092 static void DeleteSender(IntegerSenderImpl* sender) { delete sender; }
93
yzshen50269ab2015-11-26 09:31:56 +090094 Binding<IntegerSenderConnection> binding_;
95};
96
yzshen37b7abd2015-11-25 01:43:17 +090097class AssociatedInterfaceTest : public testing::Test {
98 public:
Sam McNally7854eed2017-06-20 08:34:45 +090099 AssociatedInterfaceTest()
100 : main_runner_(base::ThreadTaskRunnerHandle::Get()) {}
fdorayc2783162016-07-05 06:56:42 +0900101 ~AssociatedInterfaceTest() override { base::RunLoop().RunUntilIdle(); }
yzshen37b7abd2015-11-25 01:43:17 +0900102
fdorayc2783162016-07-05 06:56:42 +0900103 void PumpMessages() { base::RunLoop().RunUntilIdle(); }
yzshen37b7abd2015-11-25 01:43:17 +0900104
105 template <typename T>
106 AssociatedInterfacePtrInfo<T> EmulatePassingAssociatedPtrInfo(
107 AssociatedInterfacePtrInfo<T> ptr_info,
yzshen8dc7bd72017-02-15 07:24:25 +0900108 scoped_refptr<MultiplexRouter> source,
yzshen37b7abd2015-11-25 01:43:17 +0900109 scoped_refptr<MultiplexRouter> target) {
rockota3695c52016-05-18 10:16:03 +0900110 ScopedInterfaceEndpointHandle handle = ptr_info.PassHandle();
yzshen8dc7bd72017-02-15 07:24:25 +0900111 CHECK(handle.pending_association());
112 auto id = source->AssociateInterface(std::move(handle));
113 return AssociatedInterfacePtrInfo<T>(target->CreateLocalEndpointHandle(id),
114 ptr_info.version());
yzshen37b7abd2015-11-25 01:43:17 +0900115 }
116
yzshen626de042016-09-14 02:03:53 +0900117 void CreateRouterPair(scoped_refptr<MultiplexRouter>* router0,
118 scoped_refptr<MultiplexRouter>* router1) {
119 MessagePipe pipe;
yzshen3830edd2016-09-16 08:30:31 +0900120 *router0 = new MultiplexRouter(std::move(pipe.handle0),
121 MultiplexRouter::MULTI_INTERFACE, true,
Sam McNally7854eed2017-06-20 08:34:45 +0900122 main_runner_);
yzshen3830edd2016-09-16 08:30:31 +0900123 *router1 = new MultiplexRouter(std::move(pipe.handle1),
124 MultiplexRouter::MULTI_INTERFACE, false,
Sam McNally7854eed2017-06-20 08:34:45 +0900125 main_runner_);
yzshen626de042016-09-14 02:03:53 +0900126 }
127
128 void CreateIntegerSenderWithExistingRouters(
129 scoped_refptr<MultiplexRouter> router0,
130 IntegerSenderAssociatedPtrInfo* ptr_info0,
131 scoped_refptr<MultiplexRouter> router1,
132 IntegerSenderAssociatedRequest* request1) {
yzshene968d282017-02-16 08:22:41 +0900133 *request1 = MakeRequest(ptr_info0);
yzshen8dc7bd72017-02-15 07:24:25 +0900134 *ptr_info0 = EmulatePassingAssociatedPtrInfo(std::move(*ptr_info0), router1,
135 router0);
yzshen626de042016-09-14 02:03:53 +0900136 }
137
138 void CreateIntegerSender(IntegerSenderAssociatedPtrInfo* ptr_info,
139 IntegerSenderAssociatedRequest* request) {
140 scoped_refptr<MultiplexRouter> router0;
141 scoped_refptr<MultiplexRouter> router1;
142 CreateRouterPair(&router0, &router1);
143 CreateIntegerSenderWithExistingRouters(router1, ptr_info, router0, request);
yzshen37b7abd2015-11-25 01:43:17 +0900144 }
145
146 // Okay to call from any thread.
147 void QuitRunLoop(base::RunLoop* run_loop) {
peary2e3be2352017-06-29 11:15:28 +0900148 if (main_runner_->RunsTasksInCurrentSequence()) {
yzshen37b7abd2015-11-25 01:43:17 +0900149 run_loop->Quit();
150 } else {
Sam McNally7854eed2017-06-20 08:34:45 +0900151 main_runner_->PostTask(
yzshen37b7abd2015-11-25 01:43:17 +0900152 FROM_HERE,
153 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
154 base::Unretained(this), base::Unretained(run_loop)));
155 }
156 }
157
158 private:
Sam McNally7854eed2017-06-20 08:34:45 +0900159 base::test::ScopedTaskEnvironment task_environment;
160 scoped_refptr<base::SequencedTaskRunner> main_runner_;
yzshen37b7abd2015-11-25 01:43:17 +0900161};
162
rockot453673f2016-06-19 05:15:51 +0900163void DoSetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
164 *flag = true;
165 closure.Run();
166}
167
168void DoExpectValueSetFlagAndRunClosure(int32_t expected_value,
169 bool* flag,
170 const base::Closure& closure,
171 int32_t value) {
172 EXPECT_EQ(expected_value, value);
173 DoSetFlagAndRunClosure(flag, closure);
174}
175
176base::Closure SetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
177 return base::Bind(&DoSetFlagAndRunClosure, flag, closure);
178}
179
180base::Callback<void(int32_t)> ExpectValueSetFlagAndRunClosure(
181 int32_t expected_value,
182 bool* flag,
183 const base::Closure& closure) {
184 return base::Bind(
185 &DoExpectValueSetFlagAndRunClosure, expected_value, flag, closure);
186}
187
sammc70588902016-09-01 18:52:58 +0900188void Fail() {
189 FAIL() << "Unexpected connection error";
190}
191
yzshen37b7abd2015-11-25 01:43:17 +0900192TEST_F(AssociatedInterfaceTest, InterfacesAtBothEnds) {
193 // Bind to the same pipe two associated interfaces, whose implementation lives
194 // at different ends. Test that the two don't interfere with each other.
195
yzshen626de042016-09-14 02:03:53 +0900196 scoped_refptr<MultiplexRouter> router0;
197 scoped_refptr<MultiplexRouter> router1;
198 CreateRouterPair(&router0, &router1);
yzshen37b7abd2015-11-25 01:43:17 +0900199
200 AssociatedInterfaceRequest<IntegerSender> request;
yzshen9ce81092016-01-20 09:42:42 +0900201 IntegerSenderAssociatedPtrInfo ptr_info;
yzshen626de042016-09-14 02:03:53 +0900202 CreateIntegerSenderWithExistingRouters(router1, &ptr_info, router0, &request);
yzshen37b7abd2015-11-25 01:43:17 +0900203
dchengcb035232015-12-26 13:46:36 +0900204 IntegerSenderImpl impl0(std::move(request));
yzshen37b7abd2015-11-25 01:43:17 +0900205 AssociatedInterfacePtr<IntegerSender> ptr0;
dchengcb035232015-12-26 13:46:36 +0900206 ptr0.Bind(std::move(ptr_info));
yzshen37b7abd2015-11-25 01:43:17 +0900207
yzshen626de042016-09-14 02:03:53 +0900208 CreateIntegerSenderWithExistingRouters(router0, &ptr_info, router1, &request);
yzshen37b7abd2015-11-25 01:43:17 +0900209
dchengcb035232015-12-26 13:46:36 +0900210 IntegerSenderImpl impl1(std::move(request));
yzshen37b7abd2015-11-25 01:43:17 +0900211 AssociatedInterfacePtr<IntegerSender> ptr1;
dchengcb035232015-12-26 13:46:36 +0900212 ptr1.Bind(std::move(ptr_info));
yzshen37b7abd2015-11-25 01:43:17 +0900213
jamc0e79fc2016-01-05 09:06:02 +0900214 base::RunLoop run_loop, run_loop2;
yzshen37b7abd2015-11-25 01:43:17 +0900215 bool ptr0_callback_run = false;
rockot453673f2016-06-19 05:15:51 +0900216 ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
217 run_loop.QuitClosure()));
yzshen37b7abd2015-11-25 01:43:17 +0900218
219 bool ptr1_callback_run = false;
rockot453673f2016-06-19 05:15:51 +0900220 ptr1->Echo(456, ExpectValueSetFlagAndRunClosure(456, &ptr1_callback_run,
221 run_loop2.QuitClosure()));
yzshen37b7abd2015-11-25 01:43:17 +0900222
jamc0e79fc2016-01-05 09:06:02 +0900223 run_loop.Run();
224 run_loop2.Run();
yzshen37b7abd2015-11-25 01:43:17 +0900225 EXPECT_TRUE(ptr0_callback_run);
226 EXPECT_TRUE(ptr1_callback_run);
227
228 bool ptr0_error_callback_run = false;
jamc0e79fc2016-01-05 09:06:02 +0900229 base::RunLoop run_loop3;
rockot453673f2016-06-19 05:15:51 +0900230 ptr0.set_connection_error_handler(
231 SetFlagAndRunClosure(&ptr0_error_callback_run, run_loop3.QuitClosure()));
yzshen37b7abd2015-11-25 01:43:17 +0900232
233 impl0.binding()->Close();
jamc0e79fc2016-01-05 09:06:02 +0900234 run_loop3.Run();
yzshen37b7abd2015-11-25 01:43:17 +0900235 EXPECT_TRUE(ptr0_error_callback_run);
236
237 bool impl1_error_callback_run = false;
jamc0e79fc2016-01-05 09:06:02 +0900238 base::RunLoop run_loop4;
yzshen37b7abd2015-11-25 01:43:17 +0900239 impl1.binding()->set_connection_error_handler(
rockot453673f2016-06-19 05:15:51 +0900240 SetFlagAndRunClosure(&impl1_error_callback_run, run_loop4.QuitClosure()));
yzshen37b7abd2015-11-25 01:43:17 +0900241
242 ptr1.reset();
jamc0e79fc2016-01-05 09:06:02 +0900243 run_loop4.Run();
yzshen37b7abd2015-11-25 01:43:17 +0900244 EXPECT_TRUE(impl1_error_callback_run);
245}
246
247class TestSender {
248 public:
249 TestSender()
Sam McNally7854eed2017-06-20 08:34:45 +0900250 : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
yzshen37b7abd2015-11-25 01:43:17 +0900251 next_sender_(nullptr),
Sam McNally7854eed2017-06-20 08:34:45 +0900252 max_value_to_send_(-1) {}
yzshen37b7abd2015-11-25 01:43:17 +0900253
254 // The following three methods are called on the corresponding sender thread.
yzshen9ce81092016-01-20 09:42:42 +0900255 void SetUp(IntegerSenderAssociatedPtrInfo ptr_info,
yzshen37b7abd2015-11-25 01:43:17 +0900256 TestSender* next_sender,
257 int32_t max_value_to_send) {
peary2e3be2352017-06-29 11:15:28 +0900258 CHECK(task_runner()->RunsTasksInCurrentSequence());
yzshen37b7abd2015-11-25 01:43:17 +0900259
dchengcb035232015-12-26 13:46:36 +0900260 ptr_.Bind(std::move(ptr_info));
yzshen37b7abd2015-11-25 01:43:17 +0900261 next_sender_ = next_sender ? next_sender : this;
262 max_value_to_send_ = max_value_to_send;
263 }
264
265 void Send(int32_t value) {
peary2e3be2352017-06-29 11:15:28 +0900266 CHECK(task_runner()->RunsTasksInCurrentSequence());
yzshen37b7abd2015-11-25 01:43:17 +0900267
268 if (value > max_value_to_send_)
269 return;
270
271 ptr_->Send(value);
272
Sam McNally7854eed2017-06-20 08:34:45 +0900273 next_sender_->task_runner()->PostTask(
yzshen37b7abd2015-11-25 01:43:17 +0900274 FROM_HERE,
275 base::Bind(&TestSender::Send, base::Unretained(next_sender_), ++value));
276 }
277
278 void TearDown() {
peary2e3be2352017-06-29 11:15:28 +0900279 CHECK(task_runner()->RunsTasksInCurrentSequence());
yzshen37b7abd2015-11-25 01:43:17 +0900280
281 ptr_.reset();
282 }
283
Sam McNally7854eed2017-06-20 08:34:45 +0900284 base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
yzshen37b7abd2015-11-25 01:43:17 +0900285
286 private:
Sam McNally7854eed2017-06-20 08:34:45 +0900287 scoped_refptr<base::SequencedTaskRunner> task_runner_;
yzshen37b7abd2015-11-25 01:43:17 +0900288 TestSender* next_sender_;
289 int32_t max_value_to_send_;
290
291 AssociatedInterfacePtr<IntegerSender> ptr_;
292};
293
294class TestReceiver {
295 public:
Sam McNally7854eed2017-06-20 08:34:45 +0900296 TestReceiver()
297 : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
298 expected_calls_(0) {}
yzshen37b7abd2015-11-25 01:43:17 +0900299
300 void SetUp(AssociatedInterfaceRequest<IntegerSender> request0,
301 AssociatedInterfaceRequest<IntegerSender> request1,
yzshen645103a2016-06-01 04:01:04 +0900302 size_t expected_calls,
yzshen37b7abd2015-11-25 01:43:17 +0900303 const base::Closure& notify_finish) {
peary2e3be2352017-06-29 11:15:28 +0900304 CHECK(task_runner()->RunsTasksInCurrentSequence());
yzshen37b7abd2015-11-25 01:43:17 +0900305
dchengcb035232015-12-26 13:46:36 +0900306 impl0_.reset(new IntegerSenderImpl(std::move(request0)));
yzshen37b7abd2015-11-25 01:43:17 +0900307 impl0_->set_notify_send_method_called(
308 base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this)));
dchengcb035232015-12-26 13:46:36 +0900309 impl1_.reset(new IntegerSenderImpl(std::move(request1)));
yzshen37b7abd2015-11-25 01:43:17 +0900310 impl1_->set_notify_send_method_called(
311 base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this)));
312
yzshen645103a2016-06-01 04:01:04 +0900313 expected_calls_ = expected_calls;
yzshen37b7abd2015-11-25 01:43:17 +0900314 notify_finish_ = notify_finish;
315 }
316
317 void TearDown() {
peary2e3be2352017-06-29 11:15:28 +0900318 CHECK(task_runner()->RunsTasksInCurrentSequence());
yzshen37b7abd2015-11-25 01:43:17 +0900319
320 impl0_.reset();
321 impl1_.reset();
322 }
323
Sam McNally7854eed2017-06-20 08:34:45 +0900324 base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
yzshen37b7abd2015-11-25 01:43:17 +0900325 const std::vector<int32_t>& values() const { return values_; }
326
327 private:
328 void SendMethodCalled(int32_t value) {
329 values_.push_back(value);
330
yzshen645103a2016-06-01 04:01:04 +0900331 if (values_.size() >= expected_calls_)
yzshen37b7abd2015-11-25 01:43:17 +0900332 notify_finish_.Run();
333 }
334
Sam McNally7854eed2017-06-20 08:34:45 +0900335 scoped_refptr<base::SequencedTaskRunner> task_runner_;
yzshen645103a2016-06-01 04:01:04 +0900336 size_t expected_calls_;
yzshen37b7abd2015-11-25 01:43:17 +0900337
dcheng551f9e52016-04-22 09:57:38 +0900338 std::unique_ptr<IntegerSenderImpl> impl0_;
339 std::unique_ptr<IntegerSenderImpl> impl1_;
yzshen37b7abd2015-11-25 01:43:17 +0900340
341 std::vector<int32_t> values_;
342
343 base::Closure notify_finish_;
344};
345
yzshenf9cc80a2015-12-09 06:48:32 +0900346class NotificationCounter {
347 public:
348 NotificationCounter(size_t total_count, const base::Closure& notify_finish)
349 : total_count_(total_count),
350 current_count_(0),
351 notify_finish_(notify_finish) {}
dtrainora2e37bb2015-12-08 10:09:57 +0900352
yzshenf9cc80a2015-12-09 06:48:32 +0900353 ~NotificationCounter() {}
354
355 // Okay to call from any thread.
356 void OnGotNotification() {
357 bool finshed = false;
358 {
359 base::AutoLock locker(lock_);
360 CHECK_LT(current_count_, total_count_);
361 current_count_++;
362 finshed = current_count_ == total_count_;
363 }
364
365 if (finshed)
366 notify_finish_.Run();
367 }
368
369 private:
370 base::Lock lock_;
371 const size_t total_count_;
372 size_t current_count_;
373 base::Closure notify_finish_;
374};
375
yzshen645103a2016-06-01 04:01:04 +0900376TEST_F(AssociatedInterfaceTest, MultiThreadAccess) {
yzshen37b7abd2015-11-25 01:43:17 +0900377 // Set up four associated interfaces on a message pipe. Use the inteface
378 // pointers on four threads in parallel; run the interface implementations on
379 // two threads. Test that multi-threaded access works.
380
381 const int32_t kMaxValue = 1000;
382 MessagePipe pipe;
yzshen626de042016-09-14 02:03:53 +0900383 scoped_refptr<MultiplexRouter> router0;
384 scoped_refptr<MultiplexRouter> router1;
385 CreateRouterPair(&router0, &router1);
yzshen37b7abd2015-11-25 01:43:17 +0900386
387 AssociatedInterfaceRequest<IntegerSender> requests[4];
yzshen9ce81092016-01-20 09:42:42 +0900388 IntegerSenderAssociatedPtrInfo ptr_infos[4];
yzshen37b7abd2015-11-25 01:43:17 +0900389 for (size_t i = 0; i < 4; ++i) {
yzshen626de042016-09-14 02:03:53 +0900390 CreateIntegerSenderWithExistingRouters(router1, &ptr_infos[i], router0,
391 &requests[i]);
yzshen37b7abd2015-11-25 01:43:17 +0900392 }
393
394 TestSender senders[4];
395 for (size_t i = 0; i < 4; ++i) {
Sam McNally7854eed2017-06-20 08:34:45 +0900396 senders[i].task_runner()->PostTask(
yzshen37b7abd2015-11-25 01:43:17 +0900397 FROM_HERE, base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
398 base::Passed(&ptr_infos[i]), nullptr,
yzshen645103a2016-06-01 04:01:04 +0900399 kMaxValue * (i + 1) / 4));
yzshen37b7abd2015-11-25 01:43:17 +0900400 }
401
402 base::RunLoop run_loop;
403 TestReceiver receivers[2];
yzshenf9cc80a2015-12-09 06:48:32 +0900404 NotificationCounter counter(
405 2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
406 base::Unretained(this), base::Unretained(&run_loop)));
yzshen37b7abd2015-11-25 01:43:17 +0900407 for (size_t i = 0; i < 2; ++i) {
Sam McNally7854eed2017-06-20 08:34:45 +0900408 receivers[i].task_runner()->PostTask(
yzshen37b7abd2015-11-25 01:43:17 +0900409 FROM_HERE,
yzshenf9cc80a2015-12-09 06:48:32 +0900410 base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
411 base::Passed(&requests[2 * i]),
412 base::Passed(&requests[2 * i + 1]),
yzshen645103a2016-06-01 04:01:04 +0900413 static_cast<size_t>(kMaxValue / 2),
yzshenf9cc80a2015-12-09 06:48:32 +0900414 base::Bind(&NotificationCounter::OnGotNotification,
415 base::Unretained(&counter))));
yzshen37b7abd2015-11-25 01:43:17 +0900416 }
417
418 for (size_t i = 0; i < 4; ++i) {
Sam McNally7854eed2017-06-20 08:34:45 +0900419 senders[i].task_runner()->PostTask(
yzshen37b7abd2015-11-25 01:43:17 +0900420 FROM_HERE, base::Bind(&TestSender::Send, base::Unretained(&senders[i]),
yzshen645103a2016-06-01 04:01:04 +0900421 kMaxValue * i / 4 + 1));
yzshen37b7abd2015-11-25 01:43:17 +0900422 }
423
424 run_loop.Run();
425
426 for (size_t i = 0; i < 4; ++i) {
427 base::RunLoop run_loop;
Sam McNally7854eed2017-06-20 08:34:45 +0900428 senders[i].task_runner()->PostTaskAndReply(
yzshen37b7abd2015-11-25 01:43:17 +0900429 FROM_HERE,
430 base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
431 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
432 base::Unretained(this), base::Unretained(&run_loop)));
433 run_loop.Run();
434 }
435
436 for (size_t i = 0; i < 2; ++i) {
437 base::RunLoop run_loop;
Sam McNally7854eed2017-06-20 08:34:45 +0900438 receivers[i].task_runner()->PostTaskAndReply(
yzshen37b7abd2015-11-25 01:43:17 +0900439 FROM_HERE,
440 base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
441 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
442 base::Unretained(this), base::Unretained(&run_loop)));
443 run_loop.Run();
444 }
445
446 EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size());
447 EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size());
448
449 std::vector<int32_t> all_values;
450 all_values.insert(all_values.end(), receivers[0].values().begin(),
451 receivers[0].values().end());
452 all_values.insert(all_values.end(), receivers[1].values().begin(),
453 receivers[1].values().end());
454
455 std::sort(all_values.begin(), all_values.end());
456 for (size_t i = 0; i < all_values.size(); ++i)
457 ASSERT_EQ(static_cast<int32_t>(i + 1), all_values[i]);
458}
459
460TEST_F(AssociatedInterfaceTest, FIFO) {
461 // Set up four associated interfaces on a message pipe. Use the inteface
462 // pointers on four threads; run the interface implementations on two threads.
463 // Take turns to make calls using the four pointers. Test that FIFO-ness is
464 // preserved.
465
466 const int32_t kMaxValue = 100;
467 MessagePipe pipe;
yzshen626de042016-09-14 02:03:53 +0900468 scoped_refptr<MultiplexRouter> router0;
469 scoped_refptr<MultiplexRouter> router1;
470 CreateRouterPair(&router0, &router1);
yzshen37b7abd2015-11-25 01:43:17 +0900471
472 AssociatedInterfaceRequest<IntegerSender> requests[4];
yzshen9ce81092016-01-20 09:42:42 +0900473 IntegerSenderAssociatedPtrInfo ptr_infos[4];
yzshen37b7abd2015-11-25 01:43:17 +0900474 for (size_t i = 0; i < 4; ++i) {
yzshen626de042016-09-14 02:03:53 +0900475 CreateIntegerSenderWithExistingRouters(router1, &ptr_infos[i], router0,
476 &requests[i]);
yzshen37b7abd2015-11-25 01:43:17 +0900477 }
478
479 TestSender senders[4];
480 for (size_t i = 0; i < 4; ++i) {
Sam McNally7854eed2017-06-20 08:34:45 +0900481 senders[i].task_runner()->PostTask(
yzshen37b7abd2015-11-25 01:43:17 +0900482 FROM_HERE,
483 base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
484 base::Passed(&ptr_infos[i]),
485 base::Unretained(&senders[(i + 1) % 4]), kMaxValue));
486 }
487
488 base::RunLoop run_loop;
489 TestReceiver receivers[2];
yzshen645103a2016-06-01 04:01:04 +0900490 NotificationCounter counter(
491 2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
492 base::Unretained(this), base::Unretained(&run_loop)));
yzshen37b7abd2015-11-25 01:43:17 +0900493 for (size_t i = 0; i < 2; ++i) {
Sam McNally7854eed2017-06-20 08:34:45 +0900494 receivers[i].task_runner()->PostTask(
yzshen37b7abd2015-11-25 01:43:17 +0900495 FROM_HERE,
yzshen645103a2016-06-01 04:01:04 +0900496 base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
497 base::Passed(&requests[2 * i]),
498 base::Passed(&requests[2 * i + 1]),
499 static_cast<size_t>(kMaxValue / 2),
500 base::Bind(&NotificationCounter::OnGotNotification,
501 base::Unretained(&counter))));
yzshen37b7abd2015-11-25 01:43:17 +0900502 }
503
Sam McNally7854eed2017-06-20 08:34:45 +0900504 senders[0].task_runner()->PostTask(
yzshen37b7abd2015-11-25 01:43:17 +0900505 FROM_HERE,
506 base::Bind(&TestSender::Send, base::Unretained(&senders[0]), 1));
507
508 run_loop.Run();
509
510 for (size_t i = 0; i < 4; ++i) {
511 base::RunLoop run_loop;
Sam McNally7854eed2017-06-20 08:34:45 +0900512 senders[i].task_runner()->PostTaskAndReply(
yzshen37b7abd2015-11-25 01:43:17 +0900513 FROM_HERE,
514 base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
515 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
516 base::Unretained(this), base::Unretained(&run_loop)));
517 run_loop.Run();
518 }
519
520 for (size_t i = 0; i < 2; ++i) {
521 base::RunLoop run_loop;
Sam McNally7854eed2017-06-20 08:34:45 +0900522 receivers[i].task_runner()->PostTaskAndReply(
yzshen37b7abd2015-11-25 01:43:17 +0900523 FROM_HERE,
524 base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
525 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
526 base::Unretained(this), base::Unretained(&run_loop)));
527 run_loop.Run();
528 }
529
530 EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size());
531 EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size());
532
533 for (size_t i = 0; i < 2; ++i) {
534 for (size_t j = 1; j < receivers[i].values().size(); ++j)
535 EXPECT_LT(receivers[i].values()[j - 1], receivers[i].values()[j]);
536 }
537}
538
rockot453673f2016-06-19 05:15:51 +0900539void CaptureInt32(int32_t* storage,
540 const base::Closure& closure,
541 int32_t value) {
542 *storage = value;
543 closure.Run();
544}
545
546void CaptureSenderPtrInfo(IntegerSenderAssociatedPtr* storage,
547 const base::Closure& closure,
548 IntegerSenderAssociatedPtrInfo info) {
549 storage->Bind(std::move(info));
550 closure.Run();
551}
552
yzshen50269ab2015-11-26 09:31:56 +0900553TEST_F(AssociatedInterfaceTest, PassAssociatedInterfaces) {
554 IntegerSenderConnectionPtr connection_ptr;
blundell984c9e42016-12-20 20:23:32 +0900555 IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));
yzshen50269ab2015-11-26 09:31:56 +0900556
yzshen8b050fa2015-12-01 07:44:14 +0900557 IntegerSenderAssociatedPtr sender0;
yzshene968d282017-02-16 08:22:41 +0900558 connection_ptr->GetSender(MakeRequest(&sender0));
yzshen50269ab2015-11-26 09:31:56 +0900559
560 int32_t echoed_value = 0;
jamc0e79fc2016-01-05 09:06:02 +0900561 base::RunLoop run_loop;
rockot453673f2016-06-19 05:15:51 +0900562 sender0->Echo(123, base::Bind(&CaptureInt32, &echoed_value,
563 run_loop.QuitClosure()));
jamc0e79fc2016-01-05 09:06:02 +0900564 run_loop.Run();
yzshen50269ab2015-11-26 09:31:56 +0900565 EXPECT_EQ(123, echoed_value);
566
yzshen8b050fa2015-12-01 07:44:14 +0900567 IntegerSenderAssociatedPtr sender1;
jamc0e79fc2016-01-05 09:06:02 +0900568 base::RunLoop run_loop2;
yzshen50269ab2015-11-26 09:31:56 +0900569 connection_ptr->AsyncGetSender(
rockot453673f2016-06-19 05:15:51 +0900570 base::Bind(&CaptureSenderPtrInfo, &sender1, run_loop2.QuitClosure()));
jamc0e79fc2016-01-05 09:06:02 +0900571 run_loop2.Run();
yzshen50269ab2015-11-26 09:31:56 +0900572 EXPECT_TRUE(sender1);
573
jamc0e79fc2016-01-05 09:06:02 +0900574 base::RunLoop run_loop3;
rockot453673f2016-06-19 05:15:51 +0900575 sender1->Echo(456, base::Bind(&CaptureInt32, &echoed_value,
576 run_loop3.QuitClosure()));
jamc0e79fc2016-01-05 09:06:02 +0900577 run_loop3.Run();
yzshen50269ab2015-11-26 09:31:56 +0900578 EXPECT_EQ(456, echoed_value);
579}
580
yzshen09b12282015-12-11 10:37:50 +0900581TEST_F(AssociatedInterfaceTest, BindingWaitAndPauseWhenNoAssociatedInterfaces) {
582 IntegerSenderConnectionPtr connection_ptr;
blundell984c9e42016-12-20 20:23:32 +0900583 IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));
yzshen09b12282015-12-11 10:37:50 +0900584
585 IntegerSenderAssociatedPtr sender0;
yzshene968d282017-02-16 08:22:41 +0900586 connection_ptr->GetSender(MakeRequest(&sender0));
yzshen09b12282015-12-11 10:37:50 +0900587
588 EXPECT_FALSE(connection.binding()->HasAssociatedInterfaces());
589 // There are no associated interfaces running on the pipe yet. It is okay to
590 // pause.
591 connection.binding()->PauseIncomingMethodCallProcessing();
592 connection.binding()->ResumeIncomingMethodCallProcessing();
593
594 // There are no associated interfaces running on the pipe yet. It is okay to
595 // wait.
596 EXPECT_TRUE(connection.binding()->WaitForIncomingMethodCall());
597
598 // The previous wait has dispatched the GetSender request message, therefore
599 // an associated interface has been set up on the pipe. It is not allowed to
600 // wait or pause.
601 EXPECT_TRUE(connection.binding()->HasAssociatedInterfaces());
602}
603
rockotcffd1b22016-08-25 08:37:11 +0900604class PingServiceImpl : public PingService {
605 public:
606 explicit PingServiceImpl(PingServiceAssociatedRequest request)
607 : binding_(this, std::move(request)) {}
608 ~PingServiceImpl() override {}
609
610 AssociatedBinding<PingService>& binding() { return binding_; }
611
612 void set_ping_handler(const base::Closure& handler) {
613 ping_handler_ = handler;
614 }
615
616 // PingService:
617 void Ping(const PingCallback& callback) override {
618 if (!ping_handler_.is_null())
619 ping_handler_.Run();
620 callback.Run();
621 }
622
623 private:
624 AssociatedBinding<PingService> binding_;
625 base::Closure ping_handler_;
626};
627
628class PingProviderImpl : public AssociatedPingProvider {
629 public:
630 explicit PingProviderImpl(AssociatedPingProviderRequest request)
631 : binding_(this, std::move(request)) {}
632 ~PingProviderImpl() override {}
633
634 // AssociatedPingProvider:
635 void GetPing(PingServiceAssociatedRequest request) override {
636 ping_services_.emplace_back(new PingServiceImpl(std::move(request)));
637
638 if (expected_bindings_count_ > 0 &&
639 ping_services_.size() == expected_bindings_count_ &&
640 !quit_waiting_.is_null()) {
641 expected_bindings_count_ = 0;
642 base::ResetAndReturn(&quit_waiting_).Run();
643 }
644 }
645
646 std::vector<std::unique_ptr<PingServiceImpl>>& ping_services() {
647 return ping_services_;
648 }
649
650 void WaitForBindings(size_t count) {
651 DCHECK(quit_waiting_.is_null());
652
653 expected_bindings_count_ = count;
654 base::RunLoop loop;
655 quit_waiting_ = loop.QuitClosure();
656 loop.Run();
657 }
658
659 private:
660 Binding<AssociatedPingProvider> binding_;
661 std::vector<std::unique_ptr<PingServiceImpl>> ping_services_;
662 size_t expected_bindings_count_ = 0;
663 base::Closure quit_waiting_;
664};
665
666class CallbackFilter : public MessageReceiver {
667 public:
668 explicit CallbackFilter(const base::Closure& callback)
669 : callback_(callback) {}
670 ~CallbackFilter() override {}
671
672 static std::unique_ptr<CallbackFilter> Wrap(const base::Closure& callback) {
Jeremy Romanfa94a992017-08-25 02:06:37 +0900673 return std::make_unique<CallbackFilter>(callback);
rockotcffd1b22016-08-25 08:37:11 +0900674 }
675
676 // MessageReceiver:
677 bool Accept(Message* message) override {
678 callback_.Run();
679 return true;
680 }
681
682 private:
683 const base::Closure callback_;
684};
685
686// Verifies that filters work as expected on associated bindings, i.e. that
687// they're notified in order, before dispatch; and that each associated
688// binding in a group operates with its own set of filters.
689TEST_F(AssociatedInterfaceTest, BindingWithFilters) {
690 AssociatedPingProviderPtr provider;
blundell984c9e42016-12-20 20:23:32 +0900691 PingProviderImpl provider_impl(MakeRequest(&provider));
rockotcffd1b22016-08-25 08:37:11 +0900692
693 PingServiceAssociatedPtr ping_a, ping_b;
yzshene968d282017-02-16 08:22:41 +0900694 provider->GetPing(MakeRequest(&ping_a));
695 provider->GetPing(MakeRequest(&ping_b));
rockotcffd1b22016-08-25 08:37:11 +0900696 provider_impl.WaitForBindings(2);
697
698 ASSERT_EQ(2u, provider_impl.ping_services().size());
699 PingServiceImpl& ping_a_impl = *provider_impl.ping_services()[0];
700 PingServiceImpl& ping_b_impl = *provider_impl.ping_services()[1];
701
702 int a_status, b_status;
703 auto handler_helper = [] (int* a_status, int* b_status, int expected_a_status,
704 int new_a_status, int expected_b_status,
705 int new_b_status) {
706 EXPECT_EQ(expected_a_status, *a_status);
707 EXPECT_EQ(expected_b_status, *b_status);
708 *a_status = new_a_status;
709 *b_status = new_b_status;
710 };
711 auto create_handler = [&] (int expected_a_status, int new_a_status,
712 int expected_b_status, int new_b_status) {
713 return base::Bind(handler_helper, &a_status, &b_status, expected_a_status,
714 new_a_status, expected_b_status, new_b_status);
715 };
716
717 ping_a_impl.binding().AddFilter(
718 CallbackFilter::Wrap(create_handler(0, 1, 0, 0)));
719 ping_a_impl.binding().AddFilter(
720 CallbackFilter::Wrap(create_handler(1, 2, 0, 0)));
721 ping_a_impl.set_ping_handler(create_handler(2, 3, 0, 0));
722
723 ping_b_impl.binding().AddFilter(
724 CallbackFilter::Wrap(create_handler(3, 3, 0, 1)));
725 ping_b_impl.binding().AddFilter(
726 CallbackFilter::Wrap(create_handler(3, 3, 1, 2)));
727 ping_b_impl.set_ping_handler(create_handler(3, 3, 2, 3));
728
729 for (int i = 0; i < 10; ++i) {
730 a_status = 0;
731 b_status = 0;
732
733 {
734 base::RunLoop loop;
735 ping_a->Ping(loop.QuitClosure());
736 loop.Run();
737 }
738
739 EXPECT_EQ(3, a_status);
740 EXPECT_EQ(0, b_status);
741
742 {
743 base::RunLoop loop;
744 ping_b->Ping(loop.QuitClosure());
745 loop.Run();
746 }
747
748 EXPECT_EQ(3, a_status);
749 EXPECT_EQ(3, b_status);
750 }
751}
752
sammc70588902016-09-01 18:52:58 +0900753TEST_F(AssociatedInterfaceTest, AssociatedPtrFlushForTesting) {
sammc70588902016-09-01 18:52:58 +0900754 AssociatedInterfaceRequest<IntegerSender> request;
755 IntegerSenderAssociatedPtrInfo ptr_info;
yzshen626de042016-09-14 02:03:53 +0900756 CreateIntegerSender(&ptr_info, &request);
sammc70588902016-09-01 18:52:58 +0900757
758 IntegerSenderImpl impl0(std::move(request));
759 AssociatedInterfacePtr<IntegerSender> ptr0;
760 ptr0.Bind(std::move(ptr_info));
761 ptr0.set_connection_error_handler(base::Bind(&Fail));
762
763 bool ptr0_callback_run = false;
Peter Kasting24efe5e2018-02-24 09:03:01 +0900764 ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
765 base::DoNothing()));
sammc70588902016-09-01 18:52:58 +0900766 ptr0.FlushForTesting();
767 EXPECT_TRUE(ptr0_callback_run);
768}
769
770void SetBool(bool* value) {
771 *value = true;
772}
773
774template <typename T>
775void SetBoolWithUnusedParameter(bool* value, T unused) {
776 *value = true;
777}
778
779TEST_F(AssociatedInterfaceTest, AssociatedPtrFlushForTestingWithClosedPeer) {
sammc70588902016-09-01 18:52:58 +0900780 AssociatedInterfaceRequest<IntegerSender> request;
781 IntegerSenderAssociatedPtrInfo ptr_info;
yzshen626de042016-09-14 02:03:53 +0900782 CreateIntegerSender(&ptr_info, &request);
sammc70588902016-09-01 18:52:58 +0900783
784 AssociatedInterfacePtr<IntegerSender> ptr0;
785 ptr0.Bind(std::move(ptr_info));
786 bool called = false;
787 ptr0.set_connection_error_handler(base::Bind(&SetBool, &called));
788 request = nullptr;
789
790 ptr0.FlushForTesting();
791 EXPECT_TRUE(called);
792 ptr0.FlushForTesting();
793}
794
795TEST_F(AssociatedInterfaceTest, AssociatedBindingFlushForTesting) {
sammc70588902016-09-01 18:52:58 +0900796 AssociatedInterfaceRequest<IntegerSender> request;
797 IntegerSenderAssociatedPtrInfo ptr_info;
yzshen626de042016-09-14 02:03:53 +0900798 CreateIntegerSender(&ptr_info, &request);
sammc70588902016-09-01 18:52:58 +0900799
800 IntegerSenderImpl impl0(std::move(request));
801 impl0.set_connection_error_handler(base::Bind(&Fail));
802 AssociatedInterfacePtr<IntegerSender> ptr0;
803 ptr0.Bind(std::move(ptr_info));
804
805 bool ptr0_callback_run = false;
Peter Kasting24efe5e2018-02-24 09:03:01 +0900806 ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
807 base::DoNothing()));
sammc70588902016-09-01 18:52:58 +0900808 // Because the flush is sent from the binding, it only guarantees that the
809 // request has been received, not the response. The second flush waits for the
810 // response to be received.
811 impl0.binding()->FlushForTesting();
812 impl0.binding()->FlushForTesting();
813 EXPECT_TRUE(ptr0_callback_run);
814}
815
816TEST_F(AssociatedInterfaceTest,
817 AssociatedBindingFlushForTestingWithClosedPeer) {
yzshen626de042016-09-14 02:03:53 +0900818 scoped_refptr<MultiplexRouter> router0;
819 scoped_refptr<MultiplexRouter> router1;
820 CreateRouterPair(&router0, &router1);
sammc70588902016-09-01 18:52:58 +0900821
822 AssociatedInterfaceRequest<IntegerSender> request;
823 {
824 IntegerSenderAssociatedPtrInfo ptr_info;
yzshen626de042016-09-14 02:03:53 +0900825 CreateIntegerSenderWithExistingRouters(router1, &ptr_info, router0,
826 &request);
sammc70588902016-09-01 18:52:58 +0900827 }
828
829 IntegerSenderImpl impl(std::move(request));
830 bool called = false;
831 impl.set_connection_error_handler(base::Bind(&SetBool, &called));
832 impl.binding()->FlushForTesting();
833 EXPECT_TRUE(called);
834 impl.binding()->FlushForTesting();
835}
836
837TEST_F(AssociatedInterfaceTest, BindingFlushForTesting) {
838 IntegerSenderConnectionPtr ptr;
blundell984c9e42016-12-20 20:23:32 +0900839 IntegerSenderConnectionImpl impl(MakeRequest(&ptr));
sammc70588902016-09-01 18:52:58 +0900840 bool called = false;
841 ptr->AsyncGetSender(base::Bind(
842 &SetBoolWithUnusedParameter<IntegerSenderAssociatedPtrInfo>, &called));
843 EXPECT_FALSE(called);
844 impl.binding()->set_connection_error_handler(base::Bind(&Fail));
845 // Because the flush is sent from the binding, it only guarantees that the
846 // request has been received, not the response. The second flush waits for the
847 // response to be received.
848 impl.binding()->FlushForTesting();
849 impl.binding()->FlushForTesting();
850 EXPECT_TRUE(called);
851}
852
853TEST_F(AssociatedInterfaceTest, BindingFlushForTestingWithClosedPeer) {
854 IntegerSenderConnectionPtr ptr;
blundell984c9e42016-12-20 20:23:32 +0900855 IntegerSenderConnectionImpl impl(MakeRequest(&ptr));
sammc70588902016-09-01 18:52:58 +0900856 bool called = false;
857 impl.binding()->set_connection_error_handler(base::Bind(&SetBool, &called));
858 ptr.reset();
859 EXPECT_FALSE(called);
860 impl.binding()->FlushForTesting();
861 EXPECT_TRUE(called);
862 impl.binding()->FlushForTesting();
863}
864
865TEST_F(AssociatedInterfaceTest, StrongBindingFlushForTesting) {
866 IntegerSenderConnectionPtr ptr;
rockot23ad5fc2016-09-13 09:48:21 +0900867 auto binding =
Jeremy Romanfa94a992017-08-25 02:06:37 +0900868 MakeStrongBinding(std::make_unique<IntegerSenderConnectionImpl>(
rockot23ad5fc2016-09-13 09:48:21 +0900869 IntegerSenderConnectionRequest{}),
blundell984c9e42016-12-20 20:23:32 +0900870 MakeRequest(&ptr));
sammc70588902016-09-01 18:52:58 +0900871 bool called = false;
872 IntegerSenderAssociatedPtr sender_ptr;
yzshene968d282017-02-16 08:22:41 +0900873 ptr->GetSender(MakeRequest(&sender_ptr));
sammc70588902016-09-01 18:52:58 +0900874 sender_ptr->Echo(1, base::Bind(&SetBoolWithUnusedParameter<int>, &called));
875 EXPECT_FALSE(called);
876 // Because the flush is sent from the binding, it only guarantees that the
877 // request has been received, not the response. The second flush waits for the
878 // response to be received.
rockot23ad5fc2016-09-13 09:48:21 +0900879 ASSERT_TRUE(binding);
880 binding->FlushForTesting();
881 ASSERT_TRUE(binding);
882 binding->FlushForTesting();
sammc70588902016-09-01 18:52:58 +0900883 EXPECT_TRUE(called);
884}
885
886TEST_F(AssociatedInterfaceTest, StrongBindingFlushForTestingWithClosedPeer) {
887 IntegerSenderConnectionPtr ptr;
sammc70588902016-09-01 18:52:58 +0900888 bool called = false;
rockot23ad5fc2016-09-13 09:48:21 +0900889 auto binding =
Jeremy Romanfa94a992017-08-25 02:06:37 +0900890 MakeStrongBinding(std::make_unique<IntegerSenderConnectionImpl>(
rockot23ad5fc2016-09-13 09:48:21 +0900891 IntegerSenderConnectionRequest{}),
blundell984c9e42016-12-20 20:23:32 +0900892 MakeRequest(&ptr));
rockot23ad5fc2016-09-13 09:48:21 +0900893 binding->set_connection_error_handler(base::Bind(&SetBool, &called));
sammc70588902016-09-01 18:52:58 +0900894 ptr.reset();
895 EXPECT_FALSE(called);
rockot23ad5fc2016-09-13 09:48:21 +0900896 ASSERT_TRUE(binding);
897 binding->FlushForTesting();
sammc70588902016-09-01 18:52:58 +0900898 EXPECT_TRUE(called);
rockot23ad5fc2016-09-13 09:48:21 +0900899 ASSERT_FALSE(binding);
sammc70588902016-09-01 18:52:58 +0900900}
901
902TEST_F(AssociatedInterfaceTest, PtrFlushForTesting) {
903 IntegerSenderConnectionPtr ptr;
blundell984c9e42016-12-20 20:23:32 +0900904 IntegerSenderConnectionImpl impl(MakeRequest(&ptr));
sammc70588902016-09-01 18:52:58 +0900905 bool called = false;
906 ptr.set_connection_error_handler(base::Bind(&Fail));
907 ptr->AsyncGetSender(base::Bind(
908 &SetBoolWithUnusedParameter<IntegerSenderAssociatedPtrInfo>, &called));
909 EXPECT_FALSE(called);
910 ptr.FlushForTesting();
911 EXPECT_TRUE(called);
912}
913
914TEST_F(AssociatedInterfaceTest, PtrFlushForTestingWithClosedPeer) {
915 IntegerSenderConnectionPtr ptr;
blundell984c9e42016-12-20 20:23:32 +0900916 MakeRequest(&ptr);
sammc70588902016-09-01 18:52:58 +0900917 bool called = false;
918 ptr.set_connection_error_handler(base::Bind(&SetBool, &called));
919 EXPECT_FALSE(called);
920 ptr.FlushForTesting();
921 EXPECT_TRUE(called);
922 ptr.FlushForTesting();
923}
924
yzshen626de042016-09-14 02:03:53 +0900925TEST_F(AssociatedInterfaceTest, AssociatedBindingConnectionErrorWithReason) {
926 AssociatedInterfaceRequest<IntegerSender> request;
927 IntegerSenderAssociatedPtrInfo ptr_info;
928 CreateIntegerSender(&ptr_info, &request);
929
930 IntegerSenderImpl impl(std::move(request));
931 AssociatedInterfacePtr<IntegerSender> ptr;
932 ptr.Bind(std::move(ptr_info));
933
934 base::RunLoop run_loop;
935 impl.binding()->set_connection_error_with_reason_handler(base::Bind(
936 [](const base::Closure& quit_closure, uint32_t custom_reason,
937 const std::string& description) {
938 EXPECT_EQ(123u, custom_reason);
939 EXPECT_EQ("farewell", description);
940 quit_closure.Run();
941 },
942 run_loop.QuitClosure()));
943
944 ptr.ResetWithReason(123u, "farewell");
945
946 run_loop.Run();
947}
948
yzshen8dc7bd72017-02-15 07:24:25 +0900949TEST_F(AssociatedInterfaceTest,
950 PendingAssociatedBindingConnectionErrorWithReason) {
951 // Test that AssociatedBinding is notified with connection error when the
952 // interface hasn't associated with a message pipe and the peer is closed.
953
yzshen8dc7bd72017-02-15 07:24:25 +0900954 IntegerSenderAssociatedPtr ptr;
yzshene968d282017-02-16 08:22:41 +0900955 IntegerSenderImpl impl(MakeRequest(&ptr));
yzshen8dc7bd72017-02-15 07:24:25 +0900956
957 base::RunLoop run_loop;
958 impl.binding()->set_connection_error_with_reason_handler(base::Bind(
959 [](const base::Closure& quit_closure, uint32_t custom_reason,
960 const std::string& description) {
961 EXPECT_EQ(123u, custom_reason);
962 EXPECT_EQ("farewell", description);
963 quit_closure.Run();
964 },
965 run_loop.QuitClosure()));
966
967 ptr.ResetWithReason(123u, "farewell");
968
969 run_loop.Run();
970}
971
yzshen626de042016-09-14 02:03:53 +0900972TEST_F(AssociatedInterfaceTest, AssociatedPtrConnectionErrorWithReason) {
973 AssociatedInterfaceRequest<IntegerSender> request;
974 IntegerSenderAssociatedPtrInfo ptr_info;
975 CreateIntegerSender(&ptr_info, &request);
976
977 IntegerSenderImpl impl(std::move(request));
978 AssociatedInterfacePtr<IntegerSender> ptr;
979 ptr.Bind(std::move(ptr_info));
980
981 base::RunLoop run_loop;
982 ptr.set_connection_error_with_reason_handler(base::Bind(
983 [](const base::Closure& quit_closure, uint32_t custom_reason,
984 const std::string& description) {
985 EXPECT_EQ(456u, custom_reason);
986 EXPECT_EQ("farewell", description);
987 quit_closure.Run();
988 },
989 run_loop.QuitClosure()));
990
991 impl.binding()->CloseWithReason(456u, "farewell");
992
993 run_loop.Run();
994}
995
yzshen8dc7bd72017-02-15 07:24:25 +0900996TEST_F(AssociatedInterfaceTest, PendingAssociatedPtrConnectionErrorWithReason) {
997 // Test that AssociatedInterfacePtr is notified with connection error when the
998 // interface hasn't associated with a message pipe and the peer is closed.
999
yzshen8dc7bd72017-02-15 07:24:25 +09001000 IntegerSenderAssociatedPtr ptr;
yzshene968d282017-02-16 08:22:41 +09001001 auto request = MakeRequest(&ptr);
yzshen8dc7bd72017-02-15 07:24:25 +09001002
1003 base::RunLoop run_loop;
1004 ptr.set_connection_error_with_reason_handler(base::Bind(
1005 [](const base::Closure& quit_closure, uint32_t custom_reason,
1006 const std::string& description) {
1007 EXPECT_EQ(456u, custom_reason);
1008 EXPECT_EQ("farewell", description);
1009 quit_closure.Run();
1010 },
1011 run_loop.QuitClosure()));
1012
1013 request.ResetWithReason(456u, "farewell");
1014
1015 run_loop.Run();
1016}
1017
yzshen7f476722016-09-14 06:50:07 +09001018TEST_F(AssociatedInterfaceTest, AssociatedRequestResetWithReason) {
1019 AssociatedInterfaceRequest<IntegerSender> request;
1020 IntegerSenderAssociatedPtrInfo ptr_info;
1021 CreateIntegerSender(&ptr_info, &request);
1022
1023 AssociatedInterfacePtr<IntegerSender> ptr;
1024 ptr.Bind(std::move(ptr_info));
1025
1026 base::RunLoop run_loop;
1027 ptr.set_connection_error_with_reason_handler(base::Bind(
1028 [](const base::Closure& quit_closure, uint32_t custom_reason,
1029 const std::string& description) {
1030 EXPECT_EQ(789u, custom_reason);
1031 EXPECT_EQ("long time no see", description);
1032 quit_closure.Run();
1033 },
1034 run_loop.QuitClosure()));
1035
1036 request.ResetWithReason(789u, "long time no see");
1037
1038 run_loop.Run();
1039}
1040
jcivelli9027ad72016-11-18 12:22:41 +09001041TEST_F(AssociatedInterfaceTest, ThreadSafeAssociatedInterfacePtr) {
1042 IntegerSenderConnectionPtr connection_ptr;
blundell984c9e42016-12-20 20:23:32 +09001043 IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));
jcivelli9027ad72016-11-18 12:22:41 +09001044
1045 IntegerSenderAssociatedPtr sender;
yzshene968d282017-02-16 08:22:41 +09001046 connection_ptr->GetSender(MakeRequest(&sender));
jcivelli9027ad72016-11-18 12:22:41 +09001047
1048 scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_sender =
1049 ThreadSafeIntegerSenderAssociatedPtr::Create(std::move(sender));
1050
1051 {
1052 // Test the thread safe pointer can be used from the interface ptr thread.
1053 int32_t echoed_value = 0;
1054 base::RunLoop run_loop;
1055 (*thread_safe_sender)
1056 ->Echo(123, base::Bind(&CaptureInt32, &echoed_value,
1057 run_loop.QuitClosure()));
1058 run_loop.Run();
1059 EXPECT_EQ(123, echoed_value);
1060 }
1061
1062 // Test the thread safe pointer can be used from another thread.
1063 base::RunLoop run_loop;
jcivelli9027ad72016-11-18 12:22:41 +09001064
1065 auto run_method = base::Bind(
1066 [](const scoped_refptr<base::TaskRunner>& main_task_runner,
1067 const base::Closure& quit_closure,
1068 const scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr>&
1069 thread_safe_sender) {
1070 auto done_callback = base::Bind(
1071 [](const scoped_refptr<base::TaskRunner>& main_task_runner,
1072 const base::Closure& quit_closure,
Scott Graham052687f2017-08-09 00:19:01 +09001073 scoped_refptr<base::SequencedTaskRunner> sender_sequence_runner,
1074 int32_t result) {
jcivelli9027ad72016-11-18 12:22:41 +09001075 EXPECT_EQ(123, result);
Scott Graham052687f2017-08-09 00:19:01 +09001076 // Validate the callback is invoked on the calling sequence.
1077 EXPECT_TRUE(sender_sequence_runner->RunsTasksInCurrentSequence());
jcivelli9027ad72016-11-18 12:22:41 +09001078 // Notify the run_loop to quit.
1079 main_task_runner->PostTask(FROM_HERE, quit_closure);
1080 });
Scott Graham052687f2017-08-09 00:19:01 +09001081 scoped_refptr<base::SequencedTaskRunner> current_sequence_runner =
1082 base::SequencedTaskRunnerHandle::Get();
jcivelli9027ad72016-11-18 12:22:41 +09001083 (*thread_safe_sender)
Scott Graham052687f2017-08-09 00:19:01 +09001084 ->Echo(123, base::Bind(done_callback, main_task_runner,
1085 quit_closure, current_sequence_runner));
jcivelli9027ad72016-11-18 12:22:41 +09001086 },
1087 base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(),
1088 thread_safe_sender);
Sam McNally7854eed2017-06-20 08:34:45 +09001089 base::CreateSequencedTaskRunnerWithTraits({})->PostTask(FROM_HERE,
1090 run_method);
jcivelli9027ad72016-11-18 12:22:41 +09001091
1092 // Block until the method callback is called on the background thread.
1093 run_loop.Run();
1094}
1095
jcivelli4e08bca2016-11-30 01:15:05 +09001096struct ForwarderTestContext {
1097 IntegerSenderConnectionPtr connection_ptr;
1098 std::unique_ptr<IntegerSenderConnectionImpl> interface_impl;
rockot7900d342017-02-09 17:40:15 +09001099 IntegerSenderAssociatedRequest sender_request;
jcivelli4e08bca2016-11-30 01:15:05 +09001100};
1101
rockot7900d342017-02-09 17:40:15 +09001102TEST_F(AssociatedInterfaceTest,
1103 ThreadSafeAssociatedInterfacePtrWithTaskRunner) {
Sam McNally7854eed2017-06-20 08:34:45 +09001104 const scoped_refptr<base::SequencedTaskRunner> other_thread_task_runner =
1105 base::CreateSequencedTaskRunnerWithTraits({});
jcivelli4e08bca2016-11-30 01:15:05 +09001106
rockot7900d342017-02-09 17:40:15 +09001107 ForwarderTestContext* context = new ForwarderTestContext();
1108 IntegerSenderAssociatedPtrInfo sender_info;
1109 base::WaitableEvent sender_info_bound_event(
jcivelli3907bec2017-01-07 03:23:01 +09001110 base::WaitableEvent::ResetPolicy::MANUAL,
1111 base::WaitableEvent::InitialState::NOT_SIGNALED);
rockot7900d342017-02-09 17:40:15 +09001112 auto setup = [](base::WaitableEvent* sender_info_bound_event,
1113 IntegerSenderAssociatedPtrInfo* sender_info,
1114 ForwarderTestContext* context) {
Jeremy Romanfa94a992017-08-25 02:06:37 +09001115 context->interface_impl = std::make_unique<IntegerSenderConnectionImpl>(
rockot7900d342017-02-09 17:40:15 +09001116 MakeRequest(&context->connection_ptr));
jcivelli3907bec2017-01-07 03:23:01 +09001117
yzshene968d282017-02-16 08:22:41 +09001118 auto sender_request = MakeRequest(sender_info);
rockot7900d342017-02-09 17:40:15 +09001119 context->connection_ptr->GetSender(std::move(sender_request));
1120
1121 // Unblock the main thread as soon as |sender_info| is set.
1122 sender_info_bound_event->Signal();
1123 };
1124 other_thread_task_runner->PostTask(
1125 FROM_HERE,
1126 base::Bind(setup, &sender_info_bound_event, &sender_info, context));
1127 sender_info_bound_event.Wait();
1128
1129 // Create a ThreadSafeAssociatedPtr that binds on the background thread and is
1130 // associated with |connection_ptr| there.
jcivelli3907bec2017-01-07 03:23:01 +09001131 scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_ptr =
rockot7900d342017-02-09 17:40:15 +09001132 ThreadSafeIntegerSenderAssociatedPtr::Create(std::move(sender_info),
1133 other_thread_task_runner);
jcivelli3907bec2017-01-07 03:23:01 +09001134
rockot7900d342017-02-09 17:40:15 +09001135 // Issue a call on the thread-safe ptr immediately. Note that this may happen
1136 // before the interface is bound on the background thread, and that must be
1137 // OK.
jcivelli4e08bca2016-11-30 01:15:05 +09001138 {
jcivelli4e08bca2016-11-30 01:15:05 +09001139 auto echo_callback =
1140 base::Bind([](const base::Closure& quit_closure, int32_t result) {
1141 EXPECT_EQ(123, result);
1142 quit_closure.Run();
1143 });
1144 base::RunLoop run_loop;
1145 (*thread_safe_ptr)
1146 ->Echo(123, base::Bind(echo_callback, run_loop.QuitClosure()));
jcivelli3907bec2017-01-07 03:23:01 +09001147
jcivelli4e08bca2016-11-30 01:15:05 +09001148 // Block until the method callback is called.
1149 run_loop.Run();
1150 }
1151
1152 other_thread_task_runner->DeleteSoon(FROM_HERE, context);
1153
1154 // Reset the pointer now so the InterfacePtr associated resources can be
1155 // deleted before the background thread's message loop is invalidated.
1156 thread_safe_ptr = nullptr;
1157}
1158
sammc92d4ac62017-02-04 10:33:38 +09001159class DiscardingAssociatedPingProviderProvider
1160 : public AssociatedPingProviderProvider {
1161 public:
1162 void GetPingProvider(
1163 AssociatedPingProviderAssociatedRequest request) override {}
1164};
1165
1166TEST_F(AssociatedInterfaceTest, CloseWithoutBindingAssociatedRequest) {
1167 DiscardingAssociatedPingProviderProvider ping_provider_provider;
1168 mojo::Binding<AssociatedPingProviderProvider> binding(
1169 &ping_provider_provider);
Ken Rockotc87a0fd2017-06-08 02:35:19 +09001170 AssociatedPingProviderProviderPtr provider_provider;
1171 binding.Bind(mojo::MakeRequest(&provider_provider));
sammc92d4ac62017-02-04 10:33:38 +09001172 AssociatedPingProviderAssociatedPtr provider;
yzshene968d282017-02-16 08:22:41 +09001173 provider_provider->GetPingProvider(mojo::MakeRequest(&provider));
sammc92d4ac62017-02-04 10:33:38 +09001174 PingServiceAssociatedPtr ping;
yzshene968d282017-02-16 08:22:41 +09001175 provider->GetPing(mojo::MakeRequest(&ping));
sammc92d4ac62017-02-04 10:33:38 +09001176 base::RunLoop run_loop;
1177 ping.set_connection_error_handler(run_loop.QuitClosure());
1178 run_loop.Run();
1179}
1180
Balazs Engedy4522c122017-11-04 09:50:21 +09001181TEST_F(AssociatedInterfaceTest, AssociateWithDisconnectedPipe) {
yzshen91dd4642017-03-25 17:27:17 +09001182 IntegerSenderAssociatedPtr sender;
Balazs Engedy4522c122017-11-04 09:50:21 +09001183 AssociateWithDisconnectedPipe(MakeRequest(&sender).PassHandle());
yzshen91dd4642017-03-25 17:27:17 +09001184 sender->Send(42);
1185}
1186
yzshen37b7abd2015-11-25 01:43:17 +09001187} // namespace
1188} // namespace test
1189} // namespace mojo