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)#include "mojo/system/message_pipe.h"
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/memory/ref_counted.h"
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/threading/platform_thread.h"  // For |Sleep()|.
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/time/time.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/waiter.h"
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/waiter_test_utils.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace mojo {
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace system {
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Tests:
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//  - only default flags
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//  - reading messages from a port
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//    - when there are no/one/two messages available for that port
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//    - with buffer size 0 (and null buffer) -- should get size
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//    - with too-small buffer -- should get size
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//    - also verify that buffers aren't modified when/where they shouldn't be
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//  - writing messages to a port
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//    - in the obvious scenarios (as above)
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//    - to a port that's been closed
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//  - writing a message to a port, closing the other (would be the source) port,
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//    and reading it
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(MessagePipeTest, Basic) {
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_refptr<MessagePipe> mp(new MessagePipe());
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int32_t buffer[2];
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32_t buffer_size;
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Nothing to read yet on port 0.
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123;
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 456;
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(kBufferSize, buffer_size);
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(123, buffer[0]);
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(456, buffer[1]);
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Ditto for port 1.
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123;
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 456;
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(1,
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Write from port 1 (to port 0).
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 789012345;
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 0;
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(1,
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, static_cast<uint32_t>(sizeof(buffer[0])),
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read from port 0.
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123;
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 456;
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(789012345, buffer[0]);
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(456, buffer[1]);
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read again from port 0 -- it should be empty.
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Write two messages from port 0 (to port 1).
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123456789;
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 0;
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(0,
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, static_cast<uint32_t>(sizeof(buffer[0])),
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 234567890;
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 0;
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(0,
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, static_cast<uint32_t>(sizeof(buffer[0])),
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read from port 1 with buffer size 0 (should get the size of next message).
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Also test that giving a null buffer is okay when the buffer size is 0.
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = 0;
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(1,
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            NULL, &buffer_size,
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read from port 1 with buffer size 1 (too small; should get the size of next
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // message).
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123;
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 456;
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = 1;
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(1,
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(123, buffer[0]);
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(456, buffer[1]);
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read from port 1.
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123;
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 456;
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(1,
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(123456789, buffer[0]);
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(456, buffer[1]);
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read again from port 1.
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123;
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 456;
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(1,
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(234567890, buffer[0]);
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(456, buffer[1]);
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read again from port 1 -- it should be empty.
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(1,
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Write from port 0 (to port 1).
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 345678901;
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 0;
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(0,
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, static_cast<uint32_t>(sizeof(buffer[0])),
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Close port 0.
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  mp->Close(0);
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Try to write from port 1 (to port 0).
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 456789012;
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 0;
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(1,
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, static_cast<uint32_t>(sizeof(buffer[0])),
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read from port 1; should still get message (even though port 0 was closed).
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123;
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 456;
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(1,
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(345678901, buffer[0]);
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(456, buffer[1]);
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Read again from port 1 -- it should be empty (and port 0 is closed).
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(1,
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  mp->Close(1);
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)TEST(MessagePipeTest, CloseWithQueuedIncomingMessages) {
2100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  scoped_refptr<MessagePipe> mp(new MessagePipe());
2110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  int32_t buffer[1];
2130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
2140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  uint32_t buffer_size;
2150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Write some messages from port 1 (to port 0).
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (int32_t i = 0; i < 5; i++) {
2180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    buffer[0] = i;
2190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
2200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)              mp->WriteMessage(1,
2210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                               buffer, kBufferSize,
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               NULL,
2230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                               MOJO_WRITE_MESSAGE_FLAG_NONE));
2240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
2250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Port 0 shouldn't be empty.
2270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  buffer_size = 0;
2280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
2290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)            mp->ReadMessage(0,
2300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                            NULL, &buffer_size,
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
2320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
2330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(kBufferSize, buffer_size);
2340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Close port 0 first, which should have outstanding (incoming) messages.
2360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  mp->Close(0);
2370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  mp->Close(1);
2380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
2390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(MessagePipeTest, DiscardMode) {
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_refptr<MessagePipe> mp(new MessagePipe());
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int32_t buffer[2];
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32_t buffer_size;
2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Write from port 1 (to port 0).
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 789012345;
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 0;
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(1,
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, static_cast<uint32_t>(sizeof(buffer[0])),
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read/discard from port 0 (no buffer); get size.
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = 0;
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            NULL, &buffer_size,
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read again from port 0 -- it should be empty.
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Write from port 1 (to port 0).
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 890123456;
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 0;
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(1,
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, static_cast<uint32_t>(sizeof(buffer[0])),
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read from port 0 (buffer big enough).
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123;
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 456;
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(890123456, buffer[0]);
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(456, buffer[1]);
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read again from port 0 -- it should be empty.
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Write from port 1 (to port 0).
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 901234567;
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 0;
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(1,
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, static_cast<uint32_t>(sizeof(buffer[0])),
309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read/discard from port 0 (buffer too small); get size.
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = 1;
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read again from port 0 -- it should be empty.
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Write from port 1 (to port 0).
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123456789;
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[1] = 0;
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(1,
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, static_cast<uint32_t>(sizeof(buffer[0])),
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Discard from port 0.
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = 1;
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            NULL, NULL,
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read again from port 0 -- it should be empty.
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(0,
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  mp->Close(0);
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  mp->Close(1);
3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(MessagePipeTest, BasicWaiting) {
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_refptr<MessagePipe> mp(new MessagePipe());
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Waiter waiter;
3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int32_t buffer[1];
3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32_t buffer_size;
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Always writable (until the other port is closed).
3678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  waiter.Init();
3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->AddWaiter(0, &waiter, MOJO_WAIT_FLAG_WRITABLE, 0));
3708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  waiter.Init();
3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->AddWaiter(0,
3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          &waiter,
3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE,
3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          0));
3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Not yet readable.
3788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  waiter.Init();
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->AddWaiter(0, &waiter, MOJO_WAIT_FLAG_READABLE, 1));
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  mp->RemoveWaiter(0, &waiter);
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Write from port 0 (to port 1), to make port 1 readable.
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 123456789;
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->WriteMessage(0,
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             buffer, kBufferSize,
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             NULL,
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             MOJO_WRITE_MESSAGE_FLAG_NONE));
3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Port 1 should already be readable now.
3938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  waiter.Init();
3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_READABLE, 2));
3968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  waiter.Init();
3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->AddWaiter(1,
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          &waiter,
4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE,
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          0));
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // ... and still writable.
4038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  waiter.Init();
4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
4054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_WRITABLE, 3));
4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Close port 0.
4084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  mp->Close(0);
4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Now port 1 should not be writable.
4118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  waiter.Init();
4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_WRITABLE, 4));
4144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // But it should still be readable.
4168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  waiter.Init();
4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_READABLE, 5));
4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Read from port 1.
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer[0] = 0;
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  buffer_size = kBufferSize;
4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_OK,
4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->ReadMessage(1,
4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            buffer, &buffer_size,
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            0, NULL,
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            MOJO_READ_MESSAGE_FLAG_NONE));
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(123456789, buffer[0]);
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Now port 1 should no longer be readable.
4318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  waiter.Init();
4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            mp->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_READABLE, 6));
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  mp->Close(1);
4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(MessagePipeTest, ThreadedWaiting) {
4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int32_t buffer[1];
4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  MojoResult result;
4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Write to wake up waiter waiting for read.
4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_refptr<MessagePipe> mp(new MessagePipe());
4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    test::SimpleWaiterThread thread(&result);
4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    thread.waiter()->Init();
4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              mp->AddWaiter(1, thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0));
4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    buffer[0] = 123456789;
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Write from port 0 (to port 1), which should wake up the waiter.
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              mp->WriteMessage(0,
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               buffer, kBufferSize,
459f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               NULL,
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               MOJO_WRITE_MESSAGE_FLAG_NONE));
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->RemoveWaiter(1, thread.waiter());
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->Close(0);
4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->Close(1);
4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }  // Joins |thread|.
4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The waiter should have woken up successfully.
4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, result);
4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Close to cancel waiter.
4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_refptr<MessagePipe> mp(new MessagePipe());
4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    test::SimpleWaiterThread thread(&result);
4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    thread.waiter()->Init();
4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              mp->AddWaiter(1, thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0));
4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
4794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Close port 1 first -- this should result in the waiter being cancelled.
4814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->CancelAllWaiters(1);
4824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->Close(1);
4834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Port 1 is closed, so |Dispatcher::RemoveWaiter()| wouldn't call into the
4854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // |MessagePipe| to remove any waiter.
4864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->Close(0);
4884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }  // Joins |thread|.
4894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
4904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Close to make waiter un-wake-up-able.
4924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
4934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_refptr<MessagePipe> mp(new MessagePipe());
4944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    test::SimpleWaiterThread thread(&result);
4954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    thread.waiter()->Init();
4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_OK,
4984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              mp->AddWaiter(1, thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0));
4994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
5004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Close port 0 first -- this should wake the waiter up, since port 1 will
5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // never be readable.
5034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->CancelAllWaiters(0);
5044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->Close(0);
5054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->RemoveWaiter(1, thread.waiter());
5074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->CancelAllWaiters(1);
5094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    mp->Close(1);
5104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }  // Joins |thread|.
5114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
5124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace
5154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace system
5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace mojo
517