• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016 Fujitsu Ltd.
3  * Author: Xiao Yang <yangx.jy@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 
setup(void)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 
cleanup(void)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 
has_event(struct epoll_event * epvs,int len,int fd,unsigned int events)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 
check_epoll_ctl(int opt,int exp_num)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 
opera_epoll_ctl(int opt,int fd,struct epoll_event * epvs)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 
verify_epoll_ctl(void)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