#include "mojo/public/c/system/data_pipe.h"
#include <limits>
#include <vector>
#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/test/task_environment.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
namespace {
TEST(DataPipeCppTest, BeginWriteDataGracefullyHandlesBigSizeHint) {
base::test::TaskEnvironment task_environment;
ScopedDataPipeProducerHandle producer_handle;
ScopedDataPipeConsumerHandle consumer_handle;
ASSERT_EQ(CreateDataPipe(16, producer_handle, consumer_handle),
MOJO_RESULT_OK);
base::span<uint8_t> data;
size_t size_hint = std::numeric_limits<size_t>::max();
ASSERT_EQ(producer_handle->BeginWriteData(
size_hint, MOJO_BEGIN_WRITE_DATA_FLAG_NONE, data),
MOJO_RESULT_OK);
EXPECT_LE(data.size(), 16u);
}
TEST(DataPipeCppTest, EndWriteDataErrorWhenSizeTooBig) {
base::test::TaskEnvironment task_environment;
const std::array<size_t, 2> kTooBigSizes = {
20,
std::numeric_limits<size_t>::max()};
for (size_t big_size : kTooBigSizes) {
ScopedDataPipeProducerHandle producer_handle;
ScopedDataPipeConsumerHandle consumer_handle;
ASSERT_EQ(CreateDataPipe(16, producer_handle, consumer_handle),
MOJO_RESULT_OK);
base::span<uint8_t> data;
ASSERT_EQ(
producer_handle->BeginWriteData(DataPipeProducerHandle::kNoSizeHint,
MOJO_BEGIN_WRITE_DATA_FLAG_NONE, data),
MOJO_RESULT_OK);
EXPECT_LE(data.size(), 16u);
ASSERT_EQ(producer_handle->EndWriteData(big_size),
MOJO_RESULT_INVALID_ARGUMENT);
}
}
TEST(DataPipeCppTest, WriteDataGracefullyHandlesBigSize) {
base::test::TaskEnvironment task_environment;
ScopedDataPipeProducerHandle producer_handle;
ScopedDataPipeConsumerHandle consumer_handle;
ASSERT_EQ(CreateDataPipe(16, producer_handle, consumer_handle),
MOJO_RESULT_OK);
std::vector<uint8_t> kData(1024, 0x00);
base::span<const uint8_t> big_span = UNSAFE_BUFFERS(base::span<const uint8_t>(
kData.data(),
std::numeric_limits<size_t>::max()));
size_t bytes_written = 0;
ASSERT_EQ(producer_handle->WriteData(
big_span, MOJO_BEGIN_WRITE_DATA_FLAG_NONE, bytes_written),
MOJO_RESULT_OK);
EXPECT_EQ(bytes_written, 16u);
}
TEST(DataPipeCppTest, ReadDataGracefullyHandlesBigSize) {
base::test::TaskEnvironment task_environment;
ScopedDataPipeProducerHandle producer_handle;
ScopedDataPipeConsumerHandle consumer_handle;
ASSERT_EQ(CreateDataPipe(16, producer_handle, consumer_handle),
MOJO_RESULT_OK);
const std::string kData = "0123456789";
size_t bytes_written = 0;
ASSERT_EQ(producer_handle->WriteData(base::as_byte_span(kData),
MOJO_BEGIN_WRITE_DATA_FLAG_NONE,
bytes_written),
MOJO_RESULT_OK);
EXPECT_EQ(bytes_written, 10u);
std::vector<uint8_t> read_buffer(100);
base::span<uint8_t> big_span = UNSAFE_BUFFERS(base::span<uint8_t>(
read_buffer.data(), std::numeric_limits<size_t>::max()));
size_t actually_read_bytes;
ASSERT_EQ(consumer_handle->ReadData(MOJO_READ_DATA_FLAG_NONE, big_span,
actually_read_bytes),
MOJO_RESULT_OK);
EXPECT_EQ(actually_read_bytes, 10u);
EXPECT_EQ(base::as_byte_span(read_buffer).first(10u),
base::as_byte_span(std::string_view(kData)));
}
TEST(DataPipeCppTest, EndReadDataErrorWhenSizeTooBig) {
base::test::TaskEnvironment task_environment;
const std::array<size_t, 2> kTooBigSizes = {
11,
std::numeric_limits<size_t>::max()};
for (size_t big_size : kTooBigSizes) {
ScopedDataPipeProducerHandle producer_handle;
ScopedDataPipeConsumerHandle consumer_handle;
ASSERT_EQ(CreateDataPipe(16, producer_handle, consumer_handle),
MOJO_RESULT_OK);
const std::string kData = "0123456789";
size_t bytes_written = 0;
ASSERT_EQ(producer_handle->WriteData(base::as_byte_span(kData),
MOJO_BEGIN_WRITE_DATA_FLAG_NONE,
bytes_written),
MOJO_RESULT_OK);
EXPECT_EQ(bytes_written, 10u);
base::span<const uint8_t> read_buffer;
ASSERT_EQ(
consumer_handle->BeginReadData(MOJO_READ_DATA_FLAG_NONE, read_buffer),
MOJO_RESULT_OK);
EXPECT_EQ(read_buffer.size(), 10u);
ASSERT_EQ(consumer_handle->EndReadData(big_size),
MOJO_RESULT_INVALID_ARGUMENT);
}
}
}
}