OLD | NEW |
| (Empty) |
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 "mojo/edk/system/raw_channel.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 #include <stdio.h> | |
10 #include <utility> | |
11 #include <vector> | |
12 | |
13 #include "base/bind.h" | |
14 #include "base/files/file_path.h" | |
15 #include "base/files/file_util.h" | |
16 #include "base/files/scoped_file.h" | |
17 #include "base/files/scoped_temp_dir.h" | |
18 #include "base/location.h" | |
19 #include "base/logging.h" | |
20 #include "base/memory/scoped_ptr.h" | |
21 #include "base/memory/scoped_vector.h" | |
22 #include "base/rand_util.h" | |
23 #include "base/synchronization/lock.h" | |
24 #include "base/synchronization/waitable_event.h" | |
25 #include "base/test/test_io_thread.h" | |
26 #include "base/threading/simple_thread.h" | |
27 #include "build/build_config.h" | |
28 #include "mojo/edk/embedder/embedder.h" | |
29 #include "mojo/edk/embedder/embedder_internal.h" | |
30 #include "mojo/edk/embedder/platform_channel_pair.h" | |
31 #include "mojo/edk/embedder/platform_handle.h" | |
32 #include "mojo/edk/embedder/scoped_platform_handle.h" | |
33 #include "mojo/edk/system/message_in_transit.h" | |
34 #include "mojo/edk/system/test_utils.h" | |
35 #include "mojo/edk/system/transport_data.h" | |
36 #include "mojo/edk/test/test_utils.h" | |
37 #include "mojo/public/cpp/system/macros.h" | |
38 #include "testing/gtest/include/gtest/gtest.h" | |
39 | |
40 namespace mojo { | |
41 namespace edk { | |
42 namespace { | |
43 | |
44 scoped_ptr<MessageInTransit> MakeTestMessage(uint32_t num_bytes) { | |
45 std::vector<unsigned char> bytes(num_bytes, 0); | |
46 for (size_t i = 0; i < num_bytes; i++) | |
47 bytes[i] = static_cast<unsigned char>(i + num_bytes); | |
48 return make_scoped_ptr( | |
49 new MessageInTransit(MessageInTransit::Type::MESSAGE, | |
50 num_bytes, bytes.empty() ? nullptr : &bytes[0])); | |
51 } | |
52 | |
53 bool CheckMessageData(const void* bytes, uint32_t num_bytes) { | |
54 const unsigned char* b = static_cast<const unsigned char*>(bytes); | |
55 for (uint32_t i = 0; i < num_bytes; i++) { | |
56 if (b[i] != static_cast<unsigned char>(i + num_bytes)) | |
57 return false; | |
58 } | |
59 return true; | |
60 } | |
61 | |
62 void InitOnIOThread(RawChannel* raw_channel, RawChannel::Delegate* delegate) { | |
63 raw_channel->Init(delegate); | |
64 raw_channel->EnsureLazyInitialized(); | |
65 } | |
66 | |
67 bool WriteTestMessageToHandle(const PlatformHandle& handle, | |
68 uint32_t num_bytes) { | |
69 scoped_ptr<MessageInTransit> message(MakeTestMessage(num_bytes)); | |
70 | |
71 size_t write_size = 0; | |
72 test::BlockingWrite(handle, message->main_buffer(), | |
73 message->main_buffer_size(), &write_size); | |
74 return write_size == message->main_buffer_size(); | |
75 } | |
76 | |
77 // ----------------------------------------------------------------------------- | |
78 | |
79 class RawChannelTest : public testing::Test { | |
80 public: | |
81 RawChannelTest() {} | |
82 ~RawChannelTest() override {} | |
83 | |
84 void SetUp() override { | |
85 PlatformChannelPair channel_pair; | |
86 handles[0] = channel_pair.PassServerHandle(); | |
87 handles[1] = channel_pair.PassClientHandle();\ | |
88 } | |
89 | |
90 void TearDown() override { | |
91 handles[0].reset(); | |
92 handles[1].reset(); | |
93 } | |
94 | |
95 void FlushIOThread() { | |
96 base::WaitableEvent event(false, false); | |
97 internal::g_io_thread_task_runner->PostTask( | |
98 FROM_HERE, | |
99 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event))); | |
100 event.Wait(); | |
101 } | |
102 | |
103 protected: | |
104 ScopedPlatformHandle handles[2]; | |
105 | |
106 private: | |
107 MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelTest); | |
108 }; | |
109 | |
110 // RawChannelTest.WriteMessage ------------------------------------------------- | |
111 | |
112 class WriteOnlyRawChannelDelegate : public RawChannel::Delegate { | |
113 public: | |
114 WriteOnlyRawChannelDelegate() {} | |
115 ~WriteOnlyRawChannelDelegate() override {} | |
116 | |
117 // |RawChannel::Delegate| implementation: | |
118 void OnReadMessage( | |
119 const MessageInTransit::View& /*message_view*/, | |
120 ScopedPlatformHandleVectorPtr /*platform_handles*/) override { | |
121 CHECK(false); // Should not get called. | |
122 } | |
123 void OnError(Error error) override { | |
124 // We'll get a read (shutdown) error when the connection is closed. | |
125 CHECK_EQ(error, ERROR_READ_SHUTDOWN); | |
126 } | |
127 | |
128 private: | |
129 MOJO_DISALLOW_COPY_AND_ASSIGN(WriteOnlyRawChannelDelegate); | |
130 }; | |
131 | |
132 static const unsigned kMessageReaderSleepMs = 1; | |
133 static const size_t kMessageReaderMaxPollIterations = 3000; | |
134 | |
135 class TestMessageReaderAndChecker { | |
136 public: | |
137 explicit TestMessageReaderAndChecker(PlatformHandle handle) | |
138 : handle_(handle) {} | |
139 ~TestMessageReaderAndChecker() { CHECK(bytes_.empty()); } | |
140 | |
141 bool ReadAndCheckNextMessage(uint32_t expected_size) { | |
142 unsigned char buffer[4096]; | |
143 | |
144 for (size_t i = 0; i < kMessageReaderMaxPollIterations;) { | |
145 size_t read_size = 0; | |
146 CHECK(test::NonBlockingRead(handle_, buffer, sizeof(buffer), &read_size)); | |
147 | |
148 // Append newly-read data to |bytes_|. | |
149 bytes_.insert(bytes_.end(), buffer, buffer + read_size); | |
150 | |
151 // If we have the header.... | |
152 size_t message_size; | |
153 if (MessageInTransit::GetNextMessageSize( | |
154 bytes_.empty() ? nullptr : &bytes_[0], bytes_.size(), | |
155 &message_size)) { | |
156 // If we've read the whole message.... | |
157 if (bytes_.size() >= message_size) { | |
158 bool rv = true; | |
159 MessageInTransit::View message_view(message_size, &bytes_[0]); | |
160 CHECK_EQ(message_view.main_buffer_size(), message_size); | |
161 | |
162 if (message_view.num_bytes() != expected_size) { | |
163 LOG(ERROR) << "Wrong size: " << message_size << " instead of " | |
164 << expected_size << " bytes."; | |
165 rv = false; | |
166 } else if (!CheckMessageData(message_view.bytes(), | |
167 message_view.num_bytes())) { | |
168 LOG(ERROR) << "Incorrect message bytes."; | |
169 rv = false; | |
170 } | |
171 | |
172 // Erase message data. | |
173 bytes_.erase(bytes_.begin(), | |
174 bytes_.begin() + message_view.main_buffer_size()); | |
175 return rv; | |
176 } | |
177 } | |
178 | |
179 if (static_cast<size_t>(read_size) < sizeof(buffer)) { | |
180 i++; | |
181 test::Sleep(test::DeadlineFromMilliseconds(kMessageReaderSleepMs)); | |
182 } | |
183 } | |
184 | |
185 LOG(ERROR) << "Too many iterations."; | |
186 return false; | |
187 } | |
188 | |
189 private: | |
190 const PlatformHandle handle_; | |
191 | |
192 // The start of the received data should always be on a message boundary. | |
193 std::vector<unsigned char> bytes_; | |
194 | |
195 MOJO_DISALLOW_COPY_AND_ASSIGN(TestMessageReaderAndChecker); | |
196 }; | |
197 | |
198 // Tests writing (and verifies reading using our own custom reader). | |
199 TEST_F(RawChannelTest, WriteMessage) { | |
200 WriteOnlyRawChannelDelegate delegate; | |
201 RawChannel* rc = RawChannel::Create(std::move(handles[0])); | |
202 TestMessageReaderAndChecker checker(handles[1].get()); | |
203 internal::g_io_thread_task_runner->PostTask( | |
204 FROM_HERE, | |
205 base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); | |
206 | |
207 // Write and read, for a variety of sizes. | |
208 for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) { | |
209 EXPECT_TRUE(rc->WriteMessage(MakeTestMessage(size))); | |
210 EXPECT_TRUE(checker.ReadAndCheckNextMessage(size)) << size; | |
211 } | |
212 | |
213 // Write/queue and read afterwards, for a variety of sizes. | |
214 for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) | |
215 EXPECT_TRUE(rc->WriteMessage(MakeTestMessage(size))); | |
216 for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) | |
217 EXPECT_TRUE(checker.ReadAndCheckNextMessage(size)) << size; | |
218 | |
219 internal::g_io_thread_task_runner->PostTask( | |
220 FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc))); | |
221 } | |
222 | |
223 // RawChannelTest.OnReadMessage ------------------------------------------------ | |
224 | |
225 class ReadCheckerRawChannelDelegate : public RawChannel::Delegate { | |
226 public: | |
227 ReadCheckerRawChannelDelegate() : done_event_(false, false), position_(0) {} | |
228 ~ReadCheckerRawChannelDelegate() override {} | |
229 | |
230 // |RawChannel::Delegate| implementation (called on the I/O thread): | |
231 void OnReadMessage( | |
232 const MessageInTransit::View& message_view, | |
233 ScopedPlatformHandleVectorPtr platform_handles) override { | |
234 EXPECT_FALSE(platform_handles); | |
235 | |
236 size_t position; | |
237 size_t expected_size; | |
238 bool should_signal = false; | |
239 { | |
240 base::AutoLock locker(lock_); | |
241 CHECK_LT(position_, expected_sizes_.size()); | |
242 position = position_; | |
243 expected_size = expected_sizes_[position]; | |
244 position_++; | |
245 if (position_ >= expected_sizes_.size()) | |
246 should_signal = true; | |
247 } | |
248 | |
249 EXPECT_EQ(expected_size, message_view.num_bytes()) << position; | |
250 if (message_view.num_bytes() == expected_size) { | |
251 EXPECT_TRUE( | |
252 CheckMessageData(message_view.bytes(), message_view.num_bytes())) | |
253 << position; | |
254 } | |
255 | |
256 if (should_signal) | |
257 done_event_.Signal(); | |
258 } | |
259 void OnError(Error error) override { | |
260 // We'll get a read (shutdown) error when the connection is closed. | |
261 CHECK_EQ(error, ERROR_READ_SHUTDOWN); | |
262 } | |
263 | |
264 // Waits for all the messages (of sizes |expected_sizes_|) to be seen. | |
265 void Wait() { done_event_.Wait(); } | |
266 | |
267 void SetExpectedSizes(const std::vector<uint32_t>& expected_sizes) { | |
268 base::AutoLock locker(lock_); | |
269 CHECK_EQ(position_, expected_sizes_.size()); | |
270 expected_sizes_ = expected_sizes; | |
271 position_ = 0; | |
272 } | |
273 | |
274 private: | |
275 base::WaitableEvent done_event_; | |
276 | |
277 base::Lock lock_; // Protects the following members. | |
278 std::vector<uint32_t> expected_sizes_; | |
279 size_t position_; | |
280 | |
281 MOJO_DISALLOW_COPY_AND_ASSIGN(ReadCheckerRawChannelDelegate); | |
282 }; | |
283 | |
284 // Tests reading (writing using our own custom writer). | |
285 TEST_F(RawChannelTest, OnReadMessage) { | |
286 ReadCheckerRawChannelDelegate delegate; | |
287 RawChannel* rc = RawChannel::Create(std::move(handles[0])); | |
288 internal::g_io_thread_task_runner->PostTask( | |
289 FROM_HERE, | |
290 base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); | |
291 | |
292 // Write and read, for a variety of sizes. | |
293 for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) { | |
294 delegate.SetExpectedSizes(std::vector<uint32_t>(1, size)); | |
295 | |
296 EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), size)); | |
297 | |
298 delegate.Wait(); | |
299 } | |
300 | |
301 // Set up reader and write as fast as we can. | |
302 // Write/queue and read afterwards, for a variety of sizes. | |
303 std::vector<uint32_t> expected_sizes; | |
304 for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) | |
305 expected_sizes.push_back(size); | |
306 delegate.SetExpectedSizes(expected_sizes); | |
307 for (uint32_t size = 1; size < 5 * 1000 * 1000; size += size / 2 + 1) | |
308 EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), size)); | |
309 delegate.Wait(); | |
310 | |
311 internal::g_io_thread_task_runner->PostTask( | |
312 FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc))); | |
313 } | |
314 | |
315 // RawChannelTest.WriteMessageAndOnReadMessage --------------------------------- | |
316 | |
317 class RawChannelWriterThread : public base::SimpleThread { | |
318 public: | |
319 RawChannelWriterThread(RawChannel* raw_channel, size_t write_count) | |
320 : base::SimpleThread("raw_channel_writer_thread"), | |
321 raw_channel_(raw_channel), | |
322 left_to_write_(write_count) {} | |
323 | |
324 ~RawChannelWriterThread() override { Join(); } | |
325 | |
326 private: | |
327 void Run() override { | |
328 static const int kMaxRandomMessageSize = 25000; | |
329 | |
330 while (left_to_write_-- > 0) { | |
331 EXPECT_TRUE(raw_channel_->WriteMessage(MakeTestMessage( | |
332 static_cast<uint32_t>(base::RandInt(1, kMaxRandomMessageSize))))); | |
333 } | |
334 } | |
335 | |
336 RawChannel* const raw_channel_; | |
337 size_t left_to_write_; | |
338 | |
339 MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelWriterThread); | |
340 }; | |
341 | |
342 class ReadCountdownRawChannelDelegate : public RawChannel::Delegate { | |
343 public: | |
344 explicit ReadCountdownRawChannelDelegate(size_t expected_count) | |
345 : done_event_(false, false), expected_count_(expected_count), count_(0) {} | |
346 ~ReadCountdownRawChannelDelegate() override {} | |
347 | |
348 // |RawChannel::Delegate| implementation (called on the I/O thread): | |
349 void OnReadMessage( | |
350 const MessageInTransit::View& message_view, | |
351 ScopedPlatformHandleVectorPtr platform_handles) override { | |
352 EXPECT_FALSE(platform_handles); | |
353 | |
354 EXPECT_LT(count_, expected_count_); | |
355 count_++; | |
356 | |
357 EXPECT_TRUE( | |
358 CheckMessageData(message_view.bytes(), message_view.num_bytes())); | |
359 | |
360 if (count_ >= expected_count_) | |
361 done_event_.Signal(); | |
362 } | |
363 void OnError(Error error) override { | |
364 // We'll get a read (shutdown) error when the connection is closed. | |
365 CHECK_EQ(error, ERROR_READ_SHUTDOWN); | |
366 } | |
367 | |
368 // Waits for all the messages to have been seen. | |
369 void Wait() { done_event_.Wait(); } | |
370 | |
371 private: | |
372 base::WaitableEvent done_event_; | |
373 size_t expected_count_; | |
374 size_t count_; | |
375 | |
376 MOJO_DISALLOW_COPY_AND_ASSIGN(ReadCountdownRawChannelDelegate); | |
377 }; | |
378 | |
379 TEST_F(RawChannelTest, WriteMessageAndOnReadMessage) { | |
380 static const size_t kNumWriterThreads = 10; | |
381 static const size_t kNumWriteMessagesPerThread = 400; | |
382 | |
383 WriteOnlyRawChannelDelegate writer_delegate; | |
384 RawChannel* writer_rc = RawChannel::Create(std::move(handles[0])); | |
385 internal::g_io_thread_task_runner->PostTask( | |
386 FROM_HERE, | |
387 base::Bind(&InitOnIOThread, writer_rc, | |
388 base::Unretained(&writer_delegate))); | |
389 | |
390 ReadCountdownRawChannelDelegate reader_delegate(kNumWriterThreads * | |
391 kNumWriteMessagesPerThread); | |
392 RawChannel* reader_rc = RawChannel::Create(std::move(handles[1])); | |
393 internal::g_io_thread_task_runner->PostTask( | |
394 FROM_HERE, | |
395 base::Bind(&InitOnIOThread, reader_rc, | |
396 base::Unretained(&reader_delegate))); | |
397 | |
398 { | |
399 ScopedVector<RawChannelWriterThread> writer_threads; | |
400 for (size_t i = 0; i < kNumWriterThreads; i++) { | |
401 writer_threads.push_back(new RawChannelWriterThread( | |
402 writer_rc, kNumWriteMessagesPerThread)); | |
403 } | |
404 for (size_t i = 0; i < writer_threads.size(); i++) | |
405 writer_threads[i]->Start(); | |
406 } // Joins all the writer threads. | |
407 | |
408 // Sleep a bit, to let any extraneous reads be processed. (There shouldn't be | |
409 // any, but we want to know about them.) | |
410 test::Sleep(test::DeadlineFromMilliseconds(100)); | |
411 | |
412 // Wait for reading to finish. | |
413 reader_delegate.Wait(); | |
414 | |
415 internal::g_io_thread_task_runner->PostTask( | |
416 FROM_HERE, | |
417 base::Bind(&RawChannel::Shutdown, base::Unretained(reader_rc))); | |
418 | |
419 internal::g_io_thread_task_runner->PostTask( | |
420 FROM_HERE, | |
421 base::Bind(&RawChannel::Shutdown, base::Unretained(writer_rc))); | |
422 } | |
423 | |
424 // RawChannelTest.OnError ------------------------------------------------------ | |
425 | |
426 class ErrorRecordingRawChannelDelegate | |
427 : public ReadCountdownRawChannelDelegate { | |
428 public: | |
429 ErrorRecordingRawChannelDelegate(size_t expected_read_count, | |
430 bool expect_read_error, | |
431 bool expect_write_error) | |
432 : ReadCountdownRawChannelDelegate(expected_read_count), | |
433 got_read_error_event_(false, false), | |
434 got_write_error_event_(false, false), | |
435 expecting_read_error_(expect_read_error), | |
436 expecting_write_error_(expect_write_error) {} | |
437 | |
438 ~ErrorRecordingRawChannelDelegate() override {} | |
439 | |
440 void OnError(Error error) override { | |
441 switch (error) { | |
442 case ERROR_READ_SHUTDOWN: | |
443 ASSERT_TRUE(expecting_read_error_); | |
444 expecting_read_error_ = false; | |
445 got_read_error_event_.Signal(); | |
446 break; | |
447 case ERROR_READ_BROKEN: | |
448 // TODO(vtl): Test broken connections. | |
449 CHECK(false); | |
450 break; | |
451 case ERROR_READ_BAD_MESSAGE: | |
452 // TODO(vtl): Test reception/detection of bad messages. | |
453 CHECK(false); | |
454 break; | |
455 case ERROR_READ_UNKNOWN: | |
456 // TODO(vtl): Test however it is we might get here. | |
457 CHECK(false); | |
458 break; | |
459 case ERROR_WRITE: | |
460 ASSERT_TRUE(expecting_write_error_); | |
461 expecting_write_error_ = false; | |
462 got_write_error_event_.Signal(); | |
463 break; | |
464 } | |
465 } | |
466 | |
467 void WaitForReadError() { got_read_error_event_.Wait(); } | |
468 void WaitForWriteError() { got_write_error_event_.Wait(); } | |
469 | |
470 private: | |
471 base::WaitableEvent got_read_error_event_; | |
472 base::WaitableEvent got_write_error_event_; | |
473 | |
474 bool expecting_read_error_; | |
475 bool expecting_write_error_; | |
476 | |
477 MOJO_DISALLOW_COPY_AND_ASSIGN(ErrorRecordingRawChannelDelegate); | |
478 }; | |
479 | |
480 // Tests (fatal) errors. | |
481 TEST_F(RawChannelTest, OnError) { | |
482 ErrorRecordingRawChannelDelegate delegate(0, true, true); | |
483 RawChannel* rc = RawChannel::Create(std::move(handles[0])); | |
484 internal::g_io_thread_task_runner->PostTask( | |
485 FROM_HERE, | |
486 base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); | |
487 FlushIOThread(); | |
488 | |
489 // Close the handle of the other end, which should make writing fail. | |
490 handles[1].reset(); | |
491 | |
492 EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1))); | |
493 | |
494 // We should get a write error. | |
495 delegate.WaitForWriteError(); | |
496 | |
497 // We should also get a read error. | |
498 delegate.WaitForReadError(); | |
499 | |
500 EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(2))); | |
501 | |
502 // Sleep a bit, to make sure we don't get another |OnError()| | |
503 // notification. (If we actually get another one, |OnError()| crashes.) | |
504 test::Sleep(test::DeadlineFromMilliseconds(20)); | |
505 | |
506 internal::g_io_thread_task_runner->PostTask( | |
507 FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc))); | |
508 } | |
509 | |
510 // RawChannelTest.ReadUnaffectedByWriteError ----------------------------------- | |
511 | |
512 TEST_F(RawChannelTest, ReadUnaffectedByWriteError) { | |
513 const size_t kMessageCount = 5; | |
514 | |
515 // Write a few messages into the other end. | |
516 uint32_t message_size = 1; | |
517 for (size_t i = 0; i < kMessageCount; | |
518 i++, message_size += message_size / 2 + 1) | |
519 EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), message_size)); | |
520 | |
521 // Close the other end, which should make writing fail. | |
522 handles[1].reset(); | |
523 | |
524 // Only start up reading here. The system buffer should still contain the | |
525 // messages that were written. | |
526 ErrorRecordingRawChannelDelegate delegate(kMessageCount, true, true); | |
527 RawChannel* rc = RawChannel::Create(std::move(handles[0])); | |
528 internal::g_io_thread_task_runner->PostTask( | |
529 FROM_HERE, | |
530 base::Bind(&InitOnIOThread, rc, base::Unretained(&delegate))); | |
531 FlushIOThread(); | |
532 | |
533 EXPECT_FALSE(rc->WriteMessage(MakeTestMessage(1))); | |
534 | |
535 // We should definitely get a write error. | |
536 delegate.WaitForWriteError(); | |
537 | |
538 // Wait for reading to finish. A writing failure shouldn't affect reading. | |
539 delegate.Wait(); | |
540 | |
541 // And then we should get a read error. | |
542 delegate.WaitForReadError(); | |
543 | |
544 internal::g_io_thread_task_runner->PostTask( | |
545 FROM_HERE, base::Bind(&RawChannel::Shutdown, base::Unretained(rc))); | |
546 } | |
547 | |
548 // RawChannelTest.ReadWritePlatformHandles ------------------------------------- | |
549 | |
550 class ReadPlatformHandlesCheckerRawChannelDelegate | |
551 : public RawChannel::Delegate { | |
552 public: | |
553 ReadPlatformHandlesCheckerRawChannelDelegate() : done_event_(false, false) {} | |
554 ~ReadPlatformHandlesCheckerRawChannelDelegate() override {} | |
555 | |
556 // |RawChannel::Delegate| implementation (called on the I/O thread): | |
557 void OnReadMessage( | |
558 const MessageInTransit::View& message_view, | |
559 ScopedPlatformHandleVectorPtr platform_handles) override { | |
560 const char kHello[] = "hello"; | |
561 | |
562 EXPECT_EQ(sizeof(kHello), message_view.num_bytes()); | |
563 EXPECT_STREQ(kHello, static_cast<const char*>(message_view.bytes())); | |
564 | |
565 ASSERT_TRUE(platform_handles); | |
566 ASSERT_EQ(2u, platform_handles->size()); | |
567 ScopedPlatformHandle h1(platform_handles->at(0)); | |
568 EXPECT_TRUE(h1.is_valid()); | |
569 ScopedPlatformHandle h2(platform_handles->at(1)); | |
570 EXPECT_TRUE(h2.is_valid()); | |
571 platform_handles->clear(); | |
572 | |
573 { | |
574 char buffer[100] = {}; | |
575 | |
576 base::ScopedFILE fp(test::FILEFromPlatformHandle(std::move(h1), "rb")); | |
577 EXPECT_TRUE(fp); | |
578 rewind(fp.get()); | |
579 EXPECT_EQ(1u, fread(buffer, 1, sizeof(buffer), fp.get())); | |
580 EXPECT_EQ('1', buffer[0]); | |
581 } | |
582 | |
583 { | |
584 char buffer[100] = {}; | |
585 base::ScopedFILE fp(test::FILEFromPlatformHandle(std::move(h2), "rb")); | |
586 EXPECT_TRUE(fp); | |
587 rewind(fp.get()); | |
588 EXPECT_EQ(1u, fread(buffer, 1, sizeof(buffer), fp.get())); | |
589 EXPECT_EQ('2', buffer[0]); | |
590 } | |
591 | |
592 done_event_.Signal(); | |
593 } | |
594 void OnError(Error error) override { | |
595 // We'll get a read (shutdown) error when the connection is closed. | |
596 CHECK_EQ(error, ERROR_READ_SHUTDOWN); | |
597 } | |
598 | |
599 void Wait() { done_event_.Wait(); } | |
600 | |
601 private: | |
602 base::WaitableEvent done_event_; | |
603 | |
604 MOJO_DISALLOW_COPY_AND_ASSIGN(ReadPlatformHandlesCheckerRawChannelDelegate); | |
605 }; | |
606 | |
607 TEST_F(RawChannelTest, ReadWritePlatformHandles) { | |
608 base::ScopedTempDir temp_dir; | |
609 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
610 | |
611 WriteOnlyRawChannelDelegate write_delegate; | |
612 RawChannel* rc_write = RawChannel::Create(std::move(handles[0])); | |
613 internal::g_io_thread_task_runner->PostTask( | |
614 FROM_HERE, | |
615 base::Bind(&InitOnIOThread, rc_write, base::Unretained(&write_delegate))); | |
616 | |
617 ReadPlatformHandlesCheckerRawChannelDelegate read_delegate; | |
618 RawChannel* rc_read = RawChannel::Create(std::move(handles[1])); | |
619 internal::g_io_thread_task_runner->PostTask( | |
620 FROM_HERE, | |
621 base::Bind(&InitOnIOThread, rc_read, base::Unretained(&read_delegate))); | |
622 | |
623 base::FilePath unused; | |
624 base::ScopedFILE fp1( | |
625 base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); | |
626 EXPECT_EQ(1u, fwrite("1", 1, 1, fp1.get())); | |
627 base::ScopedFILE fp2( | |
628 base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); | |
629 EXPECT_EQ(1u, fwrite("2", 1, 1, fp2.get())); | |
630 | |
631 { | |
632 const char kHello[] = "hello"; | |
633 ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector()); | |
634 platform_handles->push_back( | |
635 test::PlatformHandleFromFILE(std::move(fp1)).release()); | |
636 platform_handles->push_back( | |
637 test::PlatformHandleFromFILE(std::move(fp2)).release()); | |
638 | |
639 scoped_ptr<MessageInTransit> message( | |
640 new MessageInTransit(MessageInTransit::Type::MESSAGE, | |
641 sizeof(kHello), kHello)); | |
642 message->SetTransportData(make_scoped_ptr( | |
643 new TransportData(std::move(platform_handles), | |
644 rc_write->GetSerializedPlatformHandleSize()))); | |
645 EXPECT_TRUE(rc_write->WriteMessage(std::move(message))); | |
646 } | |
647 | |
648 read_delegate.Wait(); | |
649 | |
650 internal::g_io_thread_task_runner->PostTask( | |
651 FROM_HERE, | |
652 base::Bind(&RawChannel::Shutdown, base::Unretained(rc_read))); | |
653 internal::g_io_thread_task_runner->PostTask( | |
654 FROM_HERE, | |
655 base::Bind(&RawChannel::Shutdown, base::Unretained(rc_write))); | |
656 } | |
657 | |
658 } // namespace | |
659 } // namespace edk | |
660 } // namespace mojo | |
OLD | NEW |