Index: ipc/sync_socket_unittest.cc |
=================================================================== |
--- ipc/sync_socket_unittest.cc (revision 0) |
+++ ipc/sync_socket_unittest.cc (revision 0) |
@@ -0,0 +1,211 @@ |
+// Copyright (c) 2009 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 <stdio.h> |
+#include <iostream> |
+#include <string> |
+#include <sstream> |
+ |
+#include "base/message_loop.h" |
+#include "base/platform_thread.h" |
+#include "base/process_util.h" |
+#include "base/sync_socket.h" |
+#include "ipc/ipc_channel.h" |
+#include "ipc/ipc_channel_proxy.h" |
+#include "ipc/ipc_message_utils.h" |
+#include "ipc/ipc_tests.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "testing/multiprocess_func_list.h" |
+ |
+ |
+// We don't actually use the messages defined in this file, but we do this |
+// to get to the IPC macros. |
+#define MESSAGES_INTERNAL_FILE "ipc/ipc_sync_message_unittest.h" |
+#include "ipc/ipc_message_macros.h" |
+ |
+enum IPCMessageIds { |
+ UNUSED_IPC_TYPE, |
+ SERVER_FIRST_IPC_TYPE, // SetHandle message sent to server. |
+ SERVER_SECOND_IPC_TYPE, // Shutdown message sent to server. |
+ CLIENT_FIRST_IPC_TYPE // Response message sent to client. |
+}; |
+ |
+namespace { |
+const char kHelloString[] = "Hello, SyncSocket Client"; |
+const size_t kHelloStringLength = arraysize(kHelloString); |
+} // namespace |
+ |
+// Message class to pass a HANDLE to another process. |
+class MsgClassSetHandle |
+ : public IPC::MessageWithTuple< Tuple1<base::SyncSocket::Handle> > { |
+ public: |
+ enum { ID = SERVER_FIRST_IPC_TYPE }; |
+ explicit MsgClassSetHandle(const base::SyncSocket::Handle arg1) |
+ : IPC::MessageWithTuple< Tuple1<base::SyncSocket::Handle> >( |
+ MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1)) {} |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MsgClassSetHandle); |
+}; |
+ |
+// Message class to pass a response to the server. |
+class MsgClassResponse |
+ : public IPC::MessageWithTuple< Tuple1<std::string> > { |
+ public: |
+ enum { ID = CLIENT_FIRST_IPC_TYPE }; |
+ explicit MsgClassResponse(const std::string& arg1) |
+ : IPC::MessageWithTuple< Tuple1<std::string> >( |
+ MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1)) {} |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MsgClassResponse); |
+}; |
+ |
+// Message class to tell the server to shut down. |
+class MsgClassShutdown |
+ : public IPC::MessageWithTuple< Tuple0 > { |
+ public: |
+ enum { ID = SERVER_SECOND_IPC_TYPE }; |
+ MsgClassShutdown() |
+ : IPC::MessageWithTuple< Tuple0 >( |
+ MSG_ROUTING_CONTROL, ID, MakeTuple()) {} |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MsgClassShutdown); |
+}; |
+ |
+// The SyncSocket server listener class processes two sorts of |
+// messages from the client. |
+class SyncSocketServerListener : public IPC::Channel::Listener { |
+ public: |
+ SyncSocketServerListener() : chan_(NULL) { |
+ } |
+ |
+ void Init(IPC::Channel* chan) { |
+ chan_ = chan; |
+ } |
+ |
+ virtual void OnMessageReceived(const IPC::Message& msg) { |
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) { |
+ IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg) |
+ IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle) |
+ IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown) |
+ IPC_END_MESSAGE_MAP() |
+ } |
+ } |
+ |
+ private: |
+ // This sort of message is sent first, causing the transfer of |
+ // the handle for the SyncSocket. This message sends a buffer |
+ // on the SyncSocket and then sends a response to the client. |
+ void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) { |
+ base::SyncSocket sync_socket(handle); |
+ EXPECT_EQ(sync_socket.Send(static_cast<const void*>(kHelloString), |
+ kHelloStringLength), kHelloStringLength); |
+ IPC::Message* msg = new MsgClassResponse(kHelloString); |
+ EXPECT_NE(msg, reinterpret_cast<IPC::Message*>(NULL)); |
+ EXPECT_TRUE(chan_->Send(msg)); |
+ } |
+ |
+ // When the client responds, it sends back a shutdown message, |
+ // which causes the message loop to exit. |
+ void OnMsgClassShutdown() { |
+ MessageLoop::current()->Quit(); |
+ } |
+ |
+ IPC::Channel* chan_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener); |
+}; |
+ |
+// Runs the fuzzing server child mode. Returns when the preset number |
+// of messages have been received. |
+MULTIPROCESS_TEST_MAIN(RunSyncSocketServer) { |
+ MessageLoopForIO main_message_loop; |
+ SyncSocketServerListener listener; |
+ IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_CLIENT, &listener); |
+ EXPECT_TRUE(chan.Connect()); |
+ listener.Init(&chan); |
+ MessageLoop::current()->Run(); |
+ return 0; |
+} |
+ |
+// The SyncSocket client listener only processes one sort of message, |
+// a response from the server. |
+class SyncSocketClientListener : public IPC::Channel::Listener { |
+ public: |
+ SyncSocketClientListener() { |
+ } |
+ |
+ void Init(base::SyncSocket* socket, IPC::Channel* chan) { |
+ socket_ = socket; |
+ chan_ = chan; |
+ } |
+ |
+ virtual void OnMessageReceived(const IPC::Message& msg) { |
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) { |
+ IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg) |
+ IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse) |
+ IPC_END_MESSAGE_MAP() |
+ } |
+ } |
+ |
+ private: |
+ // When a response is received from the server, it sends the same |
+ // string as was written on the SyncSocket. These are compared |
+ // and a shutdown message is sent back to the server. |
+ void OnMsgClassResponse(const std::string& str) { |
+ char buf[kHelloStringLength]; |
+ socket_->Receive(static_cast<void*>(buf), kHelloStringLength); |
+ EXPECT_EQ(strcmp(str.c_str(), buf), 0); |
+ IPC::Message* msg = new MsgClassShutdown(); |
+ EXPECT_NE(msg, reinterpret_cast<IPC::Message*>(NULL)); |
+ EXPECT_TRUE(chan_->Send(msg)); |
+ MessageLoop::current()->Quit(); |
+ } |
+ |
+ base::SyncSocket* socket_; |
+ IPC::Channel* chan_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SyncSocketClientListener); |
+}; |
+ |
+class SyncSocketTest : public IPCChannelTest { |
+}; |
+ |
+TEST_F(SyncSocketTest, SanityTest) { |
+ SyncSocketClientListener listener; |
+ IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_SERVER, |
+ &listener); |
+ base::ProcessHandle server_process = SpawnChild(SYNC_SOCKET_SERVER, &chan); |
+ ASSERT_TRUE(server_process); |
+ // Create a pair of SyncSockets. |
+ base::SyncSocket* pair[2]; |
+ base::SyncSocket::CreatePair(pair); |
+ base::SyncSocket::Handle target_handle; |
+#if defined(OS_WIN) |
+ // On windows we need to duplicate the handle into the server process. |
+ BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1]->handle(), |
+ server_process, &target_handle, |
+ 0, FALSE, DUPLICATE_SAME_ACCESS); |
+ EXPECT_TRUE(retval); |
+#else |
+ target_handle = pair[1]->handle(); |
+#endif // defined(OS_WIN) |
+ // Connect the channel and listener. |
+ ASSERT_TRUE(chan.Connect()); |
+ listener.Init(pair[0], &chan); |
+ // Set up a message to pass the handle to the server. |
+ IPC::Message* msg = new MsgClassSetHandle(target_handle); |
+ EXPECT_NE(msg, reinterpret_cast<IPC::Message*>(NULL)); |
+ EXPECT_TRUE(chan.Send(msg)); |
+ // Use the current thread as the I/O thread. |
+ MessageLoop::current()->Run(); |
+ // Shut down. |
+ delete pair[0]; |
+ delete pair[1]; |
+ EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000)); |
+ base::CloseProcessHandle(server_process); |
+} |
+ |
Property changes on: ipc\sync_socket_unittest.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |