blob: 915029df56ffbfa3cd3de81c6276e0e579d74115 [file] [log] [blame]
morrita@chromium.org15996aa2014-08-05 08:44:17 +09001// 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
17#if defined(OS_POSIX)
18#include "base/file_descriptor_posix.h"
19#endif
20
21namespace {
22
23class ListenerThatExpectsOK : public IPC::Listener {
24 public:
25 ListenerThatExpectsOK() {}
26
27 virtual ~ListenerThatExpectsOK() {}
28
29 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
30 PickleIterator iter(message);
31 std::string should_be_ok;
32 EXPECT_TRUE(iter.ReadString(&should_be_ok));
33 EXPECT_EQ(should_be_ok, "OK");
34 base::MessageLoop::current()->Quit();
35 return true;
36 }
37
38 virtual void OnChannelError() OVERRIDE {
39 NOTREACHED();
40 }
41
42 static void SendOK(IPC::Sender* sender) {
43 IPC::Message* message = new IPC::Message(
44 0, 2, IPC::Message::PRIORITY_NORMAL);
45 message->WriteString(std::string("OK"));
46 ASSERT_TRUE(sender->Send(message));
47 }
48};
49
50class ListenerThatShouldBeNeverCalled : public IPC::Listener {
51 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
52 NOTREACHED();
53 return true;
54 }
55
56 virtual void OnChannelError() OVERRIDE {
57 NOTREACHED();
58 }
59
60 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
61 NOTREACHED();
62 }
63
64 virtual void OnBadMessageReceived(const IPC::Message& message) OVERRIDE {
65 NOTREACHED();
66 }
67};
68
69class ChannelClient {
70 public:
71 explicit ChannelClient(IPC::Listener* listener, const char* name) {
72 scoped_ptr<IPC::Channel> bootstrap(IPC::Channel::CreateClient(
73 IPCTestBase::GetChannelName(name),
74 &never_called_));
75 channel_ = IPC::ChannelMojo::Create(
76 bootstrap.Pass(), IPC::Channel::MODE_CLIENT, listener,
77 main_message_loop_.message_loop_proxy());
78 }
79
80 void Connect() {
81 CHECK(channel_->Connect());
82 }
83
84 IPC::ChannelMojo* channel() const { return channel_.get(); }
85
86 private:
87 scoped_ptr<IPC::ChannelMojo> channel_;
88 ListenerThatShouldBeNeverCalled never_called_;
89 base::MessageLoopForIO main_message_loop_;
90};
91
92class IPCChannelMojoTest : public IPCTestBase {
93 public:
94 void CreateMojoChannel(IPC::Listener* listener);
95
96 protected:
97 virtual void SetUp() OVERRIDE {
98 IPCTestBase::SetUp();
99 }
100
101 ListenerThatShouldBeNeverCalled never_called_;
102};
103
104
105void IPCChannelMojoTest::CreateMojoChannel(IPC::Listener* listener) {
106 CreateChannel(&never_called_);
107 scoped_ptr<IPC::Channel> mojo_channel = IPC::ChannelMojo::Create(
108 ReleaseChannel(), IPC::Channel::MODE_SERVER, listener,
109 io_thread_task_runner()).PassAs<IPC::Channel>();
110 SetChannel(mojo_channel.PassAs<IPC::Channel>());
111}
112
113class TestChannelListenerWithExtraExpectations
114 : public IPC::TestChannelListener {
115 public:
116 TestChannelListenerWithExtraExpectations()
117 : is_connected_called_(false) {
118 }
119
120 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
121 IPC::TestChannelListener::OnChannelConnected(peer_pid);
122 EXPECT_TRUE(base::kNullProcessId != peer_pid);
123 is_connected_called_ = true;
124 }
125
126 bool is_connected_called() const { return is_connected_called_; }
127
128 private:
129 bool is_connected_called_;
130};
131
132TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
133 Init("IPCChannelMojoTestClient");
134
135 // Set up IPC channel and start client.
136 TestChannelListenerWithExtraExpectations listener;
137 CreateMojoChannel(&listener);
138 listener.Init(sender());
139 ASSERT_TRUE(ConnectChannel());
140 ASSERT_TRUE(StartClient());
141
142 IPC::TestChannelListener::SendOneMessage(
143 sender(), "hello from parent");
144
145 base::MessageLoop::current()->Run();
146 EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());
147
148 this->channel()->Close();
149
150 EXPECT_TRUE(WaitForClientShutdown());
151 EXPECT_TRUE(listener.is_connected_called());
152 EXPECT_TRUE(listener.HasSentAll());
153
154 DestroyChannel();
155}
156
157// A long running process that connects to us
158MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
159 TestChannelListenerWithExtraExpectations listener;
160 ChannelClient client(&listener, "IPCChannelMojoTestClient");
161 client.Connect();
162 listener.Init(client.channel());
163
164 IPC::TestChannelListener::SendOneMessage(
165 client.channel(), "hello from child");
166 base::MessageLoop::current()->Run();
167 EXPECT_TRUE(listener.is_connected_called());
168 EXPECT_TRUE(listener.HasSentAll());
169
170 return 0;
171}
172
173#if defined(OS_POSIX)
174class ListenerThatExpectsFile : public IPC::Listener {
175 public:
176 ListenerThatExpectsFile()
177 : sender_(NULL) {}
178
179 virtual ~ListenerThatExpectsFile() {}
180
181 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
182 PickleIterator iter(message);
183 base::FileDescriptor desc;
184 EXPECT_TRUE(message.ReadFileDescriptor(&iter, &desc));
185 std::string content(GetSendingFileContent().size(), ' ');
186 base::File file(desc.fd);
187 file.Read(0, &content[0], content.size());
188 EXPECT_EQ(content, GetSendingFileContent());
189 base::MessageLoop::current()->Quit();
190 ListenerThatExpectsOK::SendOK(sender_);
191 return true;
192 }
193
194 virtual void OnChannelError() OVERRIDE {
195 NOTREACHED();
196 }
197
198 static std::string GetSendingFileContent() {
199 return "Hello";
200 }
201
202 static base::FilePath GetSendingFilePath() {
203 base::FilePath path;
204 bool ok = PathService::Get(base::DIR_CACHE, &path);
205 EXPECT_TRUE(ok);
206 return path.Append("ListenerThatExpectsFile.txt");
207 }
208
209 static void WriteAndSendFile(IPC::Sender* sender, base::File& file) {
210 std::string content = GetSendingFileContent();
211 file.WriteAtCurrentPos(content.data(), content.size());
212 file.Flush();
213 IPC::Message* message = new IPC::Message(
214 0, 2, IPC::Message::PRIORITY_NORMAL);
215 message->WriteFileDescriptor(
216 base::FileDescriptor(file.TakePlatformFile(), false));
217 ASSERT_TRUE(sender->Send(message));
218 }
219
220 void set_sender(IPC::Sender* sender) { sender_ = sender; }
221
222 private:
223 IPC::Sender* sender_;
224};
225
226
227TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
228 Init("IPCChannelMojoTestSendPlatformHandleClient");
229
230 ListenerThatExpectsOK listener;
231 CreateMojoChannel(&listener);
232 ASSERT_TRUE(ConnectChannel());
233 ASSERT_TRUE(StartClient());
234
235 base::File file(ListenerThatExpectsFile::GetSendingFilePath(),
236 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
237 base::File::FLAG_READ);
238 ListenerThatExpectsFile::WriteAndSendFile(channel(), file);
239 base::MessageLoop::current()->Run();
240
241 this->channel()->Close();
242
243 EXPECT_TRUE(WaitForClientShutdown());
244 DestroyChannel();
245}
246
247MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
248 ListenerThatExpectsFile listener;
249 ChannelClient client(
250 &listener, "IPCChannelMojoTestSendPlatformHandleClient");
251 client.Connect();
252 listener.set_sender(client.channel());
253
254 base::MessageLoop::current()->Run();
255
256 return 0;
257}
258#endif
259
260} // namespace