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