Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: chrome/nacl/nacl_ipc_adapter_unittest.cc

Issue 16881004: Move chrome/nacl to components/nacl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Create a zygote folder Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/nacl/nacl_ipc_adapter.cc ('k') | chrome/nacl/nacl_listener.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chrome/nacl/nacl_ipc_adapter.h"
6
7 #include <string.h>
8
9 #include "base/memory/scoped_ptr.h"
10 #include "base/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"
19
20 namespace {
21
22 class NaClIPCAdapterTest : public testing::Test {
23 public:
24 NaClIPCAdapterTest() {}
25
26 // testing::Test implementation.
27 virtual void SetUp() OVERRIDE {
28 sink_ = new IPC::TestSink;
29
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());
35 }
36 virtual void TearDown() OVERRIDE {
37 sink_ = NULL; // This pointer is actually owned by the IPCAdapter.
38 adapter_ = NULL;
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();
43 }
44
45 protected:
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);
50 }
51
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);
56 }
57
58 base::MessageLoop message_loop_;
59
60 scoped_refptr<NaClIPCAdapter> adapter_;
61
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.
66 //
67 // In real life the adapter needs to take ownership so the channel can be
68 // destroyed on the right thread.
69 IPC::TestSink* sink_;
70 };
71
72 } // namespace
73
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();
80
81 int value = 0x12345678;
82 input.WriteInt(value);
83 adapter_->OnMessageReceived(input);
84
85 // Buffer just need to be big enough for our message with one int.
86 const int kBufSize = 64;
87 char buf[kBufSize];
88
89 int bytes_read = BlockingReceive(buf, kBufSize);
90 EXPECT_EQ(sizeof(NaClIPCAdapter::NaClMessageHeader) + sizeof(int),
91 static_cast<size_t>(bytes_read));
92
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);
101
102 // Validate the payload.
103 EXPECT_EQ(value,
104 *reinterpret_cast<const int*>(&buf[
105 sizeof(NaClIPCAdapter::NaClMessageHeader)]));
106 }
107
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;
113
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};
117
118 NaClIPCAdapter::NaClMessageHeader* header =
119 reinterpret_cast<NaClIPCAdapter::NaClMessageHeader*>(buf);
120 header->payload_size = sizeof(int);
121 header->routing = routing_id;
122 header->type = type;
123 header->flags = 0;
124 header->num_fds = 0;
125 *reinterpret_cast<int*>(
126 &buf[sizeof(NaClIPCAdapter::NaClMessageHeader)]) = value;
127
128 int result = Send(buf, buf_size);
129 EXPECT_EQ(buf_size, result);
130
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);
136
137 EXPECT_EQ(sizeof(int), msg->payload_size());
138 EXPECT_EQ(header->routing, msg->routing_id());
139 EXPECT_EQ(header->type, msg->type());
140
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);
147
148 // First partial send should not have made any messages.
149 message_loop_.RunUntilIdle();
150 ASSERT_EQ(0u, sink_->message_count());
151
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());
158
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],
162 third_chunk_size);
163 EXPECT_EQ(third_chunk_size, result);
164
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());
172 }
173
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);
182
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);
189
190 const int kBufSize = 64;
191 char buf[kBufSize];
192
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);
197
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));
203
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);
210
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));
215 output_header =
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);
220 }
221
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;
229
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};
235
236 NaClIPCAdapter::NaClMessageHeader* header =
237 reinterpret_cast<NaClIPCAdapter::NaClMessageHeader*>(buf);
238 header->payload_size = sizeof(int);
239 header->routing = routing_id;
240 header->type = type;
241 header->flags = 0;
242 header->num_fds = 0;
243 *reinterpret_cast<int*>(
244 &buf[sizeof(NaClIPCAdapter::NaClMessageHeader)]) = value;
245
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());
251
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);
256
257 // First partial send should not have made any messages.
258 message_loop_.RunUntilIdle();
259 ASSERT_EQ(0u, sink_->message_count());
260
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());
266 }
267
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 {
278 public:
279 explicit MyThread(NaClIPCAdapter* adapter)
280 : SimpleThread("NaClIPCAdapterThread"),
281 adapter_(adapter) {}
282 virtual void Run() OVERRIDE {
283 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
284 adapter_->OnChannelError();
285 }
286 private:
287 scoped_refptr<NaClIPCAdapter> adapter_;
288 };
289 MyThread thread(adapter_.get());
290
291 // IMPORTANT: do not return early from here down (including ASSERT_*) because
292 // the thread needs to joined or it will assert.
293 thread.Start();
294
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
297 // after 1s.
298 const int kBufSize = 64;
299 char buf[kBufSize];
300 int result = BlockingReceive(buf, kBufSize);
301 EXPECT_EQ(-1, result);
302
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);
307
308 thread.Join();
309 }
310
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_RDWR,
319 TranslatePepperFileReadWriteOpenFlagsForTesting(
320 PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE));
321
322 // The flags other than PP_FILEOPENFLAG_READ and PP_FILEOPENFLAG_WRITE are
323 // discared.
324 EXPECT_EQ(NACL_ABI_O_WRONLY,
325 TranslatePepperFileReadWriteOpenFlagsForTesting(
326 PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE));
327 EXPECT_EQ(NACL_ABI_O_WRONLY,
328 TranslatePepperFileReadWriteOpenFlagsForTesting(
329 PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_TRUNCATE));
330 EXPECT_EQ(NACL_ABI_O_WRONLY,
331 TranslatePepperFileReadWriteOpenFlagsForTesting(
332 PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_EXCLUSIVE));
333
334 // If neither of PP_FILEOPENFLAG_READ and PP_FILEOPENFLAG_WRITE is set, falls
335 // back NACL_ABI_O_READONLY
336 EXPECT_EQ(NACL_ABI_O_RDONLY,
337 TranslatePepperFileReadWriteOpenFlagsForTesting(PP_FILEOPENFLAG_CREATE));
338 EXPECT_EQ(NACL_ABI_O_RDONLY,
339 TranslatePepperFileReadWriteOpenFlagsForTesting(
340 PP_FILEOPENFLAG_TRUNCATE));
341 EXPECT_EQ(NACL_ABI_O_RDONLY,
342 TranslatePepperFileReadWriteOpenFlagsForTesting(
343 PP_FILEOPENFLAG_EXCLUSIVE));
344 }
OLDNEW
« no previous file with comments | « chrome/nacl/nacl_ipc_adapter.cc ('k') | chrome/nacl/nacl_listener.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698