| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stdint.h> |
| |
| #include <vector> |
| |
| #include "base/command_line.h" |
| #include "base/process/launch.h" |
| #include "base/test/multiprocess_test.h" |
| #include "base/test/test_timeouts.h" |
| #include "mojo/public/c/system/core.h" |
| #include "mojo/public/cpp/platform/platform_channel.h" |
| #include "mojo/public/cpp/platform/platform_handle.h" |
| #include "mojo/public/cpp/system/invitation.h" |
| #include "mojo/public/cpp/system/message_pipe.h" |
| #include "mojo/public/cpp/system/wait.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/multiprocess_func_list.h" |
| |
| namespace { |
| |
| uint64_t kTestPipeName = 0; |
| const char kTestMessage[] = "hai"; |
| const char kTestReply[] = "bai"; |
| |
| std::string ReadMessageAsString(mojo::MessagePipeHandle handle) { |
| std::vector<uint8_t> data; |
| CHECK_EQ(MOJO_RESULT_OK, mojo::ReadMessageRaw(handle, &data, nullptr, |
| MOJO_READ_MESSAGE_FLAG_NONE)); |
| return std::string(data.begin(), data.end()); |
| } |
| |
| TEST(MojoCoreTest, SanityCheck) { |
| // Exercises some APIs against the mojo_core library and expects them to work |
| // as intended. |
| |
| MojoHandle a, b; |
| EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &a, &b)); |
| |
| MojoMessageHandle m; |
| EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &m)); |
| EXPECT_EQ(MOJO_RESULT_OK, |
| MojoSetMessageContext(m, 42, nullptr, nullptr, nullptr)); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(a, m, nullptr)); |
| m = MOJO_MESSAGE_HANDLE_INVALID; |
| |
| MojoHandleSignalsState state; |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); |
| EXPECT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, nullptr, &m)); |
| |
| uintptr_t context = 0; |
| EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageContext(m, nullptr, &context)); |
| EXPECT_EQ(42u, context); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(m)); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); |
| } |
| |
| TEST(MojoCoreTest, BasicMultiprocess) { |
| base::CommandLine child_cmd(base::GetMultiProcessTestChildBaseCommandLine()); |
| base::LaunchOptions options; |
| |
| mojo::PlatformChannel channel; |
| channel.PrepareToPassRemoteEndpoint(&options, &child_cmd); |
| base::Process child_process = base::SpawnMultiProcessTestChild( |
| "BasicMultiprocessClientMain", child_cmd, options); |
| channel.RemoteProcessLaunchAttempted(); |
| |
| mojo::OutgoingInvitation invitation; |
| auto child_pipe = invitation.AttachMessagePipe(kTestPipeName); |
| mojo::OutgoingInvitation::Send(std::move(invitation), child_process.Handle(), |
| channel.TakeLocalEndpoint()); |
| |
| mojo::Wait(child_pipe.get(), MOJO_HANDLE_SIGNAL_READABLE); |
| EXPECT_EQ(kTestMessage, ReadMessageAsString(child_pipe.get())); |
| |
| mojo::WriteMessageRaw(child_pipe.get(), kTestReply, sizeof(kTestReply) - 1, |
| nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); |
| |
| int rv = -1; |
| ASSERT_TRUE(base::WaitForMultiprocessTestChildExit( |
| child_process, TestTimeouts::action_timeout(), &rv)); |
| EXPECT_EQ(0, rv); |
| } |
| |
| MULTIPROCESS_TEST_MAIN(BasicMultiprocessClientMain) { |
| auto endpoint = mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine( |
| *base::CommandLine::ForCurrentProcess()); |
| auto invitation = mojo::IncomingInvitation::Accept(std::move(endpoint)); |
| auto parent_pipe = invitation.ExtractMessagePipe(kTestPipeName); |
| |
| mojo::WriteMessageRaw(parent_pipe.get(), kTestMessage, |
| sizeof(kTestMessage) - 1, nullptr, 0, |
| MOJO_WRITE_MESSAGE_FLAG_NONE); |
| |
| mojo::Wait(parent_pipe.get(), MOJO_HANDLE_SIGNAL_READABLE); |
| EXPECT_EQ(kTestReply, ReadMessageAsString(parent_pipe.get())); |
| |
| return 0; |
| } |
| |
| } // namespace |