OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/system/local_data_pipe.h" | 5 #include "mojo/system/local_data_pipe.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 | 175 |
176 // Query. | 176 // Query. |
177 num_bytes = 0; | 177 num_bytes = 0; |
178 EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); | 178 EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); |
179 EXPECT_EQ(0u, num_bytes); | 179 EXPECT_EQ(0u, num_bytes); |
180 | 180 |
181 dp->ProducerClose(); | 181 dp->ProducerClose(); |
182 dp->ConsumerClose(); | 182 dp->ConsumerClose(); |
183 } | 183 } |
184 | 184 |
| 185 // Note: The "basic" waiting tests test that the "wait states" are correct in |
| 186 // various situations; they don't test that waiters are properly awoken on state |
| 187 // changes. (For that, we need to use multiple threads.) |
185 TEST(LocalDataPipeTest, BasicProducerWaiting) { | 188 TEST(LocalDataPipeTest, BasicProducerWaiting) { |
186 // Note: We take advantage of the fact that for |LocalDataPipe|, capacities | 189 // Note: We take advantage of the fact that for |LocalDataPipe|, capacities |
187 // are strict maximums. This is not guaranteed by the API. | 190 // are strict maximums. This is not guaranteed by the API. |
188 | 191 |
189 const MojoCreateDataPipeOptions options = { | 192 const MojoCreateDataPipeOptions options = { |
190 kSizeOfOptions, // |struct_size|. | 193 kSizeOfOptions, // |struct_size|. |
191 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. | 194 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
192 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. | 195 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
193 2 * sizeof(int32_t) // |capacity_num_bytes|. | 196 2 * sizeof(int32_t) // |capacity_num_bytes|. |
194 }; | 197 }; |
195 MojoCreateDataPipeOptions validated_options = { 0 }; | 198 MojoCreateDataPipeOptions validated_options = { 0 }; |
196 EXPECT_EQ(MOJO_RESULT_OK, | 199 EXPECT_EQ(MOJO_RESULT_OK, |
197 DataPipe::ValidateOptions(&options, &validated_options)); | 200 DataPipe::ValidateOptions(&options, &validated_options)); |
198 | 201 |
199 { | 202 scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |
200 scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); | 203 Waiter waiter; |
201 Waiter waiter; | |
202 | 204 |
203 // Never readable. | 205 // Never readable. |
204 waiter.Init(); | 206 waiter.Init(); |
205 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 207 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
206 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 12)); | 208 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 12)); |
207 | 209 |
208 // Already writable. | 210 // Already writable. |
209 waiter.Init(); | 211 waiter.Init(); |
210 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, | 212 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
211 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 34)); | 213 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 34)); |
212 | 214 |
213 // Write two elements. | 215 // Write two elements. |
214 int32_t elements[2] = { 123, 456 }; | 216 int32_t elements[2] = { 123, 456 }; |
215 uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); | 217 uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0])); |
216 EXPECT_EQ(MOJO_RESULT_OK, | 218 EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(elements, &num_bytes, true)); |
217 dp->ProducerWriteData(elements, &num_bytes, true)); | 219 EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes); |
218 EXPECT_EQ(static_cast<uint32_t>(2u * sizeof(elements[0])), num_bytes); | |
219 | 220 |
220 // Adding a waiter should now succeed. | 221 // Adding a waiter should now succeed. |
221 waiter.Init(); | 222 waiter.Init(); |
222 EXPECT_EQ(MOJO_RESULT_OK, | 223 EXPECT_EQ(MOJO_RESULT_OK, |
223 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 56)); | 224 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 56)); |
224 // And it shouldn't be writable yet. | 225 // And it shouldn't be writable yet. |
225 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0)); | 226 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0)); |
226 dp->ProducerRemoveWaiter(&waiter); | 227 dp->ProducerRemoveWaiter(&waiter); |
227 | 228 |
228 // Do it again. | 229 // Do it again. |
229 waiter.Init(); | 230 waiter.Init(); |
230 EXPECT_EQ(MOJO_RESULT_OK, | 231 EXPECT_EQ(MOJO_RESULT_OK, |
231 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 78)); | 232 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 78)); |
232 | 233 |
233 // Read one element. | 234 // Read one element. |
234 elements[0] = -1; | 235 elements[0] = -1; |
235 elements[1] = -1; | 236 elements[1] = -1; |
236 num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); | 237 num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |
237 EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(elements, &num_bytes, true)); | 238 EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(elements, &num_bytes, true)); |
238 EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); | 239 EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |
239 EXPECT_EQ(123, elements[0]); | 240 EXPECT_EQ(123, elements[0]); |
240 EXPECT_EQ(-1, elements[1]); | 241 EXPECT_EQ(-1, elements[1]); |
241 | 242 |
242 // Waiting should now succeed. | 243 // Waiting should now succeed. |
243 EXPECT_EQ(78, waiter.Wait(1000)); | 244 EXPECT_EQ(78, waiter.Wait(1000)); |
244 dp->ProducerRemoveWaiter(&waiter); | 245 dp->ProducerRemoveWaiter(&waiter); |
245 | 246 |
246 // Try writing, using a two-phase write. | 247 // Try writing, using a two-phase write. |
247 void* buffer = NULL; | 248 void* buffer = NULL; |
248 num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0])); | 249 num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0])); |
249 EXPECT_EQ(MOJO_RESULT_OK, | 250 EXPECT_EQ(MOJO_RESULT_OK, |
250 dp->ProducerBeginWriteData(&buffer, &num_bytes, false)); | 251 dp->ProducerBeginWriteData(&buffer, &num_bytes, false)); |
251 EXPECT_TRUE(buffer != NULL); | 252 EXPECT_TRUE(buffer != NULL); |
252 EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); | 253 EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |
253 static_cast<int32_t*>(buffer)[0] = 789; | |
254 EXPECT_EQ(MOJO_RESULT_OK, | |
255 dp->ProducerEndWriteData( | |
256 static_cast<uint32_t>(1u * sizeof(elements[0])))); | |
257 | 254 |
258 // Add a waiter. | 255 static_cast<int32_t*>(buffer)[0] = 789; |
259 waiter.Init(); | 256 EXPECT_EQ(MOJO_RESULT_OK, |
260 EXPECT_EQ(MOJO_RESULT_OK, | 257 dp->ProducerEndWriteData( |
261 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 90)); | 258 static_cast<uint32_t>(1u * sizeof(elements[0])))); |
262 | 259 |
263 // Read one element, using a two-phase read. | 260 // Add a waiter. |
264 const void* read_buffer = NULL; | 261 waiter.Init(); |
265 num_bytes = 0u; | 262 EXPECT_EQ(MOJO_RESULT_OK, |
266 EXPECT_EQ(MOJO_RESULT_OK, | 263 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 90)); |
267 dp->ConsumerBeginReadData(&read_buffer, &num_bytes, false)); | |
268 EXPECT_TRUE(read_buffer != NULL); | |
269 // Since we only read one element (after having written three in all), the | |
270 // two-phase read should only allow us to read one. This checks an | |
271 // implementation detail! | |
272 EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); | |
273 EXPECT_EQ(456, static_cast<const int32_t*>(read_buffer)[0]); | |
274 EXPECT_EQ(MOJO_RESULT_OK, | |
275 dp->ConsumerEndReadData( | |
276 static_cast<uint32_t>(1u * sizeof(elements[0])))); | |
277 | 264 |
278 // Waiting should succeed. | 265 // Read one element, using a two-phase read. |
279 EXPECT_EQ(90, waiter.Wait(1000)); | 266 const void* read_buffer = NULL; |
280 dp->ProducerRemoveWaiter(&waiter); | 267 num_bytes = 0u; |
| 268 EXPECT_EQ(MOJO_RESULT_OK, |
| 269 dp->ConsumerBeginReadData(&read_buffer, &num_bytes, false)); |
| 270 EXPECT_TRUE(read_buffer != NULL); |
| 271 // Since we only read one element (after having written three in all), the |
| 272 // two-phase read should only allow us to read one. This checks an |
| 273 // implementation detail! |
| 274 EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |
| 275 EXPECT_EQ(456, static_cast<const int32_t*>(read_buffer)[0]); |
| 276 EXPECT_EQ(MOJO_RESULT_OK, |
| 277 dp->ConsumerEndReadData( |
| 278 static_cast<uint32_t>(1u * sizeof(elements[0])))); |
281 | 279 |
282 // Write one element. | 280 // Waiting should succeed. |
283 elements[0] = 123; | 281 EXPECT_EQ(90, waiter.Wait(1000)); |
284 num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); | 282 dp->ProducerRemoveWaiter(&waiter); |
285 EXPECT_EQ(MOJO_RESULT_OK, | |
286 dp->ProducerWriteData(elements, &num_bytes, false)); | |
287 EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); | |
288 | 283 |
289 // Add a waiter. | 284 // Write one element. |
290 waiter.Init(); | 285 elements[0] = 123; |
291 EXPECT_EQ(MOJO_RESULT_OK, | 286 num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0])); |
292 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 12)); | 287 EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(elements, &num_bytes, false)); |
| 288 EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes); |
293 | 289 |
294 // Close the consumer. | 290 // Add a waiter. |
295 dp->ConsumerClose(); | 291 waiter.Init(); |
| 292 EXPECT_EQ(MOJO_RESULT_OK, |
| 293 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 12)); |
296 | 294 |
297 // It should now be never-writable. | 295 // Close the consumer. |
298 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000)); | 296 dp->ConsumerClose(); |
299 dp->ProducerRemoveWaiter(&waiter); | |
300 | 297 |
301 dp->ProducerClose(); | 298 // It should now be never-writable. |
302 } | 299 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000)); |
| 300 dp->ProducerRemoveWaiter(&waiter); |
| 301 |
| 302 dp->ProducerClose(); |
303 } | 303 } |
304 | 304 |
305 TEST(LocalDataPipeTest, BasicConsumerWaiting) { | 305 TEST(LocalDataPipeTest, BasicConsumerWaiting) { |
306 const MojoCreateDataPipeOptions options = { | 306 const MojoCreateDataPipeOptions options = { |
307 kSizeOfOptions, // |struct_size|. | 307 kSizeOfOptions, // |struct_size|. |
308 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. | 308 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
309 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. | 309 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
310 1000 * sizeof(int32_t) // |capacity_num_bytes|. | 310 1000 * sizeof(int32_t) // |capacity_num_bytes|. |
311 }; | 311 }; |
312 MojoCreateDataPipeOptions validated_options = { 0 }; | 312 MojoCreateDataPipeOptions validated_options = { 0 }; |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 dp->ProducerClose(); | 469 dp->ProducerClose(); |
470 | 470 |
471 // Should be never-readable. | 471 // Should be never-readable. |
472 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000)); | 472 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000)); |
473 dp->ConsumerRemoveWaiter(&waiter); | 473 dp->ConsumerRemoveWaiter(&waiter); |
474 | 474 |
475 dp->ConsumerClose(); | 475 dp->ConsumerClose(); |
476 } | 476 } |
477 } | 477 } |
478 | 478 |
| 479 // Tests that data pipes aren't writable/readable during two-phase writes/reads. |
| 480 TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) { |
| 481 const MojoCreateDataPipeOptions options = { |
| 482 kSizeOfOptions, // |struct_size|. |
| 483 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| 484 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
| 485 1000 * sizeof(int32_t) // |capacity_num_bytes|. |
| 486 }; |
| 487 MojoCreateDataPipeOptions validated_options = { 0 }; |
| 488 EXPECT_EQ(MOJO_RESULT_OK, |
| 489 DataPipe::ValidateOptions(&options, &validated_options)); |
| 490 |
| 491 scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |
| 492 Waiter waiter; |
| 493 |
| 494 // It should be writable. |
| 495 waiter.Init(); |
| 496 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 497 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 0)); |
| 498 |
| 499 uint32_t num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t)); |
| 500 void* write_ptr = NULL; |
| 501 EXPECT_EQ(MOJO_RESULT_OK, |
| 502 dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false)); |
| 503 EXPECT_TRUE(write_ptr != NULL); |
| 504 EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t))); |
| 505 |
| 506 // At this point, it shouldn't be writable. |
| 507 waiter.Init(); |
| 508 EXPECT_EQ(MOJO_RESULT_OK, |
| 509 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 1)); |
| 510 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0)); |
| 511 dp->ProducerRemoveWaiter(&waiter); |
| 512 |
| 513 // It shouldn't be readable yet either. |
| 514 waiter.Init(); |
| 515 EXPECT_EQ(MOJO_RESULT_OK, |
| 516 dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 2)); |
| 517 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0)); |
| 518 dp->ConsumerRemoveWaiter(&waiter); |
| 519 |
| 520 static_cast<int32_t*>(write_ptr)[0] = 123; |
| 521 EXPECT_EQ(MOJO_RESULT_OK, |
| 522 dp->ProducerEndWriteData( |
| 523 static_cast<uint32_t>(1u * sizeof(int32_t)))); |
| 524 |
| 525 // It should be writable again. |
| 526 waiter.Init(); |
| 527 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 528 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 3)); |
| 529 |
| 530 // And readable. |
| 531 waiter.Init(); |
| 532 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 533 dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 4)); |
| 534 |
| 535 // Start another two-phase write and check that it's readable even in the |
| 536 // middle of it. |
| 537 num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t)); |
| 538 write_ptr = NULL; |
| 539 EXPECT_EQ(MOJO_RESULT_OK, |
| 540 dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false)); |
| 541 EXPECT_TRUE(write_ptr != NULL); |
| 542 EXPECT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(int32_t))); |
| 543 |
| 544 // It should be readable. |
| 545 waiter.Init(); |
| 546 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 547 dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 5)); |
| 548 |
| 549 // End the two-phase write without writing anything. |
| 550 EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(0u)); |
| 551 |
| 552 // Start a two-phase read. |
| 553 num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t)); |
| 554 const void* read_ptr = NULL; |
| 555 EXPECT_EQ(MOJO_RESULT_OK, |
| 556 dp->ConsumerBeginReadData(&read_ptr, &num_bytes, false)); |
| 557 EXPECT_TRUE(read_ptr != NULL); |
| 558 EXPECT_EQ(static_cast<uint32_t>(1u * sizeof(int32_t)), num_bytes); |
| 559 |
| 560 // At this point, it should still be writable. |
| 561 waiter.Init(); |
| 562 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 563 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 6)); |
| 564 |
| 565 // But not readable. |
| 566 waiter.Init(); |
| 567 EXPECT_EQ(MOJO_RESULT_OK, |
| 568 dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 7)); |
| 569 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0)); |
| 570 dp->ConsumerRemoveWaiter(&waiter); |
| 571 |
| 572 // End the two-phase read without reading anything. |
| 573 EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(0u)); |
| 574 |
| 575 // It should be readable again. |
| 576 waiter.Init(); |
| 577 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 578 dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 8)); |
| 579 |
| 580 dp->ProducerClose(); |
| 581 dp->ConsumerClose(); |
| 582 } |
| 583 |
| 584 // Test that a "may discard" data pipe is writable even when it's full. |
| 585 TEST(LocalDataPipeTest, BasicMayDiscardWaiting) { |
| 586 const MojoCreateDataPipeOptions options = { |
| 587 kSizeOfOptions, // |struct_size|. |
| 588 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|. |
| 589 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
| 590 1 * sizeof(int32_t) // |capacity_num_bytes|. |
| 591 }; |
| 592 MojoCreateDataPipeOptions validated_options = { 0 }; |
| 593 EXPECT_EQ(MOJO_RESULT_OK, |
| 594 DataPipe::ValidateOptions(&options, &validated_options)); |
| 595 |
| 596 scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |
| 597 Waiter waiter; |
| 598 |
| 599 // Writable. |
| 600 waiter.Init(); |
| 601 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 602 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 0)); |
| 603 |
| 604 // Not readable. |
| 605 waiter.Init(); |
| 606 EXPECT_EQ(MOJO_RESULT_OK, |
| 607 dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 1)); |
| 608 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0)); |
| 609 dp->ConsumerRemoveWaiter(&waiter); |
| 610 |
| 611 uint32_t num_bytes = static_cast<uint32_t>(sizeof(int32_t)); |
| 612 int32_t element = 123; |
| 613 EXPECT_EQ(MOJO_RESULT_OK, |
| 614 dp->ProducerWriteData(&element, &num_bytes, false)); |
| 615 EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes); |
| 616 |
| 617 // Still writable (even though it's full. |
| 618 waiter.Init(); |
| 619 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 620 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 2)); |
| 621 |
| 622 // Now readable. |
| 623 waiter.Init(); |
| 624 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 625 dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 3)); |
| 626 |
| 627 // Overwrite that element. |
| 628 num_bytes = static_cast<uint32_t>(sizeof(int32_t)); |
| 629 element = 456; |
| 630 EXPECT_EQ(MOJO_RESULT_OK, |
| 631 dp->ProducerWriteData(&element, &num_bytes, false)); |
| 632 EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes); |
| 633 |
| 634 // Still writable. |
| 635 waiter.Init(); |
| 636 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 637 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 4)); |
| 638 |
| 639 // And still readable. |
| 640 waiter.Init(); |
| 641 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 642 dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 5)); |
| 643 |
| 644 // Read that element. |
| 645 num_bytes = static_cast<uint32_t>(sizeof(int32_t)); |
| 646 element = 0; |
| 647 EXPECT_EQ(MOJO_RESULT_OK, |
| 648 dp->ConsumerReadData(&element, &num_bytes, false)); |
| 649 EXPECT_EQ(static_cast<uint32_t>(sizeof(int32_t)), num_bytes); |
| 650 EXPECT_EQ(456, element); |
| 651 |
| 652 // Still writable. |
| 653 waiter.Init(); |
| 654 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 655 dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 6)); |
| 656 |
| 657 // No longer readable. |
| 658 waiter.Init(); |
| 659 EXPECT_EQ(MOJO_RESULT_OK, |
| 660 dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 7)); |
| 661 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0)); |
| 662 dp->ConsumerRemoveWaiter(&waiter); |
| 663 |
| 664 dp->ProducerClose(); |
| 665 dp->ConsumerClose(); |
| 666 } |
| 667 |
479 void Seq(int32_t start, size_t count, int32_t* out) { | 668 void Seq(int32_t start, size_t count, int32_t* out) { |
480 for (size_t i = 0; i < count; i++) | 669 for (size_t i = 0; i < count; i++) |
481 out[i] = start + static_cast<int32_t>(i); | 670 out[i] = start + static_cast<int32_t>(i); |
482 } | 671 } |
483 | 672 |
484 TEST(LocalDataPipeTest, MayDiscard) { | 673 TEST(LocalDataPipeTest, MayDiscard) { |
485 const MojoCreateDataPipeOptions options = { | 674 const MojoCreateDataPipeOptions options = { |
486 kSizeOfOptions, // |struct_size|. | 675 kSizeOfOptions, // |struct_size|. |
487 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|. | 676 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|. |
488 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. | 677 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 expected_buffer[2] = 106; | 755 expected_buffer[2] = 106; |
567 expected_buffer[3] = 107; | 756 expected_buffer[3] = 107; |
568 expected_buffer[4] = 200; | 757 expected_buffer[4] = 200; |
569 expected_buffer[5] = 300; | 758 expected_buffer[5] = 300; |
570 expected_buffer[6] = 301; | 759 expected_buffer[6] = 301; |
571 expected_buffer[7] = 302; | 760 expected_buffer[7] = 302; |
572 expected_buffer[8] = 303; | 761 expected_buffer[8] = 303; |
573 expected_buffer[9] = 304; | 762 expected_buffer[9] = 304; |
574 EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); | 763 EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
575 | 764 |
576 // TODO(vtl): Test two-phase write when it supports "may discard". | 765 // Test two-phase writes, including in all-or-none mode. |
| 766 // Note: Again, the following depends on an implementation detail -- namely |
| 767 // that the write pointer will point at the 5th element of the buffer (and the |
| 768 // buffer has exactly the capacity requested). |
| 769 |
| 770 num_bytes = 0u; |
| 771 void* write_ptr = NULL; |
| 772 EXPECT_EQ(MOJO_RESULT_OK, |
| 773 dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false)); |
| 774 EXPECT_TRUE(write_ptr != NULL); |
| 775 EXPECT_EQ(6u * sizeof(int32_t), num_bytes); |
| 776 Seq(400, 6, static_cast<int32_t*>(write_ptr)); |
| 777 EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(6u * sizeof(int32_t))); |
| 778 // Internally, a circular buffer would now look like: |
| 779 // -, -, -, -, 400, 401, 402, 403, 404, 405 |
| 780 |
| 781 // |ProducerBeginWriteData()| ignores |*num_bytes| except in "all-or-none" |
| 782 // mode. |
| 783 num_bytes = 6u * sizeof(int32_t); |
| 784 write_ptr = NULL; |
| 785 EXPECT_EQ(MOJO_RESULT_OK, |
| 786 dp->ProducerBeginWriteData(&write_ptr, &num_bytes, false)); |
| 787 EXPECT_EQ(4u * sizeof(int32_t), num_bytes); |
| 788 static_cast<int32_t*>(write_ptr)[0] = 500; |
| 789 EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(1u * sizeof(int32_t))); |
| 790 // Internally, a circular buffer would now look like: |
| 791 // 500, -, -, -, 400, 401, 402, 403, 404, 405 |
| 792 |
| 793 // Requesting a 10-element buffer in all-or-none mode fails at this point. |
| 794 num_bytes = 10u * sizeof(int32_t); |
| 795 write_ptr = NULL; |
| 796 EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| 797 dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true)); |
| 798 |
| 799 // But requesting, say, a 5-element (up to 9, really) buffer should be okay. |
| 800 // It will discard two elements. |
| 801 num_bytes = 5u * sizeof(int32_t); |
| 802 write_ptr = NULL; |
| 803 EXPECT_EQ(MOJO_RESULT_OK, |
| 804 dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true)); |
| 805 EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |
| 806 // Only write 4 elements though. |
| 807 Seq(600, 4, static_cast<int32_t*>(write_ptr)); |
| 808 EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(4u * sizeof(int32_t))); |
| 809 // Internally, a circular buffer would now look like: |
| 810 // 500, 600, 601, 602, 603, -, 402, 403, 404, 405 |
| 811 |
| 812 // Do this again. Make sure we can get a buffer all the way out to the end of |
| 813 // the internal buffer. |
| 814 num_bytes = 5u * sizeof(int32_t); |
| 815 write_ptr = NULL; |
| 816 EXPECT_EQ(MOJO_RESULT_OK, |
| 817 dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true)); |
| 818 EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |
| 819 // Only write 3 elements though. |
| 820 Seq(700, 3, static_cast<int32_t*>(write_ptr)); |
| 821 EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(3u * sizeof(int32_t))); |
| 822 // Internally, a circular buffer would now look like: |
| 823 // 500, 600, 601, 602, 603, 700, 701, 702, -, - |
| 824 |
| 825 // Read everything. |
| 826 num_bytes = sizeof(buffer); |
| 827 memset(buffer, 0xab, sizeof(buffer)); |
| 828 EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, false)); |
| 829 EXPECT_EQ(8u * sizeof(int32_t), num_bytes); |
| 830 memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
| 831 expected_buffer[0] = 500; |
| 832 expected_buffer[1] = 600; |
| 833 expected_buffer[2] = 601; |
| 834 expected_buffer[3] = 602; |
| 835 expected_buffer[4] = 603; |
| 836 expected_buffer[5] = 700; |
| 837 expected_buffer[6] = 701; |
| 838 expected_buffer[7] = 702; |
| 839 EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
577 | 840 |
578 dp->ProducerClose(); | 841 dp->ProducerClose(); |
579 dp->ConsumerClose(); | 842 dp->ConsumerClose(); |
580 } | 843 } |
581 | 844 |
582 TEST(LocalDataPipeTest, AllOrNone) { | 845 TEST(LocalDataPipeTest, AllOrNone) { |
583 const MojoCreateDataPipeOptions options = { | 846 const MojoCreateDataPipeOptions options = { |
584 kSizeOfOptions, // |struct_size|. | 847 kSizeOfOptions, // |struct_size|. |
585 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. | 848 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
586 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. | 849 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 | 1057 |
795 // Read everything. | 1058 // Read everything. |
796 num_bytes = 10u * sizeof(int32_t); | 1059 num_bytes = 10u * sizeof(int32_t); |
797 memset(buffer, 0xab, sizeof(buffer)); | 1060 memset(buffer, 0xab, sizeof(buffer)); |
798 EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true)); | 1061 EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true)); |
799 memset(expected_buffer, 0xab, sizeof(expected_buffer)); | 1062 memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
800 EXPECT_EQ(10u * sizeof(int32_t), num_bytes); | 1063 EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |
801 Seq(300, 10, expected_buffer); | 1064 Seq(300, 10, expected_buffer); |
802 EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); | 1065 EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
803 | 1066 |
| 1067 // Note: All-or-none two-phase writes on a "may discard" data pipe are tested |
| 1068 // in LocalDataPipeTest.MayDiscard. |
| 1069 |
804 dp->ProducerClose(); | 1070 dp->ProducerClose(); |
805 dp->ConsumerClose(); | 1071 dp->ConsumerClose(); |
806 } | 1072 } |
807 | 1073 |
808 TEST(LocalDataPipeTest, TwoPhaseAllOrNone) { | 1074 TEST(LocalDataPipeTest, TwoPhaseAllOrNone) { |
809 const MojoCreateDataPipeOptions options = { | 1075 const MojoCreateDataPipeOptions options = { |
810 kSizeOfOptions, // |struct_size|. | 1076 kSizeOfOptions, // |struct_size|. |
811 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. | 1077 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
812 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. | 1078 static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
813 10 * sizeof(int32_t) // |capacity_num_bytes|. | 1079 10 * sizeof(int32_t) // |capacity_num_bytes|. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 | 1168 |
903 // A two-phase read of two should fail, with "failed precondition". | 1169 // A two-phase read of two should fail, with "failed precondition". |
904 num_bytes = 2u * sizeof(int32_t); | 1170 num_bytes = 2u * sizeof(int32_t); |
905 read_ptr = NULL; | 1171 read_ptr = NULL; |
906 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 1172 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
907 dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true)); | 1173 dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true)); |
908 | 1174 |
909 dp->ConsumerClose(); | 1175 dp->ConsumerClose(); |
910 } | 1176 } |
911 | 1177 |
912 // TODO(vtl): Test two-phase read/write with "all or none" and "may discard", | |
913 // once that's supported. | |
914 | |
915 // Tests that |ProducerWriteData()| and |ConsumerReadData()| writes and reads, | 1178 // Tests that |ProducerWriteData()| and |ConsumerReadData()| writes and reads, |
916 // respectively, as much as possible, even if it has to "wrap around" the | 1179 // respectively, as much as possible, even if it has to "wrap around" the |
917 // internal circular buffer. (Note that the two-phase write and read do not do | 1180 // internal circular buffer. (Note that the two-phase write and read do not do |
918 // this.) | 1181 // this.) |
919 TEST(LocalDataPipeTest, WrapAround) { | 1182 TEST(LocalDataPipeTest, WrapAround) { |
920 unsigned char test_data[1000]; | 1183 unsigned char test_data[1000]; |
921 for (size_t i = 0; i < arraysize(test_data); i++) | 1184 for (size_t i = 0; i < arraysize(test_data); i++) |
922 test_data[i] = static_cast<unsigned char>(i); | 1185 test_data[i] = static_cast<unsigned char>(i); |
923 | 1186 |
924 const MojoCreateDataPipeOptions options = { | 1187 const MojoCreateDataPipeOptions options = { |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 | 1424 |
1162 // Ditto for discard. | 1425 // Ditto for discard. |
1163 num_bytes = 10u; | 1426 num_bytes = 10u; |
1164 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 1427 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
1165 dp->ConsumerDiscardData(&num_bytes, false)); | 1428 dp->ConsumerDiscardData(&num_bytes, false)); |
1166 | 1429 |
1167 dp->ConsumerClose(); | 1430 dp->ConsumerClose(); |
1168 } | 1431 } |
1169 } | 1432 } |
1170 | 1433 |
1171 // TODO(vtl): More. | |
1172 | |
1173 } // namespace | 1434 } // namespace |
1174 } // namespace system | 1435 } // namespace system |
1175 } // namespace mojo | 1436 } // namespace mojo |
OLD | NEW |