14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// increase tolerance and reduce observed flakiness (though doing so reduces the
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// meaningfulness of the test).
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/message_pipe_dispatcher.h"
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <string.h>
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <limits>
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/memory/ref_counted.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/memory/scoped_vector.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/rand_util.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/threading/platform_thread.h"  // For |Sleep()|.
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/threading/simple_thread.h"
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/time/time.h"
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/message_pipe.h"
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/test_utils.h"
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/waiter.h"
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/waiter_test_utils.h"
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace mojo {
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace system {
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(MessagePipeDispatcherTest, Basic) {
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  test::Stopwatch stopwatch;
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int32_t buffer[1];
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32_t buffer_size;
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa.
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (unsigned i = 0; i < 2; i++) {
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher(
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MessagePipeDispatcher::kDefaultCreateOptions));
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ(Dispatcher::kTypeMessagePipe, d0->GetType());
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher(
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MessagePipeDispatcher::kDefaultCreateOptions));
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      d0->Init(mp, i);      // 0, 1.
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      d1->Init(mp, i ^ 1);  // 1, 0.
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Waiter w;
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    uint32_t context = 0;
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    HandleSignalsState hss;
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Try adding a writable waiter when already writable.
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfiable_signals);
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Shouldn't need to remove the waiter (it was not added).
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Add a readable waiter to |d0|, then make it readable (by writing to
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // |d1|), then wait.
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ASSERT_EQ(MOJO_RESULT_OK,
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr));
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 123456789;
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d1->WriteMessage(UserPointer<const void>(buffer),
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               kBufferSize,
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               nullptr,
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               MOJO_WRITE_MESSAGE_FLAG_NONE));
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    stopwatch.Start();
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    EXPECT_EQ(1u, context);
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    d0->RemoveWaiter(&w, &hss);
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfied_signals);
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfiable_signals);
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Try adding a readable waiter when already readable (from above).
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfied_signals);
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfiable_signals);
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Shouldn't need to remove the waiter (it was not added).
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Make |d0| no longer readable (by reading from it).
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 0;
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer_size = kBufferSize;
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->ReadMessage(UserPointer<void>(buffer),
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              MakeUserPointer(&buffer_size),
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              0,
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              nullptr,
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              MOJO_READ_MESSAGE_FLAG_NONE));
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(kBufferSize, buffer_size);
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(123456789, buffer[0]);
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Wait for zero time for readability on |d0| (will time out).
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ASSERT_EQ(MOJO_RESULT_OK,
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr));
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    stopwatch.Start();
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr));
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    d0->RemoveWaiter(&w, &hss);
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfiable_signals);
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Wait for non-zero, finite time for readability on |d0| (will time out).
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ASSERT_EQ(MOJO_RESULT_OK,
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr));
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    stopwatch.Start();
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), nullptr));
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::TimeDelta elapsed = stopwatch.Elapsed();
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    d0->RemoveWaiter(&w, &hss);
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfiable_signals);
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(MessagePipeDispatcherTest, InvalidParams) {
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  char buffer[1];
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<MessagePipeDispatcher> d0(
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<MessagePipeDispatcher> d1(
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    d0->Init(mp, 0);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    d1->Init(mp, 1);
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // |WriteMessage|:
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Huge buffer size.
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            d0->WriteMessage(UserPointer<const void>(buffer),
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             std::numeric_limits<uint32_t>::max(),
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             nullptr,
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// These test invalid arguments that should cause death if we're being paranoid
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// about checking arguments (which we would want to do if, e.g., we were in a
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// true "kernel" situation, but we might not want to do otherwise for
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// performance reasons). Probably blatant errors like passing in null pointers
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// (for required pointer arguments) will still cause death, but perhaps not
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// predictably.
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST(MessagePipeDispatcherTest, InvalidParamsDeath) {
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const char kMemoryCheckFailedRegex[] = "Check failed";
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<MessagePipeDispatcher> d0(
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<MessagePipeDispatcher> d1(
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  {
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    d0->Init(mp, 0);
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    d1->Init(mp, 1);
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |WriteMessage|:
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Null buffer with nonzero buffer size.
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_DEATH_IF_SUPPORTED(
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      d0->WriteMessage(
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          NullUserPointer(), 1, nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE),
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      kMemoryCheckFailedRegex);
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // |ReadMessage|:
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Null buffer with nonzero buffer size.
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // First write something so that we actually have something to read.
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(MOJO_RESULT_OK,
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            d1->WriteMessage(UserPointer<const void>("x"),
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             1,
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             nullptr,
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             MOJO_WRITE_MESSAGE_FLAG_NONE));
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32_t buffer_size = 1;
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_DEATH_IF_SUPPORTED(d0->ReadMessage(NullUserPointer(),
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            MakeUserPointer(&buffer_size),
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            0,
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            nullptr,
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            MOJO_READ_MESSAGE_FLAG_NONE),
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            kMemoryCheckFailedRegex);
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Test what happens when one end is closed (single-threaded test).
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(MessagePipeDispatcherTest, BasicClosed) {
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int32_t buffer[1];
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32_t buffer_size;
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa.
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (unsigned i = 0; i < 2; i++) {
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher(
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MessagePipeDispatcher::kDefaultCreateOptions));
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher(
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MessagePipeDispatcher::kDefaultCreateOptions));
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      d0->Init(mp, i);      // 0, 1.
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      d1->Init(mp, i ^ 1);  // 1, 0.
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Waiter w;
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    HandleSignalsState hss;
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Write (twice) to |d1|.
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 123456789;
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d1->WriteMessage(UserPointer<const void>(buffer),
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               kBufferSize,
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               nullptr,
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               MOJO_WRITE_MESSAGE_FLAG_NONE));
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 234567890;
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d1->WriteMessage(UserPointer<const void>(buffer),
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               kBufferSize,
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               nullptr,
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               MOJO_WRITE_MESSAGE_FLAG_NONE));
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Try waiting for readable on |d0|; should fail (already satisfied).
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss));
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfied_signals);
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfiable_signals);
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Try reading from |d1|; should fail (nothing to read).
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    buffer[0] = 0;
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    buffer_size = kBufferSize;
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d1->ReadMessage(UserPointer<void>(buffer),
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              MakeUserPointer(&buffer_size),
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              0,
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              nullptr,
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              MOJO_READ_MESSAGE_FLAG_NONE));
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Close |d1|.
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Try waiting for readable on |d0|; should fail (already satisfied).
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, &hss));
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Read from |d0|.
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 0;
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer_size = kBufferSize;
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->ReadMessage(UserPointer<void>(buffer),
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              MakeUserPointer(&buffer_size),
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              0,
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              nullptr,
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              MOJO_READ_MESSAGE_FLAG_NONE));
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(kBufferSize, buffer_size);
2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(123456789, buffer[0]);
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Try waiting for readable on |d0|; should fail (already satisfied).
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Read again from |d0|.
3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 0;
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer_size = kBufferSize;
3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->ReadMessage(UserPointer<void>(buffer),
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              MakeUserPointer(&buffer_size),
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              0,
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              nullptr,
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              MOJO_READ_MESSAGE_FLAG_NONE));
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(kBufferSize, buffer_size);
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(234567890, buffer[0]);
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Try waiting for readable on |d0|; should fail (unsatisfiable).
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(0u, hss.satisfied_signals);
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(0u, hss.satisfiable_signals);
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Try waiting for writable on |d0|; should fail (unsatisfiable).
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    w.Init();
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    hss = HandleSignalsState();
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(0u, hss.satisfied_signals);
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(0u, hss.satisfiable_signals);
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Try reading from |d0|; should fail (nothing to read and other end
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // closed).
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 0;
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer_size = kBufferSize;
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->ReadMessage(UserPointer<void>(buffer),
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              MakeUserPointer(&buffer_size),
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              0,
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              nullptr,
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              MOJO_READ_MESSAGE_FLAG_NONE));
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Try writing to |d0|; should fail (other end closed).
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 345678901;
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d0->WriteMessage(UserPointer<const void>(buffer),
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               kBufferSize,
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               nullptr,
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               MOJO_WRITE_MESSAGE_FLAG_NONE));
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN)
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// http://crbug.com/396386
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define MAYBE_BasicThreaded DISABLED_BasicThreaded
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define MAYBE_BasicThreaded BasicThreaded
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST(MessagePipeDispatcherTest, MAYBE_BasicThreaded) {
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  test::Stopwatch stopwatch;
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int32_t buffer[1];
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32_t buffer_size;
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::TimeDelta elapsed;
3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool did_wait;
3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  MojoResult result;
364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  uint32_t context;
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  HandleSignalsState hss;
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa.
3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (unsigned i = 0; i < 2; i++) {
369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher(
370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MessagePipeDispatcher::kDefaultCreateOptions));
371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher(
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MessagePipeDispatcher::kDefaultCreateOptions));
3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      d0->Init(mp, i);      // 0, 1.
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      d1->Init(mp, i ^ 1);  // 1, 0.
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Wait for readable on |d1|, which will become readable after some time.
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      test::WaiterThread thread(d1,
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                MOJO_HANDLE_SIGNAL_READABLE,
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                MOJO_DEADLINE_INDEFINITE,
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                1,
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &did_wait,
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &result,
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &context,
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &hss);
3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      stopwatch.Start();
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      thread.Start();
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Wake it up by writing to |d0|.
3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      buffer[0] = 123456789;
3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      EXPECT_EQ(MOJO_RESULT_OK,
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                d0->WriteMessage(UserPointer<const void>(buffer),
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 kBufferSize,
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 nullptr,
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 MOJO_WRITE_MESSAGE_FLAG_NONE));
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }  // Joins the thread.
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    elapsed = stopwatch.Elapsed();
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_TRUE(did_wait);
404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK, result);
405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    EXPECT_EQ(1u, context);
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfied_signals);
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfiable_signals);
4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Now |d1| is already readable. Try waiting for it again.
4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      test::WaiterThread thread(d1,
414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                MOJO_HANDLE_SIGNAL_READABLE,
4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                MOJO_DEADLINE_INDEFINITE,
416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                2,
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &did_wait,
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &result,
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &context,
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &hss);
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      stopwatch.Start();
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      thread.Start();
4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }  // Joins the thread.
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_FALSE(did_wait);
4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result);
4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfied_signals);
4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              hss.satisfiable_signals);
4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Consume what we wrote to |d0|.
4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 0;
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer_size = kBufferSize;
4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              d1->ReadMessage(UserPointer<void>(buffer),
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              MakeUserPointer(&buffer_size),
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              0,
4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              nullptr,
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              MOJO_READ_MESSAGE_FLAG_NONE));
4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(kBufferSize, buffer_size);
4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(123456789, buffer[0]);
4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Wait for readable on |d1| and close |d0| after some time, which should
4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // cancel that wait.
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      test::WaiterThread thread(d1,
448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                MOJO_HANDLE_SIGNAL_READABLE,
4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                MOJO_DEADLINE_INDEFINITE,
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                3,
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &did_wait,
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &result,
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &context,
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &hss);
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      stopwatch.Start();
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      thread.Start();
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }  // Joins the thread.
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    elapsed = stopwatch.Elapsed();
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_TRUE(did_wait);
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    EXPECT_EQ(3u, context);
4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(0u, hss.satisfied_signals);
4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(0u, hss.satisfiable_signals);
4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (unsigned i = 0; i < 2; i++) {
473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher(
474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MessagePipeDispatcher::kDefaultCreateOptions));
475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher(
476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MessagePipeDispatcher::kDefaultCreateOptions));
4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      d0->Init(mp, i);      // 0, 1.
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      d1->Init(mp, i ^ 1);  // 1, 0.
4814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
4824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Wait for readable on |d1| and close |d1| after some time, which should
4844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // cancel that wait.
4854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      test::WaiterThread thread(d1,
487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                MOJO_HANDLE_SIGNAL_READABLE,
4884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                MOJO_DEADLINE_INDEFINITE,
489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                4,
4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &did_wait,
4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &result,
4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &context,
4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                &hss);
4944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      stopwatch.Start();
4954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      thread.Start();
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
4984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }  // Joins the thread.
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    elapsed = stopwatch.Elapsed();
5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_TRUE(did_wait);
5034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    EXPECT_EQ(4u, context);
5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(0u, hss.satisfied_signals);
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(0u, hss.satisfiable_signals);
5074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
5094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
5104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Stress test -----------------------------------------------------------------
5134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kMaxMessageSize = 2000;
5154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class WriterThread : public base::SimpleThread {
5174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
5184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // |*messages_written| and |*bytes_written| belong to the thread while it's
5194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // alive.
5204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WriterThread(scoped_refptr<Dispatcher> write_dispatcher,
5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               size_t* messages_written,
5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               size_t* bytes_written)
5234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : base::SimpleThread("writer_thread"),
5244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        write_dispatcher_(write_dispatcher),
5254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        messages_written_(messages_written),
5264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        bytes_written_(bytes_written) {
5274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *messages_written_ = 0;
5284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *bytes_written_ = 0;
5294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
5304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ~WriterThread() { Join(); }
5324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
5344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void Run() OVERRIDE {
5354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Make some data to write.
5364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    unsigned char buffer[kMaxMessageSize];
5374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t i = 0; i < kMaxMessageSize; i++)
5384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      buffer[i] = static_cast<unsigned char>(i);
5394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Number of messages to write.
5414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *messages_written_ = static_cast<size_t>(base::RandInt(1000, 6000));
5424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Write messages.
5444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t i = 0; i < *messages_written_; i++) {
5454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      uint32_t bytes_to_write = static_cast<uint32_t>(
5464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          base::RandInt(1, static_cast<int>(kMaxMessageSize)));
5474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      EXPECT_EQ(MOJO_RESULT_OK,
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                write_dispatcher_->WriteMessage(UserPointer<const void>(buffer),
5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                bytes_to_write,
5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                nullptr,
5514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                                MOJO_WRITE_MESSAGE_FLAG_NONE));
5524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      *bytes_written_ += bytes_to_write;
5534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
5544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Write one last "quit" message.
5564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              write_dispatcher_->WriteMessage(UserPointer<const void>("quit"),
5585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              4,
5591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              nullptr,
5604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                              MOJO_WRITE_MESSAGE_FLAG_NONE));
5614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
5624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const scoped_refptr<Dispatcher> write_dispatcher_;
5644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t* const messages_written_;
5654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t* const bytes_written_;
5664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WriterThread);
5684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
5694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class ReaderThread : public base::SimpleThread {
5714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
5724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // |*messages_read| and |*bytes_read| belong to the thread while it's alive.
5734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ReaderThread(scoped_refptr<Dispatcher> read_dispatcher,
5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               size_t* messages_read,
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               size_t* bytes_read)
5764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : base::SimpleThread("reader_thread"),
5774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        read_dispatcher_(read_dispatcher),
5784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        messages_read_(messages_read),
5794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        bytes_read_(bytes_read) {
5804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *messages_read_ = 0;
5814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *bytes_read_ = 0;
5824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
5834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ~ReaderThread() { Join(); }
5854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
5874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void Run() OVERRIDE {
5884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    unsigned char buffer[kMaxMessageSize];
5894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Waiter w;
5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    HandleSignalsState hss;
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    MojoResult result;
5924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Read messages.
5944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (;;) {
5954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Wait for it to be readable.
5964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      w.Init();
5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      hss = HandleSignalsState();
5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      result =
5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          read_dispatcher_->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss);
6004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      EXPECT_TRUE(result == MOJO_RESULT_OK ||
6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  result == MOJO_RESULT_ALREADY_EXISTS)
6025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          << "result: " << result;
6034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (result == MOJO_RESULT_OK) {
6044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // Actually need to wait.
6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, nullptr));
6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        read_dispatcher_->RemoveWaiter(&w, &hss);
6074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // We may not actually be readable, since we're racing with other threads.
6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
6104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Now, try to do the read.
6124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Clear the buffer so that we can check the result.
6134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      memset(buffer, 0, sizeof(buffer));
6144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      result = read_dispatcher_->ReadMessage(UserPointer<void>(buffer),
6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             MakeUserPointer(&buffer_size),
6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             0,
6181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             nullptr,
6194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                             MOJO_READ_MESSAGE_FLAG_NONE);
6205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EXPECT_TRUE(result == MOJO_RESULT_OK || result == MOJO_RESULT_SHOULD_WAIT)
6215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          << "result: " << result;
6224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // We're racing with others to read, so maybe we failed.
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (result == MOJO_RESULT_SHOULD_WAIT)
6244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        continue;  // In which case, try again.
6254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Check for quit.
6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (buffer_size == 4 && memcmp("quit", buffer, 4) == 0)
6274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return;
6284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      EXPECT_GE(buffer_size, 1u);
6294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      EXPECT_LE(buffer_size, kMaxMessageSize);
6304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      EXPECT_TRUE(IsValidMessage(buffer, buffer_size));
6314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      (*messages_read_)++;
6334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      *bytes_read_ += buffer_size;
6344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
6354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static bool IsValidMessage(const unsigned char* buffer,
6384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             uint32_t message_size) {
6394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    size_t i;
6404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (i = 0; i < message_size; i++) {
6414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (buffer[i] != static_cast<unsigned char>(i))
6424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return false;
6434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
6444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Check that the remaining bytes weren't stomped on.
6454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (; i < kMaxMessageSize; i++) {
6464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (buffer[i] != 0)
6474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return false;
6484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
6494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
6504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const scoped_refptr<Dispatcher> read_dispatcher_;
6534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t* const messages_read_;
6544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t* const bytes_read_;
6554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ReaderThread);
6574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
6584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(MessagePipeDispatcherTest, Stress) {
6604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static const size_t kNumWriters = 30;
6614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static const size_t kNumReaders = kNumWriters;
6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<MessagePipeDispatcher> d_write(
6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
6655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<MessagePipeDispatcher> d_read(
6665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions));
6674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
6681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
6694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    d_write->Init(mp, 0);
6704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    d_read->Init(mp, 1);
6714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t messages_written[kNumWriters];
6744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t bytes_written[kNumWriters];
6754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t messages_read[kNumReaders];
6764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t bytes_read[kNumReaders];
6774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
6784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Make writers.
6794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ScopedVector<WriterThread> writers;
6804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t i = 0; i < kNumWriters; i++) {
6814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      writers.push_back(
6824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          new WriterThread(d_write, &messages_written[i], &bytes_written[i]));
6834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
6844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Make readers.
6864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ScopedVector<ReaderThread> readers;
6874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t i = 0; i < kNumReaders; i++) {
6884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      readers.push_back(
6894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          new ReaderThread(d_read, &messages_read[i], &bytes_read[i]));
6904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
6914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Start writers.
6934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t i = 0; i < kNumWriters; i++)
6944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      writers[i]->Start();
6954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Start readers.
6974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t i = 0; i < kNumReaders; i++)
6984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      readers[i]->Start();
6994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // TODO(vtl): Maybe I should have an event that triggers all the threads to
7014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // start doing stuff for real (so that the first ones created/started aren't
7024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // advantaged).
7034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }  // Joins all the threads.
7044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t total_messages_written = 0;
7064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t total_bytes_written = 0;
7074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (size_t i = 0; i < kNumWriters; i++) {
7084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    total_messages_written += messages_written[i];
7094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    total_bytes_written += bytes_written[i];
7104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
7114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t total_messages_read = 0;
7124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t total_bytes_read = 0;
7134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (size_t i = 0; i < kNumReaders; i++) {
7144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    total_messages_read += messages_read[i];
7154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    total_bytes_read += bytes_read[i];
7164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // We'd have to be really unlucky to have read no messages on a thread.
7174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_GT(messages_read[i], 0u) << "reader: " << i;
7184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_GE(bytes_read[i], messages_read[i]) << "reader: " << i;
7194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
7204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(total_messages_written, total_messages_read);
7214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(total_bytes_written, total_bytes_read);
7224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK, d_write->Close());
7244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK, d_read->Close());
7254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
7264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace
7284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace system
7294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace mojo
730