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

Side by Side Diff: mojo/system/raw_channel_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698