Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ipc / mojo / ipc_channel_mojo_unittest.cc
1 // Copyright 2014 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 "ipc/mojo/ipc_channel_mojo.h"
6
7 #include "base/base_paths.h"
8 #include "base/files/file.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/pickle.h"
12 #include "base/threading/thread.h"
13 #include "ipc/ipc_message.h"
14 #include "ipc/ipc_test_base.h"
15 #include "ipc/ipc_test_channel_listener.h"
16 #include "ipc/mojo/ipc_channel_mojo_host.h"
17 #include "ipc/mojo/ipc_channel_mojo_readers.h"
18
19 #if defined(OS_POSIX)
20 #include "base/file_descriptor_posix.h"
21 #endif
22
23 namespace {
24
25 class ListenerThatExpectsOK : public IPC::Listener {
26  public:
27   ListenerThatExpectsOK()
28       : received_ok_(false) {}
29
30   virtual ~ListenerThatExpectsOK() {}
31
32   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
33     PickleIterator iter(message);
34     std::string should_be_ok;
35     EXPECT_TRUE(iter.ReadString(&should_be_ok));
36     EXPECT_EQ(should_be_ok, "OK");
37     received_ok_ = true;
38     base::MessageLoop::current()->Quit();
39     return true;
40   }
41
42   virtual void OnChannelError() OVERRIDE {
43     // The connection should be healthy while the listener is waiting
44     // message.  An error can occur after that because the peer
45     // process dies.
46     DCHECK(received_ok_);
47   }
48
49   static void SendOK(IPC::Sender* sender) {
50     IPC::Message* message = new IPC::Message(
51         0, 2, IPC::Message::PRIORITY_NORMAL);
52     message->WriteString(std::string("OK"));
53     ASSERT_TRUE(sender->Send(message));
54   }
55
56  private:
57   bool received_ok_;
58 };
59
60 class ChannelClient {
61  public:
62   explicit ChannelClient(IPC::Listener* listener, const char* name) {
63     channel_ = IPC::ChannelMojo::Create(NULL,
64                                         IPCTestBase::GetChannelName(name),
65                                         IPC::Channel::MODE_CLIENT,
66                                         listener);
67   }
68
69   void Connect() {
70     CHECK(channel_->Connect());
71   }
72
73   IPC::ChannelMojo* channel() const { return channel_.get(); }
74
75  private:
76   base::MessageLoopForIO main_message_loop_;
77   scoped_ptr<IPC::ChannelMojo> channel_;
78 };
79
80 class IPCChannelMojoTest : public IPCTestBase {
81  protected:
82   virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
83       const IPC::ChannelHandle& handle,
84       base::TaskRunner* runner) OVERRIDE {
85     host_.reset(new IPC::ChannelMojoHost(task_runner()));
86     return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
87                                                  handle);
88   }
89
90   virtual bool DidStartClient() OVERRIDE {
91     bool ok = IPCTestBase::DidStartClient();
92     DCHECK(ok);
93     host_->OnClientLaunched(client_process());
94     return ok;
95   }
96
97  private:
98   scoped_ptr<IPC::ChannelMojoHost> host_;
99 };
100
101
102 class TestChannelListenerWithExtraExpectations
103     : public IPC::TestChannelListener {
104  public:
105   TestChannelListenerWithExtraExpectations()
106       : is_connected_called_(false) {
107   }
108
109   virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
110     IPC::TestChannelListener::OnChannelConnected(peer_pid);
111     EXPECT_TRUE(base::kNullProcessId != peer_pid);
112     is_connected_called_ = true;
113   }
114
115   bool is_connected_called() const { return is_connected_called_; }
116
117  private:
118   bool is_connected_called_;
119 };
120
121 TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
122   Init("IPCChannelMojoTestClient");
123
124   // Set up IPC channel and start client.
125   TestChannelListenerWithExtraExpectations listener;
126   CreateChannel(&listener);
127   listener.Init(sender());
128   ASSERT_TRUE(ConnectChannel());
129   ASSERT_TRUE(StartClient());
130
131   IPC::TestChannelListener::SendOneMessage(
132       sender(), "hello from parent");
133
134   base::MessageLoop::current()->Run();
135   EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());
136
137   this->channel()->Close();
138
139   EXPECT_TRUE(WaitForClientShutdown());
140   EXPECT_TRUE(listener.is_connected_called());
141   EXPECT_TRUE(listener.HasSentAll());
142
143   DestroyChannel();
144 }
145
146 // A long running process that connects to us
147 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
148   TestChannelListenerWithExtraExpectations listener;
149   ChannelClient client(&listener, "IPCChannelMojoTestClient");
150   client.Connect();
151   listener.Init(client.channel());
152
153   IPC::TestChannelListener::SendOneMessage(
154       client.channel(), "hello from child");
155   base::MessageLoop::current()->Run();
156   EXPECT_TRUE(listener.is_connected_called());
157   EXPECT_TRUE(listener.HasSentAll());
158
159   return 0;
160 }
161
162 class ListenerExpectingErrors : public IPC::Listener {
163  public:
164   ListenerExpectingErrors()
165       : has_error_(false) {
166   }
167
168   virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
169     base::MessageLoop::current()->Quit();
170   }
171
172   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
173     return true;
174   }
175
176   virtual void OnChannelError() OVERRIDE {
177     has_error_ = true;
178     base::MessageLoop::current()->Quit();
179   }
180
181   bool has_error() const { return has_error_; }
182
183  private:
184   bool has_error_;
185 };
186
187
188 class IPCChannelMojoErrorTest : public IPCTestBase {
189  protected:
190   virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
191       const IPC::ChannelHandle& handle,
192       base::TaskRunner* runner) OVERRIDE {
193     host_.reset(new IPC::ChannelMojoHost(task_runner()));
194     return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
195                                                  handle);
196   }
197
198   virtual bool DidStartClient() OVERRIDE {
199     bool ok = IPCTestBase::DidStartClient();
200     DCHECK(ok);
201     host_->OnClientLaunched(client_process());
202     return ok;
203   }
204
205  private:
206   scoped_ptr<IPC::ChannelMojoHost> host_;
207 };
208
209 class ListenerThatQuits : public IPC::Listener {
210  public:
211   ListenerThatQuits() {
212   }
213
214   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
215     return true;
216   }
217
218   virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
219     base::MessageLoop::current()->Quit();
220   }
221 };
222
223 // A long running process that connects to us.
224 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
225   ListenerThatQuits listener;
226   ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
227   client.Connect();
228
229   base::MessageLoop::current()->Run();
230
231   return 0;
232 }
233
234 TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
235   Init("IPCChannelMojoErraticTestClient");
236
237   // Set up IPC channel and start client.
238   ListenerExpectingErrors listener;
239   CreateChannel(&listener);
240   ASSERT_TRUE(ConnectChannel());
241
242   // This matches a value in mojo/system/constants.h
243   const int kMaxMessageNumBytes = 4 * 1024 * 1024;
244   std::string overly_large_data(kMaxMessageNumBytes, '*');
245   // This messages are queued as pending.
246   for (size_t i = 0; i < 10; ++i) {
247     IPC::TestChannelListener::SendOneMessage(
248         sender(), overly_large_data.c_str());
249   }
250
251   ASSERT_TRUE(StartClient());
252   base::MessageLoop::current()->Run();
253
254   this->channel()->Close();
255
256   EXPECT_TRUE(WaitForClientShutdown());
257   EXPECT_TRUE(listener.has_error());
258
259   DestroyChannel();
260 }
261
262
263 #if defined(OS_POSIX)
264 class ListenerThatExpectsFile : public IPC::Listener {
265  public:
266   ListenerThatExpectsFile()
267       : sender_(NULL) {}
268
269   virtual ~ListenerThatExpectsFile() {}
270
271   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
272     PickleIterator iter(message);
273
274     base::ScopedFD fd;
275     EXPECT_TRUE(message.ReadFile(&iter, &fd));
276     base::File file(fd.release());
277     std::string content(GetSendingFileContent().size(), ' ');
278     file.Read(0, &content[0], content.size());
279     EXPECT_EQ(content, GetSendingFileContent());
280     base::MessageLoop::current()->Quit();
281     ListenerThatExpectsOK::SendOK(sender_);
282     return true;
283   }
284
285   virtual void OnChannelError() OVERRIDE {
286     NOTREACHED();
287   }
288
289   static std::string GetSendingFileContent() {
290     return "Hello";
291   }
292
293   static base::FilePath GetSendingFilePath() {
294     base::FilePath path;
295     bool ok = PathService::Get(base::DIR_CACHE, &path);
296     EXPECT_TRUE(ok);
297     return path.Append("ListenerThatExpectsFile.txt");
298   }
299
300   static void WriteAndSendFile(IPC::Sender* sender, base::File& file) {
301     std::string content = GetSendingFileContent();
302     file.WriteAtCurrentPos(content.data(), content.size());
303     file.Flush();
304     IPC::Message* message = new IPC::Message(
305         0, 2, IPC::Message::PRIORITY_NORMAL);
306     message->WriteFile(base::ScopedFD(file.TakePlatformFile()));
307     ASSERT_TRUE(sender->Send(message));
308   }
309
310   void set_sender(IPC::Sender* sender) { sender_ = sender; }
311
312  private:
313   IPC::Sender* sender_;
314 };
315
316
317 TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
318   Init("IPCChannelMojoTestSendPlatformHandleClient");
319
320   ListenerThatExpectsOK listener;
321   CreateChannel(&listener);
322   ASSERT_TRUE(ConnectChannel());
323   ASSERT_TRUE(StartClient());
324
325   base::File file(ListenerThatExpectsFile::GetSendingFilePath(),
326                   base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
327                   base::File::FLAG_READ);
328   ListenerThatExpectsFile::WriteAndSendFile(channel(), file);
329   base::MessageLoop::current()->Run();
330
331   this->channel()->Close();
332
333   EXPECT_TRUE(WaitForClientShutdown());
334   DestroyChannel();
335 }
336
337 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
338   ListenerThatExpectsFile listener;
339   ChannelClient client(
340       &listener, "IPCChannelMojoTestSendPlatformHandleClient");
341   client.Connect();
342   listener.set_sender(client.channel());
343
344   base::MessageLoop::current()->Run();
345
346   return 0;
347 }
348 #endif
349
350 }  // namespace