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
47static int epfd;
48static int fd[2];
49static int inv = -1;
50
51static struct epoll_event events[2] = {
52	{.events = EPOLLIN},
53	{.events = EPOLLOUT},
54};
55
56static 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
72static 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
88static 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
100static 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
119static struct tst_test test = {
120	.tid = "epoll_ctl02",
121	.tcnt = ARRAY_SIZE(tcases),
122	.setup = setup,
123	.cleanup = cleanup,
124	.test = verify_epoll_ctl,
125};
126