| OLD | NEW | 
|---|
|  | (Empty) | 
| 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 |  | 
| 3 // found in the LICENSE file. |  | 
| 4 |  | 
| 5 #include "mojo/edk/system/local_data_pipe.h" |  | 
| 6 |  | 
| 7 #include <string.h> |  | 
| 8 |  | 
| 9 #include "base/macros.h" |  | 
| 10 #include "base/memory/ref_counted.h" |  | 
| 11 #include "mojo/edk/system/data_pipe.h" |  | 
| 12 #include "mojo/edk/system/waiter.h" |  | 
| 13 #include "testing/gtest/include/gtest/gtest.h" |  | 
| 14 |  | 
| 15 namespace mojo { |  | 
| 16 namespace system { |  | 
| 17 namespace { |  | 
| 18 |  | 
| 19 const uint32_t kSizeOfOptions = |  | 
| 20     static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)); |  | 
| 21 |  | 
| 22 // Validate options. |  | 
| 23 TEST(LocalDataPipeTest, Creation) { |  | 
| 24   // Create using default options. |  | 
| 25   { |  | 
| 26     // Get default options. |  | 
| 27     MojoCreateDataPipeOptions default_options = {0}; |  | 
| 28     EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 29                                   NullUserPointer(), &default_options)); |  | 
| 30     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(default_options)); |  | 
| 31     dp->ProducerClose(); |  | 
| 32     dp->ConsumerClose(); |  | 
| 33   } |  | 
| 34 |  | 
| 35   // Create using non-default options. |  | 
| 36   { |  | 
| 37     const MojoCreateDataPipeOptions options = { |  | 
| 38         kSizeOfOptions,                           // |struct_size|. |  | 
| 39         MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 40         1,                                        // |element_num_bytes|. |  | 
| 41         1000                                      // |capacity_num_bytes|. |  | 
| 42     }; |  | 
| 43     MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 44     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 45               DataPipe::ValidateCreateOptions(MakeUserPointer(&options), |  | 
| 46                                               &validated_options)); |  | 
| 47     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 48     dp->ProducerClose(); |  | 
| 49     dp->ConsumerClose(); |  | 
| 50   } |  | 
| 51   { |  | 
| 52     const MojoCreateDataPipeOptions options = { |  | 
| 53         kSizeOfOptions,                           // |struct_size|. |  | 
| 54         MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 55         4,                                        // |element_num_bytes|. |  | 
| 56         4000                                      // |capacity_num_bytes|. |  | 
| 57     }; |  | 
| 58     MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 59     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 60               DataPipe::ValidateCreateOptions(MakeUserPointer(&options), |  | 
| 61                                               &validated_options)); |  | 
| 62     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 63     dp->ProducerClose(); |  | 
| 64     dp->ConsumerClose(); |  | 
| 65   } |  | 
| 66   { |  | 
| 67     const MojoCreateDataPipeOptions options = { |  | 
| 68         kSizeOfOptions,                                  // |struct_size|. |  | 
| 69         MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|. |  | 
| 70         7,                                               // |element_num_bytes|. |  | 
| 71         7000000  // |capacity_num_bytes|. |  | 
| 72     }; |  | 
| 73     MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 74     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 75               DataPipe::ValidateCreateOptions(MakeUserPointer(&options), |  | 
| 76                                               &validated_options)); |  | 
| 77     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 78     dp->ProducerClose(); |  | 
| 79     dp->ConsumerClose(); |  | 
| 80   } |  | 
| 81   // Default capacity. |  | 
| 82   { |  | 
| 83     const MojoCreateDataPipeOptions options = { |  | 
| 84         kSizeOfOptions,                                  // |struct_size|. |  | 
| 85         MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|. |  | 
| 86         100,                                             // |element_num_bytes|. |  | 
| 87         0  // |capacity_num_bytes|. |  | 
| 88     }; |  | 
| 89     MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 90     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 91               DataPipe::ValidateCreateOptions(MakeUserPointer(&options), |  | 
| 92                                               &validated_options)); |  | 
| 93     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 94     dp->ProducerClose(); |  | 
| 95     dp->ConsumerClose(); |  | 
| 96   } |  | 
| 97 } |  | 
| 98 |  | 
| 99 TEST(LocalDataPipeTest, SimpleReadWrite) { |  | 
| 100   const MojoCreateDataPipeOptions options = { |  | 
| 101       kSizeOfOptions,                           // |struct_size|. |  | 
| 102       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 103       static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|. |  | 
| 104       1000 * sizeof(int32_t)                    // |capacity_num_bytes|. |  | 
| 105   }; |  | 
| 106   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 107   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 108                                 MakeUserPointer(&options), &validated_options)); |  | 
| 109 |  | 
| 110   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 111 |  | 
| 112   int32_t elements[10] = {0}; |  | 
| 113   uint32_t num_bytes = 0; |  | 
| 114 |  | 
| 115   // Try reading; nothing there yet. |  | 
| 116   num_bytes = static_cast<uint32_t>(arraysize(elements) * sizeof(elements[0])); |  | 
| 117   EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |  | 
| 118             dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 119                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 120 |  | 
| 121   // Query; nothing there yet. |  | 
| 122   num_bytes = 0; |  | 
| 123   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 124   EXPECT_EQ(0u, num_bytes); |  | 
| 125 |  | 
| 126   // Discard; nothing there yet. |  | 
| 127   num_bytes = static_cast<uint32_t>(5u * sizeof(elements[0])); |  | 
| 128   EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |  | 
| 129             dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), false)); |  | 
| 130 |  | 
| 131   // Read with invalid |num_bytes|. |  | 
| 132   num_bytes = sizeof(elements[0]) + 1; |  | 
| 133   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |  | 
| 134             dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 135                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 136 |  | 
| 137   // Write two elements. |  | 
| 138   elements[0] = 123; |  | 
| 139   elements[1] = 456; |  | 
| 140   num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); |  | 
| 141   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 142             dp->ProducerWriteData(UserPointer<const void>(elements), |  | 
| 143                                   MakeUserPointer(&num_bytes), false)); |  | 
| 144   // It should have written everything (even without "all or none"). |  | 
| 145   EXPECT_EQ(2u * sizeof(elements[0]), num_bytes); |  | 
| 146 |  | 
| 147   // Query. |  | 
| 148   num_bytes = 0; |  | 
| 149   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 150   EXPECT_EQ(2 * sizeof(elements[0]), num_bytes); |  | 
| 151 |  | 
| 152   // Read one element. |  | 
| 153   elements[0] = -1; |  | 
| 154   elements[1] = -1; |  | 
| 155   num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 156   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 157             dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 158                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 159   EXPECT_EQ(1u * sizeof(elements[0]), num_bytes); |  | 
| 160   EXPECT_EQ(123, elements[0]); |  | 
| 161   EXPECT_EQ(-1, elements[1]); |  | 
| 162 |  | 
| 163   // Query. |  | 
| 164   num_bytes = 0; |  | 
| 165   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 166   EXPECT_EQ(1 * sizeof(elements[0]), num_bytes); |  | 
| 167 |  | 
| 168   // Peek one element. |  | 
| 169   elements[0] = -1; |  | 
| 170   elements[1] = -1; |  | 
| 171   num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 172   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 173             dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 174                                  MakeUserPointer(&num_bytes), false, true)); |  | 
| 175   EXPECT_EQ(1u * sizeof(elements[0]), num_bytes); |  | 
| 176   EXPECT_EQ(456, elements[0]); |  | 
| 177   EXPECT_EQ(-1, elements[1]); |  | 
| 178 |  | 
| 179   // Query. Still has 1 element remaining. |  | 
| 180   num_bytes = 0; |  | 
| 181   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 182   EXPECT_EQ(1 * sizeof(elements[0]), num_bytes); |  | 
| 183 |  | 
| 184   // Try to read two elements, with "all or none". |  | 
| 185   elements[0] = -1; |  | 
| 186   elements[1] = -1; |  | 
| 187   num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); |  | 
| 188   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 189             dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 190                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 191   EXPECT_EQ(-1, elements[0]); |  | 
| 192   EXPECT_EQ(-1, elements[1]); |  | 
| 193 |  | 
| 194   // Try to read two elements, without "all or none". |  | 
| 195   elements[0] = -1; |  | 
| 196   elements[1] = -1; |  | 
| 197   num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); |  | 
| 198   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 199             dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 200                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 201   EXPECT_EQ(456, elements[0]); |  | 
| 202   EXPECT_EQ(-1, elements[1]); |  | 
| 203 |  | 
| 204   // Query. |  | 
| 205   num_bytes = 0; |  | 
| 206   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 207   EXPECT_EQ(0u, num_bytes); |  | 
| 208 |  | 
| 209   dp->ProducerClose(); |  | 
| 210   dp->ConsumerClose(); |  | 
| 211 } |  | 
| 212 |  | 
| 213 // Note: The "basic" waiting tests test that the "wait states" are correct in |  | 
| 214 // various situations; they don't test that waiters are properly awoken on state |  | 
| 215 // changes. (For that, we need to use multiple threads.) |  | 
| 216 TEST(LocalDataPipeTest, BasicProducerWaiting) { |  | 
| 217   // Note: We take advantage of the fact that for |LocalDataPipe|, capacities |  | 
| 218   // are strict maximums. This is not guaranteed by the API. |  | 
| 219 |  | 
| 220   const MojoCreateDataPipeOptions options = { |  | 
| 221       kSizeOfOptions,                           // |struct_size|. |  | 
| 222       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 223       static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|. |  | 
| 224       2 * sizeof(int32_t)                       // |capacity_num_bytes|. |  | 
| 225   }; |  | 
| 226   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 227   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 228                                 MakeUserPointer(&options), &validated_options)); |  | 
| 229 |  | 
| 230   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 231   Waiter waiter; |  | 
| 232   uint32_t context = 0; |  | 
| 233   HandleSignalsState hss; |  | 
| 234 |  | 
| 235   // Never readable. |  | 
| 236   waiter.Init(); |  | 
| 237   hss = HandleSignalsState(); |  | 
| 238   EXPECT_EQ( |  | 
| 239       MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 240       dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss)); |  | 
| 241   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 242   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 243             hss.satisfiable_signals); |  | 
| 244 |  | 
| 245   // Already writable. |  | 
| 246   waiter.Init(); |  | 
| 247   hss = HandleSignalsState(); |  | 
| 248   EXPECT_EQ( |  | 
| 249       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 250       dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 34, &hss)); |  | 
| 251 |  | 
| 252   // Write two elements. |  | 
| 253   int32_t elements[2] = {123, 456}; |  | 
| 254   uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); |  | 
| 255   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 256             dp->ProducerWriteData(UserPointer<const void>(elements), |  | 
| 257                                   MakeUserPointer(&num_bytes), true)); |  | 
| 258   EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes); |  | 
| 259 |  | 
| 260   // Adding a waiter should now succeed. |  | 
| 261   waiter.Init(); |  | 
| 262   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 263             dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56, |  | 
| 264                                     nullptr)); |  | 
| 265   // And it shouldn't be writable yet. |  | 
| 266   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); |  | 
| 267   hss = HandleSignalsState(); |  | 
| 268   dp->ProducerRemoveAwakable(&waiter, &hss); |  | 
| 269   EXPECT_EQ(0u, hss.satisfied_signals); |  | 
| 270   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 271             hss.satisfiable_signals); |  | 
| 272 |  | 
| 273   // Peek one element. |  | 
| 274   elements[0] = -1; |  | 
| 275   elements[1] = -1; |  | 
| 276   num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 277   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 278             dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 279                                  MakeUserPointer(&num_bytes), true, true)); |  | 
| 280   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 281   EXPECT_EQ(123, elements[0]); |  | 
| 282   EXPECT_EQ(-1, elements[1]); |  | 
| 283 |  | 
| 284   // Add a waiter. |  | 
| 285   waiter.Init(); |  | 
| 286   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 287             dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56, |  | 
| 288                                     nullptr)); |  | 
| 289   // And it still shouldn't be writable yet. |  | 
| 290   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); |  | 
| 291   hss = HandleSignalsState(); |  | 
| 292   dp->ProducerRemoveAwakable(&waiter, &hss); |  | 
| 293   EXPECT_EQ(0u, hss.satisfied_signals); |  | 
| 294   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 295             hss.satisfiable_signals); |  | 
| 296 |  | 
| 297   // Do it again. |  | 
| 298   waiter.Init(); |  | 
| 299   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 300             dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 78, |  | 
| 301                                     nullptr)); |  | 
| 302 |  | 
| 303   // Read one element. |  | 
| 304   elements[0] = -1; |  | 
| 305   elements[1] = -1; |  | 
| 306   num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 307   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 308             dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 309                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 310   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 311   EXPECT_EQ(123, elements[0]); |  | 
| 312   EXPECT_EQ(-1, elements[1]); |  | 
| 313 |  | 
| 314   // Waiting should now succeed. |  | 
| 315   EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); |  | 
| 316   EXPECT_EQ(78u, context); |  | 
| 317   hss = HandleSignalsState(); |  | 
| 318   dp->ProducerRemoveAwakable(&waiter, &hss); |  | 
| 319   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 320   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 321             hss.satisfiable_signals); |  | 
| 322 |  | 
| 323   // Try writing, using a two-phase write. |  | 
| 324   void* buffer = nullptr; |  | 
| 325   num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0])); |  | 
| 326   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 327             dp->ProducerBeginWriteData(MakeUserPointer(&buffer), |  | 
| 328                                        MakeUserPointer(&num_bytes), false)); |  | 
| 329   EXPECT_TRUE(buffer); |  | 
| 330   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 331 |  | 
| 332   static_cast<int32_t*>(buffer)[0] = 789; |  | 
| 333   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(static_cast<uint32_t>( |  | 
| 334                                 1u * sizeof(elements[0])))); |  | 
| 335 |  | 
| 336   // Add a waiter. |  | 
| 337   waiter.Init(); |  | 
| 338   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 339             dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 90, |  | 
| 340                                     nullptr)); |  | 
| 341 |  | 
| 342   // Read one element, using a two-phase read. |  | 
| 343   const void* read_buffer = nullptr; |  | 
| 344   num_bytes = 0u; |  | 
| 345   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 346             dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer), |  | 
| 347                                       MakeUserPointer(&num_bytes), false)); |  | 
| 348   EXPECT_TRUE(read_buffer); |  | 
| 349   // Since we only read one element (after having written three in all), the |  | 
| 350   // two-phase read should only allow us to read one. This checks an |  | 
| 351   // implementation detail! |  | 
| 352   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 353   EXPECT_EQ(456, static_cast<const int32_t*>(read_buffer)[0]); |  | 
| 354   EXPECT_EQ( |  | 
| 355       MOJO_RESULT_OK, |  | 
| 356       dp->ConsumerEndReadData(static_cast<uint32_t>(1u * sizeof(elements[0])))); |  | 
| 357 |  | 
| 358   // Waiting should succeed. |  | 
| 359   EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); |  | 
| 360   EXPECT_EQ(90u, context); |  | 
| 361   hss = HandleSignalsState(); |  | 
| 362   dp->ProducerRemoveAwakable(&waiter, &hss); |  | 
| 363   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 364   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 365             hss.satisfiable_signals); |  | 
| 366 |  | 
| 367   // Write one element. |  | 
| 368   elements[0] = 123; |  | 
| 369   num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 370   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 371             dp->ProducerWriteData(UserPointer<const void>(elements), |  | 
| 372                                   MakeUserPointer(&num_bytes), false)); |  | 
| 373   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 374 |  | 
| 375   // Add a waiter. |  | 
| 376   waiter.Init(); |  | 
| 377   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 378             dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, |  | 
| 379                                     nullptr)); |  | 
| 380 |  | 
| 381   // Close the consumer. |  | 
| 382   dp->ConsumerClose(); |  | 
| 383 |  | 
| 384   // It should now be never-writable. |  | 
| 385   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context)); |  | 
| 386   EXPECT_EQ(12u, context); |  | 
| 387   hss = HandleSignalsState(); |  | 
| 388   dp->ProducerRemoveAwakable(&waiter, &hss); |  | 
| 389   EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |  | 
| 390   EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |  | 
| 391 |  | 
| 392   dp->ProducerClose(); |  | 
| 393 } |  | 
| 394 |  | 
| 395 TEST(LocalDataPipeTest, PeerClosedWaiting) { |  | 
| 396   const MojoCreateDataPipeOptions options = { |  | 
| 397       kSizeOfOptions,                           // |struct_size|. |  | 
| 398       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 399       static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|. |  | 
| 400       2 * sizeof(int32_t)                       // |capacity_num_bytes|. |  | 
| 401   }; |  | 
| 402   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 403   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 404                                 MakeUserPointer(&options), &validated_options)); |  | 
| 405 |  | 
| 406   Waiter waiter; |  | 
| 407   HandleSignalsState hss; |  | 
| 408 |  | 
| 409   // Check MOJO_HANDLE_SIGNAL_PEER_CLOSED on producer. |  | 
| 410   { |  | 
| 411     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 412     // Add a waiter. |  | 
| 413     waiter.Init(); |  | 
| 414     ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 415               dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 416                                       12, nullptr)); |  | 
| 417 |  | 
| 418     // Close the consumer. |  | 
| 419     dp->ConsumerClose(); |  | 
| 420 |  | 
| 421     // It should be signaled. |  | 
| 422     uint32_t context = 0; |  | 
| 423     EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); |  | 
| 424     EXPECT_EQ(12u, context); |  | 
| 425     hss = HandleSignalsState(); |  | 
| 426     dp->ProducerRemoveAwakable(&waiter, &hss); |  | 
| 427     EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |  | 
| 428     EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |  | 
| 429 |  | 
| 430     dp->ProducerClose(); |  | 
| 431   } |  | 
| 432 |  | 
| 433   // Check MOJO_HANDLE_SIGNAL_PEER_CLOSED on consumer. |  | 
| 434   { |  | 
| 435     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 436     // Add a waiter. |  | 
| 437     waiter.Init(); |  | 
| 438     ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 439               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 440                                       12, nullptr)); |  | 
| 441 |  | 
| 442     // Close the producer. |  | 
| 443     dp->ProducerClose(); |  | 
| 444 |  | 
| 445     // It should be signaled. |  | 
| 446     uint32_t context = 0; |  | 
| 447     EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); |  | 
| 448     EXPECT_EQ(12u, context); |  | 
| 449     hss = HandleSignalsState(); |  | 
| 450     dp->ConsumerRemoveAwakable(&waiter, &hss); |  | 
| 451     EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |  | 
| 452     EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |  | 
| 453 |  | 
| 454     dp->ConsumerClose(); |  | 
| 455   } |  | 
| 456 } |  | 
| 457 |  | 
| 458 TEST(LocalDataPipeTest, BasicConsumerWaiting) { |  | 
| 459   const MojoCreateDataPipeOptions options = { |  | 
| 460       kSizeOfOptions,                           // |struct_size|. |  | 
| 461       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 462       static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|. |  | 
| 463       1000 * sizeof(int32_t)                    // |capacity_num_bytes|. |  | 
| 464   }; |  | 
| 465   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 466   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 467                                 MakeUserPointer(&options), &validated_options)); |  | 
| 468 |  | 
| 469   { |  | 
| 470     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 471     Waiter waiter; |  | 
| 472     uint32_t context = 0; |  | 
| 473     HandleSignalsState hss; |  | 
| 474 |  | 
| 475     // Never writable. |  | 
| 476     waiter.Init(); |  | 
| 477     hss = HandleSignalsState(); |  | 
| 478     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 479               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, |  | 
| 480                                       &hss)); |  | 
| 481     EXPECT_EQ(0u, hss.satisfied_signals); |  | 
| 482     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 483               hss.satisfiable_signals); |  | 
| 484 |  | 
| 485     // Not yet readable. |  | 
| 486     waiter.Init(); |  | 
| 487     ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 488               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, |  | 
| 489                                       nullptr)); |  | 
| 490     EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); |  | 
| 491     hss = HandleSignalsState(); |  | 
| 492     dp->ConsumerRemoveAwakable(&waiter, &hss); |  | 
| 493     EXPECT_EQ(0u, hss.satisfied_signals); |  | 
| 494     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 495               hss.satisfiable_signals); |  | 
| 496 |  | 
| 497     // Write two elements. |  | 
| 498     int32_t elements[2] = {123, 456}; |  | 
| 499     uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); |  | 
| 500     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 501               dp->ProducerWriteData(UserPointer<const void>(elements), |  | 
| 502                                     MakeUserPointer(&num_bytes), true)); |  | 
| 503 |  | 
| 504     // Should already be readable. |  | 
| 505     waiter.Init(); |  | 
| 506     hss = HandleSignalsState(); |  | 
| 507     EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |  | 
| 508               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, |  | 
| 509                                       &hss)); |  | 
| 510     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 511     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 512               hss.satisfiable_signals); |  | 
| 513 |  | 
| 514     // Discard one element. |  | 
| 515     num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 516     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 517               dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); |  | 
| 518     EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 519 |  | 
| 520     // Should still be readable. |  | 
| 521     waiter.Init(); |  | 
| 522     hss = HandleSignalsState(); |  | 
| 523     EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |  | 
| 524               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, |  | 
| 525                                       &hss)); |  | 
| 526     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 527     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 528               hss.satisfiable_signals); |  | 
| 529 |  | 
| 530     // Peek one element. |  | 
| 531     elements[0] = -1; |  | 
| 532     elements[1] = -1; |  | 
| 533     num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 534     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 535               dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 536                                    MakeUserPointer(&num_bytes), true, true)); |  | 
| 537     EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 538     EXPECT_EQ(456, elements[0]); |  | 
| 539     EXPECT_EQ(-1, elements[1]); |  | 
| 540 |  | 
| 541     // Should still be readable. |  | 
| 542     waiter.Init(); |  | 
| 543     hss = HandleSignalsState(); |  | 
| 544     EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |  | 
| 545               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, |  | 
| 546                                       &hss)); |  | 
| 547     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 548     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 549               hss.satisfiable_signals); |  | 
| 550 |  | 
| 551     // Read one element. |  | 
| 552     elements[0] = -1; |  | 
| 553     elements[1] = -1; |  | 
| 554     num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 555     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 556               dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 557                                    MakeUserPointer(&num_bytes), true, false)); |  | 
| 558     EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 559     EXPECT_EQ(456, elements[0]); |  | 
| 560     EXPECT_EQ(-1, elements[1]); |  | 
| 561 |  | 
| 562     // Adding a waiter should now succeed. |  | 
| 563     waiter.Init(); |  | 
| 564     ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 565               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 90, |  | 
| 566                                       nullptr)); |  | 
| 567 |  | 
| 568     // Write one element. |  | 
| 569     elements[0] = 789; |  | 
| 570     elements[1] = -1; |  | 
| 571     num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 572     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 573               dp->ProducerWriteData(UserPointer<const void>(elements), |  | 
| 574                                     MakeUserPointer(&num_bytes), true)); |  | 
| 575 |  | 
| 576     // Waiting should now succeed. |  | 
| 577     EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); |  | 
| 578     EXPECT_EQ(90u, context); |  | 
| 579     hss = HandleSignalsState(); |  | 
| 580     dp->ConsumerRemoveAwakable(&waiter, &hss); |  | 
| 581     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 582     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 583               hss.satisfiable_signals); |  | 
| 584 |  | 
| 585     // Close the producer. |  | 
| 586     dp->ProducerClose(); |  | 
| 587 |  | 
| 588     // Should still be readable. |  | 
| 589     waiter.Init(); |  | 
| 590     hss = HandleSignalsState(); |  | 
| 591     EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |  | 
| 592               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, |  | 
| 593                                       &hss)); |  | 
| 594     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 595               hss.satisfied_signals); |  | 
| 596     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 597               hss.satisfiable_signals); |  | 
| 598 |  | 
| 599     // Read one element. |  | 
| 600     elements[0] = -1; |  | 
| 601     elements[1] = -1; |  | 
| 602     num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |  | 
| 603     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 604               dp->ConsumerReadData(UserPointer<void>(elements), |  | 
| 605                                    MakeUserPointer(&num_bytes), true, false)); |  | 
| 606     EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 607     EXPECT_EQ(789, elements[0]); |  | 
| 608     EXPECT_EQ(-1, elements[1]); |  | 
| 609 |  | 
| 610     // Should be never-readable. |  | 
| 611     waiter.Init(); |  | 
| 612     hss = HandleSignalsState(); |  | 
| 613     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 614               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, |  | 
| 615                                       &hss)); |  | 
| 616     EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |  | 
| 617     EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |  | 
| 618 |  | 
| 619     dp->ConsumerClose(); |  | 
| 620   } |  | 
| 621 |  | 
| 622   // Test with two-phase APIs and closing the producer with an active consumer |  | 
| 623   // waiter. |  | 
| 624   { |  | 
| 625     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 626     Waiter waiter; |  | 
| 627     uint32_t context = 0; |  | 
| 628     HandleSignalsState hss; |  | 
| 629 |  | 
| 630     // Write two elements. |  | 
| 631     int32_t* elements = nullptr; |  | 
| 632     void* buffer = nullptr; |  | 
| 633     // Request room for three (but we'll only write two). |  | 
| 634     uint32_t num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0])); |  | 
| 635     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 636               dp->ProducerBeginWriteData(MakeUserPointer(&buffer), |  | 
| 637                                          MakeUserPointer(&num_bytes), true)); |  | 
| 638     EXPECT_TRUE(buffer); |  | 
| 639     EXPECT_GE(num_bytes, static_cast<uint32_t>(3u * sizeof(elements[0]))); |  | 
| 640     elements = static_cast<int32_t*>(buffer); |  | 
| 641     elements[0] = 123; |  | 
| 642     elements[1] = 456; |  | 
| 643     EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(static_cast<uint32_t>( |  | 
| 644                                   2u * sizeof(elements[0])))); |  | 
| 645 |  | 
| 646     // Should already be readable. |  | 
| 647     waiter.Init(); |  | 
| 648     hss = HandleSignalsState(); |  | 
| 649     EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |  | 
| 650               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, |  | 
| 651                                       &hss)); |  | 
| 652     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 653     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 654               hss.satisfiable_signals); |  | 
| 655 |  | 
| 656     // Read one element. |  | 
| 657     // Request two in all-or-none mode, but only read one. |  | 
| 658     const void* read_buffer = nullptr; |  | 
| 659     num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); |  | 
| 660     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 661               dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer), |  | 
| 662                                         MakeUserPointer(&num_bytes), true)); |  | 
| 663     EXPECT_TRUE(read_buffer); |  | 
| 664     EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes); |  | 
| 665     const int32_t* read_elements = static_cast<const int32_t*>(read_buffer); |  | 
| 666     EXPECT_EQ(123, read_elements[0]); |  | 
| 667     EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(static_cast<uint32_t>( |  | 
| 668                                   1u * sizeof(elements[0])))); |  | 
| 669 |  | 
| 670     // Should still be readable. |  | 
| 671     waiter.Init(); |  | 
| 672     hss = HandleSignalsState(); |  | 
| 673     EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |  | 
| 674               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, |  | 
| 675                                       &hss)); |  | 
| 676     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 677     EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 678               hss.satisfiable_signals); |  | 
| 679 |  | 
| 680     // Read one element. |  | 
| 681     // Request three, but not in all-or-none mode. |  | 
| 682     read_buffer = nullptr; |  | 
| 683     num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0])); |  | 
| 684     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 685               dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer), |  | 
| 686                                         MakeUserPointer(&num_bytes), false)); |  | 
| 687     EXPECT_TRUE(read_buffer); |  | 
| 688     EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |  | 
| 689     read_elements = static_cast<const int32_t*>(read_buffer); |  | 
| 690     EXPECT_EQ(456, read_elements[0]); |  | 
| 691     EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(static_cast<uint32_t>( |  | 
| 692                                   1u * sizeof(elements[0])))); |  | 
| 693 |  | 
| 694     // Adding a waiter should now succeed. |  | 
| 695     waiter.Init(); |  | 
| 696     ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 697               dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, |  | 
| 698                                       nullptr)); |  | 
| 699 |  | 
| 700     // Close the producer. |  | 
| 701     dp->ProducerClose(); |  | 
| 702 |  | 
| 703     // Should be never-readable. |  | 
| 704     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context)); |  | 
| 705     EXPECT_EQ(56u, context); |  | 
| 706     hss = HandleSignalsState(); |  | 
| 707     dp->ConsumerRemoveAwakable(&waiter, &hss); |  | 
| 708     EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |  | 
| 709     EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |  | 
| 710 |  | 
| 711     dp->ConsumerClose(); |  | 
| 712   } |  | 
| 713 } |  | 
| 714 |  | 
| 715 // Tests that data pipes aren't writable/readable during two-phase writes/reads. |  | 
| 716 TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) { |  | 
| 717   const MojoCreateDataPipeOptions options = { |  | 
| 718       kSizeOfOptions,                           // |struct_size|. |  | 
| 719       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 720       static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|. |  | 
| 721       1000 * sizeof(int32_t)                    // |capacity_num_bytes|. |  | 
| 722   }; |  | 
| 723   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 724   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 725                                 MakeUserPointer(&options), &validated_options)); |  | 
| 726 |  | 
| 727   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 728   Waiter waiter; |  | 
| 729   HandleSignalsState hss; |  | 
| 730 |  | 
| 731   // It should be writable. |  | 
| 732   waiter.Init(); |  | 
| 733   hss = HandleSignalsState(); |  | 
| 734   EXPECT_EQ( |  | 
| 735       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 736       dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); |  | 
| 737   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 738   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 739             hss.satisfiable_signals); |  | 
| 740 |  | 
| 741   uint32_t num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t)); |  | 
| 742   void* write_ptr = nullptr; |  | 
| 743   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 744             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 745                                        MakeUserPointer(&num_bytes), false)); |  | 
| 746   EXPECT_TRUE(write_ptr); |  | 
| 747   EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t))); |  | 
| 748 |  | 
| 749   // At this point, it shouldn't be writable. |  | 
| 750   waiter.Init(); |  | 
| 751   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 752             dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 1, |  | 
| 753                                     nullptr)); |  | 
| 754   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); |  | 
| 755   hss = HandleSignalsState(); |  | 
| 756   dp->ProducerRemoveAwakable(&waiter, &hss); |  | 
| 757   EXPECT_EQ(0u, hss.satisfied_signals); |  | 
| 758   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 759             hss.satisfiable_signals); |  | 
| 760 |  | 
| 761   // It shouldn't be readable yet either. |  | 
| 762   waiter.Init(); |  | 
| 763   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 764             dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 2, |  | 
| 765                                     nullptr)); |  | 
| 766   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); |  | 
| 767   hss = HandleSignalsState(); |  | 
| 768   dp->ConsumerRemoveAwakable(&waiter, &hss); |  | 
| 769   EXPECT_EQ(0u, hss.satisfied_signals); |  | 
| 770   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 771             hss.satisfiable_signals); |  | 
| 772 |  | 
| 773   static_cast<int32_t*>(write_ptr)[0] = 123; |  | 
| 774   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData( |  | 
| 775                                 static_cast<uint32_t>(1u * sizeof(int32_t)))); |  | 
| 776 |  | 
| 777   // It should be writable again. |  | 
| 778   waiter.Init(); |  | 
| 779   hss = HandleSignalsState(); |  | 
| 780   EXPECT_EQ( |  | 
| 781       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 782       dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, &hss)); |  | 
| 783   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 784   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 785             hss.satisfiable_signals); |  | 
| 786 |  | 
| 787   // And readable. |  | 
| 788   waiter.Init(); |  | 
| 789   hss = HandleSignalsState(); |  | 
| 790   EXPECT_EQ( |  | 
| 791       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 792       dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 4, &hss)); |  | 
| 793   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 794   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 795             hss.satisfiable_signals); |  | 
| 796 |  | 
| 797   // Start another two-phase write and check that it's readable even in the |  | 
| 798   // middle of it. |  | 
| 799   num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t)); |  | 
| 800   write_ptr = nullptr; |  | 
| 801   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 802             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 803                                        MakeUserPointer(&num_bytes), false)); |  | 
| 804   EXPECT_TRUE(write_ptr); |  | 
| 805   EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t))); |  | 
| 806 |  | 
| 807   // It should be readable. |  | 
| 808   waiter.Init(); |  | 
| 809   hss = HandleSignalsState(); |  | 
| 810   EXPECT_EQ( |  | 
| 811       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 812       dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss)); |  | 
| 813   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 814   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 815             hss.satisfiable_signals); |  | 
| 816 |  | 
| 817   // End the two-phase write without writing anything. |  | 
| 818   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(0u)); |  | 
| 819 |  | 
| 820   // Start a two-phase read. |  | 
| 821   num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t)); |  | 
| 822   const void* read_ptr = nullptr; |  | 
| 823   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 824             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 825                                       MakeUserPointer(&num_bytes), false)); |  | 
| 826   EXPECT_TRUE(read_ptr); |  | 
| 827   EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(int32_t)), num_bytes); |  | 
| 828 |  | 
| 829   // At this point, it should still be writable. |  | 
| 830   waiter.Init(); |  | 
| 831   hss = HandleSignalsState(); |  | 
| 832   EXPECT_EQ( |  | 
| 833       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 834       dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss)); |  | 
| 835   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 836   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 837             hss.satisfiable_signals); |  | 
| 838 |  | 
| 839   // But not readable. |  | 
| 840   waiter.Init(); |  | 
| 841   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 842             dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, |  | 
| 843                                     nullptr)); |  | 
| 844   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); |  | 
| 845   hss = HandleSignalsState(); |  | 
| 846   dp->ConsumerRemoveAwakable(&waiter, &hss); |  | 
| 847   EXPECT_EQ(0u, hss.satisfied_signals); |  | 
| 848   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 849             hss.satisfiable_signals); |  | 
| 850 |  | 
| 851   // End the two-phase read without reading anything. |  | 
| 852   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(0u)); |  | 
| 853 |  | 
| 854   // It should be readable again. |  | 
| 855   waiter.Init(); |  | 
| 856   hss = HandleSignalsState(); |  | 
| 857   EXPECT_EQ( |  | 
| 858       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 859       dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, &hss)); |  | 
| 860   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 861   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 862             hss.satisfiable_signals); |  | 
| 863 |  | 
| 864   dp->ProducerClose(); |  | 
| 865   dp->ConsumerClose(); |  | 
| 866 } |  | 
| 867 |  | 
| 868 // Test that a "may discard" data pipe is writable even when it's full. |  | 
| 869 TEST(LocalDataPipeTest, BasicMayDiscardWaiting) { |  | 
| 870   const MojoCreateDataPipeOptions options = { |  | 
| 871       kSizeOfOptions,                                  // |struct_size|. |  | 
| 872       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|. |  | 
| 873       static_cast<uint32_t>(sizeof(int32_t)),          // |element_num_bytes|. |  | 
| 874       1 * sizeof(int32_t)                              // |capacity_num_bytes|. |  | 
| 875   }; |  | 
| 876   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 877   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 878                                 MakeUserPointer(&options), &validated_options)); |  | 
| 879 |  | 
| 880   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 881   Waiter waiter; |  | 
| 882   HandleSignalsState hss; |  | 
| 883 |  | 
| 884   // Writable. |  | 
| 885   waiter.Init(); |  | 
| 886   hss = HandleSignalsState(); |  | 
| 887   EXPECT_EQ( |  | 
| 888       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 889       dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); |  | 
| 890   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 891   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 892             hss.satisfiable_signals); |  | 
| 893 |  | 
| 894   // Not readable. |  | 
| 895   waiter.Init(); |  | 
| 896   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 897             dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, |  | 
| 898                                     nullptr)); |  | 
| 899   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); |  | 
| 900   hss = HandleSignalsState(); |  | 
| 901   dp->ConsumerRemoveAwakable(&waiter, &hss); |  | 
| 902   EXPECT_EQ(0u, hss.satisfied_signals); |  | 
| 903   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 904             hss.satisfiable_signals); |  | 
| 905 |  | 
| 906   uint32_t num_bytes = static_cast<uint32_t>(sizeof(int32_t)); |  | 
| 907   int32_t element = 123; |  | 
| 908   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 909             dp->ProducerWriteData(UserPointer<const void>(&element), |  | 
| 910                                   MakeUserPointer(&num_bytes), false)); |  | 
| 911   EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes); |  | 
| 912 |  | 
| 913   // Still writable (even though it's full). |  | 
| 914   waiter.Init(); |  | 
| 915   hss = HandleSignalsState(); |  | 
| 916   EXPECT_EQ( |  | 
| 917       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 918       dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 2, &hss)); |  | 
| 919   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 920   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 921             hss.satisfiable_signals); |  | 
| 922 |  | 
| 923   // Now readable. |  | 
| 924   waiter.Init(); |  | 
| 925   hss = HandleSignalsState(); |  | 
| 926   EXPECT_EQ( |  | 
| 927       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 928       dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss)); |  | 
| 929   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 930   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 931             hss.satisfiable_signals); |  | 
| 932 |  | 
| 933   // Overwrite that element. |  | 
| 934   num_bytes = static_cast<uint32_t>(sizeof(int32_t)); |  | 
| 935   element = 456; |  | 
| 936   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 937             dp->ProducerWriteData(UserPointer<const void>(&element), |  | 
| 938                                   MakeUserPointer(&num_bytes), false)); |  | 
| 939   EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes); |  | 
| 940 |  | 
| 941   // Still writable. |  | 
| 942   waiter.Init(); |  | 
| 943   hss = HandleSignalsState(); |  | 
| 944   EXPECT_EQ( |  | 
| 945       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 946       dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss)); |  | 
| 947   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 948   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 949             hss.satisfiable_signals); |  | 
| 950 |  | 
| 951   // And still readable. |  | 
| 952   waiter.Init(); |  | 
| 953   hss = HandleSignalsState(); |  | 
| 954   EXPECT_EQ( |  | 
| 955       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 956       dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss)); |  | 
| 957   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); |  | 
| 958   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 959             hss.satisfiable_signals); |  | 
| 960 |  | 
| 961   // Read that element. |  | 
| 962   num_bytes = static_cast<uint32_t>(sizeof(int32_t)); |  | 
| 963   element = 0; |  | 
| 964   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 965             dp->ConsumerReadData(UserPointer<void>(&element), |  | 
| 966                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 967   EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes); |  | 
| 968   EXPECT_EQ(456, element); |  | 
| 969 |  | 
| 970   // Still writable. |  | 
| 971   waiter.Init(); |  | 
| 972   hss = HandleSignalsState(); |  | 
| 973   EXPECT_EQ( |  | 
| 974       MOJO_RESULT_ALREADY_EXISTS, |  | 
| 975       dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss)); |  | 
| 976   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |  | 
| 977   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 978             hss.satisfiable_signals); |  | 
| 979 |  | 
| 980   // No longer readable. |  | 
| 981   waiter.Init(); |  | 
| 982   ASSERT_EQ(MOJO_RESULT_OK, |  | 
| 983             dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, |  | 
| 984                                     nullptr)); |  | 
| 985   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); |  | 
| 986   hss = HandleSignalsState(); |  | 
| 987   dp->ConsumerRemoveAwakable(&waiter, &hss); |  | 
| 988   EXPECT_EQ(0u, hss.satisfied_signals); |  | 
| 989   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |  | 
| 990             hss.satisfiable_signals); |  | 
| 991 |  | 
| 992   dp->ProducerClose(); |  | 
| 993   dp->ConsumerClose(); |  | 
| 994 } |  | 
| 995 |  | 
| 996 void Seq(int32_t start, size_t count, int32_t* out) { |  | 
| 997   for (size_t i = 0; i < count; i++) |  | 
| 998     out[i] = start + static_cast<int32_t>(i); |  | 
| 999 } |  | 
| 1000 |  | 
| 1001 TEST(LocalDataPipeTest, MayDiscard) { |  | 
| 1002   const MojoCreateDataPipeOptions options = { |  | 
| 1003       kSizeOfOptions,                                  // |struct_size|. |  | 
| 1004       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|. |  | 
| 1005       static_cast<uint32_t>(sizeof(int32_t)),          // |element_num_bytes|. |  | 
| 1006       10 * sizeof(int32_t)                             // |capacity_num_bytes|. |  | 
| 1007   }; |  | 
| 1008   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 1009   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 1010                                 MakeUserPointer(&options), &validated_options)); |  | 
| 1011 |  | 
| 1012   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1013 |  | 
| 1014   int32_t buffer[100] = {0}; |  | 
| 1015   uint32_t num_bytes = 0; |  | 
| 1016 |  | 
| 1017   num_bytes = 20u * sizeof(int32_t); |  | 
| 1018   Seq(0, arraysize(buffer), buffer); |  | 
| 1019   // Try writing more than capacity. (This test relies on the implementation |  | 
| 1020   // enforcing the capacity strictly.) |  | 
| 1021   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1022             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1023                                   MakeUserPointer(&num_bytes), false)); |  | 
| 1024   EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |  | 
| 1025 |  | 
| 1026   // Read half of what we wrote. |  | 
| 1027   num_bytes = 5u * sizeof(int32_t); |  | 
| 1028   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1029   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1030             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1031                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 1032   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1033   int32_t expected_buffer[100]; |  | 
| 1034   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1035   Seq(0, 5u, expected_buffer); |  | 
| 1036   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1037   // Internally, a circular buffer would now look like: |  | 
| 1038   //   -, -, -, -, -, 5, 6, 7, 8, 9 |  | 
| 1039 |  | 
| 1040   // Write a bit more than the space that's available. |  | 
| 1041   num_bytes = 8u * sizeof(int32_t); |  | 
| 1042   Seq(100, arraysize(buffer), buffer); |  | 
| 1043   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1044             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1045                                   MakeUserPointer(&num_bytes), false)); |  | 
| 1046   EXPECT_EQ(8u * sizeof(int32_t), num_bytes); |  | 
| 1047   // Internally, a circular buffer would now look like: |  | 
| 1048   //   100, 101, 102, 103, 104, 105, 106, 107, 8, 9 |  | 
| 1049 |  | 
| 1050   // Read half of what's available. |  | 
| 1051   num_bytes = 5u * sizeof(int32_t); |  | 
| 1052   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1053   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1054             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1055                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 1056   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1057   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1058   expected_buffer[0] = 8; |  | 
| 1059   expected_buffer[1] = 9; |  | 
| 1060   expected_buffer[2] = 100; |  | 
| 1061   expected_buffer[3] = 101; |  | 
| 1062   expected_buffer[4] = 102; |  | 
| 1063   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1064   // Internally, a circular buffer would now look like: |  | 
| 1065   //   -, -, -, 103, 104, 105, 106, 107, -, - |  | 
| 1066 |  | 
| 1067   // Write one integer. |  | 
| 1068   num_bytes = 1u * sizeof(int32_t); |  | 
| 1069   Seq(200, arraysize(buffer), buffer); |  | 
| 1070   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1071             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1072                                   MakeUserPointer(&num_bytes), false)); |  | 
| 1073   EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |  | 
| 1074   // Internally, a circular buffer would now look like: |  | 
| 1075   //   -, -, -, 103, 104, 105, 106, 107, 200, - |  | 
| 1076 |  | 
| 1077   // Write five more. |  | 
| 1078   num_bytes = 5u * sizeof(int32_t); |  | 
| 1079   Seq(300, arraysize(buffer), buffer); |  | 
| 1080   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1081             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1082                                   MakeUserPointer(&num_bytes), false)); |  | 
| 1083   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1084   // Internally, a circular buffer would now look like: |  | 
| 1085   //   301, 302, 303, 304, 104, 105, 106, 107, 200, 300 |  | 
| 1086 |  | 
| 1087   // Read it all. |  | 
| 1088   num_bytes = sizeof(buffer); |  | 
| 1089   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1090   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1091             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1092                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 1093   EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |  | 
| 1094   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1095   expected_buffer[0] = 104; |  | 
| 1096   expected_buffer[1] = 105; |  | 
| 1097   expected_buffer[2] = 106; |  | 
| 1098   expected_buffer[3] = 107; |  | 
| 1099   expected_buffer[4] = 200; |  | 
| 1100   expected_buffer[5] = 300; |  | 
| 1101   expected_buffer[6] = 301; |  | 
| 1102   expected_buffer[7] = 302; |  | 
| 1103   expected_buffer[8] = 303; |  | 
| 1104   expected_buffer[9] = 304; |  | 
| 1105   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1106 |  | 
| 1107   // Test two-phase writes, including in all-or-none mode. |  | 
| 1108   // Note: Again, the following depends on an implementation detail -- namely |  | 
| 1109   // that the write pointer will point at the 5th element of the buffer (and the |  | 
| 1110   // buffer has exactly the capacity requested). |  | 
| 1111 |  | 
| 1112   num_bytes = 0u; |  | 
| 1113   void* write_ptr = nullptr; |  | 
| 1114   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1115             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1116                                        MakeUserPointer(&num_bytes), false)); |  | 
| 1117   EXPECT_TRUE(write_ptr); |  | 
| 1118   EXPECT_EQ(6u * sizeof(int32_t), num_bytes); |  | 
| 1119   Seq(400, 6, static_cast<int32_t*>(write_ptr)); |  | 
| 1120   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(6u * sizeof(int32_t))); |  | 
| 1121   // Internally, a circular buffer would now look like: |  | 
| 1122   //   -, -, -, -, 400, 401, 402, 403, 404, 405 |  | 
| 1123 |  | 
| 1124   // |ProducerBeginWriteData()| ignores |*num_bytes| except in "all-or-none" |  | 
| 1125   // mode. |  | 
| 1126   num_bytes = 6u * sizeof(int32_t); |  | 
| 1127   write_ptr = nullptr; |  | 
| 1128   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1129             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1130                                        MakeUserPointer(&num_bytes), false)); |  | 
| 1131   EXPECT_EQ(4u * sizeof(int32_t), num_bytes); |  | 
| 1132   static_cast<int32_t*>(write_ptr)[0] = 500; |  | 
| 1133   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(1u * sizeof(int32_t))); |  | 
| 1134   // Internally, a circular buffer would now look like: |  | 
| 1135   //   500, -, -, -, 400, 401, 402, 403, 404, 405 |  | 
| 1136 |  | 
| 1137   // Requesting a 10-element buffer in all-or-none mode fails at this point. |  | 
| 1138   num_bytes = 10u * sizeof(int32_t); |  | 
| 1139   write_ptr = nullptr; |  | 
| 1140   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1141             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1142                                        MakeUserPointer(&num_bytes), true)); |  | 
| 1143 |  | 
| 1144   // But requesting, say, a 5-element (up to 9, really) buffer should be okay. |  | 
| 1145   // It will discard two elements. |  | 
| 1146   num_bytes = 5u * sizeof(int32_t); |  | 
| 1147   write_ptr = nullptr; |  | 
| 1148   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1149             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1150                                        MakeUserPointer(&num_bytes), true)); |  | 
| 1151   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1152   // Only write 4 elements though. |  | 
| 1153   Seq(600, 4, static_cast<int32_t*>(write_ptr)); |  | 
| 1154   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(4u * sizeof(int32_t))); |  | 
| 1155   // Internally, a circular buffer would now look like: |  | 
| 1156   //   500, 600, 601, 602, 603, -, 402, 403, 404, 405 |  | 
| 1157 |  | 
| 1158   // Do this again. Make sure we can get a buffer all the way out to the end of |  | 
| 1159   // the internal buffer. |  | 
| 1160   num_bytes = 5u * sizeof(int32_t); |  | 
| 1161   write_ptr = nullptr; |  | 
| 1162   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1163             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1164                                        MakeUserPointer(&num_bytes), true)); |  | 
| 1165   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1166   // Only write 3 elements though. |  | 
| 1167   Seq(700, 3, static_cast<int32_t*>(write_ptr)); |  | 
| 1168   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(3u * sizeof(int32_t))); |  | 
| 1169   // Internally, a circular buffer would now look like: |  | 
| 1170   //   500, 600, 601, 602, 603, 700, 701, 702, -, - |  | 
| 1171 |  | 
| 1172   // Read everything. |  | 
| 1173   num_bytes = sizeof(buffer); |  | 
| 1174   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1175   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1176             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1177                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 1178   EXPECT_EQ(8u * sizeof(int32_t), num_bytes); |  | 
| 1179   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1180   expected_buffer[0] = 500; |  | 
| 1181   expected_buffer[1] = 600; |  | 
| 1182   expected_buffer[2] = 601; |  | 
| 1183   expected_buffer[3] = 602; |  | 
| 1184   expected_buffer[4] = 603; |  | 
| 1185   expected_buffer[5] = 700; |  | 
| 1186   expected_buffer[6] = 701; |  | 
| 1187   expected_buffer[7] = 702; |  | 
| 1188   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1189 |  | 
| 1190   dp->ProducerClose(); |  | 
| 1191   dp->ConsumerClose(); |  | 
| 1192 } |  | 
| 1193 |  | 
| 1194 TEST(LocalDataPipeTest, AllOrNone) { |  | 
| 1195   const MojoCreateDataPipeOptions options = { |  | 
| 1196       kSizeOfOptions,                           // |struct_size|. |  | 
| 1197       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 1198       static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|. |  | 
| 1199       10 * sizeof(int32_t)                      // |capacity_num_bytes|. |  | 
| 1200   }; |  | 
| 1201   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 1202   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 1203                                 MakeUserPointer(&options), &validated_options)); |  | 
| 1204 |  | 
| 1205   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1206 |  | 
| 1207   // Try writing way too much. |  | 
| 1208   uint32_t num_bytes = 20u * sizeof(int32_t); |  | 
| 1209   int32_t buffer[100]; |  | 
| 1210   Seq(0, arraysize(buffer), buffer); |  | 
| 1211   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1212             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1213                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1214 |  | 
| 1215   // Should still be empty. |  | 
| 1216   num_bytes = ~0u; |  | 
| 1217   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1218   EXPECT_EQ(0u, num_bytes); |  | 
| 1219 |  | 
| 1220   // Write some data. |  | 
| 1221   num_bytes = 5u * sizeof(int32_t); |  | 
| 1222   Seq(100, arraysize(buffer), buffer); |  | 
| 1223   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1224             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1225                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1226   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1227 |  | 
| 1228   // Half full. |  | 
| 1229   num_bytes = 0u; |  | 
| 1230   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1231   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1232 |  | 
| 1233   // Too much. |  | 
| 1234   num_bytes = 6u * sizeof(int32_t); |  | 
| 1235   Seq(200, arraysize(buffer), buffer); |  | 
| 1236   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1237             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1238                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1239 |  | 
| 1240   // Try reading too much. |  | 
| 1241   num_bytes = 11u * sizeof(int32_t); |  | 
| 1242   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1243   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1244             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1245                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 1246   int32_t expected_buffer[100]; |  | 
| 1247   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1248   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1249 |  | 
| 1250   // Try discarding too much. |  | 
| 1251   num_bytes = 11u * sizeof(int32_t); |  | 
| 1252   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1253             dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); |  | 
| 1254 |  | 
| 1255   // Just a little. |  | 
| 1256   num_bytes = 2u * sizeof(int32_t); |  | 
| 1257   Seq(300, arraysize(buffer), buffer); |  | 
| 1258   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1259             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1260                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1261   EXPECT_EQ(2u * sizeof(int32_t), num_bytes); |  | 
| 1262 |  | 
| 1263   // Just right. |  | 
| 1264   num_bytes = 3u * sizeof(int32_t); |  | 
| 1265   Seq(400, arraysize(buffer), buffer); |  | 
| 1266   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1267             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1268                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1269   EXPECT_EQ(3u * sizeof(int32_t), num_bytes); |  | 
| 1270 |  | 
| 1271   // Exactly full. |  | 
| 1272   num_bytes = 0u; |  | 
| 1273   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1274   EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |  | 
| 1275 |  | 
| 1276   // Read half. |  | 
| 1277   num_bytes = 5u * sizeof(int32_t); |  | 
| 1278   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1279   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1280             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1281                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 1282   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1283   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1284   Seq(100, 5, expected_buffer); |  | 
| 1285   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1286 |  | 
| 1287   // Try reading too much again. |  | 
| 1288   num_bytes = 6u * sizeof(int32_t); |  | 
| 1289   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1290   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1291             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1292                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 1293   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1294   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1295 |  | 
| 1296   // Try discarding too much again. |  | 
| 1297   num_bytes = 6u * sizeof(int32_t); |  | 
| 1298   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1299             dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); |  | 
| 1300 |  | 
| 1301   // Discard a little. |  | 
| 1302   num_bytes = 2u * sizeof(int32_t); |  | 
| 1303   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1304             dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); |  | 
| 1305   EXPECT_EQ(2u * sizeof(int32_t), num_bytes); |  | 
| 1306 |  | 
| 1307   // Three left. |  | 
| 1308   num_bytes = 0u; |  | 
| 1309   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1310   EXPECT_EQ(3u * sizeof(int32_t), num_bytes); |  | 
| 1311 |  | 
| 1312   // Close the producer, then test producer-closed cases. |  | 
| 1313   dp->ProducerClose(); |  | 
| 1314 |  | 
| 1315   // Try reading too much; "failed precondition" since the producer is closed. |  | 
| 1316   num_bytes = 4u * sizeof(int32_t); |  | 
| 1317   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1318   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1319             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1320                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 1321   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1322   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1323 |  | 
| 1324   // Try discarding too much; "failed precondition" again. |  | 
| 1325   num_bytes = 4u * sizeof(int32_t); |  | 
| 1326   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1327             dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); |  | 
| 1328 |  | 
| 1329   // Read a little. |  | 
| 1330   num_bytes = 2u * sizeof(int32_t); |  | 
| 1331   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1332   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1333             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1334                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 1335   EXPECT_EQ(2u * sizeof(int32_t), num_bytes); |  | 
| 1336   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1337   Seq(400, 2, expected_buffer); |  | 
| 1338   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1339 |  | 
| 1340   // Discard the remaining element. |  | 
| 1341   num_bytes = 1u * sizeof(int32_t); |  | 
| 1342   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1343             dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); |  | 
| 1344   EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |  | 
| 1345 |  | 
| 1346   // Empty again. |  | 
| 1347   num_bytes = ~0u; |  | 
| 1348   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1349   EXPECT_EQ(0u, num_bytes); |  | 
| 1350 |  | 
| 1351   dp->ConsumerClose(); |  | 
| 1352 } |  | 
| 1353 |  | 
| 1354 TEST(LocalDataPipeTest, AllOrNoneMayDiscard) { |  | 
| 1355   const MojoCreateDataPipeOptions options = { |  | 
| 1356       kSizeOfOptions,                                  // |struct_size|. |  | 
| 1357       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|. |  | 
| 1358       static_cast<uint32_t>(sizeof(int32_t)),          // |element_num_bytes|. |  | 
| 1359       10 * sizeof(int32_t)                             // |capacity_num_bytes|. |  | 
| 1360   }; |  | 
| 1361   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 1362   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 1363                                 MakeUserPointer(&options), &validated_options)); |  | 
| 1364 |  | 
| 1365   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1366 |  | 
| 1367   // Try writing way too much. |  | 
| 1368   uint32_t num_bytes = 20u * sizeof(int32_t); |  | 
| 1369   int32_t buffer[100]; |  | 
| 1370   Seq(0, arraysize(buffer), buffer); |  | 
| 1371   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1372             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1373                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1374 |  | 
| 1375   // Write some stuff. |  | 
| 1376   num_bytes = 5u * sizeof(int32_t); |  | 
| 1377   Seq(100, arraysize(buffer), buffer); |  | 
| 1378   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1379             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1380                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1381   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1382 |  | 
| 1383   // Write lots of stuff (discarding all but "104"). |  | 
| 1384   num_bytes = 9u * sizeof(int32_t); |  | 
| 1385   Seq(200, arraysize(buffer), buffer); |  | 
| 1386   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1387             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1388                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1389   EXPECT_EQ(9u * sizeof(int32_t), num_bytes); |  | 
| 1390 |  | 
| 1391   // Read one. |  | 
| 1392   num_bytes = 1u * sizeof(int32_t); |  | 
| 1393   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1394   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1395             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1396                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 1397   EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |  | 
| 1398   int32_t expected_buffer[100]; |  | 
| 1399   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1400   expected_buffer[0] = 104; |  | 
| 1401   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1402 |  | 
| 1403   // Try reading too many. |  | 
| 1404   num_bytes = 10u * sizeof(int32_t); |  | 
| 1405   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1406   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1407             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1408                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 1409   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1410   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1411 |  | 
| 1412   // Try discarding too many. |  | 
| 1413   num_bytes = 10u * sizeof(int32_t); |  | 
| 1414   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1415             dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); |  | 
| 1416 |  | 
| 1417   // Discard a bunch. |  | 
| 1418   num_bytes = 4u * sizeof(int32_t); |  | 
| 1419   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1420             dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), true)); |  | 
| 1421 |  | 
| 1422   // Half full. |  | 
| 1423   num_bytes = 0u; |  | 
| 1424   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1425   EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |  | 
| 1426 |  | 
| 1427   // Write as much as possible. |  | 
| 1428   num_bytes = 10u * sizeof(int32_t); |  | 
| 1429   Seq(300, arraysize(buffer), buffer); |  | 
| 1430   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1431             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1432                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1433   EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |  | 
| 1434 |  | 
| 1435   // Read everything. |  | 
| 1436   num_bytes = 10u * sizeof(int32_t); |  | 
| 1437   memset(buffer, 0xab, sizeof(buffer)); |  | 
| 1438   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1439             dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1440                                  MakeUserPointer(&num_bytes), true, false)); |  | 
| 1441   memset(expected_buffer, 0xab, sizeof(expected_buffer)); |  | 
| 1442   EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |  | 
| 1443   Seq(300, 10, expected_buffer); |  | 
| 1444   EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |  | 
| 1445 |  | 
| 1446   // Note: All-or-none two-phase writes on a "may discard" data pipe are tested |  | 
| 1447   // in LocalDataPipeTest.MayDiscard. |  | 
| 1448 |  | 
| 1449   dp->ProducerClose(); |  | 
| 1450   dp->ConsumerClose(); |  | 
| 1451 } |  | 
| 1452 |  | 
| 1453 TEST(LocalDataPipeTest, TwoPhaseAllOrNone) { |  | 
| 1454   const MojoCreateDataPipeOptions options = { |  | 
| 1455       kSizeOfOptions,                           // |struct_size|. |  | 
| 1456       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 1457       static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|. |  | 
| 1458       10 * sizeof(int32_t)                      // |capacity_num_bytes|. |  | 
| 1459   }; |  | 
| 1460   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 1461   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 1462                                 MakeUserPointer(&options), &validated_options)); |  | 
| 1463 |  | 
| 1464   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1465 |  | 
| 1466   // Try writing way too much (two-phase). |  | 
| 1467   uint32_t num_bytes = 20u * sizeof(int32_t); |  | 
| 1468   void* write_ptr = nullptr; |  | 
| 1469   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1470             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1471                                        MakeUserPointer(&num_bytes), true)); |  | 
| 1472 |  | 
| 1473   // Try writing an amount which isn't a multiple of the element size |  | 
| 1474   // (two-phase). |  | 
| 1475   static_assert(sizeof(int32_t) > 1u, "Wow! int32_t's have size 1"); |  | 
| 1476   num_bytes = 1u; |  | 
| 1477   write_ptr = nullptr; |  | 
| 1478   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |  | 
| 1479             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1480                                        MakeUserPointer(&num_bytes), true)); |  | 
| 1481 |  | 
| 1482   // Try reading way too much (two-phase). |  | 
| 1483   num_bytes = 20u * sizeof(int32_t); |  | 
| 1484   const void* read_ptr = nullptr; |  | 
| 1485   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1486             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 1487                                       MakeUserPointer(&num_bytes), true)); |  | 
| 1488 |  | 
| 1489   // Write half (two-phase). |  | 
| 1490   num_bytes = 5u * sizeof(int32_t); |  | 
| 1491   write_ptr = nullptr; |  | 
| 1492   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1493             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1494                                        MakeUserPointer(&num_bytes), true)); |  | 
| 1495   // May provide more space than requested. |  | 
| 1496   EXPECT_GE(num_bytes, 5u * sizeof(int32_t)); |  | 
| 1497   EXPECT_TRUE(write_ptr); |  | 
| 1498   Seq(0, 5, static_cast<int32_t*>(write_ptr)); |  | 
| 1499   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(5u * sizeof(int32_t))); |  | 
| 1500 |  | 
| 1501   // Try reading an amount which isn't a multiple of the element size |  | 
| 1502   // (two-phase). |  | 
| 1503   num_bytes = 1u; |  | 
| 1504   read_ptr = nullptr; |  | 
| 1505   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |  | 
| 1506             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 1507                                       MakeUserPointer(&num_bytes), true)); |  | 
| 1508 |  | 
| 1509   // Read one (two-phase). |  | 
| 1510   num_bytes = 1u * sizeof(int32_t); |  | 
| 1511   read_ptr = nullptr; |  | 
| 1512   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1513             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 1514                                       MakeUserPointer(&num_bytes), true)); |  | 
| 1515   EXPECT_GE(num_bytes, 1u * sizeof(int32_t)); |  | 
| 1516   EXPECT_EQ(0, static_cast<const int32_t*>(read_ptr)[0]); |  | 
| 1517   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(1u * sizeof(int32_t))); |  | 
| 1518 |  | 
| 1519   // We should have four left, leaving room for six. |  | 
| 1520   num_bytes = 0u; |  | 
| 1521   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1522   EXPECT_EQ(4u * sizeof(int32_t), num_bytes); |  | 
| 1523 |  | 
| 1524   // Assuming a tight circular buffer of the specified capacity, we can't do a |  | 
| 1525   // two-phase write of six now. |  | 
| 1526   num_bytes = 6u * sizeof(int32_t); |  | 
| 1527   write_ptr = nullptr; |  | 
| 1528   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1529             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1530                                        MakeUserPointer(&num_bytes), true)); |  | 
| 1531 |  | 
| 1532   // Write six elements (simple), filling the buffer. |  | 
| 1533   num_bytes = 6u * sizeof(int32_t); |  | 
| 1534   int32_t buffer[100]; |  | 
| 1535   Seq(100, 6, buffer); |  | 
| 1536   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1537             dp->ProducerWriteData(UserPointer<const void>(buffer), |  | 
| 1538                                   MakeUserPointer(&num_bytes), true)); |  | 
| 1539   EXPECT_EQ(6u * sizeof(int32_t), num_bytes); |  | 
| 1540 |  | 
| 1541   // We have ten. |  | 
| 1542   num_bytes = 0u; |  | 
| 1543   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1544   EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |  | 
| 1545 |  | 
| 1546   // But a two-phase read of ten should fail. |  | 
| 1547   num_bytes = 10u * sizeof(int32_t); |  | 
| 1548   read_ptr = nullptr; |  | 
| 1549   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |  | 
| 1550             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 1551                                       MakeUserPointer(&num_bytes), true)); |  | 
| 1552 |  | 
| 1553   // Close the producer. |  | 
| 1554   dp->ProducerClose(); |  | 
| 1555 |  | 
| 1556   // A two-phase read of nine should work. |  | 
| 1557   num_bytes = 9u * sizeof(int32_t); |  | 
| 1558   read_ptr = nullptr; |  | 
| 1559   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1560             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 1561                                       MakeUserPointer(&num_bytes), true)); |  | 
| 1562   EXPECT_GE(num_bytes, 9u * sizeof(int32_t)); |  | 
| 1563   EXPECT_EQ(1, static_cast<const int32_t*>(read_ptr)[0]); |  | 
| 1564   EXPECT_EQ(2, static_cast<const int32_t*>(read_ptr)[1]); |  | 
| 1565   EXPECT_EQ(3, static_cast<const int32_t*>(read_ptr)[2]); |  | 
| 1566   EXPECT_EQ(4, static_cast<const int32_t*>(read_ptr)[3]); |  | 
| 1567   EXPECT_EQ(100, static_cast<const int32_t*>(read_ptr)[4]); |  | 
| 1568   EXPECT_EQ(101, static_cast<const int32_t*>(read_ptr)[5]); |  | 
| 1569   EXPECT_EQ(102, static_cast<const int32_t*>(read_ptr)[6]); |  | 
| 1570   EXPECT_EQ(103, static_cast<const int32_t*>(read_ptr)[7]); |  | 
| 1571   EXPECT_EQ(104, static_cast<const int32_t*>(read_ptr)[8]); |  | 
| 1572   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(9u * sizeof(int32_t))); |  | 
| 1573 |  | 
| 1574   // A two-phase read of two should fail, with "failed precondition". |  | 
| 1575   num_bytes = 2u * sizeof(int32_t); |  | 
| 1576   read_ptr = nullptr; |  | 
| 1577   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1578             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 1579                                       MakeUserPointer(&num_bytes), true)); |  | 
| 1580 |  | 
| 1581   dp->ConsumerClose(); |  | 
| 1582 } |  | 
| 1583 |  | 
| 1584 // Tests that |ProducerWriteData()| and |ConsumerReadData()| writes and reads, |  | 
| 1585 // respectively, as much as possible, even if it has to "wrap around" the |  | 
| 1586 // internal circular buffer. (Note that the two-phase write and read do not do |  | 
| 1587 // this.) |  | 
| 1588 TEST(LocalDataPipeTest, WrapAround) { |  | 
| 1589   unsigned char test_data[1000]; |  | 
| 1590   for (size_t i = 0; i < arraysize(test_data); i++) |  | 
| 1591     test_data[i] = static_cast<unsigned char>(i); |  | 
| 1592 |  | 
| 1593   const MojoCreateDataPipeOptions options = { |  | 
| 1594       kSizeOfOptions,                           // |struct_size|. |  | 
| 1595       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 1596       1u,                                       // |element_num_bytes|. |  | 
| 1597       100u                                      // |capacity_num_bytes|. |  | 
| 1598   }; |  | 
| 1599   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 1600   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 1601                                 MakeUserPointer(&options), &validated_options)); |  | 
| 1602   // This test won't be valid if |ValidateCreateOptions()| decides to give the |  | 
| 1603   // pipe more space. |  | 
| 1604   ASSERT_EQ(100u, validated_options.capacity_num_bytes); |  | 
| 1605 |  | 
| 1606   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1607 |  | 
| 1608   // Write 20 bytes. |  | 
| 1609   uint32_t num_bytes = 20u; |  | 
| 1610   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1611             dp->ProducerWriteData(UserPointer<const void>(&test_data[0]), |  | 
| 1612                                   MakeUserPointer(&num_bytes), false)); |  | 
| 1613   EXPECT_EQ(20u, num_bytes); |  | 
| 1614 |  | 
| 1615   // Read 10 bytes. |  | 
| 1616   unsigned char read_buffer[1000] = {0}; |  | 
| 1617   num_bytes = 10u; |  | 
| 1618   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1619             dp->ConsumerReadData(UserPointer<void>(read_buffer), |  | 
| 1620                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 1621   EXPECT_EQ(10u, num_bytes); |  | 
| 1622   EXPECT_EQ(0, memcmp(read_buffer, &test_data[0], 10u)); |  | 
| 1623 |  | 
| 1624   // Check that a two-phase write can now only write (at most) 80 bytes. (This |  | 
| 1625   // checks an implementation detail; this behavior is not guaranteed, but we |  | 
| 1626   // need it for this test.) |  | 
| 1627   void* write_buffer_ptr = nullptr; |  | 
| 1628   num_bytes = 0u; |  | 
| 1629   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1630             dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), |  | 
| 1631                                        MakeUserPointer(&num_bytes), false)); |  | 
| 1632   EXPECT_TRUE(write_buffer_ptr); |  | 
| 1633   EXPECT_EQ(80u, num_bytes); |  | 
| 1634   EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(0u)); |  | 
| 1635 |  | 
| 1636   // Write as much data as we can (using |ProducerWriteData()|). We should write |  | 
| 1637   // 90 bytes. |  | 
| 1638   num_bytes = 200u; |  | 
| 1639   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1640             dp->ProducerWriteData(UserPointer<const void>(&test_data[20]), |  | 
| 1641                                   MakeUserPointer(&num_bytes), false)); |  | 
| 1642   EXPECT_EQ(90u, num_bytes); |  | 
| 1643 |  | 
| 1644   // Check that a two-phase read can now only read (at most) 90 bytes. (This |  | 
| 1645   // checks an implementation detail; this behavior is not guaranteed, but we |  | 
| 1646   // need it for this test.) |  | 
| 1647   const void* read_buffer_ptr = nullptr; |  | 
| 1648   num_bytes = 0u; |  | 
| 1649   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1650             dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), |  | 
| 1651                                       MakeUserPointer(&num_bytes), false)); |  | 
| 1652   EXPECT_TRUE(read_buffer_ptr); |  | 
| 1653   EXPECT_EQ(90u, num_bytes); |  | 
| 1654   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(0u)); |  | 
| 1655 |  | 
| 1656   // Read as much as possible (using |ConsumerReadData()|). We should read 100 |  | 
| 1657   // bytes. |  | 
| 1658   num_bytes = |  | 
| 1659       static_cast<uint32_t>(arraysize(read_buffer) * sizeof(read_buffer[0])); |  | 
| 1660   memset(read_buffer, 0, num_bytes); |  | 
| 1661   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1662             dp->ConsumerReadData(UserPointer<void>(read_buffer), |  | 
| 1663                                  MakeUserPointer(&num_bytes), false, false)); |  | 
| 1664   EXPECT_EQ(100u, num_bytes); |  | 
| 1665   EXPECT_EQ(0, memcmp(read_buffer, &test_data[10], 100u)); |  | 
| 1666 |  | 
| 1667   dp->ProducerClose(); |  | 
| 1668   dp->ConsumerClose(); |  | 
| 1669 } |  | 
| 1670 |  | 
| 1671 // Tests the behavior of closing the producer or consumer with respect to |  | 
| 1672 // writes and reads (simple and two-phase). |  | 
| 1673 TEST(LocalDataPipeTest, CloseWriteRead) { |  | 
| 1674   const char kTestData[] = "hello world"; |  | 
| 1675   const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData)); |  | 
| 1676 |  | 
| 1677   const MojoCreateDataPipeOptions options = { |  | 
| 1678       kSizeOfOptions,                           // |struct_size|. |  | 
| 1679       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 1680       1u,                                       // |element_num_bytes|. |  | 
| 1681       1000u                                     // |capacity_num_bytes|. |  | 
| 1682   }; |  | 
| 1683   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 1684   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 1685                                 MakeUserPointer(&options), &validated_options)); |  | 
| 1686 |  | 
| 1687   // Close producer first, then consumer. |  | 
| 1688   { |  | 
| 1689     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1690 |  | 
| 1691     // Write some data, so we'll have something to read. |  | 
| 1692     uint32_t num_bytes = kTestDataSize; |  | 
| 1693     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1694               dp->ProducerWriteData(UserPointer<const void>(kTestData), |  | 
| 1695                                     MakeUserPointer(&num_bytes), false)); |  | 
| 1696     EXPECT_EQ(kTestDataSize, num_bytes); |  | 
| 1697 |  | 
| 1698     // Write it again, so we'll have something left over. |  | 
| 1699     num_bytes = kTestDataSize; |  | 
| 1700     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1701               dp->ProducerWriteData(UserPointer<const void>(kTestData), |  | 
| 1702                                     MakeUserPointer(&num_bytes), false)); |  | 
| 1703     EXPECT_EQ(kTestDataSize, num_bytes); |  | 
| 1704 |  | 
| 1705     // Start two-phase write. |  | 
| 1706     void* write_buffer_ptr = nullptr; |  | 
| 1707     num_bytes = 0u; |  | 
| 1708     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1709               dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), |  | 
| 1710                                          MakeUserPointer(&num_bytes), false)); |  | 
| 1711     EXPECT_TRUE(write_buffer_ptr); |  | 
| 1712     EXPECT_GT(num_bytes, 0u); |  | 
| 1713 |  | 
| 1714     // Start two-phase read. |  | 
| 1715     const void* read_buffer_ptr = nullptr; |  | 
| 1716     num_bytes = 0u; |  | 
| 1717     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1718               dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), |  | 
| 1719                                         MakeUserPointer(&num_bytes), false)); |  | 
| 1720     EXPECT_TRUE(read_buffer_ptr); |  | 
| 1721     EXPECT_EQ(2u * kTestDataSize, num_bytes); |  | 
| 1722 |  | 
| 1723     // Close the producer. |  | 
| 1724     dp->ProducerClose(); |  | 
| 1725 |  | 
| 1726     // The consumer can finish its two-phase read. |  | 
| 1727     EXPECT_EQ(0, memcmp(read_buffer_ptr, kTestData, kTestDataSize)); |  | 
| 1728     EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(kTestDataSize)); |  | 
| 1729 |  | 
| 1730     // And start another. |  | 
| 1731     read_buffer_ptr = nullptr; |  | 
| 1732     num_bytes = 0u; |  | 
| 1733     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1734               dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), |  | 
| 1735                                         MakeUserPointer(&num_bytes), false)); |  | 
| 1736     EXPECT_TRUE(read_buffer_ptr); |  | 
| 1737     EXPECT_EQ(kTestDataSize, num_bytes); |  | 
| 1738 |  | 
| 1739     // Close the consumer, which cancels the two-phase read. |  | 
| 1740     dp->ConsumerClose(); |  | 
| 1741   } |  | 
| 1742 |  | 
| 1743   // Close consumer first, then producer. |  | 
| 1744   { |  | 
| 1745     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1746 |  | 
| 1747     // Write some data, so we'll have something to read. |  | 
| 1748     uint32_t num_bytes = kTestDataSize; |  | 
| 1749     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1750               dp->ProducerWriteData(UserPointer<const void>(kTestData), |  | 
| 1751                                     MakeUserPointer(&num_bytes), false)); |  | 
| 1752     EXPECT_EQ(kTestDataSize, num_bytes); |  | 
| 1753 |  | 
| 1754     // Start two-phase write. |  | 
| 1755     void* write_buffer_ptr = nullptr; |  | 
| 1756     num_bytes = 0u; |  | 
| 1757     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1758               dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), |  | 
| 1759                                          MakeUserPointer(&num_bytes), false)); |  | 
| 1760     EXPECT_TRUE(write_buffer_ptr); |  | 
| 1761     ASSERT_GT(num_bytes, kTestDataSize); |  | 
| 1762 |  | 
| 1763     // Start two-phase read. |  | 
| 1764     const void* read_buffer_ptr = nullptr; |  | 
| 1765     num_bytes = 0u; |  | 
| 1766     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1767               dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), |  | 
| 1768                                         MakeUserPointer(&num_bytes), false)); |  | 
| 1769     EXPECT_TRUE(read_buffer_ptr); |  | 
| 1770     EXPECT_EQ(kTestDataSize, num_bytes); |  | 
| 1771 |  | 
| 1772     // Close the consumer. |  | 
| 1773     dp->ConsumerClose(); |  | 
| 1774 |  | 
| 1775     // Actually write some data. (Note: Premature freeing of the buffer would |  | 
| 1776     // probably only be detected under ASAN or similar.) |  | 
| 1777     memcpy(write_buffer_ptr, kTestData, kTestDataSize); |  | 
| 1778     // Note: Even though the consumer has been closed, ending the two-phase |  | 
| 1779     // write will report success. |  | 
| 1780     EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(kTestDataSize)); |  | 
| 1781 |  | 
| 1782     // But trying to write should result in failure. |  | 
| 1783     num_bytes = kTestDataSize; |  | 
| 1784     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1785               dp->ProducerWriteData(UserPointer<const void>(kTestData), |  | 
| 1786                                     MakeUserPointer(&num_bytes), false)); |  | 
| 1787 |  | 
| 1788     // As will trying to start another two-phase write. |  | 
| 1789     write_buffer_ptr = nullptr; |  | 
| 1790     num_bytes = 0u; |  | 
| 1791     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1792               dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), |  | 
| 1793                                          MakeUserPointer(&num_bytes), false)); |  | 
| 1794 |  | 
| 1795     dp->ProducerClose(); |  | 
| 1796   } |  | 
| 1797 |  | 
| 1798   // Test closing the consumer first, then the producer, with an active |  | 
| 1799   // two-phase write. |  | 
| 1800   { |  | 
| 1801     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1802 |  | 
| 1803     // Start two-phase write. |  | 
| 1804     void* write_buffer_ptr = nullptr; |  | 
| 1805     uint32_t num_bytes = 0u; |  | 
| 1806     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1807               dp->ProducerBeginWriteData(MakeUserPointer(&write_buffer_ptr), |  | 
| 1808                                          MakeUserPointer(&num_bytes), false)); |  | 
| 1809     EXPECT_TRUE(write_buffer_ptr); |  | 
| 1810     ASSERT_GT(num_bytes, kTestDataSize); |  | 
| 1811 |  | 
| 1812     dp->ConsumerClose(); |  | 
| 1813     dp->ProducerClose(); |  | 
| 1814   } |  | 
| 1815 |  | 
| 1816   // Test closing the producer and then trying to read (with no data). |  | 
| 1817   { |  | 
| 1818     scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1819 |  | 
| 1820     // Write some data, so we'll have something to read. |  | 
| 1821     uint32_t num_bytes = kTestDataSize; |  | 
| 1822     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1823               dp->ProducerWriteData(UserPointer<const void>(kTestData), |  | 
| 1824                                     MakeUserPointer(&num_bytes), false)); |  | 
| 1825     EXPECT_EQ(kTestDataSize, num_bytes); |  | 
| 1826 |  | 
| 1827     // Close the producer. |  | 
| 1828     dp->ProducerClose(); |  | 
| 1829 |  | 
| 1830     // Peek that data. |  | 
| 1831     char buffer[1000]; |  | 
| 1832     num_bytes = static_cast<uint32_t>(sizeof(buffer)); |  | 
| 1833     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1834               dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1835                                    MakeUserPointer(&num_bytes), false, true)); |  | 
| 1836     EXPECT_EQ(kTestDataSize, num_bytes); |  | 
| 1837     EXPECT_EQ(0, memcmp(buffer, kTestData, kTestDataSize)); |  | 
| 1838 |  | 
| 1839     // Read that data. |  | 
| 1840     memset(buffer, 0, 1000); |  | 
| 1841     num_bytes = static_cast<uint32_t>(sizeof(buffer)); |  | 
| 1842     EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1843               dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1844                                    MakeUserPointer(&num_bytes), false, false)); |  | 
| 1845     EXPECT_EQ(kTestDataSize, num_bytes); |  | 
| 1846     EXPECT_EQ(0, memcmp(buffer, kTestData, kTestDataSize)); |  | 
| 1847 |  | 
| 1848     // A second read should fail. |  | 
| 1849     num_bytes = static_cast<uint32_t>(sizeof(buffer)); |  | 
| 1850     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1851               dp->ConsumerReadData(UserPointer<void>(buffer), |  | 
| 1852                                    MakeUserPointer(&num_bytes), false, false)); |  | 
| 1853 |  | 
| 1854     // A two-phase read should also fail. |  | 
| 1855     const void* read_buffer_ptr = nullptr; |  | 
| 1856     num_bytes = 0u; |  | 
| 1857     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1858               dp->ConsumerBeginReadData(MakeUserPointer(&read_buffer_ptr), |  | 
| 1859                                         MakeUserPointer(&num_bytes), false)); |  | 
| 1860 |  | 
| 1861     // Ditto for discard. |  | 
| 1862     num_bytes = 10u; |  | 
| 1863     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1864               dp->ConsumerDiscardData(MakeUserPointer(&num_bytes), false)); |  | 
| 1865 |  | 
| 1866     dp->ConsumerClose(); |  | 
| 1867   } |  | 
| 1868 } |  | 
| 1869 |  | 
| 1870 TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) { |  | 
| 1871   const MojoCreateDataPipeOptions options = { |  | 
| 1872       kSizeOfOptions,                           // |struct_size|. |  | 
| 1873       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|. |  | 
| 1874       static_cast<uint32_t>(sizeof(int32_t)),   // |element_num_bytes|. |  | 
| 1875       10 * sizeof(int32_t)                      // |capacity_num_bytes|. |  | 
| 1876   }; |  | 
| 1877   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 1878   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 1879                                 MakeUserPointer(&options), &validated_options)); |  | 
| 1880 |  | 
| 1881   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 1882 |  | 
| 1883   // No data. |  | 
| 1884   uint32_t num_bytes = 1000u; |  | 
| 1885   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1886   EXPECT_EQ(0u, num_bytes); |  | 
| 1887 |  | 
| 1888   // Try "ending" a two-phase write when one isn't active. |  | 
| 1889   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1890             dp->ProducerEndWriteData(1u * sizeof(int32_t))); |  | 
| 1891 |  | 
| 1892   // Still no data. |  | 
| 1893   num_bytes = 1000u; |  | 
| 1894   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1895   EXPECT_EQ(0u, num_bytes); |  | 
| 1896 |  | 
| 1897   // Try ending a two-phase write with an invalid amount (too much). |  | 
| 1898   num_bytes = 0u; |  | 
| 1899   void* write_ptr = nullptr; |  | 
| 1900   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1901             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1902                                        MakeUserPointer(&num_bytes), false)); |  | 
| 1903   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |  | 
| 1904             dp->ProducerEndWriteData(num_bytes + |  | 
| 1905                                      static_cast<uint32_t>(sizeof(int32_t)))); |  | 
| 1906 |  | 
| 1907   // But the two-phase write still ended. |  | 
| 1908   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, dp->ProducerEndWriteData(0u)); |  | 
| 1909 |  | 
| 1910   // Still no data. |  | 
| 1911   num_bytes = 1000u; |  | 
| 1912   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1913   EXPECT_EQ(0u, num_bytes); |  | 
| 1914 |  | 
| 1915   // Try ending a two-phase write with an invalid amount (not a multiple of the |  | 
| 1916   // element size). |  | 
| 1917   num_bytes = 0u; |  | 
| 1918   write_ptr = nullptr; |  | 
| 1919   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1920             dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), |  | 
| 1921                                        MakeUserPointer(&num_bytes), false)); |  | 
| 1922   EXPECT_GE(num_bytes, 1u); |  | 
| 1923   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dp->ProducerEndWriteData(1u)); |  | 
| 1924 |  | 
| 1925   // But the two-phase write still ended. |  | 
| 1926   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, dp->ProducerEndWriteData(0u)); |  | 
| 1927 |  | 
| 1928   // Still no data. |  | 
| 1929   num_bytes = 1000u; |  | 
| 1930   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1931   EXPECT_EQ(0u, num_bytes); |  | 
| 1932 |  | 
| 1933   // Now write some data, so we'll be able to try reading. |  | 
| 1934   int32_t element = 123; |  | 
| 1935   num_bytes = 1u * sizeof(int32_t); |  | 
| 1936   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1937             dp->ProducerWriteData(UserPointer<const void>(&element), |  | 
| 1938                                   MakeUserPointer(&num_bytes), false)); |  | 
| 1939 |  | 
| 1940   // One element available. |  | 
| 1941   num_bytes = 0u; |  | 
| 1942   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1943   EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |  | 
| 1944 |  | 
| 1945   // Try "ending" a two-phase read when one isn't active. |  | 
| 1946   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |  | 
| 1947             dp->ConsumerEndReadData(1u * sizeof(int32_t))); |  | 
| 1948 |  | 
| 1949   // Still one element available. |  | 
| 1950   num_bytes = 0u; |  | 
| 1951   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1952   EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |  | 
| 1953 |  | 
| 1954   // Try ending a two-phase read with an invalid amount (too much). |  | 
| 1955   num_bytes = 0u; |  | 
| 1956   const void* read_ptr = nullptr; |  | 
| 1957   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1958             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 1959                                       MakeUserPointer(&num_bytes), false)); |  | 
| 1960   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |  | 
| 1961             dp->ConsumerEndReadData(num_bytes + |  | 
| 1962                                     static_cast<uint32_t>(sizeof(int32_t)))); |  | 
| 1963 |  | 
| 1964   // Still one element available. |  | 
| 1965   num_bytes = 0u; |  | 
| 1966   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1967   EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |  | 
| 1968 |  | 
| 1969   // Try ending a two-phase read with an invalid amount (not a multiple of the |  | 
| 1970   // element size). |  | 
| 1971   num_bytes = 0u; |  | 
| 1972   read_ptr = nullptr; |  | 
| 1973   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 1974             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 1975                                       MakeUserPointer(&num_bytes), false)); |  | 
| 1976   EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |  | 
| 1977   EXPECT_EQ(123, static_cast<const int32_t*>(read_ptr)[0]); |  | 
| 1978   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dp->ConsumerEndReadData(1u)); |  | 
| 1979 |  | 
| 1980   // Still one element available. |  | 
| 1981   num_bytes = 0u; |  | 
| 1982   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(MakeUserPointer(&num_bytes))); |  | 
| 1983   EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |  | 
| 1984 |  | 
| 1985   dp->ProducerClose(); |  | 
| 1986   dp->ConsumerClose(); |  | 
| 1987 } |  | 
| 1988 |  | 
| 1989 // Tests that even with "may discard", the data won't change under a two-phase |  | 
| 1990 // read. |  | 
| 1991 // TODO(vtl): crbug.com/348644: We currently don't pass this. (There are two |  | 
| 1992 // related issues: First, we don't recognize that the data given to |  | 
| 1993 // |ConsumerBeginReadData()| isn't discardable until |ConsumerEndReadData()|, |  | 
| 1994 // and thus we erroneously allow |ProducerWriteData()| to succeed. Second, the |  | 
| 1995 // |ProducerWriteData()| then changes the data underneath the two-phase read.) |  | 
| 1996 TEST(LocalDataPipeTest, DISABLED_MayDiscardTwoPhaseConsistent) { |  | 
| 1997   const MojoCreateDataPipeOptions options = { |  | 
| 1998       kSizeOfOptions,                                  // |struct_size|. |  | 
| 1999       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD,  // |flags|. |  | 
| 2000       1,                                               // |element_num_bytes|. |  | 
| 2001       2                                                // |capacity_num_bytes|. |  | 
| 2002   }; |  | 
| 2003   MojoCreateDataPipeOptions validated_options = {0}; |  | 
| 2004   EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions( |  | 
| 2005                                 MakeUserPointer(&options), &validated_options)); |  | 
| 2006 |  | 
| 2007   scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |  | 
| 2008 |  | 
| 2009   // Write some elements. |  | 
| 2010   char elements[2] = {'a', 'b'}; |  | 
| 2011   uint32_t num_bytes = 2u; |  | 
| 2012   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 2013             dp->ProducerWriteData(UserPointer<const void>(elements), |  | 
| 2014                                   MakeUserPointer(&num_bytes), false)); |  | 
| 2015   EXPECT_EQ(2u, num_bytes); |  | 
| 2016 |  | 
| 2017   // Begin reading. |  | 
| 2018   const void* read_ptr = nullptr; |  | 
| 2019   num_bytes = 2u; |  | 
| 2020   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 2021             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 2022                                       MakeUserPointer(&num_bytes), false)); |  | 
| 2023   EXPECT_EQ(2u, num_bytes); |  | 
| 2024   EXPECT_EQ('a', static_cast<const char*>(read_ptr)[0]); |  | 
| 2025   EXPECT_EQ('b', static_cast<const char*>(read_ptr)[1]); |  | 
| 2026 |  | 
| 2027   // Try to write some more. But nothing should be discardable right now. |  | 
| 2028   elements[0] = 'x'; |  | 
| 2029   elements[1] = 'y'; |  | 
| 2030   num_bytes = 2u; |  | 
| 2031   // TODO(vtl): This should be: |  | 
| 2032   //  EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |  | 
| 2033   //            dp->ProducerWriteData(elements, &num_bytes, false)); |  | 
| 2034   // but we incorrectly think that the bytes being read are discardable. Letting |  | 
| 2035   // this through reveals the significant consequence. |  | 
| 2036   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 2037             dp->ProducerWriteData(UserPointer<const void>(elements), |  | 
| 2038                                   MakeUserPointer(&num_bytes), false)); |  | 
| 2039 |  | 
| 2040   // Check that our read buffer hasn't changed underneath us. |  | 
| 2041   EXPECT_EQ('a', static_cast<const char*>(read_ptr)[0]); |  | 
| 2042   EXPECT_EQ('b', static_cast<const char*>(read_ptr)[1]); |  | 
| 2043 |  | 
| 2044   // End reading. |  | 
| 2045   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(2u)); |  | 
| 2046 |  | 
| 2047   // Now writing should succeed. |  | 
| 2048   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 2049             dp->ProducerWriteData(UserPointer<const void>(elements), |  | 
| 2050                                   MakeUserPointer(&num_bytes), false)); |  | 
| 2051 |  | 
| 2052   // And if we read, we should get the new values. |  | 
| 2053   read_ptr = nullptr; |  | 
| 2054   num_bytes = 2u; |  | 
| 2055   EXPECT_EQ(MOJO_RESULT_OK, |  | 
| 2056             dp->ConsumerBeginReadData(MakeUserPointer(&read_ptr), |  | 
| 2057                                       MakeUserPointer(&num_bytes), false)); |  | 
| 2058   EXPECT_EQ(2u, num_bytes); |  | 
| 2059   EXPECT_EQ('x', static_cast<const char*>(read_ptr)[0]); |  | 
| 2060   EXPECT_EQ('y', static_cast<const char*>(read_ptr)[1]); |  | 
| 2061 |  | 
| 2062   // End reading. |  | 
| 2063   EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(2u)); |  | 
| 2064 |  | 
| 2065   dp->ProducerClose(); |  | 
| 2066   dp->ConsumerClose(); |  | 
| 2067 } |  | 
| 2068 |  | 
| 2069 }  // namespace |  | 
| 2070 }  // namespace system |  | 
| 2071 }  // namespace mojo |  | 
| OLD | NEW | 
|---|