blob: c20d992758c1c3c6a1849b16e6de02014b158d01 [file] [log] [blame]
#include <gmock/gmock.h>
#include <string>
#include <process/future.hpp>
#include <process/gtest.hpp>
#include <process/io.hpp>
#include <stout/gtest.hpp>
#include <stout/os.hpp>
#include "encoder.hpp"
using namespace process;
using std::string;
TEST(IO, Poll)
{
ASSERT_TRUE(GTEST_IS_THREADSAFE);
int pipes[2];
pipe(pipes);
Future<short> future = io::poll(pipes[0], io::READ);
EXPECT_FALSE(future.isReady());
ASSERT_EQ(3, write(pipes[1], "hi", 3));
AWAIT_EXPECT_EQ(io::READ, future);
close(pipes[0]);
close(pipes[1]);
}
TEST(IO, Read)
{
ASSERT_TRUE(GTEST_IS_THREADSAFE);
int pipes[2];
char data[3];
// Create a blocking pipe.
ASSERT_NE(-1, ::pipe(pipes));
// Test on a blocking file descriptor.
AWAIT_EXPECT_FAILED(io::read(pipes[0], data, 3));
close(pipes[0]);
close(pipes[1]);
// Test on a closed file descriptor.
AWAIT_EXPECT_FAILED(io::read(pipes[0], data, 3));
// Create a nonblocking pipe.
ASSERT_NE(-1, ::pipe(pipes));
ASSERT_SOME(os::nonblock(pipes[0]));
ASSERT_SOME(os::nonblock(pipes[1]));
// Test reading nothing.
AWAIT_EXPECT_FAILED(io::read(pipes[0], data, 0));
// Test successful read.
Future<size_t> future = io::read(pipes[0], data, 3);
ASSERT_FALSE(future.isReady());
ASSERT_EQ(2, write(pipes[1], "hi", 2));
AWAIT_ASSERT_EQ(2u, future);
EXPECT_EQ('h', data[0]);
EXPECT_EQ('i', data[1]);
// Test cancellation.
future = io::read(pipes[0], data, 1);
ASSERT_FALSE(future.isReady());
future.discard();
ASSERT_EQ(3, write(pipes[1], "omg", 3));
AWAIT_ASSERT_EQ(3u, io::read(pipes[0], data, 3));
EXPECT_EQ('o', data[0]);
EXPECT_EQ('m', data[1]);
EXPECT_EQ('g', data[2]);
// Test read EOF.
future = io::read(pipes[0], data, 3);
ASSERT_FALSE(future.isReady());
close(pipes[1]);
AWAIT_ASSERT_EQ(0u, future);
close(pipes[0]);
}
TEST(IO, BufferedRead)
{
// 128 Bytes.
string data =
"This data is much larger than BUFFERED_READ_SIZE, which means it will "
"trigger multiple buffered async reads as a result.........";
ASSERT_EQ(128u, data.size());
// Keep doubling the data size until we're guaranteed to trigger at least
// 3 buffered async reads.
while (data.length() < 3 * io::BUFFERED_READ_SIZE) {
data.append(data);
}
// First read from a file.
ASSERT_SOME(os::write("file", data));
Try<int> fd = os::open("file", O_RDONLY);
ASSERT_SOME(fd);
// Read from blocking fd.
AWAIT_EXPECT_FAILED(io::read(fd.get()));
// Read from non-blocking fd.
ASSERT_TRUE(os::nonblock(fd.get()).isSome());
AWAIT_EXPECT_EQ(data, io::read(fd.get()));
os::close(fd.get());
// Now read from pipes.
int pipes[2];
// Create a blocking pipe.
ASSERT_NE(-1, ::pipe(pipes));
// Test on a blocking pipe.
AWAIT_EXPECT_FAILED(io::read(pipes[0]));
close(pipes[0]);
close(pipes[1]);
// Test on a closed pipe.
AWAIT_EXPECT_FAILED(io::read(pipes[0]));
// Create a nonblocking pipe for reading.
ASSERT_NE(-1, ::pipe(pipes));
ASSERT_SOME(os::nonblock(pipes[0]));
// Test a successful read from the pipe.
Future<string> future = io::read(pipes[0]);
// At first, the future will not be ready until we write to and
// close the pipe.
ASSERT_FALSE(future.isReady());
ASSERT_SOME(os::write(pipes[1], data));
close(pipes[1]);
AWAIT_EXPECT_EQ(data, future);
close(pipes[0]);
ASSERT_SOME(os::rm("file"));
}