Home | History | Annotate | Download | only in epoll_ctl
      1 /*
      2  * Copyright (c) 2016 Fujitsu Ltd.
      3  * Author: Xiao Yang <yangx.jy (at) cn.fujitsu.com>
      4  *
      5  * This program is free software; you can redistribute it and/or modify it
      6  * under the terms of version 2 of the GNU General Public License as
      7  * published by the Free Software Foundation.
      8  *
      9  * This program is distributed in the hope that it would be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * alone with this program.
     15  */
     16 
     17 /*
     18  * Test Name: epoll_ctl01.c
     19  *
     20  * Description:
     21  *    Testcase to check the basic functionality of the epoll_ctl(2).
     22  * 1) when epoll_ctl(2) succeeds to register fd on the epoll instance and
     23  *    associates event with fd, epoll_wait(2) will get registered fd and
     24  *    event correctly.
     25  * 2) when epoll_ctl(2) succeeds to chage event which is related to fd,
     26  *    epoll_wait(2) will get chaged event correctly.
     27  * 3) when epoll_ctl(2) succeeds to deregister fd from the epoll instance
     28  *    epoll_wait(2) won't get deregistered fd and event.
     29  *
     30  */
     31 
     32 #include <sys/epoll.h>
     33 #include <poll.h>
     34 #include <string.h>
     35 #include <errno.h>
     36 #include "tst_test.h"
     37 
     38 static int epfd;
     39 static int fd[2];
     40 
     41 static struct epoll_event events[3] = {
     42 	{.events = EPOLLIN},
     43 	{.events = EPOLLOUT},
     44 	{.events = EPOLLIN}
     45 };
     46 
     47 static void setup(void)
     48 {
     49 	epfd = epoll_create(2);
     50 	if (epfd == -1)
     51 		tst_brk(TBROK | TERRNO, "fail to create epoll instance");
     52 
     53 	SAFE_PIPE(fd);
     54 
     55 	events[0].data.fd = fd[0];
     56 	events[1].data.fd = fd[1];
     57 	events[2].data.fd = fd[1];
     58 }
     59 
     60 static void cleanup(void)
     61 {
     62 	if (epfd > 0 && close(epfd))
     63 		tst_res(TWARN | TERRNO, "failed to close epoll instance");
     64 
     65 	if (fd[0] > 0 && close(fd[0]))
     66 		tst_res(TWARN | TERRNO, "failed to close pipe");
     67 
     68 	if (fd[1] > 0 && close(fd[1]))
     69 		tst_res(TWARN | TERRNO, "failed to close pipe");
     70 }
     71 
     72 static int has_event(struct epoll_event *epvs, int len,
     73 	int fd, unsigned int events)
     74 {
     75 	int i;
     76 
     77 	for (i = 0; i < len; i++) {
     78 		if ((epvs[i].data.fd == fd) && (epvs[i].events == events))
     79 			return 1;
     80 	}
     81 
     82 	return 0;
     83 }
     84 
     85 static void check_epoll_ctl(int opt, int exp_num)
     86 {
     87 	int res;
     88 
     89 	char write_buf[] = "test";
     90 	char read_buf[sizeof(write_buf)];
     91 
     92 	struct epoll_event res_evs[2] = {
     93 		{.events = 0, .data.fd = 0},
     94 		{.events = 0, .data.fd = 0}
     95 	};
     96 
     97 	SAFE_WRITE(1, fd[1], write_buf, sizeof(write_buf));
     98 
     99 	res = epoll_wait(epfd, res_evs, 2, -1);
    100 	if (res == -1)
    101 		tst_brk(TBROK | TERRNO, "epoll_wait() fails");
    102 
    103 	if (res != exp_num) {
    104 		tst_res(TFAIL, "epoll_wait() returns %i, expected %i",
    105 			res, exp_num);
    106 		goto end;
    107 	}
    108 
    109 	if (exp_num == 1) {
    110 		if (!has_event(res_evs, 2, fd[0], EPOLLIN) ||
    111 		    !has_event(res_evs, 2, 0, 0)) {
    112 			tst_res(TFAIL, "epoll_wait() fails to "
    113 				"get expected fd and event");
    114 			goto end;
    115 		}
    116 	}
    117 
    118 	if (exp_num == 2) {
    119 		if (!has_event(res_evs, 2, fd[0], EPOLLIN) ||
    120 		    !has_event(res_evs, 2, fd[1], EPOLLOUT)) {
    121 			tst_res(TFAIL, "epoll_wait() fails to "
    122 				"get expected fd and event");
    123 			goto end;
    124 		}
    125 	}
    126 
    127 	tst_res(TPASS, "epoll_ctl() succeeds with op %i", opt);
    128 
    129 end:
    130 	SAFE_READ(1, fd[0], read_buf, sizeof(write_buf));
    131 }
    132 
    133 static void opera_epoll_ctl(int opt, int fd, struct epoll_event *epvs)
    134 {
    135 	TEST(epoll_ctl(epfd, opt, fd, epvs));
    136 	if (TEST_RETURN == -1)
    137 		tst_brk(TBROK | TTERRNO, "epoll_ctl() fails with op %i", opt);
    138 }
    139 
    140 static void verify_epoll_ctl(void)
    141 {
    142 	opera_epoll_ctl(EPOLL_CTL_ADD, fd[0], &events[0]);
    143 	opera_epoll_ctl(EPOLL_CTL_ADD, fd[1], &events[2]);
    144 	check_epoll_ctl(EPOLL_CTL_ADD, 1);
    145 	opera_epoll_ctl(EPOLL_CTL_MOD, fd[1], &events[1]);
    146 	check_epoll_ctl(EPOLL_CTL_MOD, 2);
    147 	opera_epoll_ctl(EPOLL_CTL_DEL, fd[1], &events[1]);
    148 	check_epoll_ctl(EPOLL_CTL_DEL, 1);
    149 	opera_epoll_ctl(EPOLL_CTL_DEL, fd[0], &events[0]);
    150 }
    151 
    152 static struct tst_test test = {
    153 	.tid = "epoll_ctl01",
    154 	.setup = setup,
    155 	.cleanup = cleanup,
    156 	.test_all = verify_epoll_ctl,
    157 };
    158