| // Copyright 2017 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 "build/build_config.h" |
| #include "mojo/core/test/mojo_test_base.h" |
| #include "mojo/public/c/system/buffer.h" |
| #include "mojo/public/c/system/data_pipe.h" |
| #include "mojo/public/c/system/functions.h" |
| #include "mojo/public/c/system/message_pipe.h" |
| #include "mojo/public/c/system/trap.h" |
| #include "mojo/public/c/system/types.h" |
| |
| namespace mojo { |
| namespace core { |
| namespace { |
| |
| using SignalsTest = test::MojoTestBase; |
| |
| TEST_F(SignalsTest, QueryInvalidArguments) { |
| MojoHandleSignalsState state = {0, 0}; |
| EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| MojoQueryHandleSignalsState(MOJO_HANDLE_INVALID, &state)); |
| |
| MojoHandle a, b; |
| CreateMessagePipe(&a, &b); |
| EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| MojoQueryHandleSignalsState(a, nullptr)); |
| } |
| |
| TEST_F(SignalsTest, QueryMessagePipeSignals) { |
| MojoHandleSignalsState state = {0, 0}; |
| |
| MojoHandle a, b; |
| CreateMessagePipe(&a, &b); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| MOJO_HANDLE_SIGNAL_PEER_CLOSED | |
| MOJO_HANDLE_SIGNAL_PEER_REMOTE | |
| MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED, |
| state.satisfiable_signals); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| MOJO_HANDLE_SIGNAL_PEER_CLOSED | |
| MOJO_HANDLE_SIGNAL_PEER_REMOTE | |
| MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED, |
| state.satisfiable_signals); |
| |
| WriteMessage(a, "ok"); |
| EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE)); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
| state.satisfied_signals); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| MOJO_HANDLE_SIGNAL_PEER_CLOSED | |
| MOJO_HANDLE_SIGNAL_PEER_REMOTE | |
| MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED, |
| state.satisfiable_signals); |
| |
| EXPECT_EQ("ok", ReadMessage(b)); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| MOJO_HANDLE_SIGNAL_PEER_CLOSED | |
| MOJO_HANDLE_SIGNAL_PEER_REMOTE | |
| MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED, |
| state.satisfiable_signals); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); |
| EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED, |
| state.satisfiable_signals); |
| } |
| |
| TEST_F(SignalsTest, LocalPeers) { |
| MojoHandleSignalsState state = {0, 0}; |
| MojoHandle a, b, c, d; |
| CreateMessagePipe(&a, &b); |
| CreateMessagePipe(&c, &d); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); |
| EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); |
| EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(c, &state)); |
| EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(d, &state)); |
| EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| |
| // Verify that sending a local pipe over a local pipe doesn't change the |
| // perceived locality of the peer. |
| const char kMessage[] = "ayyy"; |
| WriteMessageWithHandles(a, kMessage, &c, 1); |
| EXPECT_EQ(kMessage, ReadMessageWithHandles(b, &c, 1)); |
| |
| WriteMessage(c, kMessage); |
| EXPECT_EQ(kMessage, ReadMessage(d)); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(c, &state)); |
| EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(d, &state)); |
| EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| |
| // Sanity check: a closed peer can never signal remoteness. |
| EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(d, &state)); |
| EXPECT_FALSE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d)); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); |
| } |
| |
| #if !defined(OS_IOS) |
| |
| TEST_F(SignalsTest, RemotePeers) { |
| MojoHandleSignalsState state = {0, 0}; |
| MojoHandle a, b; |
| CreateMessagePipe(&a, &b); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); |
| EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_EQ(MOJO_RESULT_OK, |
| WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, |
| MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED)); |
| |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); |
| EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| EXPECT_EQ(MOJO_RESULT_OK, |
| WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_REMOTE, |
| MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED)); |
| |
| RunTestClient("RemotePeersClient", [&](MojoHandle h) { |
| // The bootstrap pipe should eventually signal remoteness. |
| EXPECT_EQ(MOJO_RESULT_OK, |
| WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE, |
| MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); |
| |
| // And so should |a| after we send its peer. |
| WriteMessageWithHandles(h, ":)", &b, 1); |
| EXPECT_EQ(MOJO_RESULT_OK, |
| WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, |
| MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); |
| EXPECT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| |
| // And so should |c| after we fuse |d| to |a|. |
| MojoHandle c, d; |
| CreateMessagePipe(&c, &d); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(d, a, nullptr)); |
| EXPECT_EQ(MOJO_RESULT_OK, |
| WaitForSignals(c, MOJO_HANDLE_SIGNAL_PEER_REMOTE, |
| MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(c, &state)); |
| EXPECT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| |
| // We fused c-d to a-b, so we'll just sort of "rename" |c| back to |a| so |
| // the system resembles the state it was in before we did that. |
| a = c; |
| |
| WriteMessage(h, "OK!"); |
| |
| // Read |b| back before joining the client. |
| EXPECT_EQ("O_O", ReadMessageWithHandles(h, &b, 1)); |
| |
| // Wait for |a| to see its peer as local again. |
| EXPECT_EQ(MOJO_RESULT_OK, |
| WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, |
| MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED)); |
| EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); |
| EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); |
| }); |
| } |
| |
| DEFINE_TEST_CLIENT_TEST_WITH_PIPE(RemotePeersClient, SignalsTest, h) { |
| // The bootstrap pipe should eventually signal remoteness. |
| EXPECT_EQ(MOJO_RESULT_OK, |
| WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE, |
| MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); |
| |
| MojoHandle b; |
| EXPECT_EQ(":)", ReadMessageWithHandles(h, &b, 1)); |
| |
| // And so should |b|. |
| EXPECT_EQ(MOJO_RESULT_OK, |
| WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_REMOTE, |
| MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED)); |
| |
| // Wait for the test to signal that it's ready to read |b| back. |
| EXPECT_EQ("OK!", ReadMessage(h)); |
| |
| // Now send |b| back home. |
| WriteMessageWithHandles(h, "O_O", &b, 1); |
| } |
| |
| #endif // !defined(OS_IOS) |
| |
| } // namespace |
| } // namespace core |
| } // namespace mojo |