Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Unified Diff: mojo/edk/system/data_pipe_unittest.cc

Issue 1585493002: [mojo] Ports EDK (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/edk/system/data_pipe_unittest.cc
diff --git a/mojo/edk/system/data_pipe_unittest.cc b/mojo/edk/system/data_pipe_unittest.cc
index af2cf3e6e815170e5c929df195fc2fd8c46a65dc..36d793a20fd523b992f549b092045fc79882dc8f 100644
--- a/mojo/edk/system/data_pipe_unittest.cc
+++ b/mojo/edk/system/data_pipe_unittest.cc
@@ -15,7 +15,7 @@
#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/waiter.h"
-#include "mojo/edk/test/multiprocess_test_helper.h"
+#include "mojo/edk/test/mojo_test_base.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/c/system/message_pipe.h"
@@ -38,9 +38,9 @@ const size_t kMaxPoll = 100;
// Used in Multiprocess test.
const size_t kMultiprocessCapacity = 37;
const char kMultiprocessTestData[] = "hello i'm a string that is 36 bytes";
-const int kMultiprocessMaxIter = 513;
+const int kMultiprocessMaxIter = 5;
-class DataPipeTest : public testing::Test {
+class DataPipeTest : public test::MojoTestBase {
public:
DataPipeTest() : producer_(MOJO_HANDLE_INVALID),
consumer_(MOJO_HANDLE_INVALID) {}
@@ -391,10 +391,8 @@ TEST_F(DataPipeTest, BasicProducerWaiting) {
ASSERT_EQ(MOJO_RESULT_OK,
BeginReadData(&read_buffer, &num_bytes, false));
EXPECT_TRUE(read_buffer);
- // Since we only read one element (after having written three in all), the
- // two-phase read should only allow us to read one. This checks an
- // implementation detail!
- ASSERT_EQ(static_cast<uint32_t>(1u * sizeof(elements[0])), num_bytes);
+ // The two-phase read should be able to read at least one element.
+ ASSERT_GE(num_bytes, static_cast<uint32_t>(1u * sizeof(elements[0])));
ASSERT_EQ(456, static_cast<const int32_t*>(read_buffer)[0]);
ASSERT_EQ(MOJO_RESULT_OK, EndReadData(static_cast<uint32_t>(
1u * sizeof(elements[0]))));
@@ -560,7 +558,7 @@ TEST_F(DataPipeTest, BasicConsumerWaiting) {
ASSERT_EQ(MOJO_RESULT_OK,
MojoWait(consumer_, MOJO_HANDLE_SIGNAL_READABLE,
MOJO_DEADLINE_INDEFINITE, &hss));
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+ ASSERT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE) != 0);
ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
hss.satisfiable_signals);
@@ -952,14 +950,11 @@ TEST_F(DataPipeTest, AllOrNone) {
ASSERT_EQ(0u, num_bytes);
}
-/*
-jam: this is testing that the implementation uses a circular buffer, which we
-don't use currently.
// Tests that |ProducerWriteData()| and |ConsumerReadData()| writes and reads,
// respectively, as much as possible, even if it may have to "wrap around" the
// internal circular buffer. (Note that the two-phase write and read need not do
// this.)
-TYPED_TEST(DataPipeImplTest, WrapAround) {
+TEST_F(DataPipeTest, WrapAround) {
unsigned char test_data[1000];
for (size_t i = 0; i < MOJO_ARRAYSIZE(test_data); i++)
test_data[i] = static_cast<unsigned char>(i);
@@ -970,119 +965,80 @@ TYPED_TEST(DataPipeImplTest, WrapAround) {
1u, // |element_num_bytes|.
100u // |capacity_num_bytes|.
};
- MojoCreateDataPipeOptions validated_options = {};
- // This test won't be valid if |ValidateCreateOptions()| decides to give the
- // pipe more space.
- ASSERT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
- &options, &validated_options));
- ASSERT_EQ(100u, validated_options.capacity_num_bytes);
- this->Create(options);
- this->DoTransfer();
-
- Waiter waiter;
- HandleSignalsState hss;
-
- // Add waiter.
- waiter.Init();
- ASSERT_EQ(MOJO_RESULT_OK,
- this->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1,
- nullptr));
+
+ ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
+ MojoHandleSignalsState hss;
// Write 20 bytes.
uint32_t num_bytes = 20u;
- ASSERT_EQ(MOJO_RESULT_OK,
- this->ProducerWriteData(&test_data[0], &num_bytes, false));
+ ASSERT_EQ(MOJO_RESULT_OK, WriteData(&test_data[0], &num_bytes, true));
ASSERT_EQ(20u, num_bytes);
// Wait for data.
- // TODO(vtl): (See corresponding TODO in AllOrNone.)
- ASSERT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
- hss = HandleSignalsState();
- this->ConsumerRemoveAwakable(&waiter, &hss);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoWait(consumer_, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_DEADLINE_INDEFINITE, &hss));
+ ASSERT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE) != 0);
ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
hss.satisfiable_signals);
// Read 10 bytes.
unsigned char read_buffer[1000] = {0};
num_bytes = 10u;
- ASSERT_EQ(MOJO_RESULT_OK,
- this->ConsumerReadData(read_buffer, &num_bytes, false, false));
+ ASSERT_EQ(MOJO_RESULT_OK, ReadData(read_buffer, &num_bytes, true));
ASSERT_EQ(10u, num_bytes);
ASSERT_EQ(0, memcmp(read_buffer, &test_data[0], 10u));
- if (this->IsStrictCircularBuffer()) {
- // Check that a two-phase write can now only write (at most) 80 bytes. (This
- // checks an implementation detail; this behavior is not guaranteed.)
- void* write_buffer_ptr = nullptr;
- num_bytes = 0u;
- ASSERT_EQ(MOJO_RESULT_OK,
- this->ProducerBeginWriteData(&write_buffer_ptr, &num_bytes,
- false));
- EXPECT_TRUE(write_buffer_ptr);
- ASSERT_EQ(80u, num_bytes);
- ASSERT_EQ(MOJO_RESULT_OK, this->ProducerEndWriteData(0u));
- }
+ // Check that a two-phase write can now only write (at most) 80 bytes. (This
+ // checks an implementation detail; this behavior is not guaranteed.)
+ void* write_buffer_ptr = nullptr;
+ num_bytes = 0u;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ BeginWriteData(&write_buffer_ptr, &num_bytes, false));
+ EXPECT_TRUE(write_buffer_ptr);
+ ASSERT_EQ(80u, num_bytes);
+ ASSERT_EQ(MOJO_RESULT_OK, EndWriteData(0));
- // TODO(vtl): (See corresponding TODO in TwoPhaseAllOrNone.)
size_t total_num_bytes = 0;
- for (size_t i = 0; i < kMaxPoll; i++) {
- // Write as much data as we can (using |ProducerWriteData()|). We should
- // write 90 bytes (eventually).
- num_bytes = 200u;
- MojoResult result = this->ProducerWriteData(
- &test_data[20 + total_num_bytes], &num_bytes, false);
- if (result == MOJO_RESULT_OK) {
- total_num_bytes += num_bytes;
- if (total_num_bytes >= 90u)
- break;
- } else {
- ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, result);
- }
-
- test::Sleep(test::EpsilonDeadline());
+ while (total_num_bytes < 90) {
+ // Wait to write.
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoWait(producer_, MOJO_HANDLE_SIGNAL_WRITABLE,
+ MOJO_DEADLINE_INDEFINITE, &hss));
+ ASSERT_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_WRITABLE);
+ ASSERT_EQ(hss.satisfiable_signals,
+ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+
+ // Write as much as we can.
+ num_bytes = 100;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ WriteData(&test_data[20 + total_num_bytes], &num_bytes, false));
+ total_num_bytes += num_bytes;
}
- ASSERT_EQ(90u, total_num_bytes);
- // TODO(vtl): (See corresponding TODO in TwoPhaseAllOrNone.)
- for (size_t i = 0; i < kMaxPoll; i++) {
- // We have 100.
- num_bytes = 0u;
- ASSERT_EQ(MOJO_RESULT_OK,
- this->ConsumerQueryData(&num_bytes));
- if (num_bytes >= 100u)
- break;
+ ASSERT_EQ(90u, total_num_bytes);
- test::Sleep(test::EpsilonDeadline());
- }
+ num_bytes = 0;
+ ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes));
ASSERT_EQ(100u, num_bytes);
- if (this->IsStrictCircularBuffer()) {
- // Check that a two-phase read can now only read (at most) 90 bytes. (This
- // checks an implementation detail; this behavior is not guaranteed.)
- const void* read_buffer_ptr = nullptr;
- num_bytes = 0u;
- ASSERT_EQ(MOJO_RESULT_OK,
- this->ConsumerBeginReadData(&read_buffer_ptr, &num_bytes, false));
- EXPECT_TRUE(read_buffer_ptr);
- ASSERT_EQ(90u, num_bytes);
- ASSERT_EQ(MOJO_RESULT_OK, this->ConsumerEndReadData(0u));
- }
+ // Check that a two-phase read can now only read (at most) 90 bytes. (This
+ // checks an implementation detail; this behavior is not guaranteed.)
+ const void* read_buffer_ptr = nullptr;
+ num_bytes = 0;
+ ASSERT_EQ(MOJO_RESULT_OK, BeginReadData(&read_buffer_ptr, &num_bytes, false));
+ EXPECT_TRUE(read_buffer_ptr);
+ ASSERT_EQ(90u, num_bytes);
+ ASSERT_EQ(MOJO_RESULT_OK, EndReadData(0));
- // Read as much as possible (using |ConsumerReadData()|). We should read 100
- // bytes.
+ // Read as much as possible. We should read 100 bytes.
num_bytes = static_cast<uint32_t>(MOJO_ARRAYSIZE(read_buffer) *
sizeof(read_buffer[0]));
memset(read_buffer, 0, num_bytes);
- ASSERT_EQ(MOJO_RESULT_OK,
- this->ConsumerReadData(read_buffer, &num_bytes, false, false));
+ ASSERT_EQ(MOJO_RESULT_OK, ReadData(read_buffer, &num_bytes));
ASSERT_EQ(100u, num_bytes);
ASSERT_EQ(0, memcmp(read_buffer, &test_data[10], 100u));
-
- this->ProducerClose();
- this->ConsumerClose();
}
-*/
// Tests the behavior of writing (simple and two-phase), closing the producer,
// then reading (simple and two-phase).
@@ -1717,79 +1673,68 @@ TEST_F(DataPipeTest, MAYBE_Multiprocess) {
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
- test::MultiprocessTestHelper multiprocess_test_helper;
- multiprocess_test_helper.StartChild("MultiprocessClient");
+ RUN_CHILD_ON_PIPE(MultiprocessClient, server_mp)
+ // Send some data before serialising and sending the data pipe over.
+ // This is the first write so we don't need to use WriteAllData.
+ uint32_t num_bytes = kTestDataSize;
+ ASSERT_EQ(MOJO_RESULT_OK, WriteData(kMultiprocessTestData, &num_bytes,
+ MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
+ ASSERT_EQ(kTestDataSize, num_bytes);
- // Send some data before serialising and sending the data pipe over.
- // This is the first write so we don't need to use WriteAllData.
- uint32_t num_bytes = kTestDataSize;
- ASSERT_EQ(MOJO_RESULT_OK, WriteData(kMultiprocessTestData, &num_bytes,
- MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
- ASSERT_EQ(kTestDataSize, num_bytes);
-
- MojoHandle server_mp =
- CreateMessagePipe(
- std::move(multiprocess_test_helper.server_platform_handle))
- .release()
- .value();
-
- // Send child process the data pipe.
- ASSERT_EQ(MOJO_RESULT_OK, MojoWriteMessage(server_mp, nullptr, 0, &consumer_,
- 1, MOJO_WRITE_MESSAGE_FLAG_NONE));
-
- // Send a bunch of data of varying sizes.
- uint8_t buffer[100];
- int seq = 0;
- for (int i = 0; i < kMultiprocessMaxIter; ++i) {
- for (uint32_t size = 1; size <= kMultiprocessCapacity; size++) {
- for (unsigned int j = 0; j < size; ++j)
- buffer[j] = seq + j;
- EXPECT_TRUE(WriteAllData(producer_, buffer, size));
- seq += size;
+ // Send child process the data pipe.
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoWriteMessage(server_mp, nullptr, 0, &consumer_, 1,
+ MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+ // Send a bunch of data of varying sizes.
+ uint8_t buffer[100];
+ int seq = 0;
+ for (int i = 0; i < kMultiprocessMaxIter; ++i) {
+ for (uint32_t size = 1; size <= kMultiprocessCapacity; size++) {
+ for (unsigned int j = 0; j < size; ++j)
+ buffer[j] = seq + j;
+ EXPECT_TRUE(WriteAllData(producer_, buffer, size));
+ seq += size;
+ }
}
- }
- // Write the test string in again.
- EXPECT_TRUE(WriteAllData(producer_, kMultiprocessTestData, kTestDataSize));
+ // Write the test string in again.
+ ASSERT_TRUE(WriteAllData(producer_, kMultiprocessTestData, kTestDataSize));
- // Swap ends.
- ASSERT_EQ(MOJO_RESULT_OK, MojoWriteMessage(server_mp, nullptr, 0, &producer_,
- 1, MOJO_WRITE_MESSAGE_FLAG_NONE));
+ // Swap ends.
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoWriteMessage(server_mp, nullptr, 0, &producer_, 1,
+ MOJO_WRITE_MESSAGE_FLAG_NONE));
- // Receive the consumer from the other side.
- producer_ = MOJO_HANDLE_INVALID;
- MojoHandleSignalsState hss = MojoHandleSignalsState();
- ASSERT_EQ(MOJO_RESULT_OK, MojoWait(server_mp, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &hss));
- MojoHandle handles[2];
- uint32_t num_handles = MOJO_ARRAYSIZE(handles);
- ASSERT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(server_mp, nullptr, 0, handles, &num_handles,
- MOJO_READ_MESSAGE_FLAG_NONE));
- ASSERT_EQ(1u, num_handles);
- consumer_ = handles[0];
+ // Receive the consumer from the other side.
+ producer_ = MOJO_HANDLE_INVALID;
+ MojoHandleSignalsState hss = MojoHandleSignalsState();
+ ASSERT_EQ(MOJO_RESULT_OK, MojoWait(server_mp, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_DEADLINE_INDEFINITE, &hss));
+ MojoHandle handles[2];
+ uint32_t num_handles = MOJO_ARRAYSIZE(handles);
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoReadMessage(server_mp, nullptr, 0, handles, &num_handles,
+ MOJO_READ_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(1u, num_handles);
+ consumer_ = handles[0];
+
+ // Read the test string twice. Once for when we sent it, and once for the
+ // other end sending it.
+ for (int i = 0; i < 2; ++i) {
+ EXPECT_TRUE(ReadAllData(consumer_, buffer, kTestDataSize, i == 1));
+ EXPECT_EQ(0, memcmp(buffer, kMultiprocessTestData, kTestDataSize));
+ }
- // Read the test string twice. Once for when we sent it, and once for the
- // other end sending it.
- for (int i = 0; i < 2; ++i) {
- EXPECT_TRUE(ReadAllData(consumer_, buffer, kTestDataSize, i == 1));
- EXPECT_EQ(0, memcmp(buffer, kMultiprocessTestData, kTestDataSize));
- }
+ WriteMessage(server_mp, "quit");
- // Don't have to close the consumer here because it will be done for us.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp));
- EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown());
+ // Don't have to close the consumer here because it will be done for us.
+ END_CHILD()
}
-MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessClient) {
- ScopedPlatformHandle client_platform_handle =
- std::move(test::MultiprocessTestHelper::client_platform_handle);
+DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessClient, DataPipeTest, client_mp) {
const uint32_t kTestDataSize =
static_cast<uint32_t>(sizeof(kMultiprocessTestData));
- EXPECT_TRUE(client_platform_handle.is_valid());
-
- MojoHandle client_mp =
- CreateMessagePipe(std::move(client_platform_handle)).release().value();
// Receive the data pipe from the other side.
MojoHandle consumer = MOJO_HANDLE_INVALID;
@@ -1844,7 +1789,68 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessClient) {
// We swapped ends, so close the producer.
EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp));
+
+ // Wait to receive a "quit" message before exiting.
+ EXPECT_EQ("quit", ReadMessage(client_mp));
+}
+
+DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteAndCloseProducer, DataPipeTest, h) {
+ MojoHandle p;
+ std::string message = ReadMessageWithHandles(h, &p, 1);
+
+ // Write some data to the producer and close it.
+ uint32_t num_bytes = static_cast<uint32_t>(message.size());
+ EXPECT_EQ(MOJO_RESULT_OK, MojoWriteData(p, message.data(), &num_bytes,
+ MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(num_bytes, static_cast<uint32_t>(message.size()));
+
+ // Close the producer before quitting.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(p));
+
+ // Wait for a quit message.
+ EXPECT_EQ("quit", ReadMessage(h));
+}
+
+DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndCloseConsumer, DataPipeTest, h) {
+ MojoHandle c;
+ std::string expected_message = ReadMessageWithHandles(h, &c, 1);
+
+ // Wait for the consumer to become readable.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoWait(c, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_DEADLINE_INDEFINITE, nullptr));
+
+ // Drain the consumer and expect to find the given message.
+ uint32_t num_bytes = static_cast<uint32_t>(expected_message.size());
+ std::vector<char> bytes(expected_message.size());
+ EXPECT_EQ(MOJO_RESULT_OK, MojoReadData(c, bytes.data(), &num_bytes,
+ MOJO_READ_DATA_FLAG_NONE));
+ EXPECT_EQ(num_bytes, static_cast<uint32_t>(bytes.size()));
+
+ std::string message(bytes.data(), bytes.size());
+ EXPECT_EQ(expected_message, message);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c));
+
+ // Wait for a quit message.
+ EXPECT_EQ("quit", ReadMessage(h));
+}
+
+TEST_F(DataPipeTest, SendConsumerAndCloseProducer) {
+ // Create a new data pipe.
+ MojoHandle p, c;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p ,&c));
+
+ RUN_CHILD_ON_PIPE(WriteAndCloseProducer, producer_client)
+ RUN_CHILD_ON_PIPE(ReadAndCloseConsumer, consumer_client)
+ const std::string kMessage = "Hello, world!";
+ WriteMessageWithHandles(producer_client, kMessage, &p, 1);
+ WriteMessageWithHandles(consumer_client, kMessage, &c, 1);
+
+ WriteMessage(consumer_client, "quit");
+ END_CHILD()
+
+ WriteMessage(producer_client, "quit");
+ END_CHILD()
}
} // namespace

Powered by Google App Engine
This is Rietveld 408576698