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 "tst_test.h" 32 33 static int write_size, epfd, fds[2]; 34 35 static int get_writesize(void) 36 { 37 int nfd, write_size = 0; 38 char buf[4096]; 39 struct pollfd pfd[] = { 40 {.fd = fds[1], .events = POLLOUT}, 41 }; 42 43 memset(buf, 'a', sizeof(buf)); 44 45 do { 46 write_size += SAFE_WRITE(0, fds[1], buf, sizeof(buf)); 47 nfd = poll(pfd, 1, 1); 48 if (nfd == -1) 49 tst_brk(TBROK | TERRNO, "poll() failed"); 50 } while (nfd > 0); 51 52 char read_buf[write_size]; 53 54 SAFE_READ(1, fds[0], read_buf, sizeof(read_buf)); 55 56 tst_res(TINFO, "Pipe buffer size is %i bytes", write_size); 57 58 return write_size; 59 } 60 61 static void setup(void) 62 { 63 static struct epoll_event epevs[2] = { 64 {.events = EPOLLIN}, 65 {.events = EPOLLOUT}, 66 }; 67 68 SAFE_PIPE(fds); 69 70 epevs[0].data.fd = fds[0]; 71 epevs[1].data.fd = fds[1]; 72 73 write_size = get_writesize(); 74 75 epfd = epoll_create(3); 76 if (epfd == -1) 77 tst_brk(TBROK | TERRNO, "epoll_create() failed"); 78 79 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]) || 80 epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[1])) { 81 tst_brk(TBROK | TERRNO, "epoll_ctl() failed"); 82 } 83 } 84 85 static int has_event(struct epoll_event *epevs, int epevs_len, 86 int fd, uint32_t events) 87 { 88 int i; 89 90 for (i = 0; i < epevs_len; i++) { 91 if ((epevs[i].data.fd == fd) && (epevs[i].events == events)) 92 return 1; 93 } 94 95 return 0; 96 } 97 98 static void dump_epevs(struct epoll_event *epevs, int epevs_len) 99 { 100 int i; 101 102 for (i = 0; i < epevs_len; i++) { 103 tst_res(TINFO, "epevs[%d]: epoll.data.fd %d, epoll.events %x", 104 i, epevs[i].data.fd, epevs[i].events); 105 } 106 } 107 108 static void verify_epollout(void) 109 { 110 struct epoll_event ret_evs = {.events = 0, .data.fd = 0}; 111 112 TEST(epoll_wait(epfd, &ret_evs, 1, -1)); 113 114 if (TEST_RETURN == -1) { 115 tst_res(TFAIL | TTERRNO, "epoll_wait() epollout failed"); 116 return; 117 } 118 119 if (TEST_RETURN != 1) { 120 tst_res(TFAIL, "epoll_wait() returned %li, expected 1", 121 TEST_RETURN); 122 return; 123 } 124 125 if (ret_evs.data.fd != fds[1]) { 126 tst_res(TFAIL, "epoll.data.fd %i, expected %i", 127 ret_evs.data.fd, fds[1]); 128 return; 129 } 130 131 if (ret_evs.events != EPOLLOUT) { 132 tst_res(TFAIL, "epoll.events %x, expected EPOLLOUT %x", 133 ret_evs.events, EPOLLOUT); 134 return; 135 } 136 137 tst_res(TPASS, "epoll_wait() epollout"); 138 } 139 140 static void verify_epollin(void) 141 { 142 char write_buf[write_size]; 143 char read_buf[sizeof(write_buf)]; 144 struct epoll_event ret_evs = {.events = 0, .data.fd = 0}; 145 146 memset(write_buf, 'a', sizeof(write_buf)); 147 148 SAFE_WRITE(1, fds[1], write_buf, sizeof(write_buf)); 149 150 TEST(epoll_wait(epfd, &ret_evs, 1, -1)); 151 152 if (TEST_RETURN == -1) { 153 tst_res(TFAIL | TTERRNO, "epoll_wait() epollin failed"); 154 goto end; 155 } 156 157 if (TEST_RETURN != 1) { 158 tst_res(TFAIL, "epoll_wait() returned %li, expected 1", 159 TEST_RETURN); 160 goto end; 161 } 162 163 if (ret_evs.data.fd != fds[0]) { 164 tst_res(TFAIL, "epoll.data.fd %i, expected %i", 165 ret_evs.data.fd, fds[0]); 166 goto end; 167 } 168 169 if (ret_evs.events != EPOLLIN) { 170 tst_res(TFAIL, "epoll.events %x, expected EPOLLIN %x", 171 ret_evs.events, EPOLLIN); 172 goto end; 173 } 174 175 tst_res(TPASS, "epoll_wait() epollin"); 176 177 end: 178 SAFE_READ(1, fds[0], read_buf, sizeof(write_buf)); 179 } 180 181 static void verify_epollio(void) 182 { 183 char write_buf[] = "Testing"; 184 char read_buf[sizeof(write_buf)]; 185 uint32_t events = EPOLLIN | EPOLLOUT; 186 struct epoll_event ret_evs[2]; 187 188 SAFE_WRITE(1, fds[1], write_buf, sizeof(write_buf)); 189 190 while (events) { 191 int events_matched = 0; 192 193 bzero(ret_evs, sizeof(ret_evs)); 194 TEST(epoll_wait(epfd, ret_evs, 2, -1)); 195 196 if (TEST_RETURN <= 0) { 197 tst_res(TFAIL | TTERRNO, "epoll_wait() returned %li", 198 TEST_RETURN); 199 goto end; 200 } 201 202 if ((events & EPOLLIN) && 203 has_event(ret_evs, 2, fds[0], EPOLLIN)) { 204 events_matched++; 205 events &= ~EPOLLIN; 206 } 207 208 if ((events & EPOLLOUT) && 209 has_event(ret_evs, 2, fds[1], EPOLLOUT)) { 210 events_matched++; 211 events &= ~EPOLLOUT; 212 } 213 214 if (TEST_RETURN != events_matched) { 215 tst_res(TFAIL, 216 "epoll_wait() returned unexpected events"); 217 dump_epevs(ret_evs, 2); 218 goto end; 219 } 220 } 221 222 tst_res(TPASS, "epoll_wait() epollio"); 223 224 end: 225 SAFE_READ(1, fds[0], read_buf, sizeof(write_buf)); 226 } 227 228 static void cleanup(void) 229 { 230 if (epfd > 0) 231 SAFE_CLOSE(epfd); 232 233 if (fds[0]) { 234 SAFE_CLOSE(fds[0]); 235 SAFE_CLOSE(fds[1]); 236 } 237 } 238 239 static void do_test(unsigned int n) 240 { 241 switch (n) { 242 case 0: 243 verify_epollout(); 244 break; 245 case 1: 246 verify_epollin(); 247 break; 248 case 2: 249 verify_epollio(); 250 break; 251 } 252 } 253 254 static struct tst_test test = { 255 .setup = setup, 256 .cleanup = cleanup, 257 .test = do_test, 258 .tcnt = 3, 259 }; 260