Chromium Code Reviews| Index: mojo/system/local_data_pipe_unittest.cc |
| diff --git a/mojo/system/local_data_pipe_unittest.cc b/mojo/system/local_data_pipe_unittest.cc |
| index 98a5ae1080e4c5da5c7264f7e73596c2a8116893..bafc5972b456d46126a3d2c54d797383d6a5a53f 100644 |
| --- a/mojo/system/local_data_pipe_unittest.cc |
| +++ b/mojo/system/local_data_pipe_unittest.cc |
| @@ -579,7 +579,338 @@ TEST(LocalDataPipeTest, MayDiscard) { |
| dp->ConsumerClose(); |
| } |
| -// TODO(vtl): More "all or none" tests (without and with "may discard"). |
| +TEST(LocalDataPipeTest, AllOrNone) { |
| + const MojoCreateDataPipeOptions options = { |
| + kSizeOfOptions, // |struct_size|. |
| + MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| + static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
| + 10 * sizeof(int32_t) // |capacity_num_bytes|. |
| + }; |
| + MojoCreateDataPipeOptions validated_options = { 0 }; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + DataPipe::ValidateOptions(&options, &validated_options)); |
| + |
| + scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |
| + |
| + // Try writing way too much. |
| + uint32_t num_bytes = 20u * sizeof(int32_t); |
| + int32_t buffer[100]; |
| + Seq(0, arraysize(buffer), buffer); |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + |
| + // Should still be empty. |
| + num_bytes = 0u; |
|
DaveMoore
2014/01/07 23:51:01
Nit: this would be better if you didn't initialize
viettrungluu
2014/01/07 23:56:43
Done.
|
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); |
| + EXPECT_EQ(0u, num_bytes); |
| + |
| + // Write some data. |
| + num_bytes = 5u * sizeof(int32_t); |
| + Seq(100, arraysize(buffer), buffer); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |
| + |
| + // Half full. |
| + num_bytes = 0u; |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); |
| + EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |
| + |
| + // Too much. |
| + num_bytes = 6u * sizeof(int32_t); |
| + Seq(200, arraysize(buffer), buffer); |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + |
| + // Try reading too much. |
| + num_bytes = 11u * sizeof(int32_t); |
| + memset(buffer, 0xab, sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ConsumerReadData(buffer, &num_bytes, true)); |
| + int32_t expected_buffer[100]; |
| + memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
| + EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
| + |
| + // Try discarding too much. |
| + num_bytes = 11u * sizeof(int32_t); |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ConsumerDiscardData(&num_bytes, true)); |
| + |
| + // Just a little. |
| + num_bytes = 2u * sizeof(int32_t); |
| + Seq(300, arraysize(buffer), buffer); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(2u * sizeof(int32_t), num_bytes); |
| + |
| + // Just right. |
| + num_bytes = 3u * sizeof(int32_t); |
| + Seq(400, arraysize(buffer), buffer); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(3u * sizeof(int32_t), num_bytes); |
| + |
| + // Exactly full. |
| + num_bytes = 0u; |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); |
| + EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |
| + |
| + // Read half. |
| + num_bytes = 5u * sizeof(int32_t); |
| + memset(buffer, 0xab, sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |
| + memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
| + Seq(100, 5, expected_buffer); |
| + EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
| + |
| + // Try reading too much again. |
| + num_bytes = 6u * sizeof(int32_t); |
| + memset(buffer, 0xab, sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ConsumerReadData(buffer, &num_bytes, true)); |
| + memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
| + EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
| + |
| + // Try discarding too much again. |
| + num_bytes = 6u * sizeof(int32_t); |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ConsumerDiscardData(&num_bytes, true)); |
| + |
| + // Discard a little. |
| + num_bytes = 2u * sizeof(int32_t); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerDiscardData(&num_bytes, true)); |
| + EXPECT_EQ(2u * sizeof(int32_t), num_bytes); |
| + |
| + // Three left. |
| + num_bytes = 0u; |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); |
| + EXPECT_EQ(3u * sizeof(int32_t), num_bytes); |
| + |
| + // Close the producer, then test producer-closed cases. |
| + dp->ProducerClose(); |
| + |
| + // Try reading too much; "failed precondition" since the producer is closed. |
| + num_bytes = 4u * sizeof(int32_t); |
| + memset(buffer, 0xab, sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| + dp->ConsumerReadData(buffer, &num_bytes, true)); |
| + memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
| + EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
| + |
| + // Try discarding too much; "failed precondition" again. |
| + num_bytes = 4u * sizeof(int32_t); |
| + EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| + dp->ConsumerDiscardData(&num_bytes, true)); |
| + |
| + // Read a little. |
| + num_bytes = 2u * sizeof(int32_t); |
| + memset(buffer, 0xab, sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(2u * sizeof(int32_t), num_bytes); |
| + memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
| + Seq(400, 2, expected_buffer); |
| + EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
| + |
| + // Discard the remaining element. |
| + num_bytes = 1u * sizeof(int32_t); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerDiscardData(&num_bytes, true)); |
| + EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |
| + |
| + // Empty again. |
| + num_bytes = 0u; |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); |
| + EXPECT_EQ(0u, num_bytes); |
| + |
| + dp->ConsumerClose(); |
| +} |
| + |
| +TEST(LocalDataPipeTest, AllOrNoneMayDiscard) { |
| + const MojoCreateDataPipeOptions options = { |
| + kSizeOfOptions, // |struct_size|. |
| + MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|. |
| + static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
| + 10 * sizeof(int32_t) // |capacity_num_bytes|. |
| + }; |
| + MojoCreateDataPipeOptions validated_options = { 0 }; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + DataPipe::ValidateOptions(&options, &validated_options)); |
| + |
| + scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |
| + |
| + // Try writing way too much. |
| + uint32_t num_bytes = 20u * sizeof(int32_t); |
| + int32_t buffer[100]; |
| + Seq(0, arraysize(buffer), buffer); |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + |
| + // Write some stuff. |
| + num_bytes = 5u * sizeof(int32_t); |
| + Seq(100, arraysize(buffer), buffer); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |
| + |
| + // Write lots of stuff (discarding all but "104"). |
| + num_bytes = 9u * sizeof(int32_t); |
| + Seq(200, arraysize(buffer), buffer); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(9u * sizeof(int32_t), num_bytes); |
| + |
| + // Read one. |
| + num_bytes = 1u * sizeof(int32_t); |
| + memset(buffer, 0xab, sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(1u * sizeof(int32_t), num_bytes); |
| + int32_t expected_buffer[100]; |
| + memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
| + expected_buffer[0] = 104; |
| + EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
| + |
| + // Try reading too many. |
| + num_bytes = 10u * sizeof(int32_t); |
| + memset(buffer, 0xab, sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ConsumerReadData(buffer, &num_bytes, true)); |
| + memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
| + EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
| + |
| + // Try discarding too many. |
| + num_bytes = 10u * sizeof(int32_t); |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ConsumerDiscardData(&num_bytes, true)); |
| + |
| + // Discard a bunch. |
| + num_bytes = 4u * sizeof(int32_t); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerDiscardData(&num_bytes, true)); |
| + |
| + // Half full. |
| + num_bytes = 0u; |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); |
| + EXPECT_EQ(5u * sizeof(int32_t), num_bytes); |
| + |
| + // Write as much as possible. |
| + num_bytes = 10u * sizeof(int32_t); |
| + Seq(300, arraysize(buffer), buffer); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |
| + |
| + // Read everything. |
| + num_bytes = 10u * sizeof(int32_t); |
| + memset(buffer, 0xab, sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerReadData(buffer, &num_bytes, true)); |
| + memset(expected_buffer, 0xab, sizeof(expected_buffer)); |
| + EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |
| + Seq(300, 10, expected_buffer); |
| + EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); |
| + |
| + dp->ProducerClose(); |
| + dp->ConsumerClose(); |
| +} |
| + |
| +TEST(LocalDataPipeTest, TwoPhaseAllOrNone) { |
| + const MojoCreateDataPipeOptions options = { |
| + kSizeOfOptions, // |struct_size|. |
| + MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| + static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|. |
| + 10 * sizeof(int32_t) // |capacity_num_bytes|. |
| + }; |
| + MojoCreateDataPipeOptions validated_options = { 0 }; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + DataPipe::ValidateOptions(&options, &validated_options)); |
| + |
| + scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options)); |
| + |
| + // Try writing way too much (two-phase). |
| + uint32_t num_bytes = 20u * sizeof(int32_t); |
| + void* write_ptr = NULL; |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true)); |
| + |
| + // Try reading way too much (two-phase). |
| + num_bytes = 20u * sizeof(int32_t); |
| + const void* read_ptr = NULL; |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true)); |
| + |
| + // Write half (two-phase). |
| + num_bytes = 5u * sizeof(int32_t); |
| + write_ptr = NULL; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true)); |
| + // May provide more space than requested. |
| + EXPECT_GE(num_bytes, 5u * sizeof(int32_t)); |
| + EXPECT_TRUE(write_ptr != NULL); |
| + Seq(0, 5, static_cast<int32_t*>(write_ptr)); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(5u * sizeof(int32_t))); |
| + |
| + // Read one (two-phase). |
| + num_bytes = 1u * sizeof(int32_t); |
| + read_ptr = NULL; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true)); |
| + EXPECT_GE(num_bytes, 1u * sizeof(int32_t)); |
| + EXPECT_EQ(0, static_cast<const int32_t*>(read_ptr)[0]); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(1u * sizeof(int32_t))); |
| + |
| + // We should have four left, leaving room for six. |
| + num_bytes = 0u; |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); |
| + EXPECT_EQ(4u * sizeof(int32_t), num_bytes); |
| + |
| + // Assuming a tight circular buffer of the specified capacity, we can't do a |
| + // two-phase write of six now. |
| + num_bytes = 6u * sizeof(int32_t); |
| + write_ptr = NULL; |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ProducerBeginWriteData(&write_ptr, &num_bytes, true)); |
| + |
| + // Write six elements (simple), filling the buffer. |
| + num_bytes = 6u * sizeof(int32_t); |
| + int32_t buffer[100]; |
| + Seq(100, 6, buffer); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerWriteData(buffer, &num_bytes, true)); |
| + EXPECT_EQ(6u * sizeof(int32_t), num_bytes); |
| + |
| + // We have ten. |
| + num_bytes = 0u; |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerQueryData(&num_bytes)); |
| + EXPECT_EQ(10u * sizeof(int32_t), num_bytes); |
| + |
| + // But a two-phase read of ten should fail. |
| + num_bytes = 10u * sizeof(int32_t); |
| + read_ptr = NULL; |
| + EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, |
| + dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true)); |
| + |
| + // Close the producer. |
| + dp->ProducerClose(); |
| + |
| + // A two-phase read of nine should work. |
| + num_bytes = 9u * sizeof(int32_t); |
| + read_ptr = NULL; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true)); |
| + EXPECT_GE(num_bytes, 9u * sizeof(int32_t)); |
| + EXPECT_EQ(1, static_cast<const int32_t*>(read_ptr)[0]); |
| + EXPECT_EQ(2, static_cast<const int32_t*>(read_ptr)[1]); |
| + EXPECT_EQ(3, static_cast<const int32_t*>(read_ptr)[2]); |
| + EXPECT_EQ(4, static_cast<const int32_t*>(read_ptr)[3]); |
| + EXPECT_EQ(100, static_cast<const int32_t*>(read_ptr)[4]); |
| + EXPECT_EQ(101, static_cast<const int32_t*>(read_ptr)[5]); |
| + EXPECT_EQ(102, static_cast<const int32_t*>(read_ptr)[6]); |
| + EXPECT_EQ(103, static_cast<const int32_t*>(read_ptr)[7]); |
| + EXPECT_EQ(104, static_cast<const int32_t*>(read_ptr)[8]); |
| + EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(9u * sizeof(int32_t))); |
| + |
| + // A two-phase read of two should fail, with "failed precondition". |
| + num_bytes = 2u * sizeof(int32_t); |
| + read_ptr = NULL; |
| + EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| + dp->ConsumerBeginReadData(&read_ptr, &num_bytes, true)); |
| + |
| + dp->ConsumerClose(); |
| +} |
| + |
| +// TODO(vtl): Test two-phase read/write with "all or none" and "may discard", |
| +// once that's supported. |
| // Tests that |ProducerWriteData()| and |ConsumerReadData()| writes and reads, |
| // respectively, as much as possible, even if it has to "wrap around" the |