This source file includes following definitions.
- SetUp
- TearDown
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- ki_ioctl_wrapper
- JSPipeWrite
- IsReadable
- TEST_F
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <string>
#include "dev_fs_for_testing.h"
#include "fake_ppapi/fake_messaging_interface.h"
#include "gtest/gtest.h"
#include "nacl_io/devfs/dev_fs.h"
#include "nacl_io/filesystem.h"
#include "nacl_io/ioctl.h"
#include "nacl_io/kernel_intercept.h"
#include "nacl_io/kernel_proxy.h"
#include "nacl_io/osdirent.h"
using namespace nacl_io;
namespace {
class JSPipeTest : public ::testing::Test {
public:
void SetUp() {
ASSERT_EQ(0, ki_push_state_for_testing());
ASSERT_EQ(0, ki_init(&kp_));
ASSERT_EQ(0, fs_.Access(Path("/jspipe1"), R_OK | W_OK));
ASSERT_EQ(EACCES, fs_.Access(Path("/jspipe1"), X_OK));
ASSERT_EQ(0, fs_.Open(Path("/jspipe1"), O_RDWR, &pipe_dev_));
ASSERT_NE(NULL_NODE, pipe_dev_.get());
}
void TearDown() { ki_uninit(); }
protected:
KernelProxy kp_;
DevFsForTesting fs_;
ScopedNode pipe_dev_;
};
TEST_F(JSPipeTest, InvalidIoctl) {
EXPECT_EQ(EINVAL, pipe_dev_->Ioctl(123));
}
TEST_F(JSPipeTest, JSPipeInput) {
std::string message("hello, how are you?\n");
struct tioc_nacl_input_string packaged_message;
packaged_message.length = message.size();
packaged_message.buffer = message.data();
ASSERT_EQ(0, pipe_dev_->Ioctl(TIOCNACLINPUT, &packaged_message));
int bytes_read;
char buffer[100];
char backup_buffer[100];
memset(buffer, 'a', sizeof(buffer));
memset(backup_buffer, 'a', sizeof(backup_buffer));
HandleAttr attrs;
ASSERT_EQ(0, pipe_dev_->Read(attrs, buffer, 5, &bytes_read));
EXPECT_EQ(5, bytes_read);
EXPECT_EQ(0, memcmp(message.data(), buffer, 5));
EXPECT_EQ(0, memcmp(buffer + 5, backup_buffer + 5, sizeof(buffer)-5));
ASSERT_EQ(0, pipe_dev_->Read(attrs, buffer + 5, sizeof(buffer)-5,
&bytes_read));
EXPECT_EQ(bytes_read, message.size() - 5);
EXPECT_EQ(0, memcmp(message.data(), buffer, message.size()));
EXPECT_EQ(0, memcmp(buffer + message.size(),
backup_buffer + message.size(),
100 - message.size()));
}
TEST_F(JSPipeTest, JSPipeOutput) {
const char* message = "hello";
const int message_len = strlen(message);
int bytes_written = 999;
HandleAttr attrs;
ASSERT_EQ(0, pipe_dev_->Write(attrs, message, message_len, &bytes_written));
ASSERT_EQ(message_len, bytes_written);
FakeMessagingInterface* iface =
(FakeMessagingInterface*)fs_.ppapi()->GetMessagingInterface();
VarArrayInterface* array_iface = fs_.ppapi()->GetVarArrayInterface();
VarInterface* var_iface = fs_.ppapi()->GetVarInterface();
VarArrayBufferInterface* buffer_iface =
fs_.ppapi()->GetVarArrayBufferInterface();
ASSERT_EQ(1, iface->messages.size());
PP_Var array = iface->messages[0];
ASSERT_EQ(PP_VARTYPE_ARRAY, array.type);
ASSERT_EQ(2, array_iface->GetLength(array));
PP_Var item0 = array_iface->Get(array, 0);
PP_Var item1 = array_iface->Get(array, 1);
ASSERT_EQ(PP_VARTYPE_STRING, item0.type);
ASSERT_EQ(PP_VARTYPE_ARRAY_BUFFER, item1.type);
uint32_t len = 0;
const char* item0_string = var_iface->VarToUtf8(item0, &len);
ASSERT_STREQ("jspipe1", std::string(item0_string, len).c_str());
ASSERT_EQ(0, memcmp(message, buffer_iface->Map(item1), strlen(message)));
var_iface->Release(item0);
var_iface->Release(item1);
}
TEST_F(JSPipeTest, JSPipeOutputWithNulls) {
char message[20];
int message_len = sizeof(message);
memset(message, 0 , message_len);
memcpy(message+10, "hello", 5);
int bytes_written = 999;
HandleAttr attrs;
EXPECT_EQ(0, pipe_dev_->Write(attrs, message, message_len, &bytes_written));
EXPECT_EQ(message_len, bytes_written);
FakeMessagingInterface* iface =
(FakeMessagingInterface*)fs_.ppapi()->GetMessagingInterface();
VarArrayInterface* array_iface = fs_.ppapi()->GetVarArrayInterface();
VarInterface* var_iface = fs_.ppapi()->GetVarInterface();
VarArrayBufferInterface* buffer_iface =
fs_.ppapi()->GetVarArrayBufferInterface();
EXPECT_EQ(1, iface->messages.size());
PP_Var array = iface->messages[0];
ASSERT_EQ(PP_VARTYPE_ARRAY, array.type);
ASSERT_EQ(2, array_iface->GetLength(array));
PP_Var item0 = array_iface->Get(array, 0);
PP_Var item1 = array_iface->Get(array, 1);
ASSERT_EQ(PP_VARTYPE_STRING, item0.type);
ASSERT_EQ(PP_VARTYPE_ARRAY_BUFFER, item1.type);
uint32_t len = 0;
ASSERT_STREQ("jspipe1", var_iface->VarToUtf8(item0, &len));
ASSERT_EQ(0, memcmp(message, buffer_iface->Map(item1), strlen(message)));
var_iface->Release(item0);
var_iface->Release(item1);
}
static int ki_ioctl_wrapper(int fd, int request, ...) {
va_list ap;
va_start(ap, request);
int rtn = ki_ioctl(fd, request, ap);
va_end(ap);
return rtn;
}
static int JSPipeWrite(int fd, const char* string) {
struct tioc_nacl_input_string input;
input.buffer = string;
input.length = strlen(input.buffer);
return ki_ioctl_wrapper(fd, TIOCNACLINPUT, &input);
}
static int IsReadable(int fd) {
struct timeval timeout = {0, 0};
fd_set readfds;
fd_set errorfds;
FD_ZERO(&readfds);
FD_ZERO(&errorfds);
FD_SET(fd, &readfds);
FD_SET(fd, &errorfds);
int rtn = ki_select(fd + 1, &readfds, NULL, &errorfds, &timeout);
if (rtn == 0)
return 0;
if (rtn != 1)
return -1;
if (FD_ISSET(fd, &errorfds))
return -2;
if (!FD_ISSET(fd, &readfds))
return -3;
return 1;
}
TEST_F(JSPipeTest, JSPipeSelect) {
struct timeval timeout;
fd_set readfds;
fd_set writefds;
fd_set errorfds;
int pipe_fd = ki_open("/dev/jspipe1", O_RDONLY);
ASSERT_GT(pipe_fd, 0) << "jspipe1 open failed: " << errno;
FD_ZERO(&readfds);
FD_ZERO(&errorfds);
FD_SET(pipe_fd, &readfds);
FD_SET(pipe_fd, &errorfds);
timeout.tv_sec = 0;
timeout.tv_usec = 10 * 1000;
int rtn = ki_select(pipe_fd + 1, &readfds, NULL, &errorfds, &timeout);
ASSERT_EQ(0, rtn) << "select failed: " << rtn << " err=" << strerror(errno);
ASSERT_FALSE(FD_ISSET(pipe_fd, &readfds));
ASSERT_FALSE(FD_ISSET(pipe_fd, &errorfds));
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&errorfds);
FD_SET(pipe_fd, &readfds);
FD_SET(pipe_fd, &writefds);
FD_SET(pipe_fd, &errorfds);
rtn = ki_select(pipe_fd + 1, &readfds, &writefds, &errorfds, NULL);
ASSERT_EQ(1, rtn);
ASSERT_TRUE(FD_ISSET(pipe_fd, &writefds));
ASSERT_FALSE(FD_ISSET(pipe_fd, &readfds));
ASSERT_FALSE(FD_ISSET(pipe_fd, &errorfds));
ASSERT_EQ(0, JSPipeWrite(pipe_fd, "test"));
ASSERT_EQ(1, IsReadable(pipe_fd));
ki_close(pipe_fd);
}
}