X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmojo%2Fembedder%2Fplatform_channel_pair_posix_unittest.cc;h=17fb3bc8e1be48aa6117bb23514214b1b69f633b;hb=004985e17e624662a4c85c76a7654039dc83f028;hp=e03c05384285f7cb2f27575cf6113946e53b08bc;hpb=2f108dbacb161091e42a3479f4e171339b7e7623;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/mojo/embedder/platform_channel_pair_posix_unittest.cc b/src/mojo/embedder/platform_channel_pair_posix_unittest.cc index e03c053..17fb3bc 100644 --- a/src/mojo/embedder/platform_channel_pair_posix_unittest.cc +++ b/src/mojo/embedder/platform_channel_pair_posix_unittest.cc @@ -5,14 +5,21 @@ #include "mojo/embedder/platform_channel_pair.h" #include +#include #include +#include #include #include +#include #include +#include + +#include "base/file_util.h" +#include "base/files/file_path.h" #include "base/logging.h" #include "base/macros.h" -#include "build/build_config.h" +#include "mojo/embedder/platform_channel_utils_posix.h" #include "mojo/embedder/scoped_platform_handle.h" #include "testing/gtest/include/gtest/gtest.h" @@ -20,6 +27,23 @@ namespace mojo { namespace embedder { namespace { +ScopedPlatformHandle PlatformHandleFromFILE(FILE* fp) { + CHECK(fp); + return ScopedPlatformHandle(PlatformHandle(dup(fileno(fp)))); +} + +FILE* FILEFromPlatformHandle(ScopedPlatformHandle h, const char* mode) { + CHECK(h.is_valid()); + return fdopen(h.release().fd, mode); +} + +void WaitReadable(PlatformHandle h) { + struct pollfd pfds = {}; + pfds.fd = h.fd; + pfds.events = POLLIN; + CHECK_EQ(poll(&pfds, 1, -1), 1); +} + class PlatformChannelPairPosixTest : public testing::Test { public: PlatformChannelPairPosixTest() {} @@ -45,7 +69,6 @@ class PlatformChannelPairPosixTest : public testing::Test { TEST_F(PlatformChannelPairPosixTest, NoSigPipe) { PlatformChannelPair channel_pair; - ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass(); ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass(); @@ -70,18 +93,145 @@ TEST_F(PlatformChannelPairPosixTest, NoSigPipe) { if (result == -1) PLOG(WARNING) << "read (expected 0 for EOF)"; - // However, |write()|/|send()| should fail outright. - // On Mac, |SIGPIPE| needs to be suppressed on the socket itself and we can - // use |write()|/|writev()|. On Linux, we have to suppress it by using - // |send()|/|sendmsg()| with |MSG_NOSIGNAL|. -#if defined(OS_MACOSX) - result = write(server_handle.get().fd, kHello, sizeof(kHello)); -#else - result = send(server_handle.get().fd, kHello, sizeof(kHello), MSG_NOSIGNAL); -#endif + // Test our replacement for |write()|/|send()|. + result = PlatformChannelWrite(server_handle.get(), kHello, sizeof(kHello)); EXPECT_EQ(-1, result); if (errno != EPIPE) PLOG(WARNING) << "write (expected EPIPE)"; + + // Test our replacement for |writev()|/|sendv()|. + struct iovec iov[2] = { + { const_cast(kHello), sizeof(kHello) }, + { const_cast(kHello), sizeof(kHello) } + }; + result = PlatformChannelWritev(server_handle.get(), iov, 2); + EXPECT_EQ(-1, result); + if (errno != EPIPE) + PLOG(WARNING) << "write (expected EPIPE)"; +} + +TEST_F(PlatformChannelPairPosixTest, SendReceiveData) { + PlatformChannelPair channel_pair; + ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass(); + ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass(); + + for (size_t i = 0; i < 10; i++) { + std::string send_string(1 << i, 'A' + i); + + EXPECT_EQ(static_cast(send_string.size()), + PlatformChannelWrite(server_handle.get(), send_string.data(), + send_string.size())); + + WaitReadable(client_handle.get()); + + char buf[10000] = {}; + scoped_ptr received_handles; + ssize_t result = PlatformChannelRecvmsg(client_handle.get(), buf, + sizeof(buf), &received_handles); + EXPECT_EQ(static_cast(send_string.size()), result); + EXPECT_EQ(send_string, std::string(buf, static_cast(result))); + EXPECT_FALSE(received_handles); + } +} + +TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) { + PlatformChannelPair channel_pair; + ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass(); + ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass(); + + for (size_t i = 1; i < kPlatformChannelMaxNumHandles; i++) { + // Make |i| files, with the j-th file consisting of j copies of the digit i. + PlatformHandleVector platform_handles; + for (size_t j = 1; j <= i; j++) { + base::FilePath ignored; + FILE* fp = base::CreateAndOpenTemporaryFile(&ignored); + ASSERT_TRUE(fp); + platform_handles.push_back(PlatformHandleFromFILE(fp).release()); + ASSERT_TRUE(platform_handles.back().is_valid()); + fwrite(std::string(j, '0' + i).data(), 1, j, fp); + fclose(fp); + } + + // Send the FDs. + EXPECT_TRUE(PlatformChannelSendHandles(server_handle.get(), + &platform_handles[0], + platform_handles.size())); + + WaitReadable(client_handle.get()); + + char buf[100] = { 'a' }; + scoped_ptr received_handles; + EXPECT_EQ(1, PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf), + &received_handles)); + EXPECT_EQ('\0', buf[0]); + ASSERT_TRUE(received_handles); + EXPECT_EQ(i, received_handles->size()); + + for (size_t j = 0; j < received_handles->size(); j++) { + FILE* fp = FILEFromPlatformHandle( + ScopedPlatformHandle((*received_handles)[j]), "rb"); + (*received_handles)[j] = PlatformHandle(); + ASSERT_TRUE(fp); + rewind(fp); + char read_buf[100]; + size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp); + fclose(fp); + EXPECT_EQ(j + 1, bytes_read); + EXPECT_EQ(std::string(j + 1, '0' + i), std::string(read_buf, bytes_read)); + } + } +} + +TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) { + PlatformChannelPair channel_pair; + ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass(); + ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass(); + + const std::string file_contents("hello world"); + + { + base::FilePath ignored; + FILE* fp = base::CreateAndOpenTemporaryFile(&ignored); + ASSERT_TRUE(fp); + PlatformHandleVector platform_handles; + platform_handles.push_back(PlatformHandleFromFILE(fp).release()); + ASSERT_TRUE(platform_handles.back().is_valid()); + fwrite(file_contents.data(), 1, file_contents.size(), fp); + fclose(fp); + + // Send the FD. + EXPECT_TRUE(PlatformChannelSendHandles(server_handle.get(), + &platform_handles[0], + platform_handles.size())); + } + + WaitReadable(client_handle.get()); + + // Start with an invalid handle in the vector. + scoped_ptr handles(new PlatformHandleVector()); + handles->push_back(PlatformHandle()); + + char buf[100] = { 'a' }; + EXPECT_EQ(1, PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf), + &handles)); + EXPECT_EQ('\0', buf[0]); + ASSERT_TRUE(handles); + ASSERT_EQ(2u, handles->size()); + EXPECT_FALSE((*handles)[0].is_valid()); + EXPECT_TRUE((*handles)[1].is_valid()); + + { + FILE* fp = FILEFromPlatformHandle(ScopedPlatformHandle((*handles)[1]), + "rb"); + (*handles)[1] = PlatformHandle(); + ASSERT_TRUE(fp); + rewind(fp); + char read_buf[100]; + size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp); + fclose(fp); + EXPECT_EQ(file_contents.size(), bytes_read); + EXPECT_EQ(file_contents, std::string(read_buf, bytes_read)); + } } } // namespace