1 /* 2 * Copyright (c) 2016 Fujitsu Ltd. 3 * Author: Xiao Yang <yangx.jy (at) 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 && 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 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 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 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 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