blob: d2d67250af012ceeec5896ab6c2f9dfe3f8895b0 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 <sys/epoll.h>
#include <unistd.h>
#include <zxtest/zxtest.h>
TEST(EpollTest, EpollCreateBad) {
int epollfd = epoll_create(0);
ASSERT_EQ(epollfd, -1, "epoll_create() did not fail with 0 arg");
}
TEST(EpollTest, EpollCreateClose) {
int epollfd = epoll_create(1);
ASSERT_GT(epollfd, -1, "epoll_create() failed");
int closeres = close(epollfd);
ASSERT_EQ(closeres, 0, "epoll close() failed");
}
TEST(EpollTest, EpollWait) {
int epoll_fd = epoll_create(1);
ASSERT_NE(-1, epoll_fd);
epoll_event events[1];
// Regular epoll_wait.
ASSERT_EQ(0, epoll_wait(epoll_fd, events, 1, 1));
close(epoll_fd);
}
TEST(EpollTest, EpollEventNoData) {
int epoll_fd = epoll_create(1);
ASSERT_NE(-1, epoll_fd);
int fds[2];
ASSERT_NE(-1, pipe(fds));
const uint64_t expected = 0x123456789abcdef0;
// Get ready to poll on read end of pipe.
epoll_event ev;
ev.events = EPOLLIN;
ev.data.u64 = expected;
ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fds[0], &ev));
// Poll.
epoll_event events[1];
ASSERT_EQ(0, epoll_wait(epoll_fd, events, 1, 1));
close(fds[0]);
close(fds[1]);
close(epoll_fd);
}
TEST(EpollTest, EpollEventData) {
int epoll_fd = epoll_create(1);
ASSERT_NE(-1, epoll_fd);
int fds[2];
ASSERT_NE(-1, pipe(fds));
const uint64_t expected = 0x123456789abcdef0;
// Get ready to poll on read end of pipe.
epoll_event ev;
ev.events = EPOLLIN;
ev.data.u64 = expected;
ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fds[0], &ev));
// Ensure there's something in the pipe.
ASSERT_EQ(1, write(fds[1], "\n", 1));
// Poll.
epoll_event events[1];
events[0].events = 0;
events[0].data.u64 = 0;
ASSERT_EQ(1, epoll_wait(epoll_fd, events, 1, 1));
uint64_t observed = events[0].data.u64;
ASSERT_EQ(expected, observed);
char c;
ASSERT_EQ(1, read(fds[0], &c, sizeof(c)));
close(fds[0]);
close(fds[1]);
close(epoll_fd);
}
TEST(EpollTest, EpollEventDataMultiple) {
int epoll_fd = epoll_create(1);
ASSERT_NE(-1, epoll_fd);
int fds[2];
ASSERT_NE(-1, pipe(fds));
const uint64_t expected = 0x123456789abcdef0;
// Get ready to poll on read end of pipe.
epoll_event ev;
ev.events = EPOLLIN;
ev.data.u64 = expected;
ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fds[0], &ev));
// Ensure there is something in the pipe.
ASSERT_EQ(1, write(fds[1], "\n", 1));
// Poll.
epoll_event events[1];
events[0].events = 0;
events[0].data.u64 = 0;
ASSERT_EQ(1, epoll_wait(epoll_fd, events, 1, 1));
uint64_t observed = events[0].data.u64;
ASSERT_EQ(expected, observed);
char c;
ASSERT_EQ(1, read(fds[0], &c, sizeof(c)));
// now there should be nothing to be read
ASSERT_EQ(0, epoll_wait(epoll_fd, events, 1, 1));
// now poll when there is something to be read
ASSERT_EQ(1, write(fds[1], "\n", 1));
events[0].events = 0;
events[0].data.u64 = 0;
ASSERT_EQ(1, epoll_wait(epoll_fd, events, 1, 1));
observed = events[0].data.u64;
ASSERT_EQ(expected, observed);
ASSERT_EQ(1, read(fds[0], &c, sizeof(c)));
close(fds[0]);
close(fds[1]);
close(epoll_fd);
}
TEST(EpollTest, EpollEventRemoveFd) {
int epoll_fd = epoll_create(1);
ASSERT_NE(-1, epoll_fd);
int fds[2];
ASSERT_NE(-1, pipe(fds));
const uint64_t expected = 0x123456789abcdef0;
// Get ready to poll on read end of pipe.
epoll_event ev;
ev.events = EPOLLIN;
ev.data.u64 = expected;
ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fds[0], &ev));
// Ensure there is something in the pipe.
ASSERT_EQ(1, write(fds[1], "\n", 1));
// Now remove the fd
ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fds[0], &ev));
// Poll.
epoll_event events[1];
events[0].events = 0;
events[0].data.u64 = 0;
ASSERT_EQ(0, epoll_wait(epoll_fd, events, 1, 1));
close(fds[0]);
close(fds[1]);
close(epoll_fd);
}
TEST(EpollTest, EpollEventWriteMod) {
int epoll_fd = epoll_create(1);
ASSERT_NE(-1, epoll_fd);
int fds[2];
ASSERT_NE(-1, pipe(fds));
const uint64_t unexpected = 0x1;
const uint64_t expected = 0x2;
// Get ready to poll on read end of pipe.
epoll_event ev;
ev.events = EPOLLIN;
ev.data.u64 = unexpected;
ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fds[0], &ev));
// Ensure there is something in the pipe.
ASSERT_EQ(1, write(fds[1], "\n", 1));
ev.events = EPOLLIN;
ev.data.u64 = expected;
ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fds[0], &ev));
// Poll.
epoll_event events[2];
events[0].events = 0;
events[0].data.u64 = 0;
events[1].events = 0;
events[1].data.u64 = 0;
ASSERT_EQ(1, epoll_wait(epoll_fd, events, 2, 1));
uint64_t observed = events[0].data.u64;
ASSERT_EQ(expected, observed);
close(fds[0]);
close(fds[1]);
close(epoll_fd);
}
TEST(EpollTest, EpollEventModWrite) {
int epoll_fd = epoll_create(1);
ASSERT_NE(-1, epoll_fd);
int fds[2];
ASSERT_NE(-1, pipe(fds));
const uint64_t unexpected = 0x1;
const uint64_t expected = 0x2;
// Get ready to poll on read end of pipe.
epoll_event ev;
ev.events = EPOLLIN;
ev.data.u64 = unexpected;
ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fds[0], &ev));
ev.events = EPOLLIN;
ev.data.u64 = expected;
ASSERT_NE(-1, epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fds[0], &ev));
ASSERT_EQ(1, write(fds[1], "\n", 1));
// Poll.
epoll_event events[2];
events[0].events = 0;
events[0].data.u64 = 0;
events[1].events = 0;
events[1].data.u64 = 0;
ASSERT_EQ(1, epoll_wait(epoll_fd, events, 2, 1));
uint64_t observed = events[0].data.u64;
ASSERT_EQ(expected, observed);
close(fds[0]);
close(fds[1]);
close(epoll_fd);
}