1 // Copyright 2013 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.
5 #include "components/nacl/loader/nacl_ipc_adapter.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/threading/platform_thread.h"
12 #include "base/threading/simple_thread.h"
13 #include "ipc/ipc_test_sink.h"
14 #include "native_client/src/public/nacl_desc_custom.h"
15 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
16 #include "ppapi/c/ppb_file_io.h"
17 #include "testing/gtest/include/gtest/gtest.h"
21 class NaClIPCAdapterTest
: public testing::Test
{
23 NaClIPCAdapterTest() {}
25 // testing::Test implementation.
26 void SetUp() override
{
27 sink_
= new IPC::TestSink
;
29 // Takes ownership of the sink_ pointer. Note we provide the current message
30 // loop instead of using a real IO thread. This should work OK since we do
31 // not need real IPC for the tests.
32 adapter_
= new NaClIPCAdapter(scoped_ptr
<IPC::Channel
>(sink_
),
33 base::ThreadTaskRunnerHandle::Get().get());
35 void TearDown() override
{
36 sink_
= NULL
; // This pointer is actually owned by the IPCAdapter.
38 // The adapter destructor has to post a task to destroy the Channel on the
39 // IO thread. For the purposes of the test, we just need to make sure that
40 // task gets run, or it will appear as a leak.
41 message_loop_
.RunUntilIdle();
45 int BlockingReceive(void* buf
, size_t buf_size
) {
46 NaClImcMsgIoVec iov
= {buf
, buf_size
};
47 NaClImcTypedMsgHdr msg
= {&iov
, 1};
48 return adapter_
->BlockingReceive(&msg
);
51 int Send(void* buf
, size_t buf_size
) {
52 NaClImcMsgIoVec iov
= {buf
, buf_size
};
53 NaClImcTypedMsgHdr msg
= {&iov
, 1};
54 return adapter_
->Send(&msg
);
57 base::MessageLoop message_loop_
;
59 scoped_refptr
<NaClIPCAdapter
> adapter_
;
61 // Messages sent from nacl to the adapter end up here. Note that we create
62 // this pointer and pass ownership of it to the IPC adapter, who will keep
63 // it alive as long as the adapter is alive. This means that when the
64 // adapter goes away, this pointer will become invalid.
66 // In real life the adapter needs to take ownership so the channel can be
67 // destroyed on the right thread.
73 // Tests a simple message getting rewritten sent from native code to NaCl.
74 TEST_F(NaClIPCAdapterTest
, SimpleReceiveRewriting
) {
75 int routing_id
= 0x89898989;
76 uint32 type
= 0x55555555;
77 IPC::Message
input(routing_id
, type
, IPC::Message::PRIORITY_NORMAL
);
78 uint32 flags
= input
.flags();
80 int value
= 0x12345678;
81 input
.WriteInt(value
);
82 adapter_
->OnMessageReceived(input
);
84 // Buffer just need to be big enough for our message with one int.
85 const int kBufSize
= 64;
88 int bytes_read
= BlockingReceive(buf
, kBufSize
);
89 EXPECT_EQ(sizeof(NaClIPCAdapter::NaClMessageHeader
) + sizeof(int),
90 static_cast<size_t>(bytes_read
));
92 const NaClIPCAdapter::NaClMessageHeader
* output_header
=
93 reinterpret_cast<const NaClIPCAdapter::NaClMessageHeader
*>(buf
);
94 EXPECT_EQ(sizeof(int), output_header
->payload_size
);
95 EXPECT_EQ(routing_id
, output_header
->routing
);
96 EXPECT_EQ(type
, output_header
->type
);
97 EXPECT_EQ(flags
, output_header
->flags
);
98 EXPECT_EQ(0u, output_header
->num_fds
);
99 EXPECT_EQ(0u, output_header
->pad
);
101 // Validate the payload.
103 *reinterpret_cast<const int*>(&buf
[
104 sizeof(NaClIPCAdapter::NaClMessageHeader
)]));
107 // Tests a simple message getting rewritten sent from NaCl to native code.
108 TEST_F(NaClIPCAdapterTest
, SendRewriting
) {
109 int routing_id
= 0x89898989;
110 uint32 type
= 0x55555555;
111 int value
= 0x12345678;
113 // Send a message with one int inside it.
114 const int buf_size
= sizeof(NaClIPCAdapter::NaClMessageHeader
) + sizeof(int);
115 char buf
[buf_size
] = {0};
117 NaClIPCAdapter::NaClMessageHeader
* header
=
118 reinterpret_cast<NaClIPCAdapter::NaClMessageHeader
*>(buf
);
119 header
->payload_size
= sizeof(int);
120 header
->routing
= routing_id
;
124 *reinterpret_cast<int*>(
125 &buf
[sizeof(NaClIPCAdapter::NaClMessageHeader
)]) = value
;
127 int result
= Send(buf
, buf_size
);
128 EXPECT_EQ(buf_size
, result
);
130 // Check that the message came out the other end in the test sink
131 // (messages are posted, so we have to pump).
132 message_loop_
.RunUntilIdle();
133 ASSERT_EQ(1u, sink_
->message_count());
134 const IPC::Message
* msg
= sink_
->GetMessageAt(0);
136 EXPECT_EQ(sizeof(int), msg
->payload_size());
137 EXPECT_EQ(header
->routing
, msg
->routing_id());
138 EXPECT_EQ(header
->type
, msg
->type());
140 // Now test the partial send case. We should be able to break the message
141 // into two parts and it should still work.
142 sink_
->ClearMessages();
143 int first_chunk_size
= 7;
144 result
= Send(buf
, first_chunk_size
);
145 EXPECT_EQ(first_chunk_size
, result
);
147 // First partial send should not have made any messages.
148 message_loop_
.RunUntilIdle();
149 ASSERT_EQ(0u, sink_
->message_count());
151 // Second partial send should do the same.
152 int second_chunk_size
= 2;
153 result
= Send(&buf
[first_chunk_size
], second_chunk_size
);
154 EXPECT_EQ(second_chunk_size
, result
);
155 message_loop_
.RunUntilIdle();
156 ASSERT_EQ(0u, sink_
->message_count());
158 // Send the rest of the message in a third chunk.
159 int third_chunk_size
= buf_size
- first_chunk_size
- second_chunk_size
;
160 result
= Send(&buf
[first_chunk_size
+ second_chunk_size
],
162 EXPECT_EQ(third_chunk_size
, result
);
164 // Last send should have generated one message.
165 message_loop_
.RunUntilIdle();
166 ASSERT_EQ(1u, sink_
->message_count());
167 msg
= sink_
->GetMessageAt(0);
168 EXPECT_EQ(sizeof(int), msg
->payload_size());
169 EXPECT_EQ(header
->routing
, msg
->routing_id());
170 EXPECT_EQ(header
->type
, msg
->type());
173 // Tests when a buffer is too small to receive the entire message.
174 TEST_F(NaClIPCAdapterTest
, PartialReceive
) {
175 int routing_id_1
= 0x89898989;
176 uint32 type_1
= 0x55555555;
177 IPC::Message
input_1(routing_id_1
, type_1
, IPC::Message::PRIORITY_NORMAL
);
178 int value_1
= 0x12121212;
179 input_1
.WriteInt(value_1
);
180 adapter_
->OnMessageReceived(input_1
);
182 int routing_id_2
= 0x90909090;
183 uint32 type_2
= 0x66666666;
184 IPC::Message
input_2(routing_id_2
, type_2
, IPC::Message::PRIORITY_NORMAL
);
185 int value_2
= 0x23232323;
186 input_2
.WriteInt(value_2
);
187 adapter_
->OnMessageReceived(input_2
);
189 const int kBufSize
= 64;
192 // Read part of the first message.
193 int bytes_requested
= 7;
194 int bytes_read
= BlockingReceive(buf
, bytes_requested
);
195 ASSERT_EQ(bytes_requested
, bytes_read
);
197 // Read the rest, this should give us the rest of the first message only.
198 bytes_read
+= BlockingReceive(&buf
[bytes_requested
],
199 kBufSize
- bytes_requested
);
200 EXPECT_EQ(sizeof(NaClIPCAdapter::NaClMessageHeader
) + sizeof(int),
201 static_cast<size_t>(bytes_read
));
203 // Make sure we got the right message.
204 const NaClIPCAdapter::NaClMessageHeader
* output_header
=
205 reinterpret_cast<const NaClIPCAdapter::NaClMessageHeader
*>(buf
);
206 EXPECT_EQ(sizeof(int), output_header
->payload_size
);
207 EXPECT_EQ(routing_id_1
, output_header
->routing
);
208 EXPECT_EQ(type_1
, output_header
->type
);
210 // Read the second message to make sure we went on to it.
211 bytes_read
= BlockingReceive(buf
, kBufSize
);
212 EXPECT_EQ(sizeof(NaClIPCAdapter::NaClMessageHeader
) + sizeof(int),
213 static_cast<size_t>(bytes_read
));
215 reinterpret_cast<const NaClIPCAdapter::NaClMessageHeader
*>(buf
);
216 EXPECT_EQ(sizeof(int), output_header
->payload_size
);
217 EXPECT_EQ(routing_id_2
, output_header
->routing
);
218 EXPECT_EQ(type_2
, output_header
->type
);
221 // Tests sending messages that are too large. We test sends that are too
222 // small implicitly here and in the success case because in that case it
223 // succeeds and buffers the data.
224 TEST_F(NaClIPCAdapterTest
, SendOverflow
) {
225 int routing_id
= 0x89898989;
226 uint32 type
= 0x55555555;
227 int value
= 0x12345678;
229 // Make a message with one int inside it. Reserve some extra space so
230 // we can test what happens when we send too much data.
231 const int buf_size
= sizeof(NaClIPCAdapter::NaClMessageHeader
) + sizeof(int);
232 const int big_buf_size
= buf_size
+ 4;
233 char buf
[big_buf_size
] = {0};
235 NaClIPCAdapter::NaClMessageHeader
* header
=
236 reinterpret_cast<NaClIPCAdapter::NaClMessageHeader
*>(buf
);
237 header
->payload_size
= sizeof(int);
238 header
->routing
= routing_id
;
242 *reinterpret_cast<int*>(
243 &buf
[sizeof(NaClIPCAdapter::NaClMessageHeader
)]) = value
;
245 // Send too much data and make sure that the send fails.
246 int result
= Send(buf
, big_buf_size
);
247 EXPECT_EQ(-1, result
);
248 message_loop_
.RunUntilIdle();
249 ASSERT_EQ(0u, sink_
->message_count());
251 // Send too much data in two chunks and make sure that the send fails.
252 int first_chunk_size
= 7;
253 result
= Send(buf
, first_chunk_size
);
254 EXPECT_EQ(first_chunk_size
, result
);
256 // First partial send should not have made any messages.
257 message_loop_
.RunUntilIdle();
258 ASSERT_EQ(0u, sink_
->message_count());
260 int second_chunk_size
= big_buf_size
- first_chunk_size
;
261 result
= Send(&buf
[first_chunk_size
], second_chunk_size
);
262 EXPECT_EQ(-1, result
);
263 message_loop_
.RunUntilIdle();
264 ASSERT_EQ(0u, sink_
->message_count());
267 // Tests that when the IPC channel reports an error, that waiting reads are
268 // unblocked and return a -1 error code.
269 TEST_F(NaClIPCAdapterTest
, ReadWithChannelError
) {
270 // Have a background thread that waits a bit and calls the channel error
271 // handler. This should wake up any waiting threads and immediately return
272 // -1. There is an inherent race condition in that we can't be sure if the
273 // other thread is actually waiting when this happens. This is OK, since the
274 // behavior (which we also explicitly test later) is to return -1 if the
275 // channel has already had an error when you start waiting.
276 class MyThread
: public base::SimpleThread
{
278 explicit MyThread(NaClIPCAdapter
* adapter
)
279 : SimpleThread("NaClIPCAdapterThread"),
281 void Run() override
{
282 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
283 adapter_
->OnChannelError();
286 scoped_refptr
<NaClIPCAdapter
> adapter_
;
288 MyThread
thread(adapter_
.get());
290 // IMPORTANT: do not return early from here down (including ASSERT_*) because
291 // the thread needs to joined or it will assert.
294 // Request data. This will normally (modulo races) block until data is
295 // received or there is an error, and the thread above will wake us up
297 const int kBufSize
= 64;
299 int result
= BlockingReceive(buf
, kBufSize
);
300 EXPECT_EQ(-1, result
);
302 // Test the "previously had an error" case. BlockingReceive should return
303 // immediately if there was an error.
304 result
= BlockingReceive(buf
, kBufSize
);
305 EXPECT_EQ(-1, result
);
310 // Tests that TranslatePepperFileOpenFlags translates pepper read/write open
311 // flags into NaCl open flags correctly.
312 TEST_F(NaClIPCAdapterTest
, TranslatePepperFileReadWriteOpenFlags
) {
313 EXPECT_EQ(NACL_ABI_O_RDONLY
,
314 TranslatePepperFileReadWriteOpenFlagsForTesting(PP_FILEOPENFLAG_READ
));
315 EXPECT_EQ(NACL_ABI_O_WRONLY
,
316 TranslatePepperFileReadWriteOpenFlagsForTesting(PP_FILEOPENFLAG_WRITE
));
317 EXPECT_EQ(NACL_ABI_O_WRONLY
| NACL_ABI_O_APPEND
,
318 TranslatePepperFileReadWriteOpenFlagsForTesting(
319 PP_FILEOPENFLAG_APPEND
));
320 EXPECT_EQ(NACL_ABI_O_RDWR
,
321 TranslatePepperFileReadWriteOpenFlagsForTesting(
322 PP_FILEOPENFLAG_READ
| PP_FILEOPENFLAG_WRITE
));
323 EXPECT_EQ(NACL_ABI_O_WRONLY
| NACL_ABI_O_APPEND
,
324 TranslatePepperFileReadWriteOpenFlagsForTesting(
325 PP_FILEOPENFLAG_APPEND
));
326 EXPECT_EQ(NACL_ABI_O_RDWR
| NACL_ABI_O_APPEND
,
327 TranslatePepperFileReadWriteOpenFlagsForTesting(
328 PP_FILEOPENFLAG_READ
| PP_FILEOPENFLAG_APPEND
));
330 // Flags other than PP_FILEOPENFLAG_READ, PP_FILEOPENFLAG_WRITE, and
331 // PP_FILEOPENFLAG_APPEND are discarded.
332 EXPECT_EQ(NACL_ABI_O_WRONLY
,
333 TranslatePepperFileReadWriteOpenFlagsForTesting(
334 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_CREATE
));
335 EXPECT_EQ(NACL_ABI_O_WRONLY
,
336 TranslatePepperFileReadWriteOpenFlagsForTesting(
337 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_TRUNCATE
));
338 EXPECT_EQ(NACL_ABI_O_WRONLY
,
339 TranslatePepperFileReadWriteOpenFlagsForTesting(
340 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_EXCLUSIVE
));
342 // If none of PP_FILEOPENFLAG_READ, PP_FILEOPENFLAG_WRITE, and
343 // PP_FILEOPENFLAG_APPEND are set, the result should fall back to
344 // NACL_ABI_O_READONLY.
345 EXPECT_EQ(NACL_ABI_O_RDONLY
,
346 TranslatePepperFileReadWriteOpenFlagsForTesting(0));
347 EXPECT_EQ(NACL_ABI_O_RDONLY
,
348 TranslatePepperFileReadWriteOpenFlagsForTesting(
349 PP_FILEOPENFLAG_CREATE
));
350 EXPECT_EQ(NACL_ABI_O_RDONLY
,
351 TranslatePepperFileReadWriteOpenFlagsForTesting(
352 PP_FILEOPENFLAG_TRUNCATE
));
353 EXPECT_EQ(NACL_ABI_O_RDONLY
,
354 TranslatePepperFileReadWriteOpenFlagsForTesting(
355 PP_FILEOPENFLAG_EXCLUSIVE
));