149 lines
3.2 KiB
C
149 lines
3.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (c) 2016 Fujitsu Ltd.
|
|
* Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
|
|
*/
|
|
|
|
/*
|
|
* Test Name: epoll_ctl01.c
|
|
*
|
|
* Description:
|
|
* Testcase to check the basic functionality of the epoll_ctl(2).
|
|
* 1) when epoll_ctl(2) succeeds to register fd on the epoll instance and
|
|
* associates event with fd, epoll_wait(2) will get registered fd and
|
|
* event correctly.
|
|
* 2) when epoll_ctl(2) succeeds to chage event which is related to fd,
|
|
* epoll_wait(2) will get chaged event correctly.
|
|
* 3) when epoll_ctl(2) succeeds to deregister fd from the epoll instance
|
|
* epoll_wait(2) won't get deregistered fd and event.
|
|
*
|
|
*/
|
|
|
|
#include <sys/epoll.h>
|
|
#include <poll.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include "tst_test.h"
|
|
|
|
static int epfd;
|
|
static int fd[2];
|
|
|
|
static struct epoll_event events[3] = {
|
|
{.events = EPOLLIN},
|
|
{.events = EPOLLOUT},
|
|
{.events = EPOLLIN}
|
|
};
|
|
|
|
static void setup(void)
|
|
{
|
|
epfd = epoll_create(2);
|
|
if (epfd == -1)
|
|
tst_brk(TBROK | TERRNO, "fail to create epoll instance");
|
|
|
|
SAFE_PIPE(fd);
|
|
|
|
events[0].data.fd = fd[0];
|
|
events[1].data.fd = fd[1];
|
|
events[2].data.fd = fd[1];
|
|
}
|
|
|
|
static void cleanup(void)
|
|
{
|
|
if (epfd > 0)
|
|
SAFE_CLOSE(epfd);
|
|
|
|
if (fd[0] > 0)
|
|
SAFE_CLOSE(fd[0]);
|
|
|
|
if (fd[1] > 0)
|
|
SAFE_CLOSE(fd[1]);
|
|
}
|
|
|
|
static int has_event(struct epoll_event *epvs, int len,
|
|
int fd, unsigned int events)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if ((epvs[i].data.fd == fd) && (epvs[i].events == events))
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void check_epoll_ctl(int opt, int exp_num)
|
|
{
|
|
int res;
|
|
unsigned int events;
|
|
char write_buf[] = "test";
|
|
char read_buf[sizeof(write_buf)];
|
|
struct epoll_event res_evs[2];
|
|
|
|
events = EPOLLIN;
|
|
if (exp_num == 2)
|
|
events |= EPOLLOUT;
|
|
|
|
SAFE_WRITE(1, fd[1], write_buf, sizeof(write_buf));
|
|
|
|
while (events) {
|
|
int events_matched = 0;
|
|
memset(res_evs, 0, sizeof(res_evs));
|
|
|
|
res = epoll_wait(epfd, res_evs, 2, -1);
|
|
if (res <= 0) {
|
|
tst_res(TFAIL | TERRNO, "epoll_wait() returned %i",
|
|
res);
|
|
goto end;
|
|
}
|
|
|
|
if ((events & EPOLLIN) &&
|
|
has_event(res_evs, 2, fd[0], EPOLLIN)) {
|
|
events_matched++;
|
|
events &= ~EPOLLIN;
|
|
}
|
|
|
|
if ((events & EPOLLOUT) &&
|
|
has_event(res_evs, 2, fd[1], EPOLLOUT)) {
|
|
events_matched++;
|
|
events &= ~EPOLLOUT;
|
|
}
|
|
|
|
if (res != events_matched) {
|
|
tst_res(TFAIL,
|
|
"epoll_wait() returned unexpected events");
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
tst_res(TPASS, "epoll_ctl() succeeds with op %i", opt);
|
|
|
|
end:
|
|
SAFE_READ(1, fd[0], read_buf, sizeof(write_buf));
|
|
}
|
|
|
|
static void opera_epoll_ctl(int opt, int fd, struct epoll_event *epvs)
|
|
{
|
|
TEST(epoll_ctl(epfd, opt, fd, epvs));
|
|
if (TST_RET == -1)
|
|
tst_brk(TBROK | TTERRNO, "epoll_ctl() fails with op %i", opt);
|
|
}
|
|
|
|
static void verify_epoll_ctl(void)
|
|
{
|
|
opera_epoll_ctl(EPOLL_CTL_ADD, fd[0], &events[0]);
|
|
opera_epoll_ctl(EPOLL_CTL_ADD, fd[1], &events[2]);
|
|
check_epoll_ctl(EPOLL_CTL_ADD, 1);
|
|
opera_epoll_ctl(EPOLL_CTL_MOD, fd[1], &events[1]);
|
|
check_epoll_ctl(EPOLL_CTL_MOD, 2);
|
|
opera_epoll_ctl(EPOLL_CTL_DEL, fd[1], &events[1]);
|
|
check_epoll_ctl(EPOLL_CTL_DEL, 1);
|
|
opera_epoll_ctl(EPOLL_CTL_DEL, fd[0], &events[0]);
|
|
}
|
|
|
|
static struct tst_test test = {
|
|
.setup = setup,
|
|
.cleanup = cleanup,
|
|
.test_all = verify_epoll_ctl,
|
|
};
|