diff options
Diffstat (limited to 'mojo/edk/system/core_unittest.cc')
-rw-r--r-- | mojo/edk/system/core_unittest.cc | 1317 |
1 files changed, 0 insertions, 1317 deletions
diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc deleted file mode 100644 index b789301..0000000 --- a/mojo/edk/system/core_unittest.cc +++ /dev/null @@ -1,1317 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/core.h" - -#include <stdint.h> - -#include <limits> - -#include "base/bind.h" -#include "base/threading/platform_thread.h" -#include "base/time/time.h" -#include "mojo/edk/system/awakable.h" -#include "mojo/edk/system/core_test_base.h" - -namespace mojo { -namespace system { -namespace { - -const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u}; -const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u}; -const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -typedef test::CoreTestBase CoreTest; - -TEST_F(CoreTest, GetTimeTicksNow) { - const MojoTimeTicks start = core()->GetTimeTicksNow(); - EXPECT_NE(static_cast<MojoTimeTicks>(0), start) - << "GetTimeTicksNow should return nonzero value"; - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(15)); - const MojoTimeTicks finish = core()->GetTimeTicksNow(); - // Allow for some fuzz in sleep. - EXPECT_GE((finish - start), static_cast<MojoTimeTicks>(8000)) - << "Sleeping should result in increasing time ticks"; -} - -TEST_F(CoreTest, Basic) { - MockHandleInfo info; - - EXPECT_EQ(0u, info.GetCtorCallCount()); - MojoHandle h = CreateMockHandle(&info); - EXPECT_EQ(1u, info.GetCtorCallCount()); - EXPECT_NE(h, MOJO_HANDLE_INVALID); - - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h, NullUserPointer(), 0, NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - EXPECT_EQ(0u, info.GetReadMessageCallCount()); - uint32_t num_bytes = 0; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->ReadMessage(h, NullUserPointer(), MakeUserPointer(&num_bytes), - NullUserPointer(), NullUserPointer(), - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetReadMessageCallCount()); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage(h, NullUserPointer(), NullUserPointer(), - NullUserPointer(), NullUserPointer(), - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(2u, info.GetReadMessageCallCount()); - - EXPECT_EQ(0u, info.GetWriteDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->WriteData(h, NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteDataCallCount()); - - EXPECT_EQ(0u, info.GetBeginWriteDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->BeginWriteData(h, NullUserPointer(), NullUserPointer(), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(1u, info.GetBeginWriteDataCallCount()); - - EXPECT_EQ(0u, info.GetEndWriteDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndWriteData(h, 0)); - EXPECT_EQ(1u, info.GetEndWriteDataCallCount()); - - EXPECT_EQ(0u, info.GetReadDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->ReadData(h, NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(1u, info.GetReadDataCallCount()); - - EXPECT_EQ(0u, info.GetBeginReadDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->BeginReadData(h, NullUserPointer(), NullUserPointer(), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(1u, info.GetBeginReadDataCallCount()); - - EXPECT_EQ(0u, info.GetEndReadDataCallCount()); - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0)); - EXPECT_EQ(1u, info.GetEndReadDataCallCount()); - - EXPECT_EQ(0u, info.GetAddAwakableCallCount()); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE, - NullUserPointer())); - EXPECT_EQ(1u, info.GetAddAwakableCallCount()); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 0, NullUserPointer())); - EXPECT_EQ(2u, info.GetAddAwakableCallCount()); - MojoHandleSignalsState hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE, - MakeUserPointer(&hss))); - EXPECT_EQ(3u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, NullUserPointer())); - EXPECT_EQ(4u, info.GetAddAwakableCallCount()); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, - MakeUserPointer(&hss))); - EXPECT_EQ(5u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - MojoHandleSignals handle_signals = ~MOJO_HANDLE_SIGNAL_NONE; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - EXPECT_EQ(6u, info.GetAddAwakableCallCount()); - uint32_t result_index = static_cast<uint32_t>(-1); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - NullUserPointer())); - EXPECT_EQ(7u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, result_index); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - MakeUserPointer(&hss))); - EXPECT_EQ(8u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - result_index = static_cast<uint32_t>(-1); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(9u, info.GetAddAwakableCallCount()); - EXPECT_EQ(0u, result_index); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - EXPECT_EQ(0u, info.GetDtorCallCount()); - EXPECT_EQ(0u, info.GetCloseCallCount()); - EXPECT_EQ(0u, info.GetCancelAllAwakablesCallCount()); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - EXPECT_EQ(1u, info.GetCancelAllAwakablesCallCount()); - EXPECT_EQ(1u, info.GetCloseCallCount()); - EXPECT_EQ(1u, info.GetDtorCallCount()); - - // No awakables should ever have ever been added. - EXPECT_EQ(0u, info.GetRemoveAwakableCallCount()); -} - -TEST_F(CoreTest, InvalidArguments) { - // |Close()|: - { - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(MOJO_HANDLE_INVALID)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(10)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(1000000000)); - - // Test a double-close. - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - EXPECT_EQ(1u, info.GetCloseCallCount()); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h)); - EXPECT_EQ(1u, info.GetCloseCallCount()); - } - - // |Wait()|: - { - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->Wait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, - MOJO_DEADLINE_INDEFINITE, NullUserPointer())); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->Wait(10, ~MOJO_HANDLE_SIGNAL_NONE, - MOJO_DEADLINE_INDEFINITE, NullUserPointer())); - - MojoHandleSignalsState hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->Wait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&hss))); - // On invalid argument, it shouldn't modify the handle signals state. - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->Wait(10, ~MOJO_HANDLE_SIGNAL_NONE, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&hss))); - // On invalid argument, it shouldn't modify the handle signals state. - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - } - - // |WaitMany()|: - { - MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID}; - MojoHandleSignals signals[2] = {~MOJO_HANDLE_SIGNAL_NONE, - ~MOJO_HANDLE_SIGNAL_NONE}; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 0, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(NullUserPointer(), MakeUserPointer(signals), 0, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - // If |num_handles| is invalid, it should leave |result_index| and - // |signals_states| alone. - // (We use -1 internally; make sure that doesn't leak.) - uint32_t result_index = 123; - MojoHandleSignalsState hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(NullUserPointer(), MakeUserPointer(signals), 0, - MOJO_DEADLINE_INDEFINITE, - MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(123u, result_index); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(MakeUserPointer(handles), NullUserPointer(), 0, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - // But if a handle is bad, then it should set |result_index| but still leave - // |signals_states| alone. - result_index = static_cast<uint32_t>(-1); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany( - MakeUserPointer(handles), MakeUserPointer(signals), 1, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(0u, result_index); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - - MockHandleInfo info[2]; - handles[0] = CreateMockHandle(&info[0]); - - result_index = static_cast<uint32_t>(-1); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany( - MakeUserPointer(handles), MakeUserPointer(signals), 1, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(0u, result_index); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(0u, hss.satisfiable_signals); - - // On invalid argument, it'll leave |signals_states| alone. - result_index = static_cast<uint32_t>(-1); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany( - MakeUserPointer(handles), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(&hss))); - EXPECT_EQ(1u, result_index); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals, - hss.satisfied_signals); - EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals, - hss.satisfiable_signals); - handles[1] = handles[0] + 1; // Invalid handle. - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - handles[1] = CreateMockHandle(&info[1]); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer())); - - // TODO(vtl): Test one where we get "failed precondition" only for the - // second handle (and the first one is valid to wait on). - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[0])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[1])); - } - - // |CreateMessagePipe()|: Nothing to check (apart from things that cause - // death). - - // |WriteMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(MOJO_HANDLE_INVALID, NullUserPointer(), 0, - NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID}; - - // Huge handle count (implausibly big on some systems -- more than can be - // stored in a 32-bit address space). - // Note: This may return either |MOJO_RESULT_INVALID_ARGUMENT| or - // |MOJO_RESULT_RESOURCE_EXHAUSTED|, depending on whether it's plausible or - // not. - EXPECT_NE( - MOJO_RESULT_OK, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - std::numeric_limits<uint32_t>::max(), - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - // Huge handle count (plausibly big). - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - core()->WriteMessage( - h, NullUserPointer(), 0, MakeUserPointer(handles), - std::numeric_limits<uint32_t>::max() / sizeof(handles[0]), - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - // Invalid handle in |handles|. - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - // Two invalid handles in |handles|. - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - // Can't send a handle over itself. - handles[0] = h; - EXPECT_EQ( - MOJO_RESULT_BUSY, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(0u, info.GetWriteMessageCallCount()); - - MockHandleInfo info2; - MojoHandle h2 = CreateMockHandle(&info2); - - // This is "okay", but |MockDispatcher| doesn't implement it. - handles[0] = h2; - EXPECT_EQ( - MOJO_RESULT_UNIMPLEMENTED, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - // One of the |handles| is still invalid. - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - // One of the |handles| is the same as |handle|. - handles[1] = h; - EXPECT_EQ( - MOJO_RESULT_BUSY, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - // Can't send a handle twice in the same message. - handles[1] = h2; - EXPECT_EQ( - MOJO_RESULT_BUSY, - core()->WriteMessage(h, NullUserPointer(), 0, MakeUserPointer(handles), - 2, MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, info.GetWriteMessageCallCount()); - - // Note: Since we never successfully sent anything with it, |h2| should - // still be valid. - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h2)); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } - - // |ReadMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadMessage(MOJO_HANDLE_INVALID, NullUserPointer(), - NullUserPointer(), NullUserPointer(), - NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE)); - - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - // Okay. - uint32_t handle_count = 0; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h, NullUserPointer(), NullUserPointer(), NullUserPointer(), - MakeUserPointer(&handle_count), MOJO_READ_MESSAGE_FLAG_NONE)); - // Checked by |Core|, shouldn't go through to the dispatcher. - EXPECT_EQ(1u, info.GetReadMessageCallCount()); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } -} - -// These test invalid arguments that should cause death if we're being paranoid -// about checking arguments (which we would want to do if, e.g., we were in a -// true "kernel" situation, but we might not want to do otherwise for -// performance reasons). Probably blatant errors like passing in null pointers -// (for required pointer arguments) will still cause death, but perhaps not -// predictably. -TEST_F(CoreTest, InvalidArgumentsDeath) { - const char kMemoryCheckFailedRegex[] = "Check failed"; - - // |WaitMany()|: - { - MojoHandle handle = MOJO_HANDLE_INVALID; - MojoHandleSignals signals = ~MOJO_HANDLE_SIGNAL_NONE; - EXPECT_DEATH_IF_SUPPORTED( - core()->WaitMany(NullUserPointer(), MakeUserPointer(&signals), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer()), - kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED( - core()->WaitMany(MakeUserPointer(&handle), NullUserPointer(), 1, - MOJO_DEADLINE_INDEFINITE, NullUserPointer(), - NullUserPointer()), - kMemoryCheckFailedRegex); - // TODO(vtl): |result_index| and |signals_states| are optional. Test them - // with non-null invalid pointers? - } - - // |CreateMessagePipe()|: - { - MojoHandle h; - EXPECT_DEATH_IF_SUPPORTED( - core()->CreateMessagePipe(NullUserPointer(), NullUserPointer(), - NullUserPointer()), - kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED( - core()->CreateMessagePipe(NullUserPointer(), MakeUserPointer(&h), - NullUserPointer()), - kMemoryCheckFailedRegex); - EXPECT_DEATH_IF_SUPPORTED( - core()->CreateMessagePipe(NullUserPointer(), NullUserPointer(), - MakeUserPointer(&h)), - kMemoryCheckFailedRegex); - } - - // |WriteMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - // Null |handles| with nonzero |num_handles|. - EXPECT_DEATH_IF_SUPPORTED( - core()->WriteMessage(h, NullUserPointer(), 0, NullUserPointer(), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE), - kMemoryCheckFailedRegex); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } - - // |ReadMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - uint32_t handle_count = 1; - EXPECT_DEATH_IF_SUPPORTED( - core()->ReadMessage(h, NullUserPointer(), NullUserPointer(), - NullUserPointer(), MakeUserPointer(&handle_count), - MOJO_READ_MESSAGE_FLAG_NONE), - kMemoryCheckFailedRegex); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } -} - -// TODO(vtl): test |Wait()| and |WaitMany()| properly -// - including |WaitMany()| with the same handle more than once (with -// same/different signals) - -TEST_F(CoreTest, MessagePipe) { - MojoHandle h[2]; - MojoHandleSignalsState hss[2]; - uint32_t result_index; - - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(NullUserPointer(), MakeUserPointer(&h[0]), - MakeUserPointer(&h[1]))); - // Should get two distinct, valid handles. - EXPECT_NE(h[0], MOJO_HANDLE_INVALID); - EXPECT_NE(h[1], MOJO_HANDLE_INVALID); - EXPECT_NE(h[0], h[1]); - - // Neither should be readable. - MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE, - MOJO_HANDLE_SIGNAL_READABLE}; - result_index = static_cast<uint32_t>(-1); - hss[0] = kEmptyMojoHandleSignalsState; - hss[1] = kEmptyMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_DEADLINE_EXCEEDED, - core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2, 0, - MakeUserPointer(&result_index), MakeUserPointer(hss))); - EXPECT_EQ(static_cast<uint32_t>(-1), result_index); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals); - - // Try to read anyway. - char buffer[1] = {'a'}; - uint32_t buffer_size = 1; - EXPECT_EQ( - MOJO_RESULT_SHOULD_WAIT, - core()->ReadMessage(h[0], UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), NullUserPointer(), - NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE)); - // Check that it left its inputs alone. - EXPECT_EQ('a', buffer[0]); - EXPECT_EQ(1u, buffer_size); - - // Both should be writable. - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[0], MOJO_HANDLE_SIGNAL_WRITABLE, - 1000000000, MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, - 1000000000, MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - - // Also check that |h[1]| is writable using |WaitMany()|. - signals[0] = MOJO_HANDLE_SIGNAL_READABLE; - signals[1] = MOJO_HANDLE_SIGNAL_WRITABLE; - result_index = static_cast<uint32_t>(-1); - hss[0] = kEmptyMojoHandleSignalsState; - hss[1] = kEmptyMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(hss))); - EXPECT_EQ(1u, result_index); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals); - - // Write to |h[1]|. - buffer[0] = 'b'; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->WriteMessage(h[1], UserPointer<const void>(buffer), 1, - NullUserPointer(), 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Check that |h[0]| is now readable. - signals[0] = MOJO_HANDLE_SIGNAL_READABLE; - signals[1] = MOJO_HANDLE_SIGNAL_READABLE; - result_index = static_cast<uint32_t>(-1); - hss[0] = kEmptyMojoHandleSignalsState; - hss[1] = kEmptyMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->WaitMany(MakeUserPointer(h), MakeUserPointer(signals), 2, - MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), - MakeUserPointer(hss))); - EXPECT_EQ(0u, result_index); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals); - - // Read from |h[0]|. - // First, get only the size. - buffer_size = 0; - EXPECT_EQ( - MOJO_RESULT_RESOURCE_EXHAUSTED, - core()->ReadMessage(h[0], NullUserPointer(), - MakeUserPointer(&buffer_size), NullUserPointer(), - NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(1u, buffer_size); - // Then actually read it. - buffer[0] = 'c'; - buffer_size = 1; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->ReadMessage(h[0], UserPointer<void>(buffer), - MakeUserPointer(&buffer_size), NullUserPointer(), - NullUserPointer(), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ('b', buffer[0]); - EXPECT_EQ(1u, buffer_size); - - // |h[0]| should no longer be readable. - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - core()->Wait(h[0], MOJO_HANDLE_SIGNAL_READABLE, 0, - MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals); - - // Write to |h[0]|. - buffer[0] = 'd'; - EXPECT_EQ( - MOJO_RESULT_OK, - core()->WriteMessage(h[0], UserPointer<const void>(buffer), 1, - NullUserPointer(), 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Close |h[0]|. - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[0])); - - // Check that |h[1]| is no longer writable (and will never be). - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000, - MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[0].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[0].satisfiable_signals); - - // Check that |h[1]| is still readable (for the moment). - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, - 1000000000, MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[0].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[0].satisfiable_signals); - - // Discard a message from |h[1]|. - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - core()->ReadMessage(h[1], NullUserPointer(), NullUserPointer(), - NullUserPointer(), NullUserPointer(), - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - - // |h[1]| is no longer readable (and will never be). - hss[0] = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss[0]))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[0].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[0].satisfiable_signals); - - // Try writing to |h[1]|. - buffer[0] = 'e'; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WriteMessage(h[1], UserPointer<const void>(buffer), 1, - NullUserPointer(), 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[1])); -} - -// Tests passing a message pipe handle. -TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); - const char kWorld[] = "world!!!"; - const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); - char buffer[100]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t num_bytes; - MojoHandle handles[10]; - uint32_t num_handles; - MojoHandleSignalsState hss; - MojoHandle h_received; - - MojoHandle h_passing[2]; - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(NullUserPointer(), - MakeUserPointer(&h_passing[0]), - MakeUserPointer(&h_passing[1]))); - - // Make sure that |h_passing[]| work properly. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(0u, num_handles); - - // Make sure that you can't pass either of the message pipe's handles over - // itself. - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&h_passing[0]), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&h_passing[1]), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - MojoHandle h_passed[2]; - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(NullUserPointer(), - MakeUserPointer(&h_passed[0]), - MakeUserPointer(&h_passed[1]))); - - // Make sure that |h_passed[]| work properly. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passed[0], UserPointer<const void>(kHello), - kHelloSize, NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passed[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passed[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(0u, num_handles); - - // Send |h_passed[1]| from |h_passing[0]| to |h_passing[1]|. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kWorld), - kWorldSize, MakeUserPointer(&h_passed[1]), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kWorldSize, num_bytes); - EXPECT_STREQ(kWorld, buffer); - EXPECT_EQ(1u, num_handles); - h_received = handles[0]; - EXPECT_NE(h_received, MOJO_HANDLE_INVALID); - EXPECT_NE(h_received, h_passing[0]); - EXPECT_NE(h_received, h_passing[1]); - EXPECT_NE(h_received, h_passed[0]); - - // Note: We rely on the Mojo system not re-using handle values very often. - EXPECT_NE(h_received, h_passed[1]); - - // |h_passed[1]| should no longer be valid; check that trying to close it - // fails. See above note. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h_passed[1])); - - // Write to |h_passed[0]|. Should receive on |h_received|. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passed[0], UserPointer<const void>(kHello), - kHelloSize, NullUserPointer(), 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_received, UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(0u, num_handles); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[0])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[1])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passed[0])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_received)); -} - -TEST_F(CoreTest, DataPipe) { - MojoHandle ph, ch; // p is for producer and c is for consumer. - MojoHandleSignalsState hss; - - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateDataPipe(NullUserPointer(), MakeUserPointer(&ph), - MakeUserPointer(&ch))); - // Should get two distinct, valid handles. - EXPECT_NE(ph, MOJO_HANDLE_INVALID); - EXPECT_NE(ch, MOJO_HANDLE_INVALID); - EXPECT_NE(ph, ch); - - // Producer should be never-readable, but already writable. - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(ph, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ph, MOJO_HANDLE_SIGNAL_WRITABLE, 0, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Consumer should be never-writable, and not yet readable. - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(ch, MOJO_HANDLE_SIGNAL_WRITABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_DEADLINE_EXCEEDED, - core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Write. - signed char elements[2] = {'A', 'B'}; - uint32_t num_bytes = 2u; - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteData(ph, UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(2u, num_bytes); - - // Consumer should now be readable. - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Peek one character. - elements[0] = -1; - elements[1] = -1; - num_bytes = 1u; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData( - ch, UserPointer<void>(elements), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_NONE | MOJO_READ_DATA_FLAG_PEEK)); - EXPECT_EQ('A', elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Read one character. - elements[0] = -1; - elements[1] = -1; - num_bytes = 1u; - EXPECT_EQ(MOJO_RESULT_OK, core()->ReadData(ch, UserPointer<void>(elements), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ('A', elements[0]); - EXPECT_EQ(-1, elements[1]); - - // Two-phase write. - void* write_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginWriteData(ph, MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_NONE)); - // We count on the default options providing a decent buffer size. - ASSERT_GE(num_bytes, 3u); - - // Trying to do a normal write during a two-phase write should fail. - elements[0] = 'X'; - num_bytes = 1u; - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->WriteData(ph, UserPointer<const void>(elements), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_NONE)); - - // Actually write the data, and complete it now. - static_cast<char*>(write_ptr)[0] = 'C'; - static_cast<char*>(write_ptr)[1] = 'D'; - static_cast<char*>(write_ptr)[2] = 'E'; - EXPECT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 3u)); - - // Query how much data we have. - num_bytes = 0; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_QUERY)); - EXPECT_EQ(4u, num_bytes); - - // Try to query with peek. Should fail. - num_bytes = 0; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_QUERY | MOJO_READ_DATA_FLAG_PEEK)); - EXPECT_EQ(0u, num_bytes); - - // Try to discard ten characters, in all-or-none mode. Should fail. - num_bytes = 10; - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - core()->ReadData( - ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - // Try to discard two characters, in peek mode. Should fail. - num_bytes = 2; - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_PEEK)); - - // Discard two characters. - num_bytes = 2; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData( - ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - // Try a two-phase read of the remaining two bytes with peek. Should fail. - const void* read_ptr = nullptr; - num_bytes = 2; - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->BeginReadData(ch, MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_PEEK)); - - // Read the remaining two characters, in two-phase mode (all-or-none). - num_bytes = 2; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginReadData(ch, MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - // Note: Count on still being able to do the contiguous read here. - ASSERT_EQ(2u, num_bytes); - - // Discarding right now should fail. - num_bytes = 1; - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->ReadData(ch, NullUserPointer(), MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_DISCARD)); - - // Actually check our data and end the two-phase read. - EXPECT_EQ('D', static_cast<const char*>(read_ptr)[0]); - EXPECT_EQ('E', static_cast<const char*>(read_ptr)[1]); - EXPECT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 2u)); - - // Consumer should now be no longer readable. - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_DEADLINE_EXCEEDED, - core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // TODO(vtl): More. - - // Close the producer. - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ph)); - - // The consumer should now be never-readable. - hss = kFullMojoHandleSignalsState; - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch)); -} - -// Tests passing data pipe producer and consumer handles. -TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); - const char kWorld[] = "world!!!"; - const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); - char buffer[100]; - const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); - uint32_t num_bytes; - MojoHandle handles[10]; - uint32_t num_handles; - MojoHandleSignalsState hss; - - MojoHandle h_passing[2]; - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(NullUserPointer(), - MakeUserPointer(&h_passing[0]), - MakeUserPointer(&h_passing[1]))); - - MojoHandle ph, ch; - EXPECT_EQ(MOJO_RESULT_OK, - core()->CreateDataPipe(NullUserPointer(), MakeUserPointer(&ph), - MakeUserPointer(&ch))); - - // Send |ch| from |h_passing[0]| to |h_passing[1]|. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&ch), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(1u, num_handles); - MojoHandle ch_received = handles[0]; - EXPECT_NE(ch_received, MOJO_HANDLE_INVALID); - EXPECT_NE(ch_received, h_passing[0]); - EXPECT_NE(ch_received, h_passing[1]); - EXPECT_NE(ch_received, ph); - - // Note: We rely on the Mojo system not re-using handle values very often. - EXPECT_NE(ch_received, ch); - - // |ch| should no longer be valid; check that trying to close it fails. See - // above note. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ch)); - - // Write to |ph|. Should receive on |ch_received|. - num_bytes = kWorldSize; - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteData(ph, UserPointer<const void>(kWorld), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - num_bytes = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData(ch_received, UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kWorldSize, num_bytes); - EXPECT_STREQ(kWorld, buffer); - - // Now pass |ph| in the same direction. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kWorld), - kWorldSize, MakeUserPointer(&ph), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kWorldSize, num_bytes); - EXPECT_STREQ(kWorld, buffer); - EXPECT_EQ(1u, num_handles); - MojoHandle ph_received = handles[0]; - EXPECT_NE(ph_received, MOJO_HANDLE_INVALID); - EXPECT_NE(ph_received, h_passing[0]); - EXPECT_NE(ph_received, h_passing[1]); - EXPECT_NE(ph_received, ch_received); - - // Again, rely on the Mojo system not re-using handle values very often. - EXPECT_NE(ph_received, ph); - - // |ph| should no longer be valid; check that trying to close it fails. See - // above note. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ph)); - - // Write to |ph_received|. Should receive on |ch_received|. - num_bytes = kHelloSize; - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteData(ph_received, UserPointer<const void>(kHello), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - num_bytes = kBufferSize; - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadData(ch_received, UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - - ph = ph_received; - ph_received = MOJO_HANDLE_INVALID; - ch = ch_received; - ch_received = MOJO_HANDLE_INVALID; - - // Make sure that |ph| can't be sent if it's in a two-phase write. - void* write_ptr = nullptr; - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginWriteData(ph, MakeUserPointer(&write_ptr), - MakeUserPointer(&num_bytes), - MOJO_WRITE_DATA_FLAG_NONE)); - ASSERT_GE(num_bytes, 1u); - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&ph), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // But |ch| can, even if |ph| is in a two-phase write. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&ch), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ch = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - NullUserPointer())); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kHelloSize, num_bytes); - EXPECT_STREQ(kHello, buffer); - EXPECT_EQ(1u, num_handles); - ch = handles[0]; - EXPECT_NE(ch, MOJO_HANDLE_INVALID); - - // Complete the two-phase write. - static_cast<char*>(write_ptr)[0] = 'x'; - EXPECT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 1)); - - // Wait for |ch| to be readable. - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, - 1000000000, MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Make sure that |ch| can't be sent if it's in a two-phase read. - const void* read_ptr = nullptr; - num_bytes = 1; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginReadData(ch, MakeUserPointer(&read_ptr), - MakeUserPointer(&num_bytes), - MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - EXPECT_EQ(MOJO_RESULT_BUSY, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello), - kHelloSize, MakeUserPointer(&ch), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // But |ph| can, even if |ch| is in a two-phase read. - EXPECT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], UserPointer<const void>(kWorld), - kWorldSize, MakeUserPointer(&ph), 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ph = MOJO_HANDLE_INVALID; - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000, - MakeUserPointer(&hss))); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - EXPECT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - EXPECT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], UserPointer<void>(buffer), - MakeUserPointer(&num_bytes), MakeUserPointer(handles), - MakeUserPointer(&num_handles), MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(kWorldSize, num_bytes); - EXPECT_STREQ(kWorld, buffer); - EXPECT_EQ(1u, num_handles); - ph = handles[0]; - EXPECT_NE(ph, MOJO_HANDLE_INVALID); - - // Complete the two-phase read. - EXPECT_EQ('x', static_cast<const char*>(read_ptr)[0]); - EXPECT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 1)); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[0])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[1])); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ph)); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch)); -} - -struct TestAsyncWaiter { - TestAsyncWaiter() : result(MOJO_RESULT_UNKNOWN) {} - - void Awake(MojoResult r) { result = r; } - - MojoResult result; -}; - -TEST_F(CoreTest, AsyncWait) { - TestAsyncWaiter waiter; - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - core()->AsyncWait(h, MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&TestAsyncWaiter::Awake, - base::Unretained(&waiter)))); - EXPECT_EQ(0u, info.GetAddedAwakableSize()); - - info.AllowAddAwakable(true); - EXPECT_EQ(MOJO_RESULT_OK, - core()->AsyncWait(h, MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&TestAsyncWaiter::Awake, - base::Unretained(&waiter)))); - EXPECT_EQ(1u, info.GetAddedAwakableSize()); - - EXPECT_FALSE(info.GetAddedAwakableAt(0)->Awake(MOJO_RESULT_BUSY, 0)); - EXPECT_EQ(MOJO_RESULT_BUSY, waiter.result); - - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); -} - -// TODO(vtl): Test |DuplicateBufferHandle()| and |MapBuffer()|. - -} // namespace -} // namespace system -} // namespace mojo |