blob: d41e61a97144352b7b6afd5c0921a5dc91c4ea1f [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <elf.h> // For ELFMAG
#include <fcntl.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "base/memory/ref_counted.h"
#include "gtest/gtest.h"
#include "posix_translation/passthrough.h"
#include "posix_translation/test_util/file_system_test_common.h"
namespace posix_translation {
namespace {
int DoFcntl(scoped_refptr<FileStream> stream, int cmd, ...) {
va_list ap;
va_start(ap, cmd);
const int result = stream->fcntl(cmd, ap);
va_end(ap);
return result;
}
class PassthroughTest : public FileSystemTestCommon {
};
} // namespace
TEST_F(PassthroughTest, TestHandlerOpenWithEmptyPath) {
PassthroughHandler handler;
int fd = dup(STDOUT_FILENO);
scoped_refptr<FileStream> stream =
handler.open(fd, "", O_WRONLY, 0);
ASSERT_TRUE(stream != NULL);
struct stat st;
EXPECT_EQ(0, stream->fstat(&st));
}
TEST_F(PassthroughTest, TestConstructAndCloseOnDestruct) {
int fd = dup(STDIN_FILENO);
ASSERT_NE(-1, fd);
{
scoped_refptr<FileStream> stream = new PassthroughStream(fd, "", O_WRONLY,
true);
} // |fd| should be automatically closed here.
errno = 0;
EXPECT_EQ(-1, close(fd)); // should fail.
EXPECT_EQ(EBADF, errno);
}
TEST_F(PassthroughTest, TestConstructAndNotClosedOnDestruct) {
int fd = dup(STDIN_FILENO);
ASSERT_NE(-1, fd);
{
scoped_refptr<FileStream> stream = new PassthroughStream(fd, "", O_WRONLY,
false);
// |fd| should NOT be automatically closed here since passing
// close_on_destruction = false.
}
EXPECT_EQ(0, close(fd));
}
TEST_F(PassthroughTest, TestConstructAndDestructForAnonymousMmap) {
scoped_refptr<FileStream> stream = new PassthroughStream();
size_t length = sysconf(_SC_PAGESIZE);
void* new_addr = stream->mmap(NULL, length, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0);
EXPECT_NE(MAP_FAILED, new_addr);
EXPECT_EQ(0, stream->munmap(new_addr, length));
}
TEST_F(PassthroughTest, TestFcntl) {
scoped_refptr<FileStream> stream =
new PassthroughStream(dup(STDERR_FILENO), "", O_WRONLY, true);
EXPECT_EQ(O_WRONLY, DoFcntl(stream, F_GETFL));
const long new_flag = O_WRONLY | O_NONBLOCK; // NOLINT(runtime/int)
EXPECT_EQ(0, DoFcntl(stream, F_SETFL, new_flag));
EXPECT_EQ(new_flag, DoFcntl(stream, F_GETFL));
}
TEST_F(PassthroughTest, TestSelectStdin) {
PassthroughHandler handler;
scoped_refptr<FileStream> stream =
handler.open(STDIN_FILENO, "", O_RDONLY, 0);
EXPECT_TRUE(stream->IsSelectReadReady());
EXPECT_FALSE(stream->IsSelectWriteReady());
EXPECT_FALSE(stream->IsSelectExceptionReady());
}
TEST_F(PassthroughTest, TestSelectStdout) {
PassthroughHandler handler;
scoped_refptr<FileStream> stream =
handler.open(STDOUT_FILENO, "", O_RDONLY, 0);
EXPECT_FALSE(stream->IsSelectReadReady());
EXPECT_TRUE(stream->IsSelectWriteReady());
EXPECT_FALSE(stream->IsSelectExceptionReady());
}
TEST_F(PassthroughTest, TestSelectStderr) {
PassthroughHandler handler;
scoped_refptr<FileStream> stream =
handler.open(STDERR_FILENO, "", O_RDONLY, 0);
EXPECT_FALSE(stream->IsSelectReadReady());
EXPECT_TRUE(stream->IsSelectWriteReady());
EXPECT_FALSE(stream->IsSelectExceptionReady());
}
TEST_F(PassthroughTest, TestPollStdin) {
PassthroughHandler handler;
scoped_refptr<FileStream> stream =
handler.open(STDIN_FILENO, "", O_RDONLY, 0);
EXPECT_EQ(POLLIN, stream->GetPollEvents());
}
TEST_F(PassthroughTest, TestPollStdout) {
PassthroughHandler handler;
scoped_refptr<FileStream> stream =
handler.open(STDOUT_FILENO, "", O_RDONLY, 0);
EXPECT_EQ(POLLOUT, stream->GetPollEvents());
}
TEST_F(PassthroughTest, TestPollStderr) {
PassthroughHandler handler;
scoped_refptr<FileStream> stream =
handler.open(STDERR_FILENO, "", O_RDONLY, 0);
EXPECT_EQ(POLLOUT, stream->GetPollEvents());
}
} // namespace posix_translation