Update To 11.40.268.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   ~ListenerThatExpectsOK() override {}
31
32   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   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   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   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   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   void OnChannelConnected(int32 peer_pid) override {
169     base::MessageLoop::current()->Quit();
170   }
171
172   bool OnMessageReceived(const IPC::Message& message) override { return true; }
173
174   void OnChannelError() override {
175     has_error_ = true;
176     base::MessageLoop::current()->Quit();
177   }
178
179   bool has_error() const { return has_error_; }
180
181  private:
182   bool has_error_;
183 };
184
185
186 class IPCChannelMojoErrorTest : public IPCTestBase {
187  protected:
188   scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
189       const IPC::ChannelHandle& handle,
190       base::TaskRunner* runner) override {
191     host_.reset(new IPC::ChannelMojoHost(task_runner()));
192     return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
193                                                  handle);
194   }
195
196   bool DidStartClient() override {
197     bool ok = IPCTestBase::DidStartClient();
198     DCHECK(ok);
199     host_->OnClientLaunched(client_process());
200     return ok;
201   }
202
203  private:
204   scoped_ptr<IPC::ChannelMojoHost> host_;
205 };
206
207 class ListenerThatQuits : public IPC::Listener {
208  public:
209   ListenerThatQuits() {
210   }
211
212   bool OnMessageReceived(const IPC::Message& message) override {
213     return true;
214   }
215
216   void OnChannelConnected(int32 peer_pid) override {
217     base::MessageLoop::current()->Quit();
218   }
219 };
220
221 // A long running process that connects to us.
222 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
223   ListenerThatQuits listener;
224   ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
225   client.Connect();
226
227   base::MessageLoop::current()->Run();
228
229   return 0;
230 }
231
232 TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
233   Init("IPCChannelMojoErraticTestClient");
234
235   // Set up IPC channel and start client.
236   ListenerExpectingErrors listener;
237   CreateChannel(&listener);
238   ASSERT_TRUE(ConnectChannel());
239
240   // This matches a value in mojo/edk/system/constants.h
241   const int kMaxMessageNumBytes = 4 * 1024 * 1024;
242   std::string overly_large_data(kMaxMessageNumBytes, '*');
243   // This messages are queued as pending.
244   for (size_t i = 0; i < 10; ++i) {
245     IPC::TestChannelListener::SendOneMessage(
246         sender(), overly_large_data.c_str());
247   }
248
249   ASSERT_TRUE(StartClient());
250   base::MessageLoop::current()->Run();
251
252   this->channel()->Close();
253
254   EXPECT_TRUE(WaitForClientShutdown());
255   EXPECT_TRUE(listener.has_error());
256
257   DestroyChannel();
258 }
259
260 #if defined(OS_WIN)
261 class IPCChannelMojoDeadHandleTest : public IPCTestBase {
262  protected:
263   virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
264       const IPC::ChannelHandle& handle,
265       base::TaskRunner* runner) override {
266     host_.reset(new IPC::ChannelMojoHost(task_runner()));
267     return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
268                                                  handle);
269   }
270
271   virtual bool DidStartClient() override {
272     IPCTestBase::DidStartClient();
273     base::ProcessHandle client = client_process();
274     // Forces GetFileHandleForProcess() fail. It happens occasionally
275     // in production, so we should exercise it somehow.
276     ::CloseHandle(client);
277     host_->OnClientLaunched(client);
278     return true;
279   }
280
281  private:
282   scoped_ptr<IPC::ChannelMojoHost> host_;
283 };
284
285 TEST_F(IPCChannelMojoDeadHandleTest, InvalidClientHandle) {
286   // Any client type is fine as it is going to be killed anyway.
287   Init("IPCChannelMojoTestDoNothingClient");
288
289   // Set up IPC channel and start client.
290   ListenerExpectingErrors listener;
291   CreateChannel(&listener);
292   ASSERT_TRUE(ConnectChannel());
293
294   ASSERT_TRUE(StartClient());
295   base::MessageLoop::current()->Run();
296
297   this->channel()->Close();
298
299   // WaitForClientShutdown() fails as client_hanadle() is already
300   // closed.
301   EXPECT_FALSE(WaitForClientShutdown());
302   EXPECT_TRUE(listener.has_error());
303
304   DestroyChannel();
305 }
306
307 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient) {
308   ListenerThatQuits listener;
309   ChannelClient client(&listener, "IPCChannelMojoTestDoNothingClient");
310   client.Connect();
311
312   // Quits without running the message loop as this client won't
313   // receive any messages from the server.
314
315   return 0;
316 }
317 #endif
318
319 #if defined(OS_POSIX)
320 class ListenerThatExpectsFile : public IPC::Listener {
321  public:
322   ListenerThatExpectsFile()
323       : sender_(NULL) {}
324
325   ~ListenerThatExpectsFile() override {}
326
327   bool OnMessageReceived(const IPC::Message& message) override {
328     PickleIterator iter(message);
329
330     base::ScopedFD fd;
331     EXPECT_TRUE(message.ReadFile(&iter, &fd));
332     base::File file(fd.release());
333     std::string content(GetSendingFileContent().size(), ' ');
334     file.Read(0, &content[0], content.size());
335     EXPECT_EQ(content, GetSendingFileContent());
336     base::MessageLoop::current()->Quit();
337     ListenerThatExpectsOK::SendOK(sender_);
338     return true;
339   }
340
341   void OnChannelError() override {
342     NOTREACHED();
343   }
344
345   static std::string GetSendingFileContent() {
346     return "Hello";
347   }
348
349   static base::FilePath GetSendingFilePath() {
350     base::FilePath path;
351     bool ok = PathService::Get(base::DIR_CACHE, &path);
352     EXPECT_TRUE(ok);
353     return path.Append("ListenerThatExpectsFile.txt");
354   }
355
356   static void WriteAndSendFile(IPC::Sender* sender, base::File& file) {
357     std::string content = GetSendingFileContent();
358     file.WriteAtCurrentPos(content.data(), content.size());
359     file.Flush();
360     IPC::Message* message = new IPC::Message(
361         0, 2, IPC::Message::PRIORITY_NORMAL);
362     message->WriteFile(base::ScopedFD(file.TakePlatformFile()));
363     ASSERT_TRUE(sender->Send(message));
364   }
365
366   void set_sender(IPC::Sender* sender) { sender_ = sender; }
367
368  private:
369   IPC::Sender* sender_;
370 };
371
372
373 TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
374   Init("IPCChannelMojoTestSendPlatformHandleClient");
375
376   ListenerThatExpectsOK listener;
377   CreateChannel(&listener);
378   ASSERT_TRUE(ConnectChannel());
379   ASSERT_TRUE(StartClient());
380
381   base::File file(ListenerThatExpectsFile::GetSendingFilePath(),
382                   base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
383                   base::File::FLAG_READ);
384   ListenerThatExpectsFile::WriteAndSendFile(channel(), file);
385   base::MessageLoop::current()->Run();
386
387   this->channel()->Close();
388
389   EXPECT_TRUE(WaitForClientShutdown());
390   DestroyChannel();
391 }
392
393 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
394   ListenerThatExpectsFile listener;
395   ChannelClient client(
396       &listener, "IPCChannelMojoTestSendPlatformHandleClient");
397   client.Connect();
398   listener.set_sender(client.channel());
399
400   base::MessageLoop::current()->Run();
401
402   return 0;
403 }
404 #endif
405
406 }  // namespace