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 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 60 static void cleanup(void) 61 { 62 if (epfd > 0) 63 SAFE_CLOSE(epfd); 64 65 if (fd[0] > 0) 66 SAFE_CLOSE(fd[0]); 67 68 if (fd[1] > 0) 69 SAFE_CLOSE(fd[1]); 70 } 71 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 85 static void check_epoll_ctl(int opt, int exp_num) 86 { 87 int res; 88 unsigned int events; 89 char write_buf[] = "test"; 90 char read_buf[sizeof(write_buf)]; 91 struct epoll_event res_evs[2]; 92 93 events = EPOLLIN; 94 if (exp_num == 2) 95 events |= EPOLLOUT; 96 97 SAFE_WRITE(1, fd[1], write_buf, sizeof(write_buf)); 98 99 while (events) { 100 int events_matched = 0; 101 bzero(res_evs, sizeof(res_evs)); 102 103 res = epoll_wait(epfd, res_evs, 2, -1); 104 if (res <= 0) { 105 tst_res(TFAIL | TERRNO, "epoll_wait() returned %i", 106 res); 107 goto end; 108 } 109 110 if ((events & EPOLLIN) && 111 has_event(res_evs, 2, fd[0], EPOLLIN)) { 112 events_matched++; 113 events &= ~EPOLLIN; 114 } 115 116 if ((events & EPOLLOUT) && 117 has_event(res_evs, 2, fd[1], EPOLLOUT)) { 118 events_matched++; 119 events &= ~EPOLLOUT; 120 } 121 122 if (res != events_matched) { 123 tst_res(TFAIL, 124 "epoll_wait() returned unexpected events"); 125 goto end; 126 } 127 } 128 129 tst_res(TPASS, "epoll_ctl() succeeds with op %i", opt); 130 131 end: 132 SAFE_READ(1, fd[0], read_buf, sizeof(write_buf)); 133 } 134 135 static void opera_epoll_ctl(int opt, int fd, struct epoll_event *epvs) 136 { 137 TEST(epoll_ctl(epfd, opt, fd, epvs)); 138 if (TEST_RETURN == -1) 139 tst_brk(TBROK | TTERRNO, "epoll_ctl() fails with op %i", opt); 140 } 141 142 static void verify_epoll_ctl(void) 143 { 144 opera_epoll_ctl(EPOLL_CTL_ADD, fd[0], &events[0]); 145 opera_epoll_ctl(EPOLL_CTL_ADD, fd[1], &events[2]); 146 check_epoll_ctl(EPOLL_CTL_ADD, 1); 147 opera_epoll_ctl(EPOLL_CTL_MOD, fd[1], &events[1]); 148 check_epoll_ctl(EPOLL_CTL_MOD, 2); 149 opera_epoll_ctl(EPOLL_CTL_DEL, fd[1], &events[1]); 150 check_epoll_ctl(EPOLL_CTL_DEL, 1); 151 opera_epoll_ctl(EPOLL_CTL_DEL, fd[0], &events[0]); 152 } 153 154 static struct tst_test test = { 155 .setup = setup, 156 .cleanup = cleanup, 157 .test_all = verify_epoll_ctl, 158 }; 159