diff options
author | yzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-05 18:40:13 +0000 |
---|---|---|
committer | yzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-05 18:40:13 +0000 |
commit | c6426566282ddde4f41602316f0873459caa7175 (patch) | |
tree | fc0cb72561cf72ffc54ac7a839026064c1e33e84 /mojo/common | |
parent | 807460307c2ece425c46cd150d7db2a89d38cfe0 (diff) | |
download | chromium_src-c6426566282ddde4f41602316f0873459caa7175.zip chromium_src-c6426566282ddde4f41602316f0873459caa7175.tar.gz chromium_src-c6426566282ddde4f41602316f0873459caa7175.tar.bz2 |
Implement PlatformChannelPair on Windows.
BUG=None
TEST=multiprocess_test_base_unittest works on both Windows and POSIX.
R=viettrungluu@chromium.org
Review URL: https://codereview.chromium.org/148773004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249059 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/common')
-rw-r--r-- | mojo/common/test/multiprocess_test_base.cc | 33 | ||||
-rw-r--r-- | mojo/common/test/multiprocess_test_base_unittest.cc | 132 |
2 files changed, 113 insertions, 52 deletions
diff --git a/mojo/common/test/multiprocess_test_base.cc b/mojo/common/test/multiprocess_test_base.cc index 7785b93..028990e 100644 --- a/mojo/common/test/multiprocess_test_base.cc +++ b/mojo/common/test/multiprocess_test_base.cc @@ -8,7 +8,6 @@ #include "base/logging.h" #include "base/process/kill.h" #include "base/process/process_handle.h" -// TODO(vtl): Remove build_config.h include when fully implemented on Windows. #include "build/build_config.h" #include "mojo/system/embedder/platform_channel_pair.h" @@ -28,11 +27,8 @@ void MultiprocessTestBase::SetUp() { MultiProcessTest::SetUp(); -// TODO(vtl): Not implemented on Windows yet. -#if defined(OS_POSIX) platform_channel_pair_.reset(new embedder::PlatformChannelPair()); server_platform_handle = platform_channel_pair_->PassServerHandle(); -#endif } void MultiprocessTestBase::TearDown() { @@ -51,21 +47,23 @@ void MultiprocessTestBase::StartChild(const std::string& test_child_name) { std::string test_child_main = test_child_name + "TestChildMain"; -#if defined(OS_POSIX) CommandLine unused(CommandLine::NO_PROGRAM); - base::FileHandleMappingVector fds_to_map; - platform_channel_pair_->PrepareToPassClientHandleToChildProcess(&unused, - &fds_to_map); - test_child_handle_ = SpawnChild(test_child_main, fds_to_map, false); + embedder::HandlePassingInformation handle_passing_info; + platform_channel_pair_->PrepareToPassClientHandleToChildProcess( + &unused, &handle_passing_info); + + base::LaunchOptions options; +#if defined(OS_POSIX) + options.fds_to_remap = &handle_passing_info; #elif defined(OS_WIN) - test_child_handle_ = SpawnChild(test_child_main, false); + options.start_hidden = true; + options.handles_to_inherit = &handle_passing_info; #else #error "Not supported yet." #endif -// TODO(vtl): Not implemented on Windows yet. -#if defined(OS_POSIX) + + test_child_handle_ = SpawnChildWithOptions(test_child_main, options, false); platform_channel_pair_->ChildProcessLaunched(); -#endif CHECK_NE(test_child_handle_, base::kNullProcessHandle); } @@ -88,24 +86,19 @@ CommandLine MultiprocessTestBase::MakeCmdLine(const std::string& procname, CommandLine command_line = base::MultiProcessTest::MakeCmdLine(procname, debug_on_start); -// TODO(vtl): Not implemented on Windows yet. -#if defined(OS_POSIX) - base::FileHandleMappingVector unused; + embedder::HandlePassingInformation unused; platform_channel_pair_->PrepareToPassClientHandleToChildProcess(&command_line, &unused); -#endif + return command_line; } // static void MultiprocessTestBase::ChildSetup() { CHECK(CommandLine::InitializedForCurrentProcess()); -// TODO(vtl): Not implemented on Windows yet. -#if defined(OS_POSIX) client_platform_handle = embedder::PlatformChannelPair::PassClientHandleFromParentProcess( *CommandLine::ForCurrentProcess()); -#endif } // static diff --git a/mojo/common/test/multiprocess_test_base_unittest.cc b/mojo/common/test/multiprocess_test_base_unittest.cc index 9681ee3..7b0a7ff 100644 --- a/mojo/common/test/multiprocess_test_base_unittest.cc +++ b/mojo/common/test/multiprocess_test_base_unittest.cc @@ -15,93 +15,161 @@ #include "base/posix/eintr_wrapper.h" #endif +#if defined(OS_WIN) +#include <windows.h> + +#include "base/win/windows_version.h" +#endif + namespace mojo { namespace { +// Returns true and logs a warning on Windows prior to Vista. +bool SkipTest() { +#if defined(OS_WIN) + if (base::win::GetVersion() < base::win::VERSION_VISTA) { + LOG(WARNING) << "Test skipped: Vista or later needed."; + return true; + } +#endif + + return false; +} + +bool IsNonBlocking(const embedder::PlatformHandle& handle) { +#if defined(OS_WIN) + // Haven't figured out a way to query whether a HANDLE was created with + // FILE_FLAG_OVERLAPPED. + return true; +#else + return fcntl(handle.fd, F_GETFL) & O_NONBLOCK; +#endif +} + +// Note: On POSIX, this method sets the handle to block. +bool WriteByte(const embedder::PlatformHandle& handle, char c) { +#if defined(OS_WIN) + DWORD num_bytes_written = 0; + OVERLAPPED overlapped = { 0 }; + + if (!WriteFile(handle.handle, &c, 1, &num_bytes_written, &overlapped)) { + if (GetLastError() != ERROR_IO_PENDING) + return false; + + if (GetOverlappedResult(handle.handle, &overlapped, &num_bytes_written, + TRUE)) { + return num_bytes_written == 1; + } + + return false; + } + return num_bytes_written == 1; +#else + // We're lazy. Set it to block. + PCHECK(fcntl(handle.fd, F_SETFL, 0) == 0); + + return HANDLE_EINTR(write(handle.fd, &c, 1)) == 1; +#endif +} + +// Note: On POSIX, this method sets the handle to block. +bool ReadByte(const embedder::PlatformHandle& handle, char* c) { +#if defined(OS_WIN) + DWORD num_bytes_read = 0; + OVERLAPPED overlapped = { 0 }; + + if (!ReadFile(handle.handle, c, 1, &num_bytes_read, &overlapped)) { + if (GetLastError() != ERROR_IO_PENDING) + return false; + + if (GetOverlappedResult(handle.handle, &overlapped, &num_bytes_read, TRUE)) + return num_bytes_read == 1; + + return false; + } + return num_bytes_read == 1; +#else + // We're lazy. Set it to block. + PCHECK(fcntl(handle.fd, F_SETFL, 0) == 0); + + return HANDLE_EINTR(read(handle.fd, c, 1)) == 1; +#endif +} + typedef test::MultiprocessTestBase MultiprocessTestBaseTest; TEST_F(MultiprocessTestBaseTest, RunChild) { -// TODO(vtl): Not implemented on Windows yet. -#if defined(OS_POSIX) + if (SkipTest()) + return; + EXPECT_TRUE(server_platform_handle.is_valid()); -#endif + StartChild("RunChild"); EXPECT_EQ(123, WaitForChildShutdown()); } MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild) { -// TODO(vtl): Not implemented on Windows yet. -#if defined(OS_POSIX) CHECK(MultiprocessTestBaseTest::client_platform_handle.is_valid()); -#endif return 123; } TEST_F(MultiprocessTestBaseTest, TestChildMainNotFound) { + if (SkipTest()) + return; + StartChild("NoSuchTestChildMain"); int result = WaitForChildShutdown(); EXPECT_FALSE(result >= 0 && result <= 127); } -// POSIX-specific test of passed handle ---------------------------------------- +TEST_F(MultiprocessTestBaseTest, PassedChannel) { + if (SkipTest()) + return; -#if defined(OS_POSIX) -TEST_F(MultiprocessTestBaseTest, PassedChannelPosix) { EXPECT_TRUE(server_platform_handle.is_valid()); - StartChild("PassedChannelPosix"); + StartChild("PassedChannel"); - // Take ownership of the FD. + // Take ownership of the handle. embedder::ScopedPlatformHandle handle = server_platform_handle.Pass(); - int fd = handle.get().fd; - // The FD should be non-blocking. Check this. - CHECK((fcntl(fd, F_GETFL) & O_NONBLOCK)); - // We're lazy. Set it to block. - PCHECK(fcntl(fd, F_SETFL, 0) == 0); + // The handle should be non-blocking. + EXPECT_TRUE(IsNonBlocking(handle.get())); // Write a byte. const char c = 'X'; - ssize_t write_size = HANDLE_EINTR(write(fd, &c, 1)); - EXPECT_EQ(1, write_size); + EXPECT_TRUE(WriteByte(handle.get(), c)); // It'll echo it back to us, incremented. char d = 0; - ssize_t read_size = HANDLE_EINTR(read(fd, &d, 1)); - EXPECT_EQ(1, read_size); + EXPECT_TRUE(ReadByte(handle.get(), &d)); EXPECT_EQ(c + 1, d); // And return it, incremented again. EXPECT_EQ(c + 2, WaitForChildShutdown()); } -MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PassedChannelPosix) { +MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PassedChannel) { CHECK(MultiprocessTestBaseTest::client_platform_handle.is_valid()); - // Take ownership of the FD. + // Take ownership of the handle. embedder::ScopedPlatformHandle handle = MultiprocessTestBaseTest::client_platform_handle.Pass(); - int fd = handle.get().fd; - // The FD should still be non-blocking. Check this. - CHECK((fcntl(fd, F_GETFL) & O_NONBLOCK)); - // We're lazy. Set it to block. - PCHECK(fcntl(fd, F_SETFL, 0) == 0); + // The handle should be non-blocking. + EXPECT_TRUE(IsNonBlocking(handle.get())); // Read a byte. char c = 0; - ssize_t read_size = HANDLE_EINTR(read(fd, &c, 1)); - CHECK_EQ(read_size, 1); + EXPECT_TRUE(ReadByte(handle.get(), &c)); // Write it back, incremented. c++; - ssize_t write_size = HANDLE_EINTR(write(fd, &c, 1)); - CHECK_EQ(write_size, 1); + EXPECT_TRUE(WriteByte(handle.get(), c)); // And return it, incremented again. c++; return static_cast<int>(c); } -#endif // defined(OS_POSIX) } // namespace } // namespace mojo |