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_ctl02.c
19  *
20  * Description:
21  * 1) epoll_ctl(2) fails if epfd is a invalid file descriptor.
22  * 2) epoll_ctl(2) fails if fd is a invalid file descriptor.
23  * 3) epoll_ctl(2) fails if op is not supported by this interface.
24  * 4) epoll_ctl(2) fails if fd is the same as epfd.
25  * 5) epoll_ctl(2) fails with EPOLL_CTL_DEL if fd is not registered
26  *    with this epoll instance.
27  * 6) epoll_ctl(2) fails with EPOLL_CTL_MOD if fd is not registered
28  *    with this epoll instance.
29  * 7) epoll_ctl(2) fails with EPOLL_CTL_ADD if fd is already registered
30  *    with this epoll instance.
31  *
32  * Expected Result:
33  * 1) epoll_ctl(2) should return -1 and set errno to EBADF.
34  * 2) epoll_ctl(2) should return -1 and set errno to EBADF.
35  * 3) epoll_ctl(2) should return -1 and set errno to EINVAL.
36  * 4) epoll_ctl(2) should return -1 and set errno to EINVAL.
37  * 5) epoll_ctl(2) should return -1 and set errno to ENOENT.
38  * 6) epoll_ctl(2) should return -1 and set errno to ENOENT.
39  * 7) epoll_ctl(2) should return -1 and set errno to EEXIST.
40  *
41  */
42 #include <sys/epoll.h>
43 #include <poll.h>
44 #include <errno.h>
45 #include "tst_test.h"
46 
47 static int epfd;
48 static int fd[2];
49 static int inv = -1;
50 
51 static struct epoll_event events[2] = {
52 	{.events = EPOLLIN},
53 	{.events = EPOLLOUT},
54 };
55 
56 static struct testcase {
57 	int *epfds;
58 	int opt;
59 	int *fds;
60 	struct epoll_event *ts_event;
61 	int exp_err;
62 } tcases[] = {
63 	{&inv, EPOLL_CTL_ADD, &fd[1], &events[1], EBADF},
64 	{&epfd, EPOLL_CTL_ADD, &inv, &events[1], EBADF},
65 	{&epfd, -1, &fd[1], &events[1], EINVAL},
66 	{&epfd, EPOLL_CTL_ADD, &epfd, &events[1], EINVAL},
67 	{&epfd, EPOLL_CTL_DEL, &fd[1], &events[1], ENOENT},
68 	{&epfd, EPOLL_CTL_MOD, &fd[1], &events[1], ENOENT},
69 	{&epfd, EPOLL_CTL_ADD, &fd[0], &events[0], EEXIST}
70 };
71 
72 static void setup(void)
73 {
74 	epfd = epoll_create(2);
75 	if (epfd == -1)
76 		tst_brk(TBROK | TERRNO, "fail to create epoll instance");
77 
78 	SAFE_PIPE(fd);
79 
80 	events[0].data.fd = fd[0];
81 	events[1].data.fd = fd[1];
82 
83 	TEST(epoll_ctl(epfd, EPOLL_CTL_ADD, fd[0], &events[0]));
84 	if (TEST_RETURN == -1)
85 		tst_brk(TFAIL | TTERRNO, "epoll_ctl() fails to init");
86 }
87 
88 static void cleanup(void)
89 {
90 	if (epfd)
91 		SAFE_CLOSE(epfd);
92 
93 	if (fd[0])
94 		SAFE_CLOSE(fd[0]);
95 
96 	if (fd[1])
97 		SAFE_CLOSE(fd[1]);
98 }
99 
100 static void verify_epoll_ctl(unsigned int n)
101 {
102 	struct testcase *tc = &tcases[n];
103 
104 	TEST(epoll_ctl(*tc->epfds, tc->opt, *tc->fds,  tc->ts_event));
105 	if (TEST_RETURN != -1) {
106 		tst_res(TFAIL, "epoll_ctl() succeeds unexpectedly");
107 		return;
108 	}
109 
110 	if (tc->exp_err == TEST_ERRNO) {
111 		tst_res(TPASS | TTERRNO, "epoll_ctl() fails as expected");
112 	} else {
113 		tst_res(TFAIL | TTERRNO,
114 			"epoll_ctl() fails unexpectedly, expected %i: %s",
115 			tc->exp_err, tst_strerrno(tc->exp_err));
116 	}
117 }
118 
119 static struct tst_test test = {
120 	.tcnt = ARRAY_SIZE(tcases),
121 	.setup = setup,
122 	.cleanup = cleanup,
123 	.test = verify_epoll_ctl,
124 };
125