Initialize Tizen 2.3
[external/chromium.git] / ipc / sync_socket_unittest.cc
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/sync_socket.h"
6
7 #include <stdio.h>
8 #include <string>
9 #include <sstream>
10
11 #include "base/message_loop.h"
12 #include "base/process_util.h"
13 #include "build/build_config.h"
14 #include "ipc/ipc_channel.h"
15 #include "ipc/ipc_channel_proxy.h"
16 #include "ipc/ipc_message_macros.h"
17 #include "ipc/ipc_message_utils.h"
18 #include "ipc/ipc_message_utils_impl.h"
19 #include "ipc/ipc_tests.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "testing/multiprocess_func_list.h"
22
23 #if defined(OS_POSIX)
24 #include "base/file_descriptor_posix.h"
25 #endif
26
27 enum IPCMessageIds {
28   UNUSED_IPC_TYPE,
29   SERVER_FIRST_IPC_TYPE,    // SetHandle message sent to server.
30   SERVER_SECOND_IPC_TYPE,   // Shutdown message sent to server.
31   CLIENT_FIRST_IPC_TYPE     // Response message sent to client.
32 };
33
34 namespace {
35 const char kHelloString[] = "Hello, SyncSocket Client";
36 const size_t kHelloStringLength = arraysize(kHelloString);
37 }  // namespace
38
39 // Message class to pass a base::SyncSocket::Handle to another process.
40 // This is not as easy as it sounds, because of the differences in transferring
41 // Windows HANDLEs versus posix file descriptors.
42 #if defined(OS_WIN)
43 class MsgClassSetHandle
44     : public IPC::MessageWithTuple< Tuple1<base::SyncSocket::Handle> > {
45  public:
46   enum { ID = SERVER_FIRST_IPC_TYPE };
47   explicit MsgClassSetHandle(const base::SyncSocket::Handle arg1)
48       : IPC::MessageWithTuple< Tuple1<base::SyncSocket::Handle> >(
49             MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1)) {}
50
51  private:
52   DISALLOW_COPY_AND_ASSIGN(MsgClassSetHandle);
53 };
54 #elif defined(OS_POSIX)
55 class MsgClassSetHandle
56     : public IPC::MessageWithTuple< Tuple1<base::FileDescriptor> > {
57  public:
58   enum { ID = SERVER_FIRST_IPC_TYPE };
59   explicit MsgClassSetHandle(const base::FileDescriptor& arg1)
60       : IPC::MessageWithTuple< Tuple1<base::FileDescriptor> >(
61             MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1)) {}
62
63  private:
64   DISALLOW_COPY_AND_ASSIGN(MsgClassSetHandle);
65 };
66 #else
67 # error "What platform?"
68 #endif  // defined(OS_WIN)
69
70 // Message class to pass a response to the server.
71 class MsgClassResponse
72     : public IPC::MessageWithTuple< Tuple1<std::string> > {
73  public:
74   enum { ID = CLIENT_FIRST_IPC_TYPE };
75   explicit MsgClassResponse(const std::string& arg1)
76       : IPC::MessageWithTuple< Tuple1<std::string> >(
77             MSG_ROUTING_CONTROL, ID, MakeRefTuple(arg1)) {}
78
79  private:
80   DISALLOW_COPY_AND_ASSIGN(MsgClassResponse);
81 };
82
83 // Message class to tell the server to shut down.
84 class MsgClassShutdown
85     : public IPC::MessageWithTuple< Tuple0 > {
86  public:
87   enum { ID = SERVER_SECOND_IPC_TYPE };
88   MsgClassShutdown()
89       : IPC::MessageWithTuple< Tuple0 >(
90             MSG_ROUTING_CONTROL, ID, MakeTuple()) {}
91
92  private:
93   DISALLOW_COPY_AND_ASSIGN(MsgClassShutdown);
94 };
95
96 // The SyncSocket server listener class processes two sorts of
97 // messages from the client.
98 class SyncSocketServerListener : public IPC::Channel::Listener {
99  public:
100      SyncSocketServerListener() : chan_(NULL) {
101   }
102
103   void Init(IPC::Channel* chan) {
104     chan_ = chan;
105   }
106
107   virtual bool OnMessageReceived(const IPC::Message& msg) {
108     if (msg.routing_id() == MSG_ROUTING_CONTROL) {
109       IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg)
110         IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle)
111         IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown)
112       IPC_END_MESSAGE_MAP()
113     }
114     return true;
115   }
116
117  private:
118   // This sort of message is sent first, causing the transfer of
119   // the handle for the SyncSocket.  This message sends a buffer
120   // on the SyncSocket and then sends a response to the client.
121 #if defined(OS_WIN)
122   void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) {
123     SetHandle(handle);
124   }
125 #elif defined(OS_POSIX)
126   void OnMsgClassSetHandle(const base::FileDescriptor& fd_struct) {
127     SetHandle(fd_struct.fd);
128   }
129 #else
130 # error "What platform?"
131 #endif  // defined(OS_WIN)
132
133   void SetHandle(base::SyncSocket::Handle handle) {
134     base::SyncSocket sync_socket(handle);
135     EXPECT_EQ(sync_socket.Send(static_cast<const void*>(kHelloString),
136                                kHelloStringLength), kHelloStringLength);
137     IPC::Message* msg = new MsgClassResponse(kHelloString);
138     EXPECT_TRUE(chan_->Send(msg));
139   }
140
141   // When the client responds, it sends back a shutdown message,
142   // which causes the message loop to exit.
143   void OnMsgClassShutdown() {
144     MessageLoop::current()->Quit();
145   }
146
147   IPC::Channel* chan_;
148
149   DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener);
150 };
151
152 // Runs the fuzzing server child mode. Returns when the preset number
153 // of messages have been received.
154 MULTIPROCESS_TEST_MAIN(RunSyncSocketServer) {
155   MessageLoopForIO main_message_loop;
156   SyncSocketServerListener listener;
157   IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_CLIENT, &listener);
158   EXPECT_TRUE(chan.Connect());
159   listener.Init(&chan);
160   MessageLoop::current()->Run();
161   return 0;
162 }
163
164 // The SyncSocket client listener only processes one sort of message,
165 // a response from the server.
166 class SyncSocketClientListener : public IPC::Channel::Listener {
167  public:
168   SyncSocketClientListener() {
169   }
170
171   void Init(base::SyncSocket* socket, IPC::Channel* chan) {
172     socket_ = socket;
173     chan_ = chan;
174   }
175
176   virtual bool OnMessageReceived(const IPC::Message& msg) {
177     if (msg.routing_id() == MSG_ROUTING_CONTROL) {
178       IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg)
179         IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse)
180       IPC_END_MESSAGE_MAP()
181     }
182     return true;
183   }
184
185  private:
186   // When a response is received from the server, it sends the same
187   // string as was written on the SyncSocket.  These are compared
188   // and a shutdown message is sent back to the server.
189   void OnMsgClassResponse(const std::string& str) {
190     // We rely on the order of sync_socket.Send() and chan_->Send() in
191     // the SyncSocketServerListener object.
192     EXPECT_EQ(kHelloStringLength, socket_->Peek());
193     char buf[kHelloStringLength];
194     socket_->Receive(static_cast<void*>(buf), kHelloStringLength);
195     EXPECT_EQ(strcmp(str.c_str(), buf), 0);
196     // After receiving from the socket there should be no bytes left.
197     EXPECT_EQ(0U, socket_->Peek());
198     IPC::Message* msg = new MsgClassShutdown();
199     EXPECT_TRUE(chan_->Send(msg));
200     MessageLoop::current()->Quit();
201   }
202
203   base::SyncSocket* socket_;
204   IPC::Channel* chan_;
205
206   DISALLOW_COPY_AND_ASSIGN(SyncSocketClientListener);
207 };
208
209 class SyncSocketTest : public IPCChannelTest {
210 };
211
212 TEST_F(SyncSocketTest, SanityTest) {
213   SyncSocketClientListener listener;
214   IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_SERVER,
215                     &listener);
216   base::ProcessHandle server_process = SpawnChild(SYNC_SOCKET_SERVER, &chan);
217   ASSERT_TRUE(server_process);
218   // Create a pair of SyncSockets.
219   base::SyncSocket* pair[2];
220   base::SyncSocket::CreatePair(pair);
221   // Immediately after creation there should be no pending bytes.
222   EXPECT_EQ(0U, pair[0]->Peek());
223   EXPECT_EQ(0U, pair[1]->Peek());
224   base::SyncSocket::Handle target_handle;
225   // Connect the channel and listener.
226   ASSERT_TRUE(chan.Connect());
227   listener.Init(pair[0], &chan);
228 #if defined(OS_WIN)
229   // On windows we need to duplicate the handle into the server process.
230   BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1]->handle(),
231                                 server_process, &target_handle,
232                                 0, FALSE, DUPLICATE_SAME_ACCESS);
233   EXPECT_TRUE(retval);
234   // Set up a message to pass the handle to the server.
235   IPC::Message* msg = new MsgClassSetHandle(target_handle);
236 #else
237   target_handle = pair[1]->handle();
238   // Set up a message to pass the handle to the server.
239   base::FileDescriptor filedesc(target_handle, false);
240   IPC::Message* msg = new MsgClassSetHandle(filedesc);
241 #endif  // defined(OS_WIN)
242   EXPECT_TRUE(chan.Send(msg));
243   // Use the current thread as the I/O thread.
244   MessageLoop::current()->Run();
245   // Shut down.
246   delete pair[0];
247   delete pair[1];
248   EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
249   base::CloseProcessHandle(server_process);
250 }