| OLD | NEW | 
|     1 // Copyright 2013 The Chromium Authors. All rights reserved. |     1 // Copyright 2013 The Chromium Authors. All rights reserved. | 
|     2 // Use of this source code is governed by a BSD-style license that can be |     2 // Use of this source code is governed by a BSD-style license that can be | 
|     3 // found in the LICENSE file. |     3 // found in the LICENSE file. | 
|     4  |     4  | 
|     5 #include <stddef.h> |     5 #include <stddef.h> | 
|     6 #include <stdint.h> |     6 #include <stdint.h> | 
|     7 #include <stdio.h> |     7 #include <stdio.h> | 
|     8 #include <string.h> |     8 #include <string.h> | 
 |     9  | 
|     9 #include <string> |    10 #include <string> | 
|    10 #include <utility> |    11 #include <utility> | 
|    11 #include <vector> |    12 #include <vector> | 
|    12  |    13  | 
|    13 #include "base/bind.h" |    14 #include "base/containers/hash_tables.h" | 
|    14 #include "base/files/file_path.h" |    15 #include "base/files/file_path.h" | 
|    15 #include "base/files/file_util.h" |    16 #include "base/files/file_util.h" | 
|    16 #include "base/files/scoped_file.h" |    17 #include "base/files/scoped_file.h" | 
|    17 #include "base/files/scoped_temp_dir.h" |    18 #include "base/files/scoped_temp_dir.h" | 
|    18 #include "base/location.h" |  | 
|    19 #include "base/logging.h" |    19 #include "base/logging.h" | 
 |    20 #include "base/strings/string_split.h" | 
|    20 #include "build/build_config.h" |    21 #include "build/build_config.h" | 
|    21 #include "mojo/edk/embedder/embedder.h" |  | 
|    22 #include "mojo/edk/embedder/platform_channel_pair.h" |  | 
|    23 #include "mojo/edk/embedder/platform_shared_buffer.h" |  | 
|    24 #include "mojo/edk/embedder/scoped_platform_handle.h" |    22 #include "mojo/edk/embedder/scoped_platform_handle.h" | 
|    25 #include "mojo/edk/system/dispatcher.h" |    23 #include "mojo/edk/system/handle_signals_state.h" | 
|    26 #include "mojo/edk/system/message_pipe_test_utils.h" |  | 
|    27 #include "mojo/edk/system/platform_handle_dispatcher.h" |  | 
|    28 #include "mojo/edk/system/raw_channel.h" |  | 
|    29 #include "mojo/edk/system/shared_buffer_dispatcher.h" |  | 
|    30 #include "mojo/edk/system/test_utils.h" |    24 #include "mojo/edk/system/test_utils.h" | 
 |    25 #include "mojo/edk/test/mojo_test_base.h" | 
|    31 #include "mojo/edk/test/test_utils.h" |    26 #include "mojo/edk/test/test_utils.h" | 
 |    27 #include "mojo/public/c/system/buffer.h" | 
 |    28 #include "mojo/public/c/system/functions.h" | 
 |    29 #include "mojo/public/c/system/types.h" | 
|    32 #include "testing/gtest/include/gtest/gtest.h" |    30 #include "testing/gtest/include/gtest/gtest.h" | 
|    33  |    31  | 
|    34  |    32  | 
|    35 namespace mojo { |    33 namespace mojo { | 
|    36 namespace edk { |    34 namespace edk { | 
|    37 namespace { |    35 namespace { | 
|    38  |    36  | 
|    39 class MultiprocessMessagePipeTest |    37 class MultiprocessMessagePipeTest : public test::MojoTestBase { | 
|    40     : public test::MultiprocessMessagePipeTestBase {}; |    38  protected: | 
 |    39   // Convenience class for tests which will control command-driven children. | 
 |    40   // See the CommandDrivenClient definition below. | 
 |    41   class CommandDrivenClientController { | 
 |    42    public: | 
 |    43     explicit CommandDrivenClientController(MojoHandle h) : h_(h) {} | 
 |    44  | 
 |    45     void Send(const std::string& command) { | 
 |    46       WriteMessage(h_, command); | 
 |    47       EXPECT_EQ("ok", ReadMessage(h_)); | 
 |    48     } | 
 |    49  | 
 |    50     void SendHandle(const std::string& name, MojoHandle p) { | 
 |    51       WriteMessageWithHandles(h_, "take:" + name, &p, 1); | 
 |    52       EXPECT_EQ("ok", ReadMessage(h_)); | 
 |    53     } | 
 |    54  | 
 |    55     MojoHandle RetrieveHandle(const std::string& name) { | 
 |    56       WriteMessage(h_, "return:" + name); | 
 |    57       MojoHandle p; | 
 |    58       EXPECT_EQ("ok", ReadMessageWithHandles(h_, &p, 1)); | 
 |    59       return p; | 
 |    60     } | 
 |    61  | 
 |    62     void Exit() { WriteMessage(h_, "exit"); } | 
 |    63  | 
 |    64    private: | 
 |    65     MojoHandle h_; | 
 |    66   }; | 
 |    67 }; | 
|    41  |    68  | 
|    42 // For each message received, sends a reply message with the same contents |    69 // For each message received, sends a reply message with the same contents | 
|    43 // repeated twice, until the other end is closed or it receives "quitquitquit" |    70 // repeated twice, until the other end is closed or it receives "quitquitquit" | 
|    44 // (which it doesn't reply to). It'll return the number of messages received, |    71 // (which it doesn't reply to). It'll return the number of messages received, | 
|    45 // not including any "quitquitquit" message, modulo 100. |    72 // not including any "quitquitquit" message, modulo 100. | 
|    46 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) { |    73 DEFINE_TEST_CLIENT_WITH_PIPE(EchoEcho, MultiprocessMessagePipeTest, h) { | 
|    47   ScopedPlatformHandle client_platform_handle = |  | 
|    48       std::move(test::MultiprocessTestHelper::client_platform_handle); |  | 
|    49   CHECK(client_platform_handle.is_valid()); |  | 
|    50   ScopedMessagePipeHandle mp = |  | 
|    51       CreateMessagePipe(std::move(client_platform_handle)); |  | 
|    52  |  | 
|    53   const std::string quitquitquit("quitquitquit"); |    74   const std::string quitquitquit("quitquitquit"); | 
|    54   int rv = 0; |    75   int rv = 0; | 
|    55   for (;; rv = (rv + 1) % 100) { |    76   for (;; rv = (rv + 1) % 100) { | 
|    56     // Wait for our end of the message pipe to be readable. |    77     // Wait for our end of the message pipe to be readable. | 
|    57     HandleSignalsState hss; |    78     HandleSignalsState hss; | 
|    58     MojoResult result = |    79     MojoResult result = | 
|    59         MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |    80         MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
|    60                  MOJO_DEADLINE_INDEFINITE, &hss); |    81                  MOJO_DEADLINE_INDEFINITE, &hss); | 
|    61     if (result != MOJO_RESULT_OK) { |    82     if (result != MOJO_RESULT_OK) { | 
|    62       // It was closed, probably. |    83       // It was closed, probably. | 
|    63       CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION); |    84       CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION); | 
|    64       CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); |    85       CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 
|    65       CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); |    86       CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 
|    66       break; |    87       break; | 
|    67     } else { |    88     } else { | 
|    68       CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |    89       CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|    69       CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |    90       CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|    70     } |    91     } | 
|    71  |    92  | 
|    72     std::string read_buffer(1000, '\0'); |    93     std::string read_buffer(1000, '\0'); | 
|    73     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |    94     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 
|    74     CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], |    95     CHECK_EQ(MojoReadMessage(h, &read_buffer[0], | 
|    75                              &read_buffer_size, nullptr, |    96                              &read_buffer_size, nullptr, | 
|    76                              0, MOJO_READ_MESSAGE_FLAG_NONE), |    97                              0, MOJO_READ_MESSAGE_FLAG_NONE), | 
|    77              MOJO_RESULT_OK); |    98              MOJO_RESULT_OK); | 
|    78     read_buffer.resize(read_buffer_size); |    99     read_buffer.resize(read_buffer_size); | 
|    79     VLOG(2) << "Child got: " << read_buffer; |   100     VLOG(2) << "Child got: " << read_buffer; | 
|    80  |   101  | 
|    81     if (read_buffer == quitquitquit) { |   102     if (read_buffer == quitquitquit) { | 
|    82       VLOG(2) << "Child quitting."; |   103       VLOG(2) << "Child quitting."; | 
|    83       break; |   104       break; | 
|    84     } |   105     } | 
|    85  |   106  | 
|    86     std::string write_buffer = read_buffer + read_buffer; |   107     std::string write_buffer = read_buffer + read_buffer; | 
|    87     CHECK_EQ(MojoWriteMessage(mp.get().value(), write_buffer.data(), |   108     CHECK_EQ(MojoWriteMessage(h, write_buffer.data(), | 
|    88                               static_cast<uint32_t>(write_buffer.size()), |   109                               static_cast<uint32_t>(write_buffer.size()), | 
|    89                               nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), |   110                               nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), | 
|    90              MOJO_RESULT_OK); |   111              MOJO_RESULT_OK); | 
|    91   } |   112   } | 
|    92  |   113  | 
|    93    return rv; |   114   return rv; | 
|    94 } |   115 } | 
|    95  |   116  | 
|    96 // Sends "hello" to child, and expects "hellohello" back. |   117 // Sends "hello" to child, and expects "hellohello" back. | 
|    97 #if defined(OS_ANDROID) |   118 #if defined(OS_ANDROID) | 
|    98 // Android multi-process tests are not executing the new process. This is flaky. |   119 // Android multi-process tests are not executing the new process. This is flaky. | 
|    99 #define MAYBE_Basic DISABLED_Basic |   120 #define MAYBE_Basic DISABLED_Basic | 
|   100 #else |   121 #else | 
|   101 #define MAYBE_Basic Basic |   122 #define MAYBE_Basic Basic | 
|   102 #endif  // defined(OS_ANDROID) |   123 #endif  // defined(OS_ANDROID) | 
|   103 TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { |   124 TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { | 
|   104   helper()->StartChild("EchoEcho"); |   125   RUN_CHILD_ON_PIPE(EchoEcho, h) | 
 |   126     std::string hello("hello"); | 
 |   127     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   128               MojoWriteMessage(h, hello.data(), | 
 |   129                                static_cast<uint32_t>(hello.size()), nullptr, 0u, | 
 |   130                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
|   105  |   131  | 
|   106   ScopedMessagePipeHandle mp = |   132     HandleSignalsState hss; | 
|   107       CreateMessagePipe(std::move(helper()->server_platform_handle)); |   133     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   134               MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
 |   135                        MOJO_DEADLINE_INDEFINITE, &hss)); | 
 |   136     // The child may or may not have closed its end of the message pipe and died | 
 |   137     // (and we may or may not know it yet), so our end may or may not appear as | 
 |   138     // writable. | 
 |   139     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
 |   140     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|   108  |   141  | 
|   109   std::string hello("hello"); |   142     std::string read_buffer(1000, '\0'); | 
|   110   ASSERT_EQ(MOJO_RESULT_OK, |   143     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 
|   111             MojoWriteMessage(mp.get().value(), hello.data(), |   144     CHECK_EQ(MojoReadMessage(h, &read_buffer[0], | 
|   112                              static_cast<uint32_t>(hello.size()), nullptr, 0u, |   145                              &read_buffer_size, nullptr, 0, | 
|   113                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |   146                              MOJO_READ_MESSAGE_FLAG_NONE), | 
 |   147              MOJO_RESULT_OK); | 
 |   148     read_buffer.resize(read_buffer_size); | 
 |   149     VLOG(2) << "Parent got: " << read_buffer; | 
 |   150     ASSERT_EQ(hello + hello, read_buffer); | 
|   114  |   151  | 
|   115   HandleSignalsState hss; |   152     std::string quitquitquit("quitquitquit"); | 
|   116   ASSERT_EQ(MOJO_RESULT_OK, |   153     CHECK_EQ(MojoWriteMessage(h, quitquitquit.data(), | 
|   117             MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |   154                               static_cast<uint32_t>(quitquitquit.size()), | 
|   118                MOJO_DEADLINE_INDEFINITE, &hss)); |   155                               nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), | 
|   119   // The child may or may not have closed its end of the message pipe and died |   156              MOJO_RESULT_OK); | 
|   120   // (and we may or may not know it yet), so our end may or may not appear as |   157   END_CHILD_AND_EXPECT_EXIT_CODE(1 % 100); | 
|   121   // writable. |  | 
|   122   EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |  | 
|   123   EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |  | 
|   124  |  | 
|   125   std::string read_buffer(1000, '\0'); |  | 
|   126   uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |  | 
|   127   CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], |  | 
|   128                            &read_buffer_size, nullptr, 0, |  | 
|   129                            MOJO_READ_MESSAGE_FLAG_NONE), |  | 
|   130            MOJO_RESULT_OK); |  | 
|   131   read_buffer.resize(read_buffer_size); |  | 
|   132   VLOG(2) << "Parent got: " << read_buffer; |  | 
|   133   ASSERT_EQ(hello + hello, read_buffer); |  | 
|   134  |  | 
|   135   MojoClose(mp.release().value()); |  | 
|   136  |  | 
|   137   // We sent one message. |  | 
|   138   ASSERT_EQ(1 % 100, helper()->WaitForChildShutdown()); |  | 
|   139 } |   158 } | 
|   140  |   159  | 
|   141 // Sends a bunch of messages to the child. Expects them "repeated" back. Waits |   160 // Sends a bunch of messages to the child. Expects them "repeated" back. Waits | 
|   142 // for the child to close its end before quitting. |   161 // for the child to close its end before quitting. | 
|   143 #if defined(OS_ANDROID) |   162 #if defined(OS_ANDROID) | 
|   144 // Android multi-process tests are not executing the new process. This is flaky. |   163 // Android multi-process tests are not executing the new process. This is flaky. | 
|   145 #define MAYBE_QueueMessages DISABLED_QueueMessages |   164 #define MAYBE_QueueMessages DISABLED_QueueMessages | 
|   146 #else |   165 #else | 
|   147 #define MAYBE_QueueMessages QueueMessages |   166 #define MAYBE_QueueMessages QueueMessages | 
|   148 #endif  // defined(OS_ANDROID) |   167 #endif  // defined(OS_ANDROID) | 
|   149 TEST_F(MultiprocessMessagePipeTest, MAYBE_QueueMessages) { |   168 TEST_F(MultiprocessMessagePipeTest, MAYBE_QueueMessages) { | 
|   150   helper()->StartChild("EchoEcho"); |   169   static const size_t kNumMessages = 1001; | 
 |   170   RUN_CHILD_ON_PIPE(EchoEcho, h) | 
 |   171     for (size_t i = 0; i < kNumMessages; i++) { | 
 |   172       std::string write_buffer(i, 'A' + (i % 26)); | 
 |   173       ASSERT_EQ(MOJO_RESULT_OK, | 
 |   174               MojoWriteMessage(h, write_buffer.data(), | 
 |   175                                static_cast<uint32_t>(write_buffer.size()), | 
 |   176                                nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
 |   177     } | 
|   151  |   178  | 
|   152   ScopedMessagePipeHandle mp = |   179     for (size_t i = 0; i < kNumMessages; i++) { | 
|   153       CreateMessagePipe(std::move(helper()->server_platform_handle)); |   180       HandleSignalsState hss; | 
 |   181       ASSERT_EQ(MOJO_RESULT_OK, | 
 |   182                 MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
 |   183                          MOJO_DEADLINE_INDEFINITE, &hss)); | 
 |   184       // The child may or may not have closed its end of the message pipe and | 
 |   185       // died (and we may or may not know it yet), so our end may or may not | 
 |   186       // appear as writable. | 
 |   187       ASSERT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
 |   188       ASSERT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|   154  |   189  | 
|   155   static const size_t kNumMessages = 1001; |   190       std::string read_buffer(kNumMessages * 2, '\0'); | 
|   156   for (size_t i = 0; i < kNumMessages; i++) { |   191       uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 
|   157     std::string write_buffer(i, 'A' + (i % 26)); |   192       ASSERT_EQ(MojoReadMessage(h, &read_buffer[0], | 
 |   193                                 &read_buffer_size, nullptr, 0, | 
 |   194                                 MOJO_READ_MESSAGE_FLAG_NONE), | 
 |   195                MOJO_RESULT_OK); | 
 |   196       read_buffer.resize(read_buffer_size); | 
 |   197  | 
 |   198       ASSERT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer); | 
 |   199     } | 
 |   200  | 
 |   201     const std::string quitquitquit("quitquitquit"); | 
|   158     ASSERT_EQ(MOJO_RESULT_OK, |   202     ASSERT_EQ(MOJO_RESULT_OK, | 
|   159             MojoWriteMessage(mp.get().value(), write_buffer.data(), |   203               MojoWriteMessage(h, quitquitquit.data(), | 
|   160                              static_cast<uint32_t>(write_buffer.size()), |   204                                static_cast<uint32_t>(quitquitquit.size()), | 
|   161                              nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); |   205                                nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
|   162   } |  | 
|   163  |   206  | 
|   164   for (size_t i = 0; i < kNumMessages; i++) { |   207     // Wait for it to become readable, which should fail (since we sent | 
 |   208     // "quitquitquit"). | 
|   165     HandleSignalsState hss; |   209     HandleSignalsState hss; | 
|   166     ASSERT_EQ(MOJO_RESULT_OK, |   210     ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 
|   167               MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |   211               MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
|   168                        MOJO_DEADLINE_INDEFINITE, &hss)); |   212                        MOJO_DEADLINE_INDEFINITE, &hss)); | 
|   169     // The child may or may not have closed its end of the message pipe and died |   213     ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | 
|   170     // (and we may or may not know it yet), so our end may or may not appear as |   214     ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | 
|   171     // writable. |   215   END_CHILD_AND_EXPECT_EXIT_CODE(static_cast<int>(kNumMessages % 100)); | 
|   172     ASSERT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |  | 
|   173     ASSERT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |  | 
|   174  |  | 
|   175     std::string read_buffer(kNumMessages * 2, '\0'); |  | 
|   176     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |  | 
|   177     ASSERT_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], |  | 
|   178                              &read_buffer_size, nullptr, 0, |  | 
|   179                              MOJO_READ_MESSAGE_FLAG_NONE), |  | 
|   180              MOJO_RESULT_OK); |  | 
|   181     read_buffer.resize(read_buffer_size); |  | 
|   182  |  | 
|   183     ASSERT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer); |  | 
|   184   } |  | 
|   185  |  | 
|   186   const std::string quitquitquit("quitquitquit"); |  | 
|   187   ASSERT_EQ(MOJO_RESULT_OK, |  | 
|   188             MojoWriteMessage(mp.get().value(), quitquitquit.data(), |  | 
|   189                              static_cast<uint32_t>(quitquitquit.size()), |  | 
|   190                              nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); |  | 
|   191  |  | 
|   192   // Wait for it to become readable, which should fail (since we sent |  | 
|   193   // "quitquitquit"). |  | 
|   194   HandleSignalsState hss; |  | 
|   195   ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
|   196             MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |  | 
|   197                      MOJO_DEADLINE_INDEFINITE, &hss)); |  | 
|   198   ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |  | 
|   199   ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |  | 
|   200  |  | 
|   201   ASSERT_EQ(static_cast<int>(kNumMessages % 100), |  | 
|   202             helper()->WaitForChildShutdown()); |  | 
|   203 } |   216 } | 
|   204  |   217  | 
|   205 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { |   218 DEFINE_TEST_CLIENT_WITH_PIPE(CheckSharedBuffer, MultiprocessMessagePipeTest, | 
|   206   ScopedPlatformHandle client_platform_handle = |   219                              h) { | 
|   207       std::move(test::MultiprocessTestHelper::client_platform_handle); |  | 
|   208   CHECK(client_platform_handle.is_valid()); |  | 
|   209   ScopedMessagePipeHandle mp = |  | 
|   210       CreateMessagePipe(std::move(client_platform_handle)); |  | 
|   211  |  | 
|   212   // Wait for the first message from our parent. |   220   // Wait for the first message from our parent. | 
|   213   HandleSignalsState hss; |   221   HandleSignalsState hss; | 
|   214   CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |   222   CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
|   215                MOJO_DEADLINE_INDEFINITE, &hss), |   223                MOJO_DEADLINE_INDEFINITE, &hss), | 
|   216            MOJO_RESULT_OK); |   224            MOJO_RESULT_OK); | 
|   217   // In this test, the parent definitely doesn't close its end of the message |   225   // In this test, the parent definitely doesn't close its end of the message | 
|   218   // pipe before we do. |   226   // pipe before we do. | 
|   219   CHECK_EQ(hss.satisfied_signals, |   227   CHECK_EQ(hss.satisfied_signals, | 
|   220            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |   228            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 
|   221   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |   229   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 
|   222                                     MOJO_HANDLE_SIGNAL_WRITABLE | |   230                                     MOJO_HANDLE_SIGNAL_WRITABLE | | 
|   223                                     MOJO_HANDLE_SIGNAL_PEER_CLOSED); |   231                                     MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 
|   224  |   232  | 
|   225   // It should have a shared buffer. |   233   // It should have a shared buffer. | 
|   226   std::string read_buffer(100, '\0'); |   234   std::string read_buffer(100, '\0'); | 
|   227   uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |   235   uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); | 
|   228   MojoHandle handles[10]; |   236   MojoHandle handles[10]; | 
|   229   uint32_t num_handlers = MOJO_ARRAYSIZE(handles);  // Maximum number to receive |   237   uint32_t num_handlers = MOJO_ARRAYSIZE(handles);  // Maximum number to receive | 
|   230   CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], |   238   CHECK_EQ(MojoReadMessage(h, &read_buffer[0], | 
|   231                            &num_bytes, &handles[0], |   239                            &num_bytes, &handles[0], | 
|   232                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), |   240                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | 
|   233            MOJO_RESULT_OK); |   241            MOJO_RESULT_OK); | 
|   234   read_buffer.resize(num_bytes); |   242   read_buffer.resize(num_bytes); | 
|   235   CHECK_EQ(read_buffer, std::string("go 1")); |   243   CHECK_EQ(read_buffer, std::string("go 1")); | 
|   236   CHECK_EQ(num_handlers, 1u); |   244   CHECK_EQ(num_handlers, 1u); | 
|   237  |   245  | 
|   238   // Make a mapping. |   246   // Make a mapping. | 
|   239   void* buffer; |   247   void* buffer; | 
|   240   CHECK_EQ(MojoMapBuffer(handles[0], 0, 100, &buffer, |   248   CHECK_EQ(MojoMapBuffer(handles[0], 0, 100, &buffer, | 
|   241                          MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), |   249                          MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), | 
|   242            MOJO_RESULT_OK); |   250            MOJO_RESULT_OK); | 
|   243  |   251  | 
|   244   // Write some stuff to the shared buffer. |   252   // Write some stuff to the shared buffer. | 
|   245   static const char kHello[] = "hello"; |   253   static const char kHello[] = "hello"; | 
|   246   memcpy(buffer, kHello, sizeof(kHello)); |   254   memcpy(buffer, kHello, sizeof(kHello)); | 
|   247  |   255  | 
|   248   // We should be able to close the dispatcher now. |   256   // We should be able to close the dispatcher now. | 
|   249   MojoClose(handles[0]); |   257   MojoClose(handles[0]); | 
|   250  |   258  | 
|   251   // And send a message to signal that we've written stuff. |   259   // And send a message to signal that we've written stuff. | 
|   252   const std::string go2("go 2"); |   260   const std::string go2("go 2"); | 
|   253   CHECK_EQ(MojoWriteMessage(mp.get().value(), go2.data(), |   261   CHECK_EQ(MojoWriteMessage(h, go2.data(), | 
|   254                             static_cast<uint32_t>(go2.size()), nullptr, 0u, |   262                             static_cast<uint32_t>(go2.size()), nullptr, 0u, | 
|   255                             MOJO_WRITE_MESSAGE_FLAG_NONE), |   263                             MOJO_WRITE_MESSAGE_FLAG_NONE), | 
|   256            MOJO_RESULT_OK); |   264            MOJO_RESULT_OK); | 
|   257  |   265  | 
|   258   // Now wait for our parent to send us a message. |   266   // Now wait for our parent to send us a message. | 
|   259   hss = HandleSignalsState(); |   267   hss = HandleSignalsState(); | 
|   260   CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |   268   CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
|   261                MOJO_DEADLINE_INDEFINITE, &hss), |   269                     MOJO_DEADLINE_INDEFINITE, &hss), | 
|   262            MOJO_RESULT_OK); |   270            MOJO_RESULT_OK); | 
|   263   CHECK_EQ(hss.satisfied_signals, |   271   CHECK_EQ(hss.satisfied_signals, | 
|   264            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |   272            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 
|   265   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |   273   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 
|   266                                         MOJO_HANDLE_SIGNAL_WRITABLE | |   274                                         MOJO_HANDLE_SIGNAL_WRITABLE | | 
|   267                                         MOJO_HANDLE_SIGNAL_PEER_CLOSED); |   275                                         MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 
|   268  |   276  | 
|   269   read_buffer = std::string(100, '\0'); |   277   read_buffer = std::string(100, '\0'); | 
|   270   num_bytes = static_cast<uint32_t>(read_buffer.size()); |   278   num_bytes = static_cast<uint32_t>(read_buffer.size()); | 
|   271   CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], &num_bytes, |   279   CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &num_bytes, | 
|   272                            nullptr, 0, MOJO_READ_MESSAGE_FLAG_NONE), |   280                            nullptr, 0, MOJO_READ_MESSAGE_FLAG_NONE), | 
|   273            MOJO_RESULT_OK); |   281            MOJO_RESULT_OK); | 
|   274   read_buffer.resize(num_bytes); |   282   read_buffer.resize(num_bytes); | 
|   275   CHECK_EQ(read_buffer, std::string("go 3")); |   283   CHECK_EQ(read_buffer, std::string("go 3")); | 
|   276  |   284  | 
|   277   // It should have written something to the shared buffer. |   285   // It should have written something to the shared buffer. | 
|   278   static const char kWorld[] = "world!!!"; |   286   static const char kWorld[] = "world!!!"; | 
|   279   CHECK_EQ(memcmp(buffer, kWorld, sizeof(kWorld)), 0); |   287   CHECK_EQ(memcmp(buffer, kWorld, sizeof(kWorld)), 0); | 
|   280  |   288  | 
|   281   // And we're done. |   289   // And we're done. | 
|   282  |   290  | 
|   283   return 0; |   291   return 0; | 
|   284 } |   292 } | 
|   285  |   293  | 
|   286 #if defined(OS_ANDROID) |   294 #if defined(OS_ANDROID) | 
|   287 // Android multi-process tests are not executing the new process. This is flaky. |   295 // Android multi-process tests are not executing the new process. This is flaky. | 
|   288 #define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing |   296 #define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing | 
|   289 #else |   297 #else | 
|   290 #define MAYBE_SharedBufferPassing SharedBufferPassing |   298 #define MAYBE_SharedBufferPassing SharedBufferPassing | 
|   291 #endif |   299 #endif | 
|   292 TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { |   300 TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { | 
|   293   helper()->StartChild("CheckSharedBuffer"); |   301   RUN_CHILD_ON_PIPE(CheckSharedBuffer, h) | 
 |   302     // Make a shared buffer. | 
 |   303     MojoCreateSharedBufferOptions options; | 
 |   304     options.struct_size = sizeof(options); | 
 |   305     options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; | 
|   294  |   306  | 
|   295   ScopedMessagePipeHandle mp = |   307     MojoHandle shared_buffer; | 
|   296       CreateMessagePipe(std::move(helper()->server_platform_handle)); |   308     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   309               MojoCreateSharedBuffer(&options, 100, &shared_buffer)); | 
|   297  |   310  | 
|   298   // Make a shared buffer. |   311     // Send the shared buffer. | 
|   299   MojoCreateSharedBufferOptions options; |   312     const std::string go1("go 1"); | 
|   300   options.struct_size = sizeof(options); |  | 
|   301   options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; |  | 
|   302  |   313  | 
|   303   MojoHandle shared_buffer; |   314     MojoHandle duplicated_shared_buffer; | 
|   304   ASSERT_EQ(MOJO_RESULT_OK, |   315     ASSERT_EQ(MOJO_RESULT_OK, | 
|   305             MojoCreateSharedBuffer(&options, 100, &shared_buffer)); |   316               MojoDuplicateBufferHandle( | 
 |   317                   shared_buffer, | 
 |   318                   nullptr, | 
 |   319                   &duplicated_shared_buffer)); | 
 |   320     MojoHandle handles[1]; | 
 |   321     handles[0] = duplicated_shared_buffer; | 
 |   322     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   323               MojoWriteMessage(h, &go1[0], | 
 |   324                                static_cast<uint32_t>(go1.size()), &handles[0], | 
 |   325                                MOJO_ARRAYSIZE(handles), | 
 |   326                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
|   306  |   327  | 
|   307   // Send the shared buffer. |   328     // Wait for a message from the child. | 
|   308   const std::string go1("go 1"); |   329     HandleSignalsState hss; | 
 |   330     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   331               MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
 |   332                        MOJO_DEADLINE_INDEFINITE, &hss)); | 
 |   333     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
 |   334     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|   309  |   335  | 
|   310   MojoHandle duplicated_shared_buffer; |   336     std::string read_buffer(100, '\0'); | 
|   311   ASSERT_EQ(MOJO_RESULT_OK, |   337     uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); | 
|   312             MojoDuplicateBufferHandle( |   338     ASSERT_EQ(MOJO_RESULT_OK, | 
|   313                 shared_buffer, |   339               MojoReadMessage(h, &read_buffer[0], | 
|   314                 nullptr, |   340                               &num_bytes, nullptr, 0, | 
|   315                 &duplicated_shared_buffer)); |   341                               MOJO_READ_MESSAGE_FLAG_NONE)); | 
|   316   MojoHandle handles[1]; |   342     read_buffer.resize(num_bytes); | 
|   317   handles[0] = duplicated_shared_buffer; |   343     ASSERT_EQ(std::string("go 2"), read_buffer); | 
|   318   ASSERT_EQ(MOJO_RESULT_OK, |  | 
|   319             MojoWriteMessage(mp.get().value(), &go1[0], |  | 
|   320                              static_cast<uint32_t>(go1.size()), &handles[0], |  | 
|   321                              MOJO_ARRAYSIZE(handles), |  | 
|   322                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |  | 
|   323  |   344  | 
|   324   // Wait for a message from the child. |   345     // After we get it, the child should have written something to the shared | 
|   325   HandleSignalsState hss; |   346     // buffer. | 
|   326   ASSERT_EQ(MOJO_RESULT_OK, |   347     static const char kHello[] = "hello"; | 
|   327             MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |   348     void* buffer; | 
|   328                      MOJO_DEADLINE_INDEFINITE, &hss)); |   349     CHECK_EQ(MojoMapBuffer(shared_buffer, 0, 100, &buffer, | 
|   329   EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |   350                            MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), | 
|   330   EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |   351              MOJO_RESULT_OK); | 
 |   352     ASSERT_EQ(0, memcmp(buffer, kHello, sizeof(kHello))); | 
|   331  |   353  | 
|   332   std::string read_buffer(100, '\0'); |   354     // Now we'll write some stuff to the shared buffer. | 
|   333   uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |   355     static const char kWorld[] = "world!!!"; | 
|   334   ASSERT_EQ(MOJO_RESULT_OK, |   356     memcpy(buffer, kWorld, sizeof(kWorld)); | 
|   335             MojoReadMessage(mp.get().value(), &read_buffer[0], |  | 
|   336                              &num_bytes, nullptr, 0, |  | 
|   337                              MOJO_READ_MESSAGE_FLAG_NONE)); |  | 
|   338   read_buffer.resize(num_bytes); |  | 
|   339   ASSERT_EQ(std::string("go 2"), read_buffer); |  | 
|   340  |   357  | 
|   341   // After we get it, the child should have written something to the shared |   358     // And send a message to signal that we've written stuff. | 
|   342   // buffer. |   359     const std::string go3("go 3"); | 
|   343   static const char kHello[] = "hello"; |   360     ASSERT_EQ(MOJO_RESULT_OK, | 
|   344   void* buffer; |   361               MojoWriteMessage(h, &go3[0], | 
|   345   CHECK_EQ(MojoMapBuffer(shared_buffer, 0, 100, &buffer, |   362                                static_cast<uint32_t>(go3.size()), nullptr, 0u, | 
|   346                          MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), |   363                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
|   347            MOJO_RESULT_OK); |  | 
|   348   ASSERT_EQ(0, memcmp(buffer, kHello, sizeof(kHello))); |  | 
|   349  |   364  | 
|   350   // Now we'll write some stuff to the shared buffer. |   365     // Wait for |h| to become readable, which should fail. | 
|   351   static const char kWorld[] = "world!!!"; |   366     hss = HandleSignalsState(); | 
|   352   memcpy(buffer, kWorld, sizeof(kWorld)); |   367     ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 
|   353  |   368               MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
|   354   // And send a message to signal that we've written stuff. |   369                        MOJO_DEADLINE_INDEFINITE, &hss)); | 
|   355   const std::string go3("go 3"); |   370     ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | 
|   356   ASSERT_EQ(MOJO_RESULT_OK, |   371     ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | 
|   357             MojoWriteMessage(mp.get().value(), &go3[0], |   372   END_CHILD() | 
|   358                              static_cast<uint32_t>(go3.size()), nullptr, 0u, |  | 
|   359                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |  | 
|   360  |  | 
|   361   // Wait for |mp| to become readable, which should fail. |  | 
|   362   hss = HandleSignalsState(); |  | 
|   363   ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
|   364             MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |  | 
|   365                      MOJO_DEADLINE_INDEFINITE, &hss)); |  | 
|   366   ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |  | 
|   367   ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |  | 
|   368  |  | 
|   369   MojoClose(mp.release().value()); |  | 
|   370  |  | 
|   371   ASSERT_EQ(0, helper()->WaitForChildShutdown()); |  | 
|   372 } |   373 } | 
|   373  |   374  | 
|   374 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { |   375 DEFINE_TEST_CLIENT_WITH_PIPE(CheckPlatformHandleFile, | 
|   375   ScopedPlatformHandle client_platform_handle = |   376                              MultiprocessMessagePipeTest, h) { | 
|   376       std::move(test::MultiprocessTestHelper::client_platform_handle); |  | 
|   377   CHECK(client_platform_handle.is_valid()); |  | 
|   378   ScopedMessagePipeHandle mp = |  | 
|   379       CreateMessagePipe(std::move(client_platform_handle)); |  | 
|   380  |  | 
|   381   HandleSignalsState hss; |   377   HandleSignalsState hss; | 
|   382   CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |   378   CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
|   383                MOJO_DEADLINE_INDEFINITE, &hss), |   379                     MOJO_DEADLINE_INDEFINITE, &hss), | 
|   384            MOJO_RESULT_OK); |   380            MOJO_RESULT_OK); | 
|   385   CHECK_EQ(hss.satisfied_signals, |   381   CHECK_EQ(hss.satisfied_signals, | 
|   386            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |   382            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 
|   387   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |   383   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 
|   388                                         MOJO_HANDLE_SIGNAL_WRITABLE | |   384                                         MOJO_HANDLE_SIGNAL_WRITABLE | | 
|   389                                         MOJO_HANDLE_SIGNAL_PEER_CLOSED); |   385                                         MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 
|   390  |   386  | 
|   391   std::string read_buffer(100, '\0'); |   387   std::string read_buffer(100, '\0'); | 
|   392   uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |   388   uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); | 
|   393   MojoHandle handles[255];  // Maximum number to receive. |   389   MojoHandle handles[255];  // Maximum number to receive. | 
|   394   uint32_t num_handlers = MOJO_ARRAYSIZE(handles); |   390   uint32_t num_handlers = MOJO_ARRAYSIZE(handles); | 
|   395  |   391  | 
|   396   CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], |   392   CHECK_EQ(MojoReadMessage(h, &read_buffer[0], | 
|   397                            &num_bytes, &handles[0], |   393                            &num_bytes, &handles[0], | 
|   398                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), |   394                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | 
|   399            MOJO_RESULT_OK); |   395            MOJO_RESULT_OK); | 
|   400   MojoClose(mp.release().value()); |  | 
|   401  |   396  | 
|   402   read_buffer.resize(num_bytes); |   397   read_buffer.resize(num_bytes); | 
|   403   char hello[32]; |   398   char hello[32]; | 
|   404   int num_handles = 0; |   399   int num_handles = 0; | 
|   405   sscanf(read_buffer.c_str(), "%s %d", hello, &num_handles); |   400   sscanf(read_buffer.c_str(), "%s %d", hello, &num_handles); | 
|   406   CHECK_EQ(std::string("hello"), std::string(hello)); |   401   CHECK_EQ(std::string("hello"), std::string(hello)); | 
|   407   CHECK_GT(num_handles, 0); |   402   CHECK_GT(num_handles, 0); | 
|   408  |   403  | 
|   409   for (int i = 0; i < num_handles; ++i) { |   404   for (int i = 0; i < num_handles; ++i) { | 
|   410     ScopedPlatformHandle h; |   405     ScopedPlatformHandle h; | 
|   411     CHECK_EQ(PassWrappedPlatformHandle( |   406     CHECK_EQ(PassWrappedPlatformHandle(handles[i], &h), MOJO_RESULT_OK); | 
|   412                 handles[i], &h), |  | 
|   413              MOJO_RESULT_OK); |  | 
|   414     CHECK(h.is_valid()); |   407     CHECK(h.is_valid()); | 
|   415     MojoClose(handles[i]); |   408     MojoClose(handles[i]); | 
|   416  |   409  | 
|   417     base::ScopedFILE fp(test::FILEFromPlatformHandle(std::move(h), "r")); |   410     base::ScopedFILE fp(test::FILEFromPlatformHandle(std::move(h), "r")); | 
|   418     CHECK(fp); |   411     CHECK(fp); | 
|   419     std::string fread_buffer(100, '\0'); |   412     std::string fread_buffer(100, '\0'); | 
|   420     size_t bytes_read = |   413     size_t bytes_read = | 
|   421         fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get()); |   414         fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get()); | 
|   422     fread_buffer.resize(bytes_read); |   415     fread_buffer.resize(bytes_read); | 
|   423     CHECK_EQ(fread_buffer, "world"); |   416     CHECK_EQ(fread_buffer, "world"); | 
|   424   } |   417   } | 
|   425  |   418  | 
|   426   return 0; |   419   return 0; | 
|   427 } |   420 } | 
|   428  |   421  | 
|   429 class MultiprocessMessagePipeTestWithPipeCount |   422 class MultiprocessMessagePipeTestWithPipeCount | 
|   430     : public test::MultiprocessMessagePipeTestBase, |   423     : public MultiprocessMessagePipeTest, | 
|   431       public testing::WithParamInterface<size_t> {}; |   424       public testing::WithParamInterface<size_t> {}; | 
|   432  |   425  | 
|   433 TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { |   426 TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { | 
|   434   base::ScopedTempDir temp_dir; |   427   base::ScopedTempDir temp_dir; | 
|   435   ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |   428   ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 
|   436  |   429  | 
|   437   helper()->StartChild("CheckPlatformHandleFile"); |   430   RUN_CHILD_ON_PIPE(CheckPlatformHandleFile, h) | 
|   438   ScopedMessagePipeHandle mp = |   431     std::vector<MojoHandle> handles; | 
|   439       CreateMessagePipe(std::move(helper()->server_platform_handle)); |  | 
|   440  |   432  | 
|   441   std::vector<MojoHandle> handles; |   433     size_t pipe_count = GetParam(); | 
 |   434     for (size_t i = 0; i < pipe_count; ++i) { | 
 |   435       base::FilePath unused; | 
 |   436       base::ScopedFILE fp( | 
 |   437           CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); | 
 |   438       const std::string world("world"); | 
 |   439       CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size()); | 
 |   440       fflush(fp.get()); | 
 |   441       rewind(fp.get()); | 
 |   442       MojoHandle handle; | 
 |   443       ASSERT_EQ( | 
 |   444           CreatePlatformHandleWrapper( | 
 |   445               ScopedPlatformHandle(test::PlatformHandleFromFILE(std::move(fp))), | 
 |   446               &handle), | 
 |   447           MOJO_RESULT_OK); | 
 |   448       handles.push_back(handle); | 
 |   449     } | 
|   442  |   450  | 
|   443   size_t pipe_count = GetParam(); |   451     char message[128]; | 
|   444   for (size_t i = 0; i < pipe_count; ++i) { |   452     sprintf(message, "hello %d", static_cast<int>(pipe_count)); | 
|   445     base::FilePath unused; |   453     ASSERT_EQ(MOJO_RESULT_OK, | 
|   446     base::ScopedFILE fp( |   454               MojoWriteMessage(h, message, | 
|   447         CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); |   455                                static_cast<uint32_t>(strlen(message)), | 
|   448     const std::string world("world"); |   456                                &handles[0], | 
|   449     CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size()); |   457                                static_cast<uint32_t>(handles.size()), | 
|   450     fflush(fp.get()); |   458                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
|   451     rewind(fp.get()); |  | 
|   452     MojoHandle handle; |  | 
|   453     ASSERT_EQ( |  | 
|   454         CreatePlatformHandleWrapper( |  | 
|   455             ScopedPlatformHandle(test::PlatformHandleFromFILE(std::move(fp))), |  | 
|   456             &handle), |  | 
|   457         MOJO_RESULT_OK); |  | 
|   458     handles.push_back(handle); |  | 
|   459   } |  | 
|   460  |   459  | 
|   461   char message[128]; |   460     // Wait for it to become readable, which should fail. | 
|   462   sprintf(message, "hello %d", static_cast<int>(pipe_count)); |   461     HandleSignalsState hss; | 
|   463   ASSERT_EQ(MOJO_RESULT_OK, |   462     ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 
|   464             MojoWriteMessage(mp.get().value(), message, |   463               MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
|   465                              static_cast<uint32_t>(strlen(message)), |   464                        MOJO_DEADLINE_INDEFINITE, &hss)); | 
|   466                              &handles[0], static_cast<uint32_t>(handles.size()), |   465     ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | 
|   467                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |   466     ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | 
|   468  |   467   END_CHILD() | 
|   469   // Wait for it to become readable, which should fail. |  | 
|   470   HandleSignalsState hss; |  | 
|   471   ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
|   472             MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |  | 
|   473                      MOJO_DEADLINE_INDEFINITE, &hss)); |  | 
|   474   ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |  | 
|   475   ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |  | 
|   476  |  | 
|   477   MojoClose(mp.release().value()); |  | 
|   478  |  | 
|   479   ASSERT_EQ(0, helper()->WaitForChildShutdown()); |  | 
|   480 } |   468 } | 
|   481  |   469  | 
|   482 // Android multi-process tests are not executing the new process. This is flaky. |   470 // Android multi-process tests are not executing the new process. This is flaky. | 
|   483 #if !defined(OS_ANDROID) |   471 #if !defined(OS_ANDROID) | 
|   484 INSTANTIATE_TEST_CASE_P(PipeCount, |   472 INSTANTIATE_TEST_CASE_P(PipeCount, | 
|   485                         MultiprocessMessagePipeTestWithPipeCount, |   473                         MultiprocessMessagePipeTestWithPipeCount, | 
|   486                         testing::Values(1u, 128u, 140u)); |   474                         // TODO: Re-enable the 140-pipe case when ChannelPosix | 
 |   475                         // has support for sending lots of handles. | 
 |   476                         testing::Values(1u, 128u/*, 140u*/)); | 
|   487 #endif |   477 #endif | 
|   488  |   478  | 
|   489 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckMessagePipe) { |   479 DEFINE_TEST_CLIENT_WITH_PIPE(CheckMessagePipe, MultiprocessMessagePipeTest, h) { | 
|   490   ScopedPlatformHandle client_platform_handle = |  | 
|   491       std::move(test::MultiprocessTestHelper::client_platform_handle); |  | 
|   492   CHECK(client_platform_handle.is_valid()); |  | 
|   493  |  | 
|   494   ScopedMessagePipeHandle mp = |  | 
|   495       CreateMessagePipe(std::move(client_platform_handle)); |  | 
|   496  |  | 
|   497   // Wait for the first message from our parent. |   480   // Wait for the first message from our parent. | 
|   498   HandleSignalsState hss; |   481   HandleSignalsState hss; | 
|   499   CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |   482   CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
|   500                MOJO_DEADLINE_INDEFINITE, &hss), |   483                     MOJO_DEADLINE_INDEFINITE, &hss), | 
|   501            MOJO_RESULT_OK); |   484            MOJO_RESULT_OK); | 
|   502   // In this test, the parent definitely doesn't close its end of the message |   485   // In this test, the parent definitely doesn't close its end of the message | 
|   503   // pipe before we do. |   486   // pipe before we do. | 
|   504   CHECK_EQ(hss.satisfied_signals, |   487   CHECK_EQ(hss.satisfied_signals, | 
|   505            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |   488            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 
|   506   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |   489   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 
|   507                                     MOJO_HANDLE_SIGNAL_WRITABLE | |   490                                     MOJO_HANDLE_SIGNAL_WRITABLE | | 
|   508                                     MOJO_HANDLE_SIGNAL_PEER_CLOSED); |   491                                     MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 
|   509  |   492  | 
|   510   // It should have a message pipe. |   493   // It should have a message pipe. | 
|   511   MojoHandle handles[10]; |   494   MojoHandle handles[10]; | 
|   512   uint32_t num_handlers = MOJO_ARRAYSIZE(handles); |   495   uint32_t num_handlers = MOJO_ARRAYSIZE(handles); | 
|   513   CHECK_EQ(MojoReadMessage(mp.get().value(), nullptr, |   496   CHECK_EQ(MojoReadMessage(h, nullptr, | 
|   514                            nullptr, &handles[0], |   497                            nullptr, &handles[0], | 
|   515                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), |   498                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | 
|   516            MOJO_RESULT_OK); |   499            MOJO_RESULT_OK); | 
|   517   CHECK_EQ(num_handlers, 1u); |   500   CHECK_EQ(num_handlers, 1u); | 
|   518  |   501  | 
|   519   // Read data from the received message pipe. |   502   // Read data from the received message pipe. | 
|   520   CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, |   503   CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, | 
|   521                MOJO_DEADLINE_INDEFINITE, &hss), |   504                MOJO_DEADLINE_INDEFINITE, &hss), | 
|   522            MOJO_RESULT_OK); |   505            MOJO_RESULT_OK); | 
|   523   CHECK_EQ(hss.satisfied_signals, |   506   CHECK_EQ(hss.satisfied_signals, | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|   545   return 0; |   528   return 0; | 
|   546 } |   529 } | 
|   547  |   530  | 
|   548 #if defined(OS_ANDROID) |   531 #if defined(OS_ANDROID) | 
|   549 // Android multi-process tests are not executing the new process. This is flaky. |   532 // Android multi-process tests are not executing the new process. This is flaky. | 
|   550 #define MAYBE_MessagePipePassing DISABLED_MessagePipePassing |   533 #define MAYBE_MessagePipePassing DISABLED_MessagePipePassing | 
|   551 #else |   534 #else | 
|   552 #define MAYBE_MessagePipePassing MessagePipePassing |   535 #define MAYBE_MessagePipePassing MessagePipePassing | 
|   553 #endif |   536 #endif | 
|   554 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipePassing) { |   537 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipePassing) { | 
|   555   helper()->StartChild("CheckMessagePipe"); |   538   RUN_CHILD_ON_PIPE(CheckMessagePipe, h) | 
 |   539     MojoCreateSharedBufferOptions options; | 
 |   540     options.struct_size = sizeof(options); | 
 |   541     options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; | 
|   556  |   542  | 
|   557   ScopedMessagePipeHandle mp = |   543     MojoHandle mp1, mp2; | 
|   558       CreateMessagePipe(std::move(helper()->server_platform_handle)); |   544     ASSERT_EQ(MOJO_RESULT_OK, | 
|   559   MojoCreateSharedBufferOptions options; |   545               MojoCreateMessagePipe(nullptr, &mp1, &mp2)); | 
|   560   options.struct_size = sizeof(options); |  | 
|   561   options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; |  | 
|   562  |   546  | 
|   563   MojoHandle mp1, mp2; |   547     // Write a string into one end of the new message pipe and send the other | 
|   564   ASSERT_EQ(MOJO_RESULT_OK, |   548     // end. | 
|   565             MojoCreateMessagePipe(nullptr, &mp1, &mp2)); |   549     const std::string hello("hello"); | 
 |   550     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   551               MojoWriteMessage(mp1, &hello[0], | 
 |   552                                static_cast<uint32_t>(hello.size()), nullptr, 0, | 
 |   553                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
 |   554     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   555               MojoWriteMessage(h, nullptr, 0, &mp2, 1, | 
 |   556                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
|   566  |   557  | 
|   567   // Write a string into one end of the new message pipe and send the other end. |   558     // Wait for a message from the child. | 
|   568   const std::string hello("hello"); |   559     HandleSignalsState hss; | 
|   569   ASSERT_EQ(MOJO_RESULT_OK, |   560     ASSERT_EQ(MOJO_RESULT_OK, | 
|   570             MojoWriteMessage(mp1, &hello[0], |   561               MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | 
|   571                              static_cast<uint32_t>(hello.size()), nullptr, 0, |   562                        MOJO_DEADLINE_INDEFINITE, &hss)); | 
|   572                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |   563     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|   573   ASSERT_EQ(MOJO_RESULT_OK, |   564     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|   574             MojoWriteMessage(mp.get().value(), nullptr, 0, &mp2, 1, |  | 
|   575                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |  | 
|   576  |   565  | 
|   577   // Wait for a message from the child. |   566     std::string read_buffer(100, '\0'); | 
|   578   HandleSignalsState hss; |   567     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 
|   579   ASSERT_EQ(MOJO_RESULT_OK, |   568     CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], | 
|   580             MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, |   569                              &read_buffer_size, nullptr, | 
|   581                      MOJO_DEADLINE_INDEFINITE, &hss)); |   570                              0, MOJO_READ_MESSAGE_FLAG_NONE), | 
|   582   EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |   571              MOJO_RESULT_OK); | 
|   583   EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |   572     read_buffer.resize(read_buffer_size); | 
 |   573     CHECK_EQ(read_buffer, std::string("world")); | 
|   584  |   574  | 
|   585   std::string read_buffer(100, '\0'); |   575     MojoClose(mp1); | 
|   586   uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |   576   END_CHILD() | 
|   587   CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], |  | 
|   588                            &read_buffer_size, nullptr, |  | 
|   589                            0, MOJO_READ_MESSAGE_FLAG_NONE), |  | 
|   590            MOJO_RESULT_OK); |  | 
|   591   read_buffer.resize(read_buffer_size); |  | 
|   592   CHECK_EQ(read_buffer, std::string("world")); |  | 
|   593  |  | 
|   594   MojoClose(mp1); |  | 
|   595   MojoClose(mp.release().value()); |  | 
|   596  |  | 
|   597   ASSERT_EQ(0, helper()->WaitForChildShutdown()); |  | 
|   598 } |   577 } | 
|   599  |   578  | 
|   600 // Like above test, but verifies passing the other MP handle works as well. |   579 // Like above test, but verifies passing the other MP handle works as well. | 
|   601 #if defined(OS_ANDROID) |   580 #if defined(OS_ANDROID) | 
|   602 // Android multi-process tests are not executing the new process. This is flaky. |   581 // Android multi-process tests are not executing the new process. This is flaky. | 
|   603 #define MAYBE_MessagePipeTwoPassing DISABLED_MessagePipeTwoPassing |   582 #define MAYBE_MessagePipeTwoPassing DISABLED_MessagePipeTwoPassing | 
|   604 #else |   583 #else | 
|   605 #define MAYBE_MessagePipeTwoPassing MessagePipeTwoPassing |   584 #define MAYBE_MessagePipeTwoPassing MessagePipeTwoPassing | 
|   606 #endif |   585 #endif | 
|   607 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipeTwoPassing) { |   586 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipeTwoPassing) { | 
|   608   helper()->StartChild("CheckMessagePipe"); |   587   RUN_CHILD_ON_PIPE(CheckMessagePipe, h) | 
 |   588     MojoHandle mp1, mp2; | 
 |   589     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   590               MojoCreateMessagePipe(nullptr, &mp2, &mp1)); | 
|   609  |   591  | 
|   610   ScopedMessagePipeHandle mp = |   592     // Write a string into one end of the new message pipe and send the other | 
|   611       CreateMessagePipe(std::move(helper()->server_platform_handle)); |   593     // end. | 
 |   594     const std::string hello("hello"); | 
 |   595     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   596               MojoWriteMessage(mp1, &hello[0], | 
 |   597                                static_cast<uint32_t>(hello.size()), nullptr, 0u, | 
 |   598                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
 |   599     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   600               MojoWriteMessage(h, nullptr, 0u, &mp2, 1u, | 
 |   601                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
|   612  |   602  | 
|   613   MojoHandle mp1, mp2; |   603     // Wait for a message from the child. | 
|   614   ASSERT_EQ(MOJO_RESULT_OK, |   604     HandleSignalsState hss; | 
|   615             MojoCreateMessagePipe(nullptr, &mp2, &mp1)); |   605     ASSERT_EQ(MOJO_RESULT_OK, | 
 |   606               MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | 
 |   607                        MOJO_DEADLINE_INDEFINITE, &hss)); | 
 |   608     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
 |   609     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|   616  |   610  | 
|   617   // Write a string into one end of the new message pipe and send the other end. |   611     std::string read_buffer(100, '\0'); | 
|   618   const std::string hello("hello"); |   612     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 
|   619   ASSERT_EQ(MOJO_RESULT_OK, |   613     CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], | 
|   620             MojoWriteMessage(mp1, &hello[0], |   614                              &read_buffer_size, nullptr, | 
|   621                              static_cast<uint32_t>(hello.size()), nullptr, 0u, |   615                              0, MOJO_READ_MESSAGE_FLAG_NONE), | 
|   622                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |   616              MOJO_RESULT_OK); | 
|   623   ASSERT_EQ(MOJO_RESULT_OK, |   617     read_buffer.resize(read_buffer_size); | 
|   624             MojoWriteMessage(mp.get().value(), nullptr, 0u, &mp2, 1u, |   618     CHECK_EQ(read_buffer, std::string("world")); | 
|   625                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |   619   END_CHILD(); | 
|   626  |  | 
|   627   // Wait for a message from the child. |  | 
|   628   HandleSignalsState hss; |  | 
|   629   ASSERT_EQ(MOJO_RESULT_OK, |  | 
|   630             MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, |  | 
|   631                      MOJO_DEADLINE_INDEFINITE, &hss)); |  | 
|   632   EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |  | 
|   633   EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |  | 
|   634  |  | 
|   635   std::string read_buffer(100, '\0'); |  | 
|   636   uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |  | 
|   637   CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], |  | 
|   638                            &read_buffer_size, nullptr, |  | 
|   639                            0, MOJO_READ_MESSAGE_FLAG_NONE), |  | 
|   640            MOJO_RESULT_OK); |  | 
|   641   read_buffer.resize(read_buffer_size); |  | 
|   642   CHECK_EQ(read_buffer, std::string("world")); |  | 
|   643  |  | 
|   644   MojoClose(mp.release().value()); |  | 
|   645  |  | 
|   646   ASSERT_EQ(0, helper()->WaitForChildShutdown()); |  | 
|   647 } |   620 } | 
|   648  |   621  | 
|   649 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(DataPipeConsumer) { |   622 DEFINE_TEST_CLIENT_WITH_PIPE(DataPipeConsumer, MultiprocessMessagePipeTest, h) { | 
|   650   ScopedPlatformHandle client_platform_handle = |  | 
|   651       std::move(test::MultiprocessTestHelper::client_platform_handle); |  | 
|   652   CHECK(client_platform_handle.is_valid()); |  | 
|   653  |  | 
|   654   ScopedMessagePipeHandle mp = |  | 
|   655       CreateMessagePipe(std::move(client_platform_handle)); |  | 
|   656  |  | 
|   657   // Wait for the first message from our parent. |   623   // Wait for the first message from our parent. | 
|   658   HandleSignalsState hss; |   624   HandleSignalsState hss; | 
|   659   CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |   625   CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, | 
|   660                MOJO_DEADLINE_INDEFINITE, &hss), |   626                     MOJO_DEADLINE_INDEFINITE, &hss), | 
|   661            MOJO_RESULT_OK); |   627            MOJO_RESULT_OK); | 
|   662   // In this test, the parent definitely doesn't close its end of the message |   628   // In this test, the parent definitely doesn't close its end of the message | 
|   663   // pipe before we do. |   629   // pipe before we do. | 
|   664   CHECK_EQ(hss.satisfied_signals, |   630   CHECK_EQ(hss.satisfied_signals, | 
|   665            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |   631            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 
|   666   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |   632   CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 
|   667                                     MOJO_HANDLE_SIGNAL_WRITABLE | |   633                                     MOJO_HANDLE_SIGNAL_WRITABLE | | 
|   668                                     MOJO_HANDLE_SIGNAL_PEER_CLOSED); |   634                                     MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 
|   669  |   635  | 
|   670   // It should have a message pipe. |   636   // It should have a message pipe. | 
|   671   MojoHandle handles[10]; |   637   MojoHandle handles[10]; | 
|   672   uint32_t num_handlers = MOJO_ARRAYSIZE(handles); |   638   uint32_t num_handlers = MOJO_ARRAYSIZE(handles); | 
|   673   CHECK_EQ(MojoReadMessage(mp.get().value(), nullptr, |   639   CHECK_EQ(MojoReadMessage(h, nullptr, | 
|   674                            nullptr, &handles[0], |   640                            nullptr, &handles[0], | 
|   675                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), |   641                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | 
|   676            MOJO_RESULT_OK); |   642            MOJO_RESULT_OK); | 
|   677   CHECK_EQ(num_handlers, 1u); |   643   CHECK_EQ(num_handlers, 1u); | 
|   678  |   644  | 
|   679   // Read data from the received message pipe. |   645   // Read data from the received message pipe. | 
|   680   CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, |   646   CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, | 
|   681                MOJO_DEADLINE_INDEFINITE, &hss), |   647                MOJO_DEADLINE_INDEFINITE, &hss), | 
|   682            MOJO_RESULT_OK); |   648            MOJO_RESULT_OK); | 
|   683   CHECK_EQ(hss.satisfied_signals, |   649   CHECK_EQ(hss.satisfied_signals, | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|   705   return 0; |   671   return 0; | 
|   706 } |   672 } | 
|   707  |   673  | 
|   708 #if defined(OS_ANDROID) |   674 #if defined(OS_ANDROID) | 
|   709 // Android multi-process tests are not executing the new process. This is flaky. |   675 // Android multi-process tests are not executing the new process. This is flaky. | 
|   710 #define MAYBE_DataPipeConsumer DISABLED_DataPipeConsumer |   676 #define MAYBE_DataPipeConsumer DISABLED_DataPipeConsumer | 
|   711 #else |   677 #else | 
|   712 #define MAYBE_DataPipeConsumer DataPipeConsumer |   678 #define MAYBE_DataPipeConsumer DataPipeConsumer | 
|   713 #endif |   679 #endif | 
|   714 TEST_F(MultiprocessMessagePipeTest, MAYBE_DataPipeConsumer) { |   680 TEST_F(MultiprocessMessagePipeTest, MAYBE_DataPipeConsumer) { | 
|   715   helper()->StartChild("DataPipeConsumer"); |   681   RUN_CHILD_ON_PIPE(DataPipeConsumer, h) | 
|   716  |   682     MojoCreateSharedBufferOptions options; | 
|   717   ScopedMessagePipeHandle mp = |   683     options.struct_size = sizeof(options); | 
|   718       CreateMessagePipe(std::move(helper()->server_platform_handle)); |   684     options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; | 
|   719   MojoCreateSharedBufferOptions options; |   685  | 
|   720   options.struct_size = sizeof(options); |   686     MojoHandle mp1, mp2; | 
|   721   options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; |   687     ASSERT_EQ(MOJO_RESULT_OK, | 
|   722  |   688               MojoCreateMessagePipe(nullptr, &mp2, &mp1)); | 
|   723   MojoHandle mp1, mp2; |   689  | 
|   724   ASSERT_EQ(MOJO_RESULT_OK, |   690     // Write a string into one end of the new message pipe and send the other | 
|   725             MojoCreateMessagePipe(nullptr, &mp2, &mp1)); |   691     // end. | 
|   726  |   692     const std::string hello("hello"); | 
|   727   // Write a string into one end of the new message pipe and send the other end. |   693     ASSERT_EQ(MOJO_RESULT_OK, | 
|   728   const std::string hello("hello"); |   694               MojoWriteMessage(mp1, &hello[0], | 
|   729   ASSERT_EQ(MOJO_RESULT_OK, |   695                                static_cast<uint32_t>(hello.size()), nullptr, 0u, | 
|   730             MojoWriteMessage(mp1, &hello[0], |   696                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
|   731                              static_cast<uint32_t>(hello.size()), nullptr, 0u, |   697     ASSERT_EQ(MOJO_RESULT_OK, | 
|   732                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |   698               MojoWriteMessage(h, nullptr, 0, &mp2, 1u, | 
|   733   ASSERT_EQ(MOJO_RESULT_OK, |   699                                MOJO_WRITE_MESSAGE_FLAG_NONE)); | 
|   734             MojoWriteMessage(mp.get().value(), nullptr, 0, &mp2, 1u, |   700  | 
|   735                              MOJO_WRITE_MESSAGE_FLAG_NONE)); |   701     // Wait for a message from the child. | 
|   736  |   702     HandleSignalsState hss; | 
|   737   // Wait for a message from the child. |   703     ASSERT_EQ(MOJO_RESULT_OK, | 
|   738   HandleSignalsState hss; |   704               MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | 
|   739   ASSERT_EQ(MOJO_RESULT_OK, |   705                        MOJO_DEADLINE_INDEFINITE, &hss)); | 
|   740             MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, |   706     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|   741                      MOJO_DEADLINE_INDEFINITE, &hss)); |   707     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 
|   742   EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |   708  | 
|   743   EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |   709     std::string read_buffer(100, '\0'); | 
|   744  |   710     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 
|   745   std::string read_buffer(100, '\0'); |   711     CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], | 
|   746   uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |   712                              &read_buffer_size, nullptr, | 
|   747   CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], |   713                              0, MOJO_READ_MESSAGE_FLAG_NONE), | 
|   748                            &read_buffer_size, nullptr, |   714              MOJO_RESULT_OK); | 
|   749                            0, MOJO_READ_MESSAGE_FLAG_NONE), |   715     read_buffer.resize(read_buffer_size); | 
|   750            MOJO_RESULT_OK); |   716     CHECK_EQ(read_buffer, std::string("world")); | 
|   751   read_buffer.resize(read_buffer_size); |   717  | 
|   752   CHECK_EQ(read_buffer, std::string("world")); |   718     MojoClose(mp1); | 
|   753  |   719   END_CHILD(); | 
|   754   MojoClose(mp1); |   720 } | 
|   755   MojoClose(mp.release().value()); |   721  | 
|   756  |   722 TEST_F(MultiprocessMessagePipeTest, CreateMessagePipe) { | 
|   757   ASSERT_EQ(0, helper()->WaitForChildShutdown()); |   723   MojoHandle p0, p1; | 
 |   724   CreateMessagePipe(&p0, &p1); | 
 |   725   VerifyTransmission(p0, p1, "hey man"); | 
 |   726   VerifyTransmission(p1, p0, "slow down"); | 
 |   727   VerifyTransmission(p0, p1, std::string(10 * 1024 * 1024, 'a')); | 
 |   728   VerifyTransmission(p1, p0, std::string(10 * 1024 * 1024, 'e')); | 
 |   729  | 
 |   730   CloseHandle(p0); | 
 |   731   CloseHandle(p1); | 
 |   732 } | 
 |   733  | 
 |   734 TEST_F(MultiprocessMessagePipeTest, PassMessagePipeLocal) { | 
 |   735   MojoHandle p0, p1; | 
 |   736   CreateMessagePipe(&p0, &p1); | 
 |   737   VerifyTransmission(p0, p1, "testing testing"); | 
 |   738   VerifyTransmission(p1, p0, "one two three"); | 
 |   739  | 
 |   740   MojoHandle p2, p3; | 
 |   741  | 
 |   742   CreateMessagePipe(&p2, &p3); | 
 |   743   VerifyTransmission(p2, p3, "testing testing"); | 
 |   744   VerifyTransmission(p3, p2, "one two three"); | 
 |   745  | 
 |   746   // Pass p2 over p0 to p1. | 
 |   747   const std::string message = "ceci n'est pas une pipe"; | 
 |   748   WriteMessageWithHandles(p0, message, &p2, 1); | 
 |   749   EXPECT_EQ(message, ReadMessageWithHandles(p1, &p2, 1)); | 
 |   750  | 
 |   751   CloseHandle(p0); | 
 |   752   CloseHandle(p1); | 
 |   753  | 
 |   754   // Verify that the received handle (now in p2) still works. | 
 |   755   VerifyTransmission(p2, p3, "Easy come, easy go; will you let me go?"); | 
 |   756   VerifyTransmission(p3, p2, "Bismillah! NO! We will not let you go!"); | 
 |   757  | 
 |   758   CloseHandle(p2); | 
 |   759   CloseHandle(p3); | 
 |   760 } | 
 |   761  | 
 |   762 // Echos the primordial channel until "exit". | 
 |   763 DEFINE_TEST_CLIENT_WITH_PIPE(ChannelEchoClient, MultiprocessMessagePipeTest, | 
 |   764                              h) { | 
 |   765   for (;;) { | 
 |   766     std::string message = ReadMessage(h); | 
 |   767     if (message == "exit") | 
 |   768       break; | 
 |   769     WriteMessage(h, message); | 
 |   770   } | 
 |   771   return 0; | 
 |   772 } | 
 |   773  | 
 |   774 TEST_F(MultiprocessMessagePipeTest, MultiprocessChannelPipe) { | 
 |   775   RUN_CHILD_ON_PIPE(ChannelEchoClient, h) | 
 |   776     VerifyEcho(h, "in an interstellar burst"); | 
 |   777     VerifyEcho(h, "i am back to save the universe"); | 
 |   778     VerifyEcho(h, std::string(10 * 1024 * 1024, 'o')); | 
 |   779  | 
 |   780     WriteMessage(h, "exit"); | 
 |   781   END_CHILD() | 
 |   782 } | 
 |   783  | 
 |   784 // Receives a pipe handle from the primordial channel and echos on it until | 
 |   785 // "exit". Used to test simple pipe transfer across processes via channels. | 
 |   786 DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceClient, MultiprocessMessagePipeTest, | 
 |   787                              h) { | 
 |   788   MojoHandle p; | 
 |   789   ReadMessageWithHandles(h, &p, 1); | 
 |   790   for (;;) { | 
 |   791     std::string message = ReadMessage(p); | 
 |   792     if (message == "exit") | 
 |   793       break; | 
 |   794     WriteMessage(p, message); | 
 |   795   } | 
 |   796   return 0; | 
 |   797 } | 
 |   798  | 
 |   799 TEST_F(MultiprocessMessagePipeTest, PassMessagePipeCrossProcess) { | 
 |   800   MojoHandle p0, p1; | 
 |   801   CreateMessagePipe(&p0, &p1); | 
 |   802   RUN_CHILD_ON_PIPE(EchoServiceClient, h) | 
 |   803  | 
 |   804     // Pass one end of the pipe to the other process. | 
 |   805     WriteMessageWithHandles(h, "here take this", &p1, 1); | 
 |   806  | 
 |   807     VerifyEcho(p0, "and you may ask yourself"); | 
 |   808     VerifyEcho(p0, "where does that highway go?"); | 
 |   809     VerifyEcho(p0, std::string(20 * 1024 * 1024, 'i')); | 
 |   810  | 
 |   811     WriteMessage(p0, "exit"); | 
 |   812   END_CHILD() | 
 |   813   CloseHandle(p0); | 
 |   814 } | 
 |   815  | 
 |   816 // Receives a pipe handle from the primordial channel and reads new handles | 
 |   817 // from it. Each read handle establishes a new echo channel. | 
 |   818 DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceFactoryClient, | 
 |   819                              MultiprocessMessagePipeTest, h) { | 
 |   820   MojoHandle p; | 
 |   821   ReadMessageWithHandles(h, &p, 1); | 
 |   822  | 
 |   823   std::vector<MojoHandle> handles(2); | 
 |   824   handles[0] = h; | 
 |   825   handles[1] = p; | 
 |   826   std::vector<MojoHandleSignals> signals(2, MOJO_HANDLE_SIGNAL_READABLE); | 
 |   827   for (;;) { | 
 |   828     uint32_t index; | 
 |   829     CHECK_EQ(MojoWaitMany(handles.data(), signals.data(), | 
 |   830                           static_cast<uint32_t>(handles.size()), | 
 |   831                           MOJO_DEADLINE_INDEFINITE, &index, nullptr), | 
 |   832              MOJO_RESULT_OK); | 
 |   833     DCHECK_LE(index, handles.size()); | 
 |   834     if (index == 0) { | 
 |   835       // If data is available on the first pipe, it should be an exit command. | 
 |   836       EXPECT_EQ(std::string("exit"), ReadMessage(h)); | 
 |   837       break; | 
 |   838     } else if (index == 1) { | 
 |   839       // If the second pipe, it should be a new handle requesting echo service. | 
 |   840       MojoHandle echo_request; | 
 |   841       ReadMessageWithHandles(p, &echo_request, 1); | 
 |   842       handles.push_back(echo_request); | 
 |   843       signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); | 
 |   844     } else { | 
 |   845       // Otherwise it was one of our established echo pipes. Echo! | 
 |   846       WriteMessage(handles[index], ReadMessage(handles[index])); | 
 |   847     } | 
 |   848   } | 
 |   849  | 
 |   850   for (size_t i = 1; i < handles.size(); ++i) | 
 |   851     CloseHandle(handles[i]); | 
 |   852  | 
 |   853   return 0; | 
 |   854 } | 
 |   855  | 
 |   856 TEST_F(MultiprocessMessagePipeTest, PassMoarMessagePipesCrossProcess) { | 
 |   857   MojoHandle echo_factory_proxy, echo_factory_request; | 
 |   858   CreateMessagePipe(&echo_factory_proxy, &echo_factory_request); | 
 |   859  | 
 |   860   MojoHandle echo_proxy_a, echo_request_a; | 
 |   861   CreateMessagePipe(&echo_proxy_a, &echo_request_a); | 
 |   862  | 
 |   863   MojoHandle echo_proxy_b, echo_request_b; | 
 |   864   CreateMessagePipe(&echo_proxy_b, &echo_request_b); | 
 |   865  | 
 |   866   MojoHandle echo_proxy_c, echo_request_c; | 
 |   867   CreateMessagePipe(&echo_proxy_c, &echo_request_c); | 
 |   868  | 
 |   869   RUN_CHILD_ON_PIPE(EchoServiceFactoryClient, h) | 
 |   870     WriteMessageWithHandles( | 
 |   871         h, "gief factory naow plz", &echo_factory_request, 1); | 
 |   872  | 
 |   873     WriteMessageWithHandles(echo_factory_proxy, "give me an echo service plz!", | 
 |   874                            &echo_request_a, 1); | 
 |   875     WriteMessageWithHandles(echo_factory_proxy, "give me one too!", | 
 |   876                            &echo_request_b, 1); | 
 |   877  | 
 |   878     VerifyEcho(echo_proxy_a, "i came here for an argument"); | 
 |   879     VerifyEcho(echo_proxy_a, "shut your festering gob"); | 
 |   880     VerifyEcho(echo_proxy_a, "mumble mumble mumble"); | 
 |   881  | 
 |   882     VerifyEcho(echo_proxy_b, "wubalubadubdub"); | 
 |   883     VerifyEcho(echo_proxy_b, "wubalubadubdub"); | 
 |   884  | 
 |   885     WriteMessageWithHandles(echo_factory_proxy, "hook me up also thanks", | 
 |   886                            &echo_request_c, 1); | 
 |   887  | 
 |   888     VerifyEcho(echo_proxy_a, "the frobinators taste like frobinators"); | 
 |   889     VerifyEcho(echo_proxy_b, "beep bop boop"); | 
 |   890     VerifyEcho(echo_proxy_c, "zzzzzzzzzzzzzzzzzzzzzzzzzz"); | 
 |   891  | 
 |   892     WriteMessage(h, "exit"); | 
 |   893   END_CHILD() | 
 |   894  | 
 |   895   CloseHandle(echo_factory_proxy); | 
 |   896   CloseHandle(echo_proxy_a); | 
 |   897   CloseHandle(echo_proxy_b); | 
 |   898   CloseHandle(echo_proxy_c); | 
 |   899 } | 
 |   900  | 
 |   901 TEST_F(MultiprocessMessagePipeTest, ChannelPipesWithMultipleChildren) { | 
 |   902   RUN_CHILD_ON_PIPE(ChannelEchoClient, a) | 
 |   903     RUN_CHILD_ON_PIPE(ChannelEchoClient, b) | 
 |   904       VerifyEcho(a, "hello child 0"); | 
 |   905       VerifyEcho(b, "hello child 1"); | 
 |   906  | 
 |   907       WriteMessage(a, "exit"); | 
 |   908       WriteMessage(b, "exit"); | 
 |   909     END_CHILD() | 
 |   910   END_CHILD() | 
 |   911 } | 
 |   912  | 
 |   913 // Reads and turns a pipe handle some number of times to create lots of | 
 |   914 // transient proxies. | 
 |   915 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(PingPongPipeClient, | 
 |   916                                   MultiprocessMessagePipeTest, h) { | 
 |   917   const size_t kNumBounces = 50; | 
 |   918   MojoHandle p0, p1; | 
 |   919   ReadMessageWithHandles(h, &p0, 1); | 
 |   920   ReadMessageWithHandles(h, &p1, 1); | 
 |   921   for (size_t i = 0; i < kNumBounces; ++i) { | 
 |   922     WriteMessageWithHandles(h, "", &p1, 1); | 
 |   923     ReadMessageWithHandles(h, &p1, 1); | 
 |   924   } | 
 |   925   WriteMessageWithHandles(h, "", &p0, 1); | 
 |   926   WriteMessage(p1, "bye"); | 
 |   927   MojoClose(p1); | 
 |   928   EXPECT_EQ("quit", ReadMessage(h)); | 
 |   929 } | 
 |   930  | 
 |   931 TEST_F(MultiprocessMessagePipeTest, PingPongPipe) { | 
 |   932   MojoHandle p0, p1; | 
 |   933   CreateMessagePipe(&p0, &p1); | 
 |   934  | 
 |   935   RUN_CHILD_ON_PIPE(PingPongPipeClient, h) | 
 |   936     const size_t kNumBounces = 50; | 
 |   937     WriteMessageWithHandles(h, "", &p0, 1); | 
 |   938     WriteMessageWithHandles(h, "", &p1, 1); | 
 |   939     for (size_t i = 0; i < kNumBounces; ++i) { | 
 |   940       ReadMessageWithHandles(h, &p1, 1); | 
 |   941       WriteMessageWithHandles(h, "", &p1, 1); | 
 |   942     } | 
 |   943     ReadMessageWithHandles(h, &p0, 1); | 
 |   944     WriteMessage(h, "quit"); | 
 |   945   END_CHILD() | 
 |   946  | 
 |   947   EXPECT_EQ("bye", ReadMessage(p0)); | 
 |   948  | 
 |   949   // We should still be able to observe peer closure from the other end. | 
 |   950   EXPECT_EQ(MOJO_RESULT_OK, | 
 |   951             MojoWait(p0, MOJO_HANDLE_SIGNAL_PEER_CLOSED, | 
 |   952                      MOJO_DEADLINE_INDEFINITE, nullptr)); | 
 |   953 } | 
 |   954  | 
 |   955 // Parses commands from the parent pipe and does whatever it's asked to do. | 
 |   956 DEFINE_TEST_CLIENT_WITH_PIPE(CommandDrivenClient, MultiprocessMessagePipeTest, | 
 |   957                              h) { | 
 |   958   base::hash_map<std::string, MojoHandle> named_pipes; | 
 |   959   for (;;) { | 
 |   960     MojoHandle p; | 
 |   961     auto parts = base::SplitString(ReadMessageWithOptionalHandle(h, &p), ":", | 
 |   962                                    base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | 
 |   963     CHECK(!parts.empty()); | 
 |   964     std::string command = parts[0]; | 
 |   965     if (command == "take") { | 
 |   966       // Take a pipe. | 
 |   967       CHECK_EQ(parts.size(), 2u); | 
 |   968       CHECK_NE(p, MOJO_HANDLE_INVALID); | 
 |   969       named_pipes[parts[1]] = p; | 
 |   970       WriteMessage(h, "ok"); | 
 |   971     } else if (command == "return") { | 
 |   972       // Return a pipe. | 
 |   973       CHECK_EQ(parts.size(), 2u); | 
 |   974       CHECK_EQ(p, MOJO_HANDLE_INVALID); | 
 |   975       p = named_pipes[parts[1]]; | 
 |   976       CHECK_NE(p, MOJO_HANDLE_INVALID); | 
 |   977       named_pipes.erase(parts[1]); | 
 |   978       WriteMessageWithHandles(h, "ok", &p, 1); | 
 |   979     } else if (command == "say") { | 
 |   980       // Say something to a named pipe. | 
 |   981       CHECK_EQ(parts.size(), 3u); | 
 |   982       CHECK_EQ(p, MOJO_HANDLE_INVALID); | 
 |   983       p = named_pipes[parts[1]]; | 
 |   984       CHECK_NE(p, MOJO_HANDLE_INVALID); | 
 |   985       CHECK(!parts[2].empty()); | 
 |   986       WriteMessage(p, parts[2]); | 
 |   987       WriteMessage(h, "ok"); | 
 |   988     } else if (command == "hear") { | 
 |   989       // Expect to read something from a named pipe. | 
 |   990       CHECK_EQ(parts.size(), 3u); | 
 |   991       CHECK_EQ(p, MOJO_HANDLE_INVALID); | 
 |   992       p = named_pipes[parts[1]]; | 
 |   993       CHECK_NE(p, MOJO_HANDLE_INVALID); | 
 |   994       CHECK(!parts[2].empty()); | 
 |   995       CHECK_EQ(parts[2], ReadMessage(p)); | 
 |   996       WriteMessage(h, "ok"); | 
 |   997     } else if (command == "pass") { | 
 |   998       // Pass one named pipe over another named pipe. | 
 |   999       CHECK_EQ(parts.size(), 3u); | 
 |  1000       CHECK_EQ(p, MOJO_HANDLE_INVALID); | 
 |  1001       p = named_pipes[parts[1]]; | 
 |  1002       MojoHandle carrier = named_pipes[parts[2]]; | 
 |  1003       CHECK_NE(p, MOJO_HANDLE_INVALID); | 
 |  1004       CHECK_NE(carrier, MOJO_HANDLE_INVALID); | 
 |  1005       named_pipes.erase(parts[1]); | 
 |  1006       WriteMessageWithHandles(carrier, "got a pipe for ya", &p, 1); | 
 |  1007       WriteMessage(h, "ok"); | 
 |  1008     } else if (command == "catch") { | 
 |  1009       // Expect to receive one named pipe from another named pipe. | 
 |  1010       CHECK_EQ(parts.size(), 3u); | 
 |  1011       CHECK_EQ(p, MOJO_HANDLE_INVALID); | 
 |  1012       MojoHandle carrier = named_pipes[parts[2]]; | 
 |  1013       CHECK_NE(carrier, MOJO_HANDLE_INVALID); | 
 |  1014       ReadMessageWithHandles(carrier, &p, 1); | 
 |  1015       CHECK_NE(p, MOJO_HANDLE_INVALID); | 
 |  1016       named_pipes[parts[1]] = p; | 
 |  1017       WriteMessage(h, "ok"); | 
 |  1018     } else if (command == "exit") { | 
 |  1019       CHECK_EQ(parts.size(), 1u); | 
 |  1020       break; | 
 |  1021     } | 
 |  1022   } | 
 |  1023  | 
 |  1024   for (auto& pipe: named_pipes) | 
 |  1025     CloseHandle(pipe.second); | 
 |  1026  | 
 |  1027   return 0; | 
 |  1028 } | 
 |  1029  | 
 |  1030 TEST_F(MultiprocessMessagePipeTest, ChildToChildPipes) { | 
 |  1031   RUN_CHILD_ON_PIPE(CommandDrivenClient, h0) | 
 |  1032     RUN_CHILD_ON_PIPE(CommandDrivenClient, h1) | 
 |  1033       CommandDrivenClientController a(h0); | 
 |  1034       CommandDrivenClientController b(h1); | 
 |  1035  | 
 |  1036       // Create a pipe and pass each end to a different client. | 
 |  1037       MojoHandle p0, p1; | 
 |  1038       CreateMessagePipe(&p0, &p1); | 
 |  1039       a.SendHandle("x", p0); | 
 |  1040       b.SendHandle("y", p1); | 
 |  1041  | 
 |  1042       // Make sure they can talk. | 
 |  1043       a.Send("say:x:hello sir"); | 
 |  1044       b.Send("hear:y:hello sir"); | 
 |  1045  | 
 |  1046       b.Send("say:y:i love multiprocess pipes!"); | 
 |  1047       a.Send("hear:x:i love multiprocess pipes!"); | 
 |  1048  | 
 |  1049       a.Exit(); | 
 |  1050       b.Exit(); | 
 |  1051     END_CHILD() | 
 |  1052   END_CHILD() | 
 |  1053 } | 
 |  1054  | 
 |  1055 TEST_F(MultiprocessMessagePipeTest, MoreChildToChildPipes) { | 
 |  1056   RUN_CHILD_ON_PIPE(CommandDrivenClient, h0) | 
 |  1057     RUN_CHILD_ON_PIPE(CommandDrivenClient, h1) | 
 |  1058       RUN_CHILD_ON_PIPE(CommandDrivenClient, h2) | 
 |  1059         RUN_CHILD_ON_PIPE(CommandDrivenClient, h3) | 
 |  1060           CommandDrivenClientController a(h0), b(h1), c(h2), d(h3); | 
 |  1061  | 
 |  1062           // Connect a to b and c to d | 
 |  1063  | 
 |  1064           MojoHandle p0, p1; | 
 |  1065  | 
 |  1066           CreateMessagePipe(&p0, &p1); | 
 |  1067           a.SendHandle("b_pipe", p0); | 
 |  1068           b.SendHandle("a_pipe", p1); | 
 |  1069  | 
 |  1070           MojoHandle p2, p3; | 
 |  1071  | 
 |  1072           CreateMessagePipe(&p2, &p3); | 
 |  1073           c.SendHandle("d_pipe", p2); | 
 |  1074           d.SendHandle("c_pipe", p3); | 
 |  1075  | 
 |  1076           // Connect b to c via a and d | 
 |  1077           MojoHandle p4, p5; | 
 |  1078           CreateMessagePipe(&p4, &p5); | 
 |  1079           a.SendHandle("d_pipe", p4); | 
 |  1080           d.SendHandle("a_pipe", p5); | 
 |  1081  | 
 |  1082           // Have |a| pass its new |d|-pipe to |b|. It will eventually connect | 
 |  1083           // to |c|. | 
 |  1084           a.Send("pass:d_pipe:b_pipe"); | 
 |  1085           b.Send("catch:c_pipe:a_pipe"); | 
 |  1086  | 
 |  1087           // Have |d| pass its new |a|-pipe to |c|. It will now be connected to | 
 |  1088           // |b|. | 
 |  1089           d.Send("pass:a_pipe:c_pipe"); | 
 |  1090           c.Send("catch:b_pipe:d_pipe"); | 
 |  1091  | 
 |  1092           // Make sure b and c and talk. | 
 |  1093           b.Send("say:c_pipe:it's a beautiful day"); | 
 |  1094           c.Send("hear:b_pipe:it's a beautiful day"); | 
 |  1095  | 
 |  1096           // Create x and y and have b and c exchange them. | 
 |  1097           MojoHandle x, y; | 
 |  1098           CreateMessagePipe(&x, &y); | 
 |  1099           b.SendHandle("x", x); | 
 |  1100           c.SendHandle("y", y); | 
 |  1101           b.Send("pass:x:c_pipe"); | 
 |  1102           c.Send("pass:y:b_pipe"); | 
 |  1103           b.Send("catch:y:c_pipe"); | 
 |  1104           c.Send("catch:x:b_pipe"); | 
 |  1105  | 
 |  1106           // Make sure the pipe still works in both directions. | 
 |  1107           b.Send("say:y:hello"); | 
 |  1108           c.Send("hear:x:hello"); | 
 |  1109           c.Send("say:x:goodbye"); | 
 |  1110           b.Send("hear:y:goodbye"); | 
 |  1111  | 
 |  1112           // Take both pipes back. | 
 |  1113           y = c.RetrieveHandle("x"); | 
 |  1114           x = b.RetrieveHandle("y"); | 
 |  1115  | 
 |  1116           VerifyTransmission(x, y, "still works"); | 
 |  1117           VerifyTransmission(y, x, "in both directions"); | 
 |  1118  | 
 |  1119           CloseHandle(x); | 
 |  1120           CloseHandle(y); | 
 |  1121  | 
 |  1122           a.Exit(); | 
 |  1123           b.Exit(); | 
 |  1124           c.Exit(); | 
 |  1125           d.Exit(); | 
 |  1126         END_CHILD() | 
 |  1127       END_CHILD() | 
 |  1128     END_CHILD() | 
 |  1129   END_CHILD() | 
 |  1130 } | 
 |  1131  | 
 |  1132 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeer, | 
 |  1133                                   MultiprocessMessagePipeTest, h) { | 
 |  1134   MojoHandle p; | 
 |  1135   EXPECT_EQ("foo", ReadMessageWithHandles(h, &p, 1)); | 
 |  1136  | 
 |  1137   EXPECT_EQ(MOJO_RESULT_OK, MojoWait(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED, | 
 |  1138                                      MOJO_DEADLINE_INDEFINITE, nullptr)); | 
 |  1139 } | 
 |  1140  | 
 |  1141 TEST_F(MultiprocessMessagePipeTest, SendPipeThenClosePeer) { | 
 |  1142   RUN_CHILD_ON_PIPE(ReceivePipeWithClosedPeer, h) | 
 |  1143     MojoHandle a, b; | 
 |  1144     CreateMessagePipe(&a, &b); | 
 |  1145  | 
 |  1146     // Send |a| and immediately close |b|. The child should observe closure. | 
 |  1147     WriteMessageWithHandles(h, "foo", &a, 1); | 
 |  1148     MojoClose(b); | 
 |  1149   END_CHILD() | 
 |  1150 } | 
 |  1151  | 
 |  1152 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(SendOtherChildPipeWithClosedPeer, | 
 |  1153                                   MultiprocessMessagePipeTest, h) { | 
 |  1154   // Create a new pipe and send one end to the parent, who will connect it to | 
 |  1155   // a client running ReceivePipeWithClosedPeerFromOtherChild. | 
 |  1156   MojoHandle application_proxy, application_request; | 
 |  1157   CreateMessagePipe(&application_proxy, &application_request); | 
 |  1158   WriteMessageWithHandles(h, "c2a plz", &application_request, 1); | 
 |  1159  | 
 |  1160   // Create another pipe and send one end to the remote "application". | 
 |  1161   MojoHandle service_proxy, service_request; | 
 |  1162   CreateMessagePipe(&service_proxy, &service_request); | 
 |  1163   WriteMessageWithHandles(application_proxy, "c2s lol", &service_request, 1); | 
 |  1164  | 
 |  1165   // Immediately close the service proxy. The "application" should detect this. | 
 |  1166   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(service_proxy)); | 
 |  1167  | 
 |  1168   // Wait for quit. | 
 |  1169   EXPECT_EQ("quit", ReadMessage(h)); | 
 |  1170 } | 
 |  1171  | 
 |  1172 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeerFromOtherChild, | 
 |  1173                                   MultiprocessMessagePipeTest, h) { | 
 |  1174   // Receive a pipe from the parent. This is akin to an "application request". | 
 |  1175   MojoHandle application_client; | 
 |  1176   EXPECT_EQ("c2a", ReadMessageWithHandles(h, &application_client, 1)); | 
 |  1177  | 
 |  1178   // Receive a pipe from the "application" "client". | 
 |  1179   MojoHandle service_client; | 
 |  1180   EXPECT_EQ("c2s lol", | 
 |  1181             ReadMessageWithHandles(application_client, &service_client, 1)); | 
 |  1182  | 
 |  1183   // Wait for the service client to signal closure. | 
 |  1184   EXPECT_EQ(MOJO_RESULT_OK, MojoWait(service_client, | 
 |  1185                                      MOJO_HANDLE_SIGNAL_PEER_CLOSED, | 
 |  1186                                      MOJO_DEADLINE_INDEFINITE, nullptr)); | 
 |  1187  | 
 |  1188   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(service_client)); | 
 |  1189   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(application_client)); | 
 |  1190 } | 
 |  1191  | 
 |  1192 TEST_F(MultiprocessMessagePipeTest, SendPipeWithClosedPeerBetweenChildren) { | 
 |  1193   RUN_CHILD_ON_PIPE(SendOtherChildPipeWithClosedPeer, kid_a) | 
 |  1194     RUN_CHILD_ON_PIPE(ReceivePipeWithClosedPeerFromOtherChild, kid_b) | 
 |  1195       // Receive an "application request" from the first child and forward it | 
 |  1196       // to the second child. | 
 |  1197       MojoHandle application_request; | 
 |  1198       EXPECT_EQ("c2a plz", | 
 |  1199                 ReadMessageWithHandles(kid_a, &application_request, 1)); | 
 |  1200  | 
 |  1201       WriteMessageWithHandles(kid_b, "c2a", &application_request, 1); | 
 |  1202     END_CHILD() | 
 |  1203  | 
 |  1204     WriteMessage(kid_a, "quit"); | 
 |  1205   END_CHILD() | 
 |  1206 } | 
 |  1207  | 
 |  1208 TEST_F(MultiprocessMessagePipeTest, SendClosePeerSend) { | 
 |  1209   MojoHandle a, b; | 
 |  1210   CreateMessagePipe(&a, &b); | 
 |  1211  | 
 |  1212   MojoHandle c, d; | 
 |  1213   CreateMessagePipe(&c, &d); | 
 |  1214  | 
 |  1215   // Send |a| over |c|, immediately close |b|, then send |a| back over |d|. | 
 |  1216   WriteMessageWithHandles(c, "foo", &a, 1); | 
 |  1217   EXPECT_EQ("foo", ReadMessageWithHandles(d, &a, 1)); | 
 |  1218   WriteMessageWithHandles(d, "bar", &a, 1); | 
 |  1219   EXPECT_EQ("bar", ReadMessageWithHandles(c, &a, 1)); | 
 |  1220   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | 
 |  1221  | 
 |  1222   // We should be able to detect peer closure on |a|. | 
 |  1223   EXPECT_EQ(MOJO_RESULT_OK, MojoWait(a, MOJO_HANDLE_SIGNAL_PEER_CLOSED, | 
 |  1224                                      MOJO_DEADLINE_INDEFINITE, nullptr)); | 
 |  1225 } | 
 |  1226  | 
 |  1227 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteCloseSendPeerClient, | 
 |  1228                                   MultiprocessMessagePipeTest, h) { | 
 |  1229   MojoHandle pipe[2]; | 
 |  1230   EXPECT_EQ("foo", ReadMessageWithHandles(h, pipe, 2)); | 
 |  1231  | 
 |  1232   // Write some messages to the first endpoint and then close it. | 
 |  1233   WriteMessage(pipe[0], "baz"); | 
 |  1234   WriteMessage(pipe[0], "qux"); | 
 |  1235   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe[0])); | 
 |  1236  | 
 |  1237   MojoHandle c, d; | 
 |  1238   CreateMessagePipe(&c, &d); | 
 |  1239  | 
 |  1240   // Pass the orphaned endpoint over another pipe before passing it back to | 
 |  1241   // the parent, just for some extra proxying goodness. | 
 |  1242   WriteMessageWithHandles(c, "foo", &pipe[1], 1); | 
 |  1243   EXPECT_EQ("foo", ReadMessageWithHandles(d, &pipe[1], 1)); | 
 |  1244  | 
 |  1245   // And finally pass it back to the parent. | 
 |  1246   WriteMessageWithHandles(h, "bar", &pipe[1], 1); | 
 |  1247  | 
 |  1248   EXPECT_EQ("quit", ReadMessage(h)); | 
 |  1249 } | 
 |  1250  | 
 |  1251 TEST_F(MultiprocessMessagePipeTest, WriteCloseSendPeer) { | 
 |  1252   MojoHandle pipe[2]; | 
 |  1253   CreateMessagePipe(&pipe[0], &pipe[1]); | 
 |  1254  | 
 |  1255   RUN_CHILD_ON_PIPE(WriteCloseSendPeerClient, h) | 
 |  1256     // Pass the pipe to the child. | 
 |  1257     WriteMessageWithHandles(h, "foo", pipe, 2); | 
 |  1258  | 
 |  1259     // Read back an endpoint which should have messages on it. | 
 |  1260     MojoHandle p; | 
 |  1261     EXPECT_EQ("bar", ReadMessageWithHandles(h, &p, 1)); | 
 |  1262  | 
 |  1263     EXPECT_EQ("baz", ReadMessage(p)); | 
 |  1264     EXPECT_EQ("qux", ReadMessage(p)); | 
 |  1265  | 
 |  1266     // Expect to have peer closure signaled. | 
 |  1267     EXPECT_EQ(MOJO_RESULT_OK, MojoWait(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED, | 
 |  1268                                        MOJO_DEADLINE_INDEFINITE, nullptr)); | 
 |  1269  | 
 |  1270     WriteMessage(h, "quit"); | 
 |  1271   END_CHILD() | 
|   758 } |  1272 } | 
|   759  |  1273  | 
|   760 }  // namespace |  1274 }  // namespace | 
|   761 }  // namespace edk |  1275 }  // namespace edk | 
|   762 }  // namespace mojo |  1276 }  // namespace mojo | 
| OLD | NEW |