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

Side by Side Diff: ipc/ipc_channel_mojo_unittest.cc

Issue 2455823002: Support generic synchronization against an IPC::Channel (Closed)
Patch Set: . Created 4 years, 1 month 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
« no previous file with comments | « ipc/ipc_channel_mojo.cc ('k') | ipc/ipc_channel_proxy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ipc/ipc_channel_mojo.h" 5 #include "ipc/ipc_channel_mojo.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <memory> 10 #include <memory>
(...skipping 19 matching lines...) Expand all
30 #include "build/build_config.h" 30 #include "build/build_config.h"
31 #include "ipc/ipc_message.h" 31 #include "ipc/ipc_message.h"
32 #include "ipc/ipc_mojo_handle_attachment.h" 32 #include "ipc/ipc_mojo_handle_attachment.h"
33 #include "ipc/ipc_mojo_message_helper.h" 33 #include "ipc/ipc_mojo_message_helper.h"
34 #include "ipc/ipc_mojo_param_traits.h" 34 #include "ipc/ipc_mojo_param_traits.h"
35 #include "ipc/ipc_sync_channel.h" 35 #include "ipc/ipc_sync_channel.h"
36 #include "ipc/ipc_sync_message.h" 36 #include "ipc/ipc_sync_message.h"
37 #include "ipc/ipc_test.mojom.h" 37 #include "ipc/ipc_test.mojom.h"
38 #include "ipc/ipc_test_base.h" 38 #include "ipc/ipc_test_base.h"
39 #include "ipc/ipc_test_channel_listener.h" 39 #include "ipc/ipc_test_channel_listener.h"
40 #include "mojo/public/cpp/bindings/binding.h"
40 #include "testing/gtest/include/gtest/gtest.h" 41 #include "testing/gtest/include/gtest/gtest.h"
41 42
42 #if defined(OS_POSIX) 43 #if defined(OS_POSIX)
43 #include "base/file_descriptor_posix.h" 44 #include "base/file_descriptor_posix.h"
44 #include "ipc/ipc_platform_file_attachment_posix.h" 45 #include "ipc/ipc_platform_file_attachment_posix.h"
45 #endif 46 #endif
46 47
47 namespace { 48 namespace {
48 49
49 void SendString(IPC::Sender* sender, const std::string& str) { 50 void SendString(IPC::Sender* sender, const std::string& str) {
50 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); 51 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
51 message->WriteString(str); 52 message->WriteString(str);
52 ASSERT_TRUE(sender->Send(message)); 53 ASSERT_TRUE(sender->Send(message));
53 } 54 }
54 55
55 void SendValue(IPC::Sender* sender, int32_t value) { 56 void SendValue(IPC::Sender* sender, int32_t value) {
56 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); 57 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
57 message->WriteInt(value); 58 message->WriteInt(value);
58 ASSERT_TRUE(sender->Send(message)); 59 ASSERT_TRUE(sender->Send(message));
59 } 60 }
60 61
62 void SendMessagePipe(IPC::Sender* sender, mojo::ScopedMessagePipeHandle pipe) {
63 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
64 IPC::MojoMessageHelper::WriteMessagePipeTo(message, std::move(pipe));
65 ASSERT_TRUE(sender->Send(message));
66 }
67
61 class ListenerThatExpectsOK : public IPC::Listener { 68 class ListenerThatExpectsOK : public IPC::Listener {
62 public: 69 public:
63 ListenerThatExpectsOK() : received_ok_(false) {} 70 ListenerThatExpectsOK() : received_ok_(false) {}
64 71
65 ~ListenerThatExpectsOK() override {} 72 ~ListenerThatExpectsOK() override {}
66 73
67 bool OnMessageReceived(const IPC::Message& message) override { 74 bool OnMessageReceived(const IPC::Message& message) override {
68 base::PickleIterator iter(message); 75 base::PickleIterator iter(message);
69 std::string should_be_ok; 76 std::string should_be_ok;
70 EXPECT_TRUE(iter.ReadString(&should_be_ok)); 77 EXPECT_TRUE(iter.ReadString(&should_be_ok));
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 } 690 }
684 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); } 691 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); }
685 void RunProxy() { 692 void RunProxy() {
686 runner_->RunProxy(); 693 runner_->RunProxy();
687 } 694 }
688 void DestroyProxy() { 695 void DestroyProxy() {
689 runner_.reset(); 696 runner_.reset();
690 base::RunLoop().RunUntilIdle(); 697 base::RunLoop().RunUntilIdle();
691 } 698 }
692 699
700 // Launches a secondary test client.
701 std::unique_ptr<ChannelProxyRunner>
702 LaunchClient(const std::string& client_name,
703 IPC::Listener* listener,
704 ClientHandle* client) {
705 client->Init(client_name);
706 std::unique_ptr<ChannelProxyRunner> runner(
707 new ChannelProxyRunner(client->TakeHandle(), true));
708 runner->CreateProxy(listener);
709 runner->RunProxy();
710 return runner;
711 }
712
693 IPC::ChannelProxy* proxy() { return runner_->proxy(); } 713 IPC::ChannelProxy* proxy() { return runner_->proxy(); }
694 714
695 private: 715 private:
696 std::unique_ptr<ChannelProxyRunner> runner_; 716 std::unique_ptr<ChannelProxyRunner> runner_;
697 }; 717 };
698 718
699 class ListenerWithSimpleProxyAssociatedInterface 719 class ListenerWithSimpleProxyAssociatedInterface
700 : public IPC::Listener, 720 : public IPC::Listener,
701 public IPC::mojom::SimpleTestDriver { 721 public IPC::mojom::SimpleTestDriver {
702 public: 722 public:
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
1249 expected_values.push(4); 1269 expected_values.push(4);
1250 expected_values.push(5); 1270 expected_values.push(5);
1251 expected_values.push(2); 1271 expected_values.push(2);
1252 expected_values.push(3); 1272 expected_values.push(3);
1253 RunProxy(); 1273 RunProxy();
1254 base::RunLoop().Run(); 1274 base::RunLoop().Run();
1255 EXPECT_TRUE(expected_values.empty()); 1275 EXPECT_TRUE(expected_values.empty());
1256 DestroyProxy(); 1276 DestroyProxy();
1257 } 1277 }
1258 1278
1279 class TokenListener : public IPC::Listener,
1280 public IPC::mojom::SynchronizationTestClient {
1281 public:
1282 explicit TokenListener(IPC::mojom::SynchronizationTestClientRequest request)
1283 : binding_(this, std::move(request)) {}
1284 ~TokenListener() override {}
1285
1286 bool OnMessageReceived(const IPC::Message& message) override {
1287 base::PickleIterator iter(message);
1288 EXPECT_TRUE(iter.ReadString(&registered_token_));
1289 return true;
1290 }
1291
1292 const std::string& registered_token() const { return registered_token_; }
1293
1294 void set_quit_closure(const base::Closure& closure) {
1295 quit_closure_ = closure;
1296 }
1297
1298 private:
1299 // IPC::mojom::SynchronizationTestClient:
1300 void OnTokenReceived(const std::string& token,
1301 const OnTokenReceivedCallback& callback) override {
1302 EXPECT_FALSE(registered_token_.empty());
1303 EXPECT_EQ(registered_token_, token);
1304 callback.Run();
1305 quit_closure_.Run();
1306 }
1307
1308 std::string registered_token_;
1309 base::Closure quit_closure_;
1310 mojo::Binding<IPC::mojom::SynchronizationTestClient> binding_;
1311 };
1312
1313 TEST_F(IPCChannelProxyMojoTest, ChannelSynchronizationEvent) {
1314 // This test creates two child processes A and B. It then establishes a direct
1315 // pipe between process A and B -- specifically process A gets a
1316 // SynchronizationTestReceiver proxy to process B.
1317 //
1318 // Process A sends a legacy IPC message to the main process to register a
1319 // token there (see TokenListener above).
1320 //
1321 // Process A also sends a message directly to B referencing the token, and
1322 // including a channel synchronization event for B to wait on.
1323 //
1324 // Process B waits on the event and then sends the token back to the main
1325 // process over an independent interface (SynchronizationTestClient).
1326 //
1327 // Because a channel synchronization event was used, it should be impossible
1328 // for the main process to receive process B's message before it receives
1329 // process A's token registration.
1330 //
1331 // This test verifies that.
1332 ClientHandle sender_handle;
1333 IPC::mojom::SynchronizationTestClientPtr client;
1334 TokenListener sender_listener(mojo::GetProxy(&client));
1335 std::unique_ptr<ChannelProxyRunner> sender =
1336 LaunchClient("SynchronizationTestSender", &sender_listener,
1337 &sender_handle);
1338
1339 ClientHandle receiver_handle;
1340 DummyListener receiver_listener;
1341 std::unique_ptr<ChannelProxyRunner> receiver =
1342 LaunchClient("SynchronizationTestReceiver", &receiver_listener,
1343 &receiver_handle);
1344
1345 base::RunLoop loop;
1346 sender_listener.set_quit_closure(loop.QuitClosure());
1347
1348 IPC::mojom::SynchronizationTestReceiverPtr receiver_proxy;
1349 SendMessagePipe(receiver->proxy(),
1350 mojo::GetProxy(&receiver_proxy).PassMessagePipe());
1351
1352 IPC::mojom::SynchronizationTestSenderPtr sender_proxy;
1353 SendMessagePipe(sender->proxy(),
1354 mojo::GetProxy(&sender_proxy).PassMessagePipe());
1355
1356 sender_proxy->SendToken(std::move(receiver_proxy), std::move(client));
1357 loop.Run();
1358
1359 sender_proxy->Quit();
1360
1361 EXPECT_TRUE(sender_handle.WaitForShutdown());
1362 EXPECT_TRUE(receiver_handle.WaitForShutdown());
1363 }
1364
1365 class SynchronizationTestPipeListener : public IPC::Listener {
1366 public:
1367 using PipeHandler = base::Callback<void(mojo::ScopedMessagePipeHandle)>;
1368
1369 SynchronizationTestPipeListener() {}
1370 ~SynchronizationTestPipeListener() override {}
1371
1372 bool OnMessageReceived(const IPC::Message& message) override {
1373 base::PickleIterator iter(message);
1374 mojo::ScopedMessagePipeHandle handle;
1375 EXPECT_TRUE(IPC::MojoMessageHelper::ReadMessagePipeFrom(
1376 &message, &iter, &handle));
1377 pipe_handler_.Run(std::move(handle));
1378 return true;
1379 }
1380
1381 void set_pipe_handler(const PipeHandler& handler) { pipe_handler_ = handler; }
1382
1383 private:
1384 PipeHandler pipe_handler_;
1385 base::Closure quit_closure_;
1386 };
1387
1388 class SynchronizationTestSenderImpl
1389 : public IPC::mojom::SynchronizationTestSender {
1390 public:
1391 SynchronizationTestSenderImpl(
1392 IPC::ChannelProxy* channel,
1393 const base::Closure& quit_closure)
1394 : channel_(channel), quit_closure_(quit_closure), binding_(this) {}
1395
1396 ~SynchronizationTestSenderImpl() override {}
1397
1398 void Bind(mojo::ScopedMessagePipeHandle handle) {
1399 binding_.Bind(std::move(handle));
1400 }
1401
1402 // IPC::mojom::SynchronizationTestSender:
1403 void SendToken(IPC::mojom::SynchronizationTestReceiverPtr receiver,
1404 IPC::mojom::SynchronizationTestClientPtr client) override {
1405 // Register the token with the parent process over legacy IPC, then send it
1406 // to the receiver process with a synchronization event.
1407 const std::string kToken = "make IPC great again";
1408 SendString(channel_, kToken);
1409 receiver->ReceiveToken(
1410 kToken, std::move(client), channel_->CreateSynchronizationEvent());
1411 }
1412
1413 void Quit() override { quit_closure_.Run(); }
1414
1415 private:
1416 IPC::ChannelProxy* const channel_;
1417 const base::Closure quit_closure_;
1418 mojo::Binding<IPC::mojom::SynchronizationTestSender> binding_;
1419
1420 DISALLOW_COPY_AND_ASSIGN(SynchronizationTestSenderImpl);
1421 };
1422
1423 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
1424 SynchronizationTestSender, ChannelProxyClient) {
1425 SynchronizationTestPipeListener listener;
1426 CreateProxy(&listener);
1427 RunProxy();
1428
1429 base::RunLoop loop;
1430 SynchronizationTestSenderImpl impl(proxy(), loop.QuitClosure());
1431 listener.set_pipe_handler(base::Bind(&SynchronizationTestSenderImpl::Bind,
1432 base::Unretained(&impl)));
1433 loop.Run();
1434 DestroyProxy();
1435 }
1436
1437 class SynchronizationTestReceiverImpl
1438 : public IPC::mojom::SynchronizationTestReceiver,
1439 public mojo::common::mojom::Event {
1440 public:
1441 explicit SynchronizationTestReceiverImpl(
1442 const base::Closure& quit_closure)
1443 : quit_closure_(quit_closure), binding_(this), event_binding_(this) {}
1444
1445 ~SynchronizationTestReceiverImpl() override {}
1446
1447 void Bind(mojo::ScopedMessagePipeHandle handle) {
1448 binding_.Bind(std::move(handle));
1449 }
1450
1451 // IPC::mojom::SynchronizationTestReceiver:
1452 void ReceiveToken(const std::string& token,
1453 IPC::mojom::SynchronizationTestClientPtr client,
1454 mojo::common::mojom::EventRequest event) override {
1455 // Hang onto the token until |event| signals.
1456 received_token_ = token;
1457 client_ = std::move(client);
1458 event_binding_.Bind(std::move(event));
1459 }
1460
1461 // mojo::common::mojom::Event:
1462 void Signal() override {
1463 // This request should always reach the parent process after the sender's
1464 // legacy IPC which registered the same token there.
1465 client_->OnTokenReceived(received_token_, quit_closure_);
1466 }
1467
1468 private:
1469 const base::Closure quit_closure_;
1470 std::string received_token_;
1471 IPC::mojom::SynchronizationTestClientPtr client_;
1472 mojo::Binding<IPC::mojom::SynchronizationTestReceiver> binding_;
1473 mojo::Binding<mojo::common::mojom::Event> event_binding_;
1474
1475 DISALLOW_COPY_AND_ASSIGN(SynchronizationTestReceiverImpl);
1476 };
1477
1478 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
1479 SynchronizationTestReceiver, ChannelProxyClient) {
1480 SynchronizationTestPipeListener listener;
1481 CreateProxy(&listener);
1482 RunProxy();
1483 base::RunLoop loop;
1484 SynchronizationTestReceiverImpl impl(loop.QuitClosure());
1485 listener.set_pipe_handler(base::Bind(&SynchronizationTestReceiverImpl::Bind,
1486 base::Unretained(&impl)));
1487 loop.Run();
1488 DestroyProxy();
1489 }
1490
1259 #if defined(OS_POSIX) 1491 #if defined(OS_POSIX)
1260 1492
1261 class ListenerThatExpectsFile : public IPC::Listener { 1493 class ListenerThatExpectsFile : public IPC::Listener {
1262 public: 1494 public:
1263 ListenerThatExpectsFile() : sender_(NULL) {} 1495 ListenerThatExpectsFile() : sender_(NULL) {}
1264 1496
1265 ~ListenerThatExpectsFile() override {} 1497 ~ListenerThatExpectsFile() override {}
1266 1498
1267 bool OnMessageReceived(const IPC::Message& message) override { 1499 bool OnMessageReceived(const IPC::Message& message) override {
1268 base::PickleIterator iter(message); 1500 base::PickleIterator iter(message);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1409 Connect(&listener); 1641 Connect(&listener);
1410 1642
1411 base::RunLoop().Run(); 1643 base::RunLoop().Run();
1412 1644
1413 Close(); 1645 Close();
1414 } 1646 }
1415 1647
1416 #endif // OS_LINUX 1648 #endif // OS_LINUX
1417 1649
1418 } // namespace 1650 } // namespace
OLDNEW
« no previous file with comments | « ipc/ipc_channel_mojo.cc ('k') | ipc/ipc_channel_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698