1 /* $NetBSD: t_epoll.c,v 1.2 2023/07/30 18:31:14 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2023 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Theodore Preduta. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: t_epoll.c,v 1.2 2023/07/30 18:31:14 christos Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/types.h> 36 #include <sys/epoll.h> 37 #include <sys/fcntl.h> 38 #include <errno.h> 39 40 #include <atf-c.h> 41 42 #include "h_macros.h" 43 44 ATF_TC(create_size); 45 ATF_TC_HEAD(create_size, tc) 46 { 47 48 atf_tc_set_md_var(tc, "descr", 49 "Checks that epoll_create requires a non-positive size"); 50 } 51 ATF_TC_BODY(create_size, tc) 52 { 53 ATF_REQUIRE_EQ_MSG(epoll_create(-1), -1, 54 "epoll_create succeeded unexpectedly"); 55 ATF_REQUIRE_ERRNO(EINVAL, true); 56 57 ATF_REQUIRE_EQ_MSG(epoll_create(0), -1, 58 "epoll_create succeeded unexpectedly"); 59 ATF_REQUIRE_ERRNO(EINVAL, true); 60 61 RL(epoll_create(1)); 62 } 63 64 ATF_TC(create_cloexec); 65 ATF_TC_HEAD(create_cloexec, tc) 66 { 67 68 atf_tc_set_md_var(tc, "descr", 69 "Checks that epoll_create1 sets close on exec when desired"); 70 } 71 ATF_TC_BODY(create_cloexec, tc) 72 { 73 int fd; 74 75 RL(fd = epoll_create1(0)); 76 ATF_REQUIRE_MSG((fcntl(fd, F_GETFD) & FD_CLOEXEC) == 0, 77 "Close on exec set unexpectedly."); 78 79 RL(fd = epoll_create1(EPOLL_CLOEXEC)); 80 ATF_REQUIRE_MSG((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0, 81 "Close on exec was not set."); 82 } 83 84 ATF_TC(bad_epfd); 85 ATF_TC_HEAD(bad_epfd, tc) 86 { 87 88 atf_tc_set_md_var(tc, "descr", 89 "Checks that epoll_ctl detects an invalid epfd"); 90 } 91 ATF_TC_BODY(bad_epfd, tc) 92 { 93 int fd; 94 struct epoll_event event; 95 96 RL(fd = epoll_create1(0)); 97 event.events = EPOLLIN; 98 99 ATF_REQUIRE_EQ_MSG(epoll_ctl(-1, EPOLL_CTL_ADD, fd, &event), -1, 100 "epoll_ctl succeeded unexpectedly"); 101 ATF_REQUIRE_ERRNO(EBADF, true); 102 } 103 104 ATF_TC(bad_fd); 105 ATF_TC_HEAD(bad_fd, tc) 106 { 107 108 atf_tc_set_md_var(tc, "descr", 109 "Checks that epoll_ctl detects an invalid fd"); 110 } 111 ATF_TC_BODY(bad_fd, tc) 112 { 113 int epfd; 114 struct epoll_event event; 115 116 RL(epfd = epoll_create1(0)); 117 event.events = EPOLLIN; 118 119 ATF_REQUIRE_EQ_MSG(epoll_ctl(epfd, EPOLL_CTL_ADD, -1, &event), -1, 120 "epoll_ctl succeeded unexpectedly"); 121 ATF_REQUIRE_ERRNO(EBADF, true); 122 } 123 124 ATF_TC(double_add); 125 ATF_TC_HEAD(double_add, tc) 126 { 127 128 atf_tc_set_md_var(tc, "descr", 129 "Checks that epoll_ctl detects if a fd has already been added"); 130 } 131 ATF_TC_BODY(double_add, tc) 132 { 133 int epfd, fd; 134 struct epoll_event event; 135 136 RL(epfd = epoll_create1(0)); 137 RL(fd = epoll_create1(0)); 138 event.events = EPOLLIN; 139 140 RL(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event)); 141 142 ATF_REQUIRE_EQ_MSG(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event), -1, 143 "epoll_ctl succeeded unexpectedly"); 144 ATF_REQUIRE_ERRNO(EEXIST, true); 145 } 146 147 ATF_TC(not_added); 148 ATF_TC_HEAD(not_added, tc) 149 { 150 151 atf_tc_set_md_var(tc, "descr", 152 "Checks that epoll_ctl detects if a fd has not been added"); 153 } 154 ATF_TC_BODY(not_added, tc) 155 { 156 int epfd, fd; 157 struct epoll_event event; 158 159 RL(epfd = epoll_create1(0)); 160 RL(fd = epoll_create1(0)); 161 event.events = EPOLLIN; 162 163 ATF_REQUIRE_EQ_MSG(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &event), -1, 164 "epoll_ctl succeeded unexpectedly"); 165 ATF_REQUIRE_ERRNO(ENOENT, true); 166 167 ATF_REQUIRE_EQ_MSG(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL), -1, 168 "epoll_ctl succeeded unexpectedly"); 169 ATF_REQUIRE_ERRNO(ENOENT, true); 170 } 171 172 ATF_TC(watching_self); 173 ATF_TC_HEAD(watching_self, tc) 174 { 175 176 atf_tc_set_md_var(tc, "descr", 177 "Checks that epoll disallows watching itself"); 178 } 179 ATF_TC_BODY(watching_self, tc) 180 { 181 int epfd; 182 struct epoll_event event; 183 184 RL(epfd = epoll_create1(0)); 185 ATF_REQUIRE_EQ_MSG(epoll_ctl(epfd, EPOLL_CTL_ADD, epfd, &event), -1, 186 "epoll_ctl succeeded unexpectedly"); 187 ATF_REQUIRE_ERRNO(EINVAL, true); 188 } 189 190 ATF_TC(watch_loops); 191 ATF_TC_HEAD(watch_loops, tc) 192 { 193 194 atf_tc_set_md_var(tc, "descr", "Checks that epoll disallows loops"); 195 } 196 ATF_TC_BODY(watch_loops, tc) 197 { 198 int epfd1, epfd2; 199 struct epoll_event event; 200 201 event.events = EPOLLIN; 202 RL(epfd1 = epoll_create1(0)); 203 RL(epfd2 = epoll_create1(0)); 204 RL(epoll_ctl(epfd1, EPOLL_CTL_ADD, epfd2, &event)); 205 ATF_REQUIRE_EQ_MSG(epoll_ctl(epfd2, EPOLL_CTL_ADD, epfd1, &event), -1, 206 "epoll_ctl succeeded unexpectedly"); 207 ATF_REQUIRE_ERRNO(ELOOP, true); 208 } 209 210 ATF_TC(watch_depth); 211 ATF_TC_HEAD(watch_depth, tc) 212 { 213 214 atf_tc_set_md_var(tc, "descr", 215 "Checks that epoll fails when the watch depth exceeds 5"); 216 } 217 ATF_TC_BODY(watch_depth, tc) 218 { 219 int epfd, tmp; 220 struct epoll_event event; 221 222 event.events = EPOLLIN; 223 RL(epfd = epoll_create1(0)); 224 for (size_t i = 0; i < 4; i++) { 225 RL(tmp = epoll_create1(0)); 226 RL(epoll_ctl(tmp, EPOLL_CTL_ADD, epfd, &event)); 227 epfd = tmp; 228 } 229 RL(tmp = epoll_create1(0)); 230 ATF_REQUIRE_EQ_MSG(epoll_ctl(tmp, EPOLL_CTL_ADD, epfd, &event), -1, 231 "epoll_ctl succeeded unexpectedly"); 232 ATF_REQUIRE_ERRNO(EINVAL, true); 233 } 234 235 ATF_TP_ADD_TCS(tp) 236 { 237 ATF_TP_ADD_TC(tp, create_size); 238 ATF_TP_ADD_TC(tp, create_cloexec); 239 ATF_TP_ADD_TC(tp, bad_epfd); 240 ATF_TP_ADD_TC(tp, bad_fd); 241 ATF_TP_ADD_TC(tp, not_added); 242 ATF_TP_ADD_TC(tp, watching_self); 243 ATF_TP_ADD_TC(tp, watch_loops); 244 ATF_TP_ADD_TC(tp, watch_depth); 245 246 return atf_no_error(); 247 } 248