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 44ATF_TC(create_size); 45ATF_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} 51ATF_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 64ATF_TC(create_cloexec); 65ATF_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} 71ATF_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 84ATF_TC(bad_epfd); 85ATF_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} 91ATF_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 104ATF_TC(bad_fd); 105ATF_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} 111ATF_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 124ATF_TC(double_add); 125ATF_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} 131ATF_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 147ATF_TC(not_added); 148ATF_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} 154ATF_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 172ATF_TC(watching_self); 173ATF_TC_HEAD(watching_self, tc) 174{ 175 176 atf_tc_set_md_var(tc, "descr", 177 "Checks that epoll disallows watching itself"); 178} 179ATF_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 190ATF_TC(watch_loops); 191ATF_TC_HEAD(watch_loops, tc) 192{ 193 194 atf_tc_set_md_var(tc, "descr", "Checks that epoll disallows loops"); 195} 196ATF_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 210ATF_TC(watch_depth); 211ATF_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} 217ATF_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 235ATF_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