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.
5 #include "mojo/system/raw_channel.h"
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"
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
,
45 bytes
.empty() ? NULL
: &bytes
[0]));
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
))
57 void InitOnIOThread(RawChannel
* raw_channel
, RawChannel::Delegate
* delegate
) {
58 CHECK(raw_channel
->Init(delegate
));
61 bool WriteTestMessageToHandle(const embedder::PlatformHandle
& handle
,
63 scoped_ptr
<MessageInTransit
> message(MakeTestMessage(num_bytes
));
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();
71 // -----------------------------------------------------------------------------
73 class RawChannelTest
: public testing::Test
{
75 RawChannelTest() : io_thread_(base::TestIOThread::kManualStart
) {}
76 virtual ~RawChannelTest() {}
78 virtual void SetUp() OVERRIDE
{
79 embedder::PlatformChannelPair channel_pair
;
80 handles
[0] = channel_pair
.PassServerHandle();
81 handles
[1] = channel_pair
.PassClientHandle();
85 virtual void TearDown() OVERRIDE
{
92 base::TestIOThread
* io_thread() { return &io_thread_
; }
94 embedder::ScopedPlatformHandle handles
[2];
97 base::TestIOThread io_thread_
;
99 DISALLOW_COPY_AND_ASSIGN(RawChannelTest
);
102 // RawChannelTest.WriteMessage -------------------------------------------------
104 class WriteOnlyRawChannelDelegate
: public RawChannel::Delegate
{
106 WriteOnlyRawChannelDelegate() {}
107 virtual ~WriteOnlyRawChannelDelegate() {}
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.
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
);
121 DISALLOW_COPY_AND_ASSIGN(WriteOnlyRawChannelDelegate
);
124 static const int64_t kMessageReaderSleepMs
= 1;
125 static const size_t kMessageReaderMaxPollIterations
= 3000;
127 class TestMessageReaderAndChecker
{
129 explicit TestMessageReaderAndChecker(embedder::PlatformHandle handle
)
131 ~TestMessageReaderAndChecker() { CHECK(bytes_
.empty()); }
133 bool ReadAndCheckNextMessage(uint32_t expected_size
) {
134 unsigned char buffer
[4096];
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
));
141 // Append newly-read data to |bytes_|.
142 bytes_
.insert(bytes_
.end(), buffer
, buffer
+ read_size
);
144 // If we have the header....
146 if (MessageInTransit::GetNextMessageSize(
147 bytes_
.empty() ? NULL
: &bytes_
[0],
150 // If we've read the whole message....
151 if (bytes_
.size() >= message_size
) {
153 MessageInTransit::View
message_view(message_size
, &bytes_
[0]);
154 CHECK_EQ(message_view
.main_buffer_size(), message_size
);
156 if (message_view
.num_bytes() != expected_size
) {
157 LOG(ERROR
) << "Wrong size: " << message_size
<< " instead of "
158 << expected_size
<< " bytes.";
160 } else if (!CheckMessageData(message_view
.bytes(),
161 message_view
.num_bytes())) {
162 LOG(ERROR
) << "Incorrect message bytes.";
166 // Erase message data.
167 bytes_
.erase(bytes_
.begin(),
168 bytes_
.begin() + message_view
.main_buffer_size());
173 if (static_cast<size_t>(read_size
) < sizeof(buffer
)) {
175 base::PlatformThread::Sleep(
176 base::TimeDelta::FromMilliseconds(kMessageReaderSleepMs
));
180 LOG(ERROR
) << "Too many iterations.";
185 const embedder::PlatformHandle handle_
;
187 // The start of the received data should always be on a message boundary.
188 std::vector
<unsigned char> bytes_
;
190 DISALLOW_COPY_AND_ASSIGN(TestMessageReaderAndChecker
);
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(
200 base::Bind(&InitOnIOThread
, rc
.get(), base::Unretained(&delegate
)));
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
;
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
;
214 io_thread()->PostTaskAndWait(
215 FROM_HERE
, base::Bind(&RawChannel::Shutdown
, base::Unretained(rc
.get())));
218 // RawChannelTest.OnReadMessage ------------------------------------------------
220 class ReadCheckerRawChannelDelegate
: public RawChannel::Delegate
{
222 ReadCheckerRawChannelDelegate() : done_event_(false, false), position_(0) {}
223 virtual ~ReadCheckerRawChannelDelegate() {}
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
);
232 size_t expected_size
;
233 bool should_signal
= false;
235 base::AutoLock
locker(lock_
);
236 CHECK_LT(position_
, expected_sizes_
.size());
237 position
= position_
;
238 expected_size
= expected_sizes_
[position
];
240 if (position_
>= expected_sizes_
.size())
241 should_signal
= true;
244 EXPECT_EQ(expected_size
, message_view
.num_bytes()) << position
;
245 if (message_view
.num_bytes() == expected_size
) {
247 CheckMessageData(message_view
.bytes(), message_view
.num_bytes()))
252 done_event_
.Signal();
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
);
259 // Waits for all the messages (of sizes |expected_sizes_|) to be seen.
260 void Wait() { done_event_
.Wait(); }
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
;
270 base::WaitableEvent done_event_
;
272 base::Lock lock_
; // Protects the following members.
273 std::vector
<uint32_t> expected_sizes_
;
276 DISALLOW_COPY_AND_ASSIGN(ReadCheckerRawChannelDelegate
);
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(
285 base::Bind(&InitOnIOThread
, rc
.get(), base::Unretained(&delegate
)));
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
));
291 EXPECT_TRUE(WriteTestMessageToHandle(handles
[1].get(), size
));
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
));
306 io_thread()->PostTaskAndWait(
307 FROM_HERE
, base::Bind(&RawChannel::Shutdown
, base::Unretained(rc
.get())));
310 // RawChannelTest.WriteMessageAndOnReadMessage ---------------------------------
312 class RawChannelWriterThread
: public base::SimpleThread
{
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
) {}
319 virtual ~RawChannelWriterThread() { Join(); }
322 virtual void Run() OVERRIDE
{
323 static const int kMaxRandomMessageSize
= 25000;
325 while (left_to_write_
-- > 0) {
326 EXPECT_TRUE(raw_channel_
->WriteMessage(MakeTestMessage(
327 static_cast<uint32_t>(base::RandInt(1, kMaxRandomMessageSize
)))));
331 RawChannel
* const raw_channel_
;
332 size_t left_to_write_
;
334 DISALLOW_COPY_AND_ASSIGN(RawChannelWriterThread
);
337 class ReadCountdownRawChannelDelegate
: public RawChannel::Delegate
{
339 explicit ReadCountdownRawChannelDelegate(size_t expected_count
)
340 : done_event_(false, false), expected_count_(expected_count
), count_(0) {}
341 virtual ~ReadCountdownRawChannelDelegate() {}
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
);
349 EXPECT_LT(count_
, expected_count_
);
353 CheckMessageData(message_view
.bytes(), message_view
.num_bytes()));
355 if (count_
>= expected_count_
)
356 done_event_
.Signal();
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
);
363 // Waits for all the messages to have been seen.
364 void Wait() { done_event_
.Wait(); }
367 base::WaitableEvent done_event_
;
368 size_t expected_count_
;
371 DISALLOW_COPY_AND_ASSIGN(ReadCountdownRawChannelDelegate
);
374 TEST_F(RawChannelTest
, WriteMessageAndOnReadMessage
) {
375 static const size_t kNumWriterThreads
= 10;
376 static const size_t kNumWriteMessagesPerThread
= 4000;
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
,
383 base::Unretained(&writer_delegate
)));
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
,
391 base::Unretained(&reader_delegate
)));
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
));
399 for (size_t i
= 0; i
< writer_threads
.size(); i
++)
400 writer_threads
[i
]->Start();
401 } // Joins all the writer threads.
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));
407 // Wait for reading to finish.
408 reader_delegate
.Wait();
410 io_thread()->PostTaskAndWait(
412 base::Bind(&RawChannel::Shutdown
, base::Unretained(reader_rc
.get())));
414 io_thread()->PostTaskAndWait(
416 base::Bind(&RawChannel::Shutdown
, base::Unretained(writer_rc
.get())));
419 // RawChannelTest.OnError ------------------------------------------------------
421 class ErrorRecordingRawChannelDelegate
422 : public ReadCountdownRawChannelDelegate
{
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
) {}
433 virtual ~ErrorRecordingRawChannelDelegate() {}
435 virtual void OnError(Error error
) OVERRIDE
{
437 case ERROR_READ_SHUTDOWN
:
438 ASSERT_TRUE(expecting_read_error_
);
439 expecting_read_error_
= false;
440 got_read_error_event_
.Signal();
442 case ERROR_READ_BROKEN
:
443 // TODO(vtl): Test broken connections.
446 case ERROR_READ_BAD_MESSAGE
:
447 // TODO(vtl): Test reception/detection of bad messages.
450 case ERROR_READ_UNKNOWN
:
451 // TODO(vtl): Test however it is we might get here.
455 ASSERT_TRUE(expecting_write_error_
);
456 expecting_write_error_
= false;
457 got_write_error_event_
.Signal();
462 void WaitForReadError() { got_read_error_event_
.Wait(); }
463 void WaitForWriteError() { got_write_error_event_
.Wait(); }
466 base::WaitableEvent got_read_error_event_
;
467 base::WaitableEvent got_write_error_event_
;
469 bool expecting_read_error_
;
470 bool expecting_write_error_
;
472 DISALLOW_COPY_AND_ASSIGN(ErrorRecordingRawChannelDelegate
);
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(
481 base::Bind(&InitOnIOThread
, rc
.get(), base::Unretained(&delegate
)));
483 // Close the handle of the other end, which should make writing fail.
486 EXPECT_FALSE(rc
->WriteMessage(MakeTestMessage(1)));
488 // We should get a write error.
489 delegate
.WaitForWriteError();
491 // We should also get a read error.
492 delegate
.WaitForReadError();
494 EXPECT_FALSE(rc
->WriteMessage(MakeTestMessage(2)));
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));
500 io_thread()->PostTaskAndWait(
501 FROM_HERE
, base::Bind(&RawChannel::Shutdown
, base::Unretained(rc
.get())));
504 // RawChannelTest.ReadUnaffectedByWriteError -----------------------------------
506 TEST_F(RawChannelTest
, ReadUnaffectedByWriteError
) {
507 const size_t kMessageCount
= 5;
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
));
515 // Close the other end, which should make writing fail.
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(
524 base::Bind(&InitOnIOThread
, rc
.get(), base::Unretained(&delegate
)));
526 EXPECT_FALSE(rc
->WriteMessage(MakeTestMessage(1)));
528 // We should definitely get a write error.
529 delegate
.WaitForWriteError();
531 // Wait for reading to finish. A writing failure shouldn't affect reading.
534 // And then we should get a read error.
535 delegate
.WaitForReadError();
537 io_thread()->PostTaskAndWait(
538 FROM_HERE
, base::Bind(&RawChannel::Shutdown
, base::Unretained(rc
.get())));
541 // RawChannelTest.WriteMessageAfterShutdown ------------------------------------
543 // Makes sure that calling |WriteMessage()| after |Shutdown()| behaves
545 TEST_F(RawChannelTest
, WriteMessageAfterShutdown
) {
546 WriteOnlyRawChannelDelegate delegate
;
547 scoped_ptr
<RawChannel
> rc(RawChannel::Create(handles
[0].Pass()));
548 io_thread()->PostTaskAndWait(
550 base::Bind(&InitOnIOThread
, rc
.get(), base::Unretained(&delegate
)));
551 io_thread()->PostTaskAndWait(
552 FROM_HERE
, base::Bind(&RawChannel::Shutdown
, base::Unretained(rc
.get())));
554 EXPECT_FALSE(rc
->WriteMessage(MakeTestMessage(1)));
557 // RawChannelTest.ShutdownOnReadMessage ----------------------------------------
559 class ShutdownOnReadMessageRawChannelDelegate
: public RawChannel::Delegate
{
561 explicit ShutdownOnReadMessageRawChannelDelegate(RawChannel
* raw_channel
)
562 : raw_channel_(raw_channel
),
563 done_event_(false, false),
564 did_shutdown_(false) {}
565 virtual ~ShutdownOnReadMessageRawChannelDelegate() {}
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_
);
574 CheckMessageData(message_view
.bytes(), message_view
.num_bytes()));
575 raw_channel_
->Shutdown();
576 did_shutdown_
= true;
577 done_event_
.Signal();
579 virtual void OnError(Error
/*error*/) OVERRIDE
{
580 CHECK(false); // Should not get called.
583 // Waits for shutdown.
586 EXPECT_TRUE(did_shutdown_
);
590 RawChannel
* const raw_channel_
;
591 base::WaitableEvent done_event_
;
594 DISALLOW_COPY_AND_ASSIGN(ShutdownOnReadMessageRawChannelDelegate
);
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));
602 scoped_ptr
<RawChannel
> rc(RawChannel::Create(handles
[0].Pass()));
603 ShutdownOnReadMessageRawChannelDelegate
delegate(rc
.get());
604 io_thread()->PostTaskAndWait(
606 base::Bind(&InitOnIOThread
, rc
.get(), base::Unretained(&delegate
)));
608 // Wait for the delegate, which will shut the |RawChannel| down.
612 // RawChannelTest.ShutdownOnError{Read, Write} ---------------------------------
614 class ShutdownOnErrorRawChannelDelegate
: public RawChannel::Delegate
{
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() {}
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.
630 virtual void OnError(Error error
) OVERRIDE
{
631 EXPECT_FALSE(did_shutdown_
);
632 if (error
!= shutdown_on_error_type_
)
634 raw_channel_
->Shutdown();
635 did_shutdown_
= true;
636 done_event_
.Signal();
639 // Waits for shutdown.
642 EXPECT_TRUE(did_shutdown_
);
646 RawChannel
* const raw_channel_
;
647 const Error shutdown_on_error_type_
;
648 base::WaitableEvent done_event_
;
651 DISALLOW_COPY_AND_ASSIGN(ShutdownOnErrorRawChannelDelegate
);
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(
660 base::Bind(&InitOnIOThread
, rc
.get(), base::Unretained(&delegate
)));
662 // Close the handle of the other end, which should stuff fail.
665 // Wait for the delegate, which will shut the |RawChannel| down.
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(
675 base::Bind(&InitOnIOThread
, rc
.get(), base::Unretained(&delegate
)));
677 // Close the handle of the other end, which should stuff fail.
680 EXPECT_FALSE(rc
->WriteMessage(MakeTestMessage(1)));
682 // Wait for the delegate, which will shut the |RawChannel| down.
687 } // namespace system