| 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 |