xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2016 Fujitsu Ltd.
4  * Author: Guangwen Feng <[email protected]>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Basic test for epoll_wait. Check that epoll_wait works for EPOLLOUT and
11  * EPOLLIN events on an epoll instance and that struct epoll_event is set
12  * correctly.
13  */
14 
15 #include <sys/epoll.h>
16 #include <poll.h>
17 #include <string.h>
18 #include <errno.h>
19 
20 #include "tst_test.h"
21 
22 static int write_size, epfd, fds[2];
23 
get_writesize(void)24 static int get_writesize(void)
25 {
26 	int nfd, write_size = 0;
27 	char buf[4096];
28 	struct pollfd pfd[] = {
29 		{.fd = fds[1], .events = POLLOUT},
30 	};
31 
32 	memset(buf, 'a', sizeof(buf));
33 
34 	do {
35 		write_size += SAFE_WRITE(SAFE_WRITE_ANY, fds[1], buf, sizeof(buf));
36 		nfd = poll(pfd, 1, 1);
37 		if (nfd == -1)
38 			tst_brk(TBROK | TERRNO, "poll() failed");
39 	} while (nfd > 0);
40 
41 	char read_buf[write_size];
42 
43 	SAFE_READ(1, fds[0], read_buf, sizeof(read_buf));
44 
45 	tst_res(TINFO, "Pipe buffer size is %i bytes", write_size);
46 
47 	return write_size;
48 }
49 
setup(void)50 static void setup(void)
51 {
52 	static struct epoll_event epevs[2] = {
53 		{.events = EPOLLIN},
54 		{.events = EPOLLOUT},
55 	};
56 
57 	SAFE_PIPE(fds);
58 
59 	epevs[0].data.fd = fds[0];
60 	epevs[1].data.fd = fds[1];
61 
62 	write_size = get_writesize();
63 
64 	epfd = epoll_create(3);
65 	if (epfd == -1)
66 		tst_brk(TBROK | TERRNO, "epoll_create() failed");
67 
68 	if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]) ||
69 	    epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[1])) {
70 		tst_brk(TBROK | TERRNO, "epoll_ctl() failed");
71 	}
72 }
73 
has_event(struct epoll_event * epevs,int epevs_len,int fd,uint32_t events)74 static int has_event(struct epoll_event *epevs, int epevs_len,
75 		     int fd, uint32_t events)
76 {
77 	int i;
78 
79 	for (i = 0; i < epevs_len; i++) {
80 		if ((epevs[i].data.fd == fd) && (epevs[i].events == events))
81 			return 1;
82 	}
83 
84 	return 0;
85 }
86 
dump_epevs(struct epoll_event * epevs,int epevs_len)87 static void dump_epevs(struct epoll_event *epevs, int epevs_len)
88 {
89 	int i;
90 
91 	for (i = 0; i < epevs_len; i++) {
92 		tst_res(TINFO, "epevs[%d]: epoll.data.fd %d, epoll.events %x",
93 			i, epevs[i].data.fd, epevs[i].events);
94 	}
95 }
96 
verify_epollout(void)97 static void verify_epollout(void)
98 {
99 	struct epoll_event ret_evs = {.events = 0, .data.fd = 0};
100 
101 	TEST(epoll_wait(epfd, &ret_evs, 1, -1));
102 
103 	if (TST_RET == -1) {
104 		tst_res(TFAIL | TTERRNO, "epoll_wait() epollout failed");
105 		return;
106 	}
107 
108 	if (TST_RET != 1) {
109 		tst_res(TFAIL, "epoll_wait() returned %li, expected 1",
110 			TST_RET);
111 		return;
112 	}
113 
114 	if (ret_evs.data.fd != fds[1]) {
115 		tst_res(TFAIL, "epoll.data.fd %i, expected %i",
116 			ret_evs.data.fd, fds[1]);
117 		return;
118 	}
119 
120 	if (ret_evs.events != EPOLLOUT) {
121 		tst_res(TFAIL, "epoll.events %x, expected EPOLLOUT %x",
122 			ret_evs.events, EPOLLOUT);
123 		return;
124 	}
125 
126 	tst_res(TPASS, "epoll_wait() epollout");
127 }
128 
verify_epollin(void)129 static void verify_epollin(void)
130 {
131 	char write_buf[write_size];
132 	char read_buf[sizeof(write_buf)];
133 	struct epoll_event ret_evs = {.events = 0, .data.fd = 0};
134 
135 	memset(write_buf, 'a', sizeof(write_buf));
136 
137 	SAFE_WRITE(SAFE_WRITE_ALL, fds[1], write_buf, sizeof(write_buf));
138 
139 	TEST(epoll_wait(epfd, &ret_evs, 1, -1));
140 
141 	if (TST_RET == -1) {
142 		tst_res(TFAIL | TTERRNO, "epoll_wait() epollin failed");
143 		goto end;
144 	}
145 
146 	if (TST_RET != 1) {
147 		tst_res(TFAIL, "epoll_wait() returned %li, expected 1",
148 			TST_RET);
149 		goto end;
150 	}
151 
152 	if (ret_evs.data.fd != fds[0]) {
153 		tst_res(TFAIL, "epoll.data.fd %i, expected %i",
154 			ret_evs.data.fd, fds[0]);
155 		goto end;
156 	}
157 
158 	if (ret_evs.events != EPOLLIN) {
159 		tst_res(TFAIL, "epoll.events %x, expected EPOLLIN %x",
160 			ret_evs.events, EPOLLIN);
161 		goto end;
162 	}
163 
164 	tst_res(TPASS, "epoll_wait() epollin");
165 
166 end:
167 	SAFE_READ(1, fds[0], read_buf, sizeof(write_buf));
168 }
169 
verify_epollio(void)170 static void verify_epollio(void)
171 {
172 	char write_buf[] = "Testing";
173 	char read_buf[sizeof(write_buf)];
174 	uint32_t events = EPOLLIN | EPOLLOUT;
175 	struct epoll_event ret_evs[2];
176 
177 	SAFE_WRITE(SAFE_WRITE_ALL, fds[1], write_buf, sizeof(write_buf));
178 
179 	while (events) {
180 		int events_matched = 0;
181 
182 		memset(ret_evs, 0, sizeof(ret_evs));
183 		TEST(epoll_wait(epfd, ret_evs, 2, -1));
184 
185 		if (TST_RET <= 0) {
186 			tst_res(TFAIL | TTERRNO, "epoll_wait() returned %li",
187 				TST_RET);
188 			goto end;
189 		}
190 
191 		if ((events & EPOLLIN) &&
192 		    has_event(ret_evs, 2, fds[0], EPOLLIN)) {
193 			events_matched++;
194 			events &= ~EPOLLIN;
195 		}
196 
197 		if ((events & EPOLLOUT) &&
198 		    has_event(ret_evs, 2, fds[1], EPOLLOUT)) {
199 			events_matched++;
200 			events &= ~EPOLLOUT;
201 		}
202 
203 		if (TST_RET != events_matched) {
204 			tst_res(TFAIL,
205 				"epoll_wait() returned unexpected events");
206 			dump_epevs(ret_evs, 2);
207 			goto end;
208 		}
209 	}
210 
211 	tst_res(TPASS, "epoll_wait() epollio");
212 
213 end:
214 	SAFE_READ(1, fds[0], read_buf, sizeof(write_buf));
215 }
216 
cleanup(void)217 static void cleanup(void)
218 {
219 	if (epfd > 0)
220 		SAFE_CLOSE(epfd);
221 
222 	if (fds[0]) {
223 		SAFE_CLOSE(fds[0]);
224 		SAFE_CLOSE(fds[1]);
225 	}
226 }
227 
228 static void (*testcase_list[])(void) = {
229 	verify_epollout, verify_epollin, verify_epollio
230 };
231 
do_test(unsigned int n)232 static void do_test(unsigned int n)
233 {
234 	testcase_list[n]();
235 }
236 
237 static struct tst_test test = {
238 	.setup = setup,
239 	.cleanup = cleanup,
240 	.test = do_test,
241 	.tcnt = ARRAY_SIZE(testcase_list),
242 };
243