Home | History | Annotate | Download | only in epoll_wait
      1 /*
      2  * Copyright (c) 2016 Fujitsu Ltd.
      3  * Author: Guangwen Feng <fenggw-fnst (at) cn.fujitsu.com>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 2 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
     13  * the GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program.
     17  */
     18 
     19 /*
     20  * Description:
     21  *  Basic test for epoll_wait(2).
     22  *  Check that epoll_wait(2) works for EPOLLOUT and EPOLLIN events
     23  *  on a epoll instance and that struct epoll_event is set correctly.
     24  */
     25 
     26 #include <sys/epoll.h>
     27 #include <poll.h>
     28 #include <string.h>
     29 #include <errno.h>
     30 
     31 #include "test.h"
     32 #include "safe_macros.h"
     33 
     34 char *TCID = "epoll_wait01";
     35 int TST_TOTAL = 3;
     36 
     37 static int write_size, epfd, fds[2], fds2[2];
     38 static struct epoll_event epevs[3] = {
     39 	{.events = EPOLLIN},
     40 	{.events = EPOLLOUT},
     41 	{.events = EPOLLIN}
     42 };
     43 
     44 static void setup(void);
     45 static int get_writesize(void);
     46 static void verify_epollout(void);
     47 static void verify_epollin(void);
     48 static void verify_epollio(void);
     49 static int has_event(struct epoll_event *, int, int, uint32_t);
     50 static void dump_epevs(struct epoll_event *, int);
     51 static void cleanup(void);
     52 
     53 int main(int ac, char **av)
     54 {
     55 	int lc;
     56 
     57 	tst_parse_opts(ac, av, NULL, NULL);
     58 
     59 	setup();
     60 
     61 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     62 		tst_count = 0;
     63 
     64 		verify_epollout();
     65 		verify_epollin();
     66 		verify_epollio();
     67 	}
     68 
     69 	cleanup();
     70 	tst_exit();
     71 }
     72 
     73 static void setup(void)
     74 {
     75 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
     76 
     77 	TEST_PAUSE;
     78 
     79 	SAFE_PIPE(NULL, fds);
     80 	SAFE_PIPE(cleanup, fds2);
     81 
     82 	write_size = get_writesize();
     83 
     84 	epfd = epoll_create(3);
     85 	if (epfd == -1) {
     86 		tst_brkm(TBROK | TERRNO, cleanup,
     87 			 "failed to create epoll instance");
     88 	}
     89 
     90 	epevs[0].data.fd = fds[0];
     91 	epevs[1].data.fd = fds[1];
     92 	epevs[2].data.fd = fds2[0];
     93 
     94 	if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]) ||
     95 	    epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[1]) ||
     96 	    epoll_ctl(epfd, EPOLL_CTL_ADD, fds2[0], &epevs[2])) {
     97 		tst_brkm(TBROK | TERRNO, cleanup,
     98 			 "failed to register epoll target");
     99 	}
    100 }
    101 
    102 static int get_writesize(void)
    103 {
    104 	int nfd, write_size = 0;
    105 	char buf[4096];
    106 
    107 	struct pollfd pfd[] = {
    108 		{.fd = fds[1], .events = POLLOUT},
    109 	};
    110 
    111 	memset(buf, 'a', sizeof(buf));
    112 
    113 	do {
    114 		write_size += SAFE_WRITE(cleanup, 0, fds[1], buf, sizeof(buf));
    115 		nfd = poll(pfd, 1, 1);
    116 		if (nfd == -1)
    117 			tst_brkm(TBROK | TERRNO, cleanup, "poll failed");
    118 	} while (nfd > 0);
    119 
    120 	char read_buf[write_size];
    121 
    122 	SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(read_buf));
    123 
    124 	tst_resm(TINFO, "Pipe buffer size is %i bytes", write_size);
    125 
    126 	return write_size;
    127 }
    128 
    129 static void verify_epollout(void)
    130 {
    131 	TEST(epoll_wait(epfd, epevs, 3, -1));
    132 
    133 	if (TEST_RETURN == -1) {
    134 		tst_resm(TFAIL | TTERRNO, "epoll_wait() epollout failed");
    135 		return;
    136 	}
    137 
    138 	if (TEST_RETURN != 1) {
    139 		tst_resm(TFAIL, "epoll_wait() returned %li, expected 1",
    140 			 TEST_RETURN);
    141 		return;
    142 	}
    143 
    144 	if (epevs[0].data.fd != fds[1]) {
    145 		tst_resm(TFAIL, "epoll.data.fd %i, expected %i",
    146 			 epevs[0].data.fd, fds[1]);
    147 		return;
    148 	}
    149 
    150 	if (epevs[0].events != EPOLLOUT) {
    151 		tst_resm(TFAIL, "epoll.events %x, expected EPOLLOUT %x",
    152 			 epevs[0].events, EPOLLOUT);
    153 		return;
    154 	}
    155 
    156 	tst_resm(TPASS, "epoll_wait() epollout");
    157 }
    158 
    159 static void verify_epollin(void)
    160 {
    161 	char write_buf[write_size];
    162 	char read_buf[sizeof(write_buf)];
    163 
    164 	memset(write_buf, 'a', sizeof(write_buf));
    165 
    166 	SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf));
    167 
    168 	TEST(epoll_wait(epfd, epevs, 3, -1));
    169 
    170 	if (TEST_RETURN == -1) {
    171 		tst_resm(TFAIL | TTERRNO, "epoll_wait() epollin failed");
    172 		goto end;
    173 	}
    174 
    175 	if (TEST_RETURN != 1) {
    176 		tst_resm(TFAIL, "epoll_wait() returned %li, expected 1",
    177 			 TEST_RETURN);
    178 		goto end;
    179 	}
    180 
    181 	if (epevs[0].data.fd != fds[0]) {
    182 		tst_resm(TFAIL, "epoll.data.fd %i, expected %i",
    183 			 epevs[0].data.fd, fds[0]);
    184 		goto end;
    185 	}
    186 
    187 	if (epevs[0].events != EPOLLIN) {
    188 		tst_resm(TFAIL, "epoll.events %x, expected EPOLLIN %x",
    189 			 epevs[0].events, EPOLLIN);
    190 		goto end;
    191 	}
    192 
    193 	tst_resm(TPASS, "epoll_wait() epollin");
    194 
    195 end:
    196 	SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf));
    197 }
    198 
    199 static void verify_epollio(void)
    200 {
    201 	char write_buf[] = "Testing";
    202 	char read_buf[sizeof(write_buf)];
    203 
    204 	SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf));
    205 
    206 	TEST(epoll_wait(epfd, epevs, 3, -1));
    207 
    208 	if (TEST_RETURN == -1) {
    209 		tst_resm(TFAIL | TTERRNO, "epoll_wait() epollio failed");
    210 		goto end;
    211 	}
    212 
    213 	if (TEST_RETURN != 2) {
    214 		tst_resm(TFAIL, "epoll_wait() returned %li, expected 2",
    215 			 TEST_RETURN);
    216 		goto end;
    217 	}
    218 
    219 	if (!has_event(epevs, 2, fds[0], EPOLLIN)) {
    220 		dump_epevs(epevs, 2);
    221 		tst_resm(TFAIL, "epoll_wait() expected %d and EPOLLIN %x",
    222 			 fds[0], EPOLLIN);
    223 		goto end;
    224 	}
    225 
    226 	if (!has_event(epevs, 2, fds[1], EPOLLOUT)) {
    227 		dump_epevs(epevs, 2);
    228 		tst_resm(TFAIL, "epoll_wait() expected %d and EPOLLOUT %x",
    229 			 fds[1], EPOLLOUT);
    230 		goto end;
    231 	}
    232 
    233 	tst_resm(TPASS, "epoll_wait() epollio");
    234 
    235 end:
    236 	SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf));
    237 }
    238 
    239 static int has_event(struct epoll_event *epevs, int epevs_len,
    240 	int fd, uint32_t events)
    241 {
    242 	int i;
    243 
    244 	for (i = 0; i < epevs_len; i++) {
    245 		if ((epevs[i].data.fd == fd) && (epevs[i].events == events))
    246 			return 1;
    247 	}
    248 
    249 	return 0;
    250 }
    251 
    252 static void dump_epevs(struct epoll_event *epevs, int epevs_len)
    253 {
    254 	int i;
    255 
    256 	for (i = 0; i < epevs_len; i++) {
    257 		tst_resm(TINFO, "epevs[%d]: epoll.data.fd %d, epoll.events %x",
    258 			 i, epevs[i].data.fd, epevs[i].events);
    259 	}
    260 }
    261 
    262 static void cleanup(void)
    263 {
    264 	if (epfd > 0 && close(epfd))
    265 		tst_resm(TWARN | TERRNO, "failed to close epfd");
    266 
    267 	if (close(fds[0]))
    268 		tst_resm(TWARN | TERRNO, "failed to close fds[0]");
    269 
    270 	if (close(fds[1]))
    271 		tst_resm(TWARN | TERRNO, "failed to close fds[1]");
    272 
    273 	if (fds2[0] > 0 && close(fds2[0]))
    274 		tst_resm(TWARN | TERRNO, "failed to close fds2[0]");
    275 
    276 	if (fds2[1] > 0 && close(fds2[1]))
    277 		tst_resm(TWARN | TERRNO, "failed to close fds2[1]");
    278 }
    279