OLD | NEW |
| (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 // This is really a unit test for |MasterConnectionManager| and | |
6 // |SlaveConnectionManager| (since they need to be tested together). | |
7 | |
8 #include "third_party/mojo/src/mojo/edk/system/connection_manager.h" | |
9 | |
10 #include <stdint.h> | |
11 | |
12 #include <string> | |
13 | |
14 #include "base/message_loop/message_loop.h" | |
15 #include "base/run_loop.h" | |
16 #include "base/threading/thread_checker.h" | |
17 #include "mojo/public/cpp/system/macros.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 #include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h" | |
20 #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" | |
21 #include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" | |
22 #include "third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h" | |
23 #include "third_party/mojo/src/mojo/edk/system/master_connection_manager.h" | |
24 #include "third_party/mojo/src/mojo/edk/system/slave_connection_manager.h" | |
25 #include "third_party/mojo/src/mojo/edk/test/test_utils.h" | |
26 | |
27 namespace mojo { | |
28 namespace system { | |
29 namespace { | |
30 | |
31 bool ArePlatformHandlesConnected(const embedder::PlatformHandle& h1, | |
32 const embedder::PlatformHandle& h2) { | |
33 const uint32_t w1 = 0xdeadbeef; | |
34 size_t num_bytes = 0; | |
35 if (!mojo::test::BlockingWrite(h1, &w1, sizeof(w1), &num_bytes) || | |
36 num_bytes != sizeof(w1)) | |
37 return false; | |
38 uint32_t r = 0; | |
39 num_bytes = 0; | |
40 if (!mojo::test::BlockingRead(h2, &r, sizeof(r), &num_bytes) || | |
41 num_bytes != sizeof(r)) | |
42 return false; | |
43 if (r != w1) | |
44 return false; | |
45 | |
46 const uint32_t w2 = 0xfeedface; | |
47 num_bytes = 0; | |
48 if (!mojo::test::BlockingWrite(h1, &w2, sizeof(w2), &num_bytes) || | |
49 num_bytes != sizeof(w2)) | |
50 return false; | |
51 r = 0; | |
52 num_bytes = 0; | |
53 if (!mojo::test::BlockingRead(h2, &r, sizeof(r), &num_bytes) || | |
54 num_bytes != sizeof(r)) | |
55 return false; | |
56 if (r != w2) | |
57 return false; | |
58 | |
59 return true; | |
60 } | |
61 | |
62 bool IsValidSlaveProcessIdentifier(ProcessIdentifier process_identifier) { | |
63 return process_identifier != kInvalidProcessIdentifier && | |
64 process_identifier != kMasterProcessIdentifier; | |
65 } | |
66 | |
67 class TestSlaveInfo { | |
68 public: | |
69 explicit TestSlaveInfo(const std::string& name) : name_(name) {} | |
70 ~TestSlaveInfo() { CHECK(thread_checker_.CalledOnValidThread()); } | |
71 | |
72 const std::string& name() const { return name_; } | |
73 | |
74 private: | |
75 base::ThreadChecker thread_checker_; | |
76 std::string name_; | |
77 | |
78 MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlaveInfo); | |
79 }; | |
80 | |
81 // Connects the given |slave| (with the given |slave_process_delegate|) to the | |
82 // given master, creating and using a |TestSlaveInfo| with the given | |
83 // |slave_name|, and returns the process identifier for the slave. | |
84 ProcessIdentifier ConnectSlave( | |
85 MasterConnectionManager* master, | |
86 embedder::SlaveProcessDelegate* slave_process_delegate, | |
87 SlaveConnectionManager* slave, | |
88 const std::string& slave_name) { | |
89 embedder::PlatformChannelPair platform_channel_pair; | |
90 ProcessIdentifier slave_process_identifier = master->AddSlave( | |
91 new TestSlaveInfo(slave_name), platform_channel_pair.PassServerHandle()); | |
92 slave->Init(slave_process_delegate, platform_channel_pair.PassClientHandle()); | |
93 return slave_process_identifier; | |
94 } | |
95 | |
96 class MockMasterProcessDelegate : public embedder::MasterProcessDelegate { | |
97 public: | |
98 MockMasterProcessDelegate() | |
99 : current_run_loop_(), on_slave_disconnect_calls_(0) {} | |
100 ~MockMasterProcessDelegate() override {} | |
101 | |
102 void RunUntilNotified() { | |
103 CHECK(!current_run_loop_); | |
104 base::RunLoop run_loop; | |
105 current_run_loop_ = &run_loop; | |
106 run_loop.Run(); | |
107 current_run_loop_ = nullptr; | |
108 } | |
109 | |
110 unsigned on_slave_disconnect_calls() const { | |
111 return on_slave_disconnect_calls_; | |
112 } | |
113 const std::string& last_slave_disconnect_name() const { | |
114 return last_slave_disconnect_name_; | |
115 } | |
116 | |
117 // |embedder::MasterProcessDelegate| implementation: | |
118 void OnShutdownComplete() override { NOTREACHED(); } | |
119 | |
120 void OnSlaveDisconnect(embedder::SlaveInfo slave_info) override { | |
121 CHECK(thread_checker_.CalledOnValidThread()); | |
122 on_slave_disconnect_calls_++; | |
123 last_slave_disconnect_name_ = | |
124 static_cast<TestSlaveInfo*>(slave_info)->name(); | |
125 DVLOG(1) << "Disconnected from slave process " | |
126 << last_slave_disconnect_name_; | |
127 delete static_cast<TestSlaveInfo*>(slave_info); | |
128 | |
129 if (current_run_loop_) | |
130 current_run_loop_->Quit(); | |
131 } | |
132 | |
133 private: | |
134 base::ThreadChecker thread_checker_; | |
135 base::RunLoop* current_run_loop_; | |
136 | |
137 unsigned on_slave_disconnect_calls_; | |
138 std::string last_slave_disconnect_name_; | |
139 | |
140 MOJO_DISALLOW_COPY_AND_ASSIGN(MockMasterProcessDelegate); | |
141 }; | |
142 | |
143 class MockSlaveProcessDelegate : public embedder::SlaveProcessDelegate { | |
144 public: | |
145 MockSlaveProcessDelegate() | |
146 : current_run_loop_(), on_master_disconnect_calls_(0) {} | |
147 ~MockSlaveProcessDelegate() override {} | |
148 | |
149 void RunUntilNotified() { | |
150 CHECK(!current_run_loop_); | |
151 base::RunLoop run_loop; | |
152 current_run_loop_ = &run_loop; | |
153 run_loop.Run(); | |
154 current_run_loop_ = nullptr; | |
155 } | |
156 | |
157 unsigned on_master_disconnect_calls() const { | |
158 return on_master_disconnect_calls_; | |
159 } | |
160 | |
161 // |embedder::SlaveProcessDelegate| implementation: | |
162 void OnShutdownComplete() override { NOTREACHED(); } | |
163 | |
164 void OnMasterDisconnect() override { | |
165 CHECK(thread_checker_.CalledOnValidThread()); | |
166 on_master_disconnect_calls_++; | |
167 DVLOG(1) << "Disconnected from master process"; | |
168 | |
169 if (current_run_loop_) | |
170 current_run_loop_->Quit(); | |
171 } | |
172 | |
173 private: | |
174 base::ThreadChecker thread_checker_; | |
175 base::RunLoop* current_run_loop_; | |
176 | |
177 unsigned on_master_disconnect_calls_; | |
178 | |
179 MOJO_DISALLOW_COPY_AND_ASSIGN(MockSlaveProcessDelegate); | |
180 }; | |
181 | |
182 class ConnectionManagerTest : public testing::Test { | |
183 protected: | |
184 ConnectionManagerTest() {} | |
185 ~ConnectionManagerTest() override {} | |
186 | |
187 embedder::PlatformSupport* platform_support() { return &platform_support_; } | |
188 | |
189 base::MessageLoop& message_loop() { return message_loop_; } | |
190 MockMasterProcessDelegate& master_process_delegate() { | |
191 return master_process_delegate_; | |
192 } | |
193 | |
194 private: | |
195 embedder::SimplePlatformSupport platform_support_; | |
196 base::MessageLoop message_loop_; | |
197 MockMasterProcessDelegate master_process_delegate_; | |
198 | |
199 MOJO_DISALLOW_COPY_AND_ASSIGN(ConnectionManagerTest); | |
200 }; | |
201 | |
202 TEST_F(ConnectionManagerTest, BasicConnectSlaves) { | |
203 MasterConnectionManager master(platform_support()); | |
204 master.Init(&master_process_delegate()); | |
205 | |
206 MockSlaveProcessDelegate slave1_process_delegate; | |
207 SlaveConnectionManager slave1(platform_support()); | |
208 ProcessIdentifier slave1_id = | |
209 ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); | |
210 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); | |
211 | |
212 MockSlaveProcessDelegate slave2_process_delegate; | |
213 SlaveConnectionManager slave2(platform_support()); | |
214 ProcessIdentifier slave2_id = | |
215 ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); | |
216 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); | |
217 // TODO(vtl): If/when I add the ability to get one's own process identifier, | |
218 // there'll be more we can check. | |
219 EXPECT_NE(slave1_id, slave2_id); | |
220 | |
221 ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); | |
222 EXPECT_TRUE(slave1.AllowConnect(connection_id)); | |
223 EXPECT_TRUE(slave2.AllowConnect(connection_id)); | |
224 | |
225 ProcessIdentifier peer1 = kInvalidProcessIdentifier; | |
226 bool is_first = false; | |
227 embedder::ScopedPlatformHandle h1; | |
228 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
229 slave1.Connect(connection_id, &peer1, &is_first, &h1)); | |
230 EXPECT_EQ(slave2_id, peer1); | |
231 EXPECT_TRUE(is_first); | |
232 EXPECT_TRUE(h1.is_valid()); | |
233 ProcessIdentifier peer2 = kInvalidProcessIdentifier; | |
234 embedder::ScopedPlatformHandle h2; | |
235 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
236 slave2.Connect(connection_id, &peer2, &is_first, &h2)); | |
237 EXPECT_EQ(slave1_id, peer2); | |
238 EXPECT_FALSE(is_first); | |
239 EXPECT_TRUE(h2.is_valid()); | |
240 | |
241 EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get())); | |
242 | |
243 // The process manager shouldn't have gotten any notifications yet. (Spin the | |
244 // message loop to make sure none were enqueued.) | |
245 base::RunLoop().RunUntilIdle(); | |
246 EXPECT_EQ(0u, master_process_delegate().on_slave_disconnect_calls()); | |
247 | |
248 slave1.Shutdown(); | |
249 | |
250 // |OnSlaveDisconnect()| should be called once. | |
251 master_process_delegate().RunUntilNotified(); | |
252 EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls()); | |
253 EXPECT_EQ("slave1", master_process_delegate().last_slave_disconnect_name()); | |
254 | |
255 slave2.Shutdown(); | |
256 | |
257 // |OnSlaveDisconnect()| should be called again. | |
258 master_process_delegate().RunUntilNotified(); | |
259 EXPECT_EQ(2u, master_process_delegate().on_slave_disconnect_calls()); | |
260 EXPECT_EQ("slave2", master_process_delegate().last_slave_disconnect_name()); | |
261 | |
262 master.Shutdown(); | |
263 | |
264 // None of the above should result in |OnMasterDisconnect()| being called. | |
265 base::RunLoop().RunUntilIdle(); | |
266 EXPECT_EQ(0u, slave1_process_delegate.on_master_disconnect_calls()); | |
267 EXPECT_EQ(0u, slave2_process_delegate.on_master_disconnect_calls()); | |
268 } | |
269 | |
270 TEST_F(ConnectionManagerTest, ShutdownMasterBeforeSlave) { | |
271 MasterConnectionManager master(platform_support()); | |
272 master.Init(&master_process_delegate()); | |
273 | |
274 MockSlaveProcessDelegate slave_process_delegate; | |
275 SlaveConnectionManager slave(platform_support()); | |
276 ProcessIdentifier slave_id = | |
277 ConnectSlave(&master, &slave_process_delegate, &slave, "slave"); | |
278 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); | |
279 | |
280 // The process manager shouldn't have gotten any notifications yet. (Spin the | |
281 // message loop to make sure none were enqueued.) | |
282 base::RunLoop().RunUntilIdle(); | |
283 EXPECT_EQ(0u, master_process_delegate().on_slave_disconnect_calls()); | |
284 | |
285 master.Shutdown(); | |
286 | |
287 // |OnSlaveDisconnect()| should be called. | |
288 master_process_delegate().RunUntilNotified(); | |
289 EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls()); | |
290 EXPECT_EQ("slave", master_process_delegate().last_slave_disconnect_name()); | |
291 | |
292 // |OnMasterDisconnect()| should also be (or have been) called. | |
293 slave_process_delegate.RunUntilNotified(); | |
294 EXPECT_EQ(1u, slave_process_delegate.on_master_disconnect_calls()); | |
295 | |
296 slave.Shutdown(); | |
297 } | |
298 | |
299 TEST_F(ConnectionManagerTest, SlaveCancelConnect) { | |
300 MasterConnectionManager master(platform_support()); | |
301 master.Init(&master_process_delegate()); | |
302 | |
303 MockSlaveProcessDelegate slave1_process_delegate; | |
304 SlaveConnectionManager slave1(platform_support()); | |
305 ProcessIdentifier slave1_id = | |
306 ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); | |
307 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); | |
308 | |
309 MockSlaveProcessDelegate slave2_process_delegate; | |
310 SlaveConnectionManager slave2(platform_support()); | |
311 ProcessIdentifier slave2_id = | |
312 ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); | |
313 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); | |
314 EXPECT_NE(slave1_id, slave2_id); | |
315 | |
316 ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); | |
317 EXPECT_TRUE(slave1.AllowConnect(connection_id)); | |
318 EXPECT_TRUE(slave2.AllowConnect(connection_id)); | |
319 | |
320 EXPECT_TRUE(slave1.CancelConnect(connection_id)); | |
321 ProcessIdentifier peer2 = kInvalidProcessIdentifier; | |
322 bool is_first = false; | |
323 embedder::ScopedPlatformHandle h2; | |
324 EXPECT_EQ(ConnectionManager::Result::FAILURE, | |
325 slave2.Connect(connection_id, &peer2, &is_first, &h2)); | |
326 EXPECT_EQ(kInvalidProcessIdentifier, peer2); | |
327 EXPECT_FALSE(is_first); | |
328 EXPECT_FALSE(h2.is_valid()); | |
329 | |
330 slave1.Shutdown(); | |
331 slave2.Shutdown(); | |
332 master.Shutdown(); | |
333 } | |
334 | |
335 // Tests that pending connections are removed on error. | |
336 TEST_F(ConnectionManagerTest, ErrorRemovePending) { | |
337 MasterConnectionManager master(platform_support()); | |
338 master.Init(&master_process_delegate()); | |
339 | |
340 MockSlaveProcessDelegate slave1_process_delegate; | |
341 SlaveConnectionManager slave1(platform_support()); | |
342 ProcessIdentifier slave1_id = | |
343 ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); | |
344 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); | |
345 | |
346 MockSlaveProcessDelegate slave2_process_delegate; | |
347 SlaveConnectionManager slave2(platform_support()); | |
348 ProcessIdentifier slave2_id = | |
349 ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); | |
350 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); | |
351 EXPECT_NE(slave1_id, slave2_id); | |
352 | |
353 ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); | |
354 EXPECT_TRUE(slave1.AllowConnect(connection_id)); | |
355 EXPECT_TRUE(slave2.AllowConnect(connection_id)); | |
356 | |
357 slave1.Shutdown(); | |
358 | |
359 // |OnSlaveDisconnect()| should be called. After it's called, this means that | |
360 // the disconnect has been detected and handled, including the removal of the | |
361 // pending connection. | |
362 master_process_delegate().RunUntilNotified(); | |
363 EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls()); | |
364 | |
365 ProcessIdentifier peer2 = kInvalidProcessIdentifier; | |
366 bool is_first = false; | |
367 embedder::ScopedPlatformHandle h2; | |
368 EXPECT_EQ(ConnectionManager::Result::FAILURE, | |
369 slave2.Connect(connection_id, &peer2, &is_first, &h2)); | |
370 EXPECT_EQ(kInvalidProcessIdentifier, peer2); | |
371 EXPECT_FALSE(is_first); | |
372 EXPECT_FALSE(h2.is_valid()); | |
373 | |
374 slave2.Shutdown(); | |
375 master.Shutdown(); | |
376 } | |
377 | |
378 TEST_F(ConnectionManagerTest, ConnectSlaveToSelf) { | |
379 MasterConnectionManager master(platform_support()); | |
380 master.Init(&master_process_delegate()); | |
381 | |
382 MockSlaveProcessDelegate slave_process_delegate; | |
383 SlaveConnectionManager slave(platform_support()); | |
384 ProcessIdentifier slave_id = | |
385 ConnectSlave(&master, &slave_process_delegate, &slave, "slave"); | |
386 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); | |
387 | |
388 ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); | |
389 EXPECT_TRUE(slave.AllowConnect(connection_id)); | |
390 EXPECT_TRUE(slave.AllowConnect(connection_id)); | |
391 | |
392 ProcessIdentifier peer1 = kInvalidProcessIdentifier; | |
393 bool is_first = false; | |
394 embedder::ScopedPlatformHandle h1; | |
395 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS, | |
396 slave.Connect(connection_id, &peer1, &is_first, &h1)); | |
397 EXPECT_EQ(slave_id, peer1); | |
398 EXPECT_TRUE(is_first); | |
399 EXPECT_FALSE(h1.is_valid()); | |
400 ProcessIdentifier peer2 = kInvalidProcessIdentifier; | |
401 embedder::ScopedPlatformHandle h2; | |
402 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS, | |
403 slave.Connect(connection_id, &peer2, &is_first, &h2)); | |
404 EXPECT_EQ(slave_id, peer2); | |
405 EXPECT_FALSE(is_first); | |
406 EXPECT_FALSE(h2.is_valid()); | |
407 | |
408 slave.Shutdown(); | |
409 master.Shutdown(); | |
410 } | |
411 | |
412 TEST_F(ConnectionManagerTest, ConnectSlavesTwice) { | |
413 MasterConnectionManager master(platform_support()); | |
414 master.Init(&master_process_delegate()); | |
415 | |
416 MockSlaveProcessDelegate slave1_process_delegate; | |
417 SlaveConnectionManager slave1(platform_support()); | |
418 ProcessIdentifier slave1_id = | |
419 ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); | |
420 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); | |
421 | |
422 MockSlaveProcessDelegate slave2_process_delegate; | |
423 SlaveConnectionManager slave2(platform_support()); | |
424 ProcessIdentifier slave2_id = | |
425 ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); | |
426 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); | |
427 EXPECT_NE(slave1_id, slave2_id); | |
428 | |
429 ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); | |
430 EXPECT_TRUE(slave1.AllowConnect(connection_id)); | |
431 EXPECT_TRUE(slave2.AllowConnect(connection_id)); | |
432 | |
433 ProcessIdentifier peer1 = kInvalidProcessIdentifier; | |
434 bool is_first = false; | |
435 embedder::ScopedPlatformHandle h1; | |
436 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
437 slave1.Connect(connection_id, &peer1, &is_first, &h1)); | |
438 EXPECT_EQ(slave2_id, peer1); | |
439 EXPECT_TRUE(is_first); | |
440 ProcessIdentifier peer2 = kInvalidProcessIdentifier; | |
441 embedder::ScopedPlatformHandle h2; | |
442 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
443 slave2.Connect(connection_id, &peer2, &is_first, &h2)); | |
444 EXPECT_EQ(slave1_id, peer2); | |
445 EXPECT_FALSE(is_first); | |
446 | |
447 EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get())); | |
448 | |
449 // TODO(vtl): Currently, the master doesn't detect the case of connecting a | |
450 // pair of slaves that are already connected. (Doing so would require more | |
451 // careful tracking and is prone to races -- especially if we want slaves to | |
452 // be able to tear down no-longer-needed connections.) But the slaves should | |
453 // be able to do the tracking themselves (using the peer process identifiers). | |
454 connection_id = master.GenerateConnectionIdentifier(); | |
455 EXPECT_TRUE(slave1.AllowConnect(connection_id)); | |
456 EXPECT_TRUE(slave2.AllowConnect(connection_id)); | |
457 | |
458 h1.reset(); | |
459 h2.reset(); | |
460 ProcessIdentifier second_peer2 = kInvalidProcessIdentifier; | |
461 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION, | |
462 slave2.Connect(connection_id, &second_peer2, &is_first, &h2)); | |
463 EXPECT_EQ(peer2, second_peer2); | |
464 EXPECT_TRUE(is_first); | |
465 EXPECT_FALSE(h2.is_valid()); | |
466 ProcessIdentifier second_peer1 = kInvalidProcessIdentifier; | |
467 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION, | |
468 slave1.Connect(connection_id, &second_peer1, &is_first, &h1)); | |
469 EXPECT_EQ(peer1, second_peer1); | |
470 EXPECT_FALSE(is_first); | |
471 EXPECT_FALSE(h1.is_valid()); | |
472 | |
473 slave2.Shutdown(); | |
474 slave1.Shutdown(); | |
475 master.Shutdown(); | |
476 } | |
477 | |
478 TEST_F(ConnectionManagerTest, OverlappingSlaveConnects) { | |
479 MasterConnectionManager master(platform_support()); | |
480 master.Init(&master_process_delegate()); | |
481 | |
482 MockSlaveProcessDelegate slave1_process_delegate; | |
483 SlaveConnectionManager slave1(platform_support()); | |
484 ProcessIdentifier slave1_id = | |
485 ConnectSlave(&master, &slave1_process_delegate, &slave1, "slave1"); | |
486 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave1_id)); | |
487 | |
488 MockSlaveProcessDelegate slave2_process_delegate; | |
489 SlaveConnectionManager slave2(platform_support()); | |
490 ProcessIdentifier slave2_id = | |
491 ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2"); | |
492 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave2_id)); | |
493 EXPECT_NE(slave1_id, slave2_id); | |
494 | |
495 ConnectionIdentifier connection_id1 = master.GenerateConnectionIdentifier(); | |
496 EXPECT_TRUE(slave1.AllowConnect(connection_id1)); | |
497 EXPECT_TRUE(slave2.AllowConnect(connection_id1)); | |
498 | |
499 ConnectionIdentifier connection_id2 = master.GenerateConnectionIdentifier(); | |
500 EXPECT_TRUE(slave1.AllowConnect(connection_id2)); | |
501 EXPECT_TRUE(slave2.AllowConnect(connection_id2)); | |
502 | |
503 ProcessIdentifier peer1 = kInvalidProcessIdentifier; | |
504 bool is_first = false; | |
505 embedder::ScopedPlatformHandle h1; | |
506 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
507 slave1.Connect(connection_id1, &peer1, &is_first, &h1)); | |
508 EXPECT_EQ(slave2_id, peer1); | |
509 EXPECT_TRUE(is_first); | |
510 ProcessIdentifier peer2 = kInvalidProcessIdentifier; | |
511 embedder::ScopedPlatformHandle h2; | |
512 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
513 slave2.Connect(connection_id2, &peer2, &is_first, &h2)); | |
514 EXPECT_EQ(slave1_id, peer2); | |
515 EXPECT_TRUE(is_first); | |
516 | |
517 EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get())); | |
518 | |
519 h1.reset(); | |
520 h2.reset(); | |
521 ProcessIdentifier second_peer1 = kInvalidProcessIdentifier; | |
522 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION, | |
523 slave1.Connect(connection_id2, &second_peer1, &is_first, &h1)); | |
524 EXPECT_EQ(peer1, second_peer1); | |
525 EXPECT_FALSE(is_first); | |
526 EXPECT_FALSE(h1.is_valid()); | |
527 ProcessIdentifier second_peer2 = kInvalidProcessIdentifier; | |
528 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_REUSE_CONNECTION, | |
529 slave2.Connect(connection_id1, &second_peer2, &is_first, &h2)); | |
530 EXPECT_EQ(peer2, second_peer2); | |
531 EXPECT_FALSE(is_first); | |
532 EXPECT_FALSE(h2.is_valid()); | |
533 | |
534 slave2.Shutdown(); | |
535 slave1.Shutdown(); | |
536 master.Shutdown(); | |
537 } | |
538 | |
539 TEST_F(ConnectionManagerTest, ConnectMasterToSlave) { | |
540 MasterConnectionManager master(platform_support()); | |
541 master.Init(&master_process_delegate()); | |
542 | |
543 MockSlaveProcessDelegate slave_process_delegate; | |
544 SlaveConnectionManager slave(platform_support()); | |
545 ProcessIdentifier slave_id = | |
546 ConnectSlave(&master, &slave_process_delegate, &slave, "slave"); | |
547 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); | |
548 | |
549 ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); | |
550 EXPECT_TRUE(master.AllowConnect(connection_id)); | |
551 EXPECT_TRUE(slave.AllowConnect(connection_id)); | |
552 | |
553 ProcessIdentifier master_peer = kInvalidProcessIdentifier; | |
554 bool is_first = false; | |
555 embedder::ScopedPlatformHandle master_h; | |
556 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
557 master.Connect(connection_id, &master_peer, &is_first, &master_h)); | |
558 EXPECT_EQ(slave_id, master_peer); | |
559 EXPECT_TRUE(is_first); | |
560 EXPECT_TRUE(master_h.is_valid()); | |
561 ProcessIdentifier slave_peer = kInvalidProcessIdentifier; | |
562 embedder::ScopedPlatformHandle slave_h; | |
563 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
564 slave.Connect(connection_id, &slave_peer, &is_first, &slave_h)); | |
565 EXPECT_EQ(kMasterProcessIdentifier, slave_peer); | |
566 EXPECT_FALSE(is_first); | |
567 EXPECT_TRUE(slave_h.is_valid()); | |
568 | |
569 EXPECT_TRUE(ArePlatformHandlesConnected(master_h.get(), slave_h.get())); | |
570 | |
571 slave.Shutdown(); | |
572 master.Shutdown(); | |
573 } | |
574 | |
575 TEST_F(ConnectionManagerTest, ConnectMasterToSelf) { | |
576 MasterConnectionManager master(platform_support()); | |
577 master.Init(&master_process_delegate()); | |
578 | |
579 ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); | |
580 EXPECT_TRUE(master.AllowConnect(connection_id)); | |
581 EXPECT_TRUE(master.AllowConnect(connection_id)); | |
582 | |
583 ProcessIdentifier peer1 = kInvalidProcessIdentifier; | |
584 bool is_first = false; | |
585 embedder::ScopedPlatformHandle h1; | |
586 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS, | |
587 master.Connect(connection_id, &peer1, &is_first, &h1)); | |
588 EXPECT_EQ(kMasterProcessIdentifier, peer1); | |
589 EXPECT_TRUE(is_first); | |
590 EXPECT_FALSE(h1.is_valid()); | |
591 ProcessIdentifier peer2 = kInvalidProcessIdentifier; | |
592 embedder::ScopedPlatformHandle h2; | |
593 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS, | |
594 master.Connect(connection_id, &peer2, &is_first, &h2)); | |
595 EXPECT_EQ(kMasterProcessIdentifier, peer2); | |
596 EXPECT_FALSE(is_first); | |
597 EXPECT_FALSE(h2.is_valid()); | |
598 | |
599 EXPECT_EQ(peer1, peer2); | |
600 | |
601 master.Shutdown(); | |
602 } | |
603 | |
604 TEST_F(ConnectionManagerTest, MasterCancelConnect) { | |
605 MasterConnectionManager master(platform_support()); | |
606 master.Init(&master_process_delegate()); | |
607 | |
608 MockSlaveProcessDelegate slave_process_delegate; | |
609 SlaveConnectionManager slave(platform_support()); | |
610 ProcessIdentifier slave_id = | |
611 ConnectSlave(&master, &slave_process_delegate, &slave, "slave"); | |
612 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); | |
613 | |
614 ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); | |
615 EXPECT_TRUE(master.AllowConnect(connection_id)); | |
616 EXPECT_TRUE(slave.AllowConnect(connection_id)); | |
617 | |
618 EXPECT_TRUE(master.CancelConnect(connection_id)); | |
619 ProcessIdentifier peer = kInvalidProcessIdentifier; | |
620 bool is_first = false; | |
621 embedder::ScopedPlatformHandle h; | |
622 EXPECT_EQ(ConnectionManager::Result::FAILURE, | |
623 slave.Connect(connection_id, &peer, &is_first, &h)); | |
624 EXPECT_EQ(kInvalidProcessIdentifier, peer); | |
625 EXPECT_FALSE(is_first); | |
626 EXPECT_FALSE(h.is_valid()); | |
627 | |
628 slave.Shutdown(); | |
629 master.Shutdown(); | |
630 } | |
631 | |
632 TEST_F(ConnectionManagerTest, AddSlaveThenImmediateShutdown) { | |
633 MasterConnectionManager master(platform_support()); | |
634 master.Init(&master_process_delegate()); | |
635 | |
636 MockSlaveProcessDelegate slave_process_delegate; | |
637 SlaveConnectionManager slave(platform_support()); | |
638 embedder::PlatformChannelPair platform_channel_pair; | |
639 ProcessIdentifier slave_id = master.AddSlave( | |
640 new TestSlaveInfo("slave"), platform_channel_pair.PassServerHandle()); | |
641 master.Shutdown(); | |
642 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); | |
643 // Since we never initialized |slave|, we don't have to shut it down. | |
644 } | |
645 | |
646 TEST_F(ConnectionManagerTest, AddSlaveAndBootstrap) { | |
647 MasterConnectionManager master(platform_support()); | |
648 master.Init(&master_process_delegate()); | |
649 | |
650 embedder::PlatformChannelPair platform_channel_pair; | |
651 ConnectionIdentifier connection_id = master.GenerateConnectionIdentifier(); | |
652 ProcessIdentifier slave_id = master.AddSlaveAndBootstrap( | |
653 new TestSlaveInfo("slave"), platform_channel_pair.PassServerHandle(), | |
654 connection_id); | |
655 EXPECT_TRUE(IsValidSlaveProcessIdentifier(slave_id)); | |
656 | |
657 embedder::ScopedPlatformHandle h1; | |
658 ProcessIdentifier master_peer = kInvalidProcessIdentifier; | |
659 bool is_first = false; | |
660 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
661 master.Connect(connection_id, &master_peer, &is_first, &h1)); | |
662 EXPECT_EQ(slave_id, master_peer); | |
663 EXPECT_TRUE(is_first); | |
664 EXPECT_TRUE(h1.is_valid()); | |
665 | |
666 // We can delay creating/initializing |slave| for quite a while. | |
667 MockSlaveProcessDelegate slave_process_delegate; | |
668 SlaveConnectionManager slave(platform_support()); | |
669 slave.Init(&slave_process_delegate, platform_channel_pair.PassClientHandle()); | |
670 | |
671 ProcessIdentifier slave_peer = kInvalidProcessIdentifier; | |
672 embedder::ScopedPlatformHandle h2; | |
673 EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION, | |
674 slave.Connect(connection_id, &slave_peer, &is_first, &h2)); | |
675 EXPECT_EQ(kMasterProcessIdentifier, slave_peer); | |
676 EXPECT_FALSE(is_first); | |
677 | |
678 EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get())); | |
679 | |
680 slave.Shutdown(); | |
681 master.Shutdown(); | |
682 } | |
683 | |
684 // TODO(vtl): More shutdown cases for |AddSlaveAndBootstrap()|? | |
685 | |
686 } // namespace | |
687 } // namespace system | |
688 } // namespace mojo | |
OLD | NEW |