• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016 Fujitsu Ltd.
3  * Author: Guangwen Feng <fenggw-fnst@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 
main(int ac,char ** av)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 
setup(void)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 
get_writesize(void)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 
verify_epollout(void)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 
verify_epollin(void)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 
verify_epollio(void)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 
has_event(struct epoll_event * epevs,int epevs_len,int fd,uint32_t events)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 
dump_epevs(struct epoll_event * epevs,int epevs_len)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 
cleanup(void)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