diff options
Diffstat (limited to 'mojo/edk/system/platform_wrapper_unittest.cc')
-rw-r--r-- | mojo/edk/system/platform_wrapper_unittest.cc | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/mojo/edk/system/platform_wrapper_unittest.cc b/mojo/edk/system/platform_wrapper_unittest.cc new file mode 100644 index 0000000..f29d62b --- /dev/null +++ b/mojo/edk/system/platform_wrapper_unittest.cc @@ -0,0 +1,212 @@ +// Copyright 2016 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 <string.h> + +#include <algorithm> +#include <string> +#include <vector> + +#include "base/files/file.h" +#include "base/files/file_util.h" +#include "base/memory/shared_memory.h" +#include "base/process/process_handle.h" +#include "mojo/edk/embedder/platform_shared_buffer.h" +#include "mojo/edk/test/mojo_test_base.h" +#include "mojo/public/c/system/platform_handle.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if defined(OS_WIN) +#include <windows.h> +#endif + +#if defined(OS_POSIX) +#define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR +#elif defined(OS_WIN) +#define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE +#endif + +#if defined(OS_MACOSX) && !defined(OS_IOS) +#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT +#else +#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE SIMPLE_PLATFORM_HANDLE_TYPE +#endif + +uint64_t PlatformHandleValueFromPlatformFile(base::PlatformFile file) { +#if defined(OS_WIN) + return reinterpret_cast<uint64_t>(file); +#else + return static_cast<uint64_t>(file); +#endif +} + +base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) { +#if defined(OS_WIN) + return reinterpret_cast<base::PlatformFile>(value); +#else + return static_cast<base::PlatformFile>(value); +#endif +} + +namespace mojo { +namespace edk { +namespace { + +using PlatformWrapperTest = test::MojoTestBase; + +TEST_F(PlatformWrapperTest, WrapPlatformHandle) { + // Create a temporary file and write a message to it. + base::FilePath temp_file_path; + ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path)); + const std::string kMessage = "Hello, world!"; + EXPECT_EQ(base::WriteFile(temp_file_path, kMessage.data(), + static_cast<int>(kMessage.size())), + static_cast<int>(kMessage.size())); + + RUN_CHILD_ON_PIPE(ReadPlatformFile, h) + // Open the temporary file for reading, wrap its handle, and send it to + // the child along with the expected message to be read. + base::File file(temp_file_path, + base::File::FLAG_OPEN | base::File::FLAG_READ); + EXPECT_TRUE(file.IsValid()); + + MojoHandle wrapped_handle; + MojoPlatformHandle os_file; + os_file.struct_size = sizeof(MojoPlatformHandle); + os_file.type = SIMPLE_PLATFORM_HANDLE_TYPE; + os_file.value = + PlatformHandleValueFromPlatformFile(file.TakePlatformFile()); + EXPECT_EQ(MOJO_RESULT_OK, + MojoWrapPlatformHandle(&os_file, &wrapped_handle)); + + WriteMessageWithHandles(h, kMessage, &wrapped_handle, 1); + END_CHILD() + + base::DeleteFile(temp_file_path, false); +} + +DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadPlatformFile, PlatformWrapperTest, h) { + // Read a message and a wrapped file handle; unwrap the handle. + MojoHandle wrapped_handle; + std::string message = ReadMessageWithHandles(h, &wrapped_handle, 1); + + MojoPlatformHandle platform_handle; + platform_handle.struct_size = sizeof(MojoPlatformHandle); + ASSERT_EQ(MOJO_RESULT_OK, + MojoUnwrapPlatformHandle(wrapped_handle, &platform_handle)); + EXPECT_EQ(SIMPLE_PLATFORM_HANDLE_TYPE, platform_handle.type); + base::File file(PlatformFileFromPlatformHandleValue(platform_handle.value)); + + // Expect to read the same message from the file. + std::vector<char> data(message.size()); + EXPECT_EQ(file.ReadAtCurrentPos(data.data(), static_cast<int>(data.size())), + static_cast<int>(data.size())); + EXPECT_TRUE(std::equal(message.begin(), message.end(), data.begin())); +} + +TEST_F(PlatformWrapperTest, WrapPlatformSharedBufferHandle) { + // Allocate a new platform shared buffer and write a message into it. + const std::string kMessage = "Hello, world!"; + base::SharedMemory buffer; + buffer.CreateAndMapAnonymous(kMessage.size()); + CHECK(buffer.memory()); + memcpy(buffer.memory(), kMessage.data(), kMessage.size()); + + RUN_CHILD_ON_PIPE(ReadPlatformSharedBuffer, h) + // Wrap the shared memory handle and send it to the child along with the + // expected message. + base::SharedMemoryHandle memory_handle = + base::SharedMemory::DuplicateHandle(buffer.handle()); + MojoPlatformHandle os_buffer; + os_buffer.struct_size = sizeof(MojoPlatformHandle); + os_buffer.type = SHARED_BUFFER_PLATFORM_HANDLE_TYPE; +#if defined(OS_MACOSX) && !defined(OS_IOS) + os_buffer.value = static_cast<uint64_t>(memory_handle.GetMemoryObject()); +#elif defined(OS_POSIX) + os_buffer.value = static_cast<uint64_t>(memory_handle.fd); +#elif defined(OS_WIN) + os_buffer.value = reinterpret_cast<uint64_t>(memory_handle.GetHandle()); +#endif + + MojoHandle wrapped_handle; + ASSERT_EQ(MOJO_RESULT_OK, + MojoWrapPlatformSharedBufferHandle( + &os_buffer, kMessage.size(), + MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE, + &wrapped_handle)); + WriteMessageWithHandles(h, kMessage, &wrapped_handle, 1); + END_CHILD() +} + +DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadPlatformSharedBuffer, PlatformWrapperTest, + h) { + // Read a message and a wrapped shared buffer handle. + MojoHandle wrapped_handle; + std::string message = ReadMessageWithHandles(h, &wrapped_handle, 1); + + // Check the message in the buffer + ExpectBufferContents(wrapped_handle, 0, message); + + // Now unwrap the buffer and verify that the base::SharedMemoryHandle also + // works as expected. + MojoPlatformHandle os_buffer; + os_buffer.struct_size = sizeof(MojoPlatformHandle); + size_t size; + MojoPlatformSharedBufferHandleFlags flags; + ASSERT_EQ(MOJO_RESULT_OK, + MojoUnwrapPlatformSharedBufferHandle(wrapped_handle, &os_buffer, + &size, &flags)); + bool read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE; + EXPECT_FALSE(read_only); + +#if defined(OS_MACOSX) && !defined(OS_IOS) + ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT, os_buffer.type); + base::SharedMemoryHandle memory_handle( + static_cast<mach_port_t>(os_buffer.value), size, + base::GetCurrentProcId()); +#elif defined(OS_POSIX) + ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR, os_buffer.type); + base::SharedMemoryHandle memory_handle(static_cast<int>(os_buffer.value), + false); +#elif defined(OS_WIN) + ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE, os_buffer.type); + base::SharedMemoryHandle memory_handle( + reinterpret_cast<HANDLE>(os_buffer.value), base::GetCurrentProcId()); +#endif + + base::SharedMemory memory(memory_handle, read_only); + memory.Map(message.size()); + ASSERT_TRUE(memory.memory()); + + EXPECT_TRUE(std::equal(message.begin(), message.end(), + static_cast<const char*>(memory.memory()))); +} + +TEST_F(PlatformWrapperTest, InvalidHandle) { + // Wrap an invalid platform handle and expect to unwrap the same. + + MojoHandle wrapped_handle; + MojoPlatformHandle invalid_handle; + invalid_handle.struct_size = sizeof(MojoPlatformHandle); + invalid_handle.type = MOJO_PLATFORM_HANDLE_TYPE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, + MojoWrapPlatformHandle(&invalid_handle, &wrapped_handle)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoUnwrapPlatformHandle(wrapped_handle, &invalid_handle)); + EXPECT_EQ(MOJO_PLATFORM_HANDLE_TYPE_INVALID, invalid_handle.type); +} + +TEST_F(PlatformWrapperTest, InvalidArgument) { + // Try to wrap an invalid MojoPlatformHandle struct and expect an error. + MojoHandle wrapped_handle; + MojoPlatformHandle platform_handle; + platform_handle.struct_size = 0; + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoWrapPlatformHandle(&platform_handle, &wrapped_handle)); +} + +} // namespace +} // namespace edk +} // namespace mojo |