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_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
setup(void)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
cleanup(void)60 static void cleanup(void)
61 {
62 if (epfd > 0)
63 SAFE_CLOSE(epfd);
64
65 if (fd[0] > 0)
66 SAFE_CLOSE(fd[0]);
67
68 if (fd[1] > 0)
69 SAFE_CLOSE(fd[1]);
70 }
71
has_event(struct epoll_event * epvs,int len,int fd,unsigned int events)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
check_epoll_ctl(int opt,int exp_num)85 static void check_epoll_ctl(int opt, int exp_num)
86 {
87 int res;
88 unsigned int events;
89 char write_buf[] = "test";
90 char read_buf[sizeof(write_buf)];
91 struct epoll_event res_evs[2];
92
93 events = EPOLLIN;
94 if (exp_num == 2)
95 events |= EPOLLOUT;
96
97 SAFE_WRITE(1, fd[1], write_buf, sizeof(write_buf));
98
99 while (events) {
100 int events_matched = 0;
101 bzero(res_evs, sizeof(res_evs));
102
103 res = epoll_wait(epfd, res_evs, 2, -1);
104 if (res <= 0) {
105 tst_res(TFAIL | TERRNO, "epoll_wait() returned %i",
106 res);
107 goto end;
108 }
109
110 if ((events & EPOLLIN) &&
111 has_event(res_evs, 2, fd[0], EPOLLIN)) {
112 events_matched++;
113 events &= ~EPOLLIN;
114 }
115
116 if ((events & EPOLLOUT) &&
117 has_event(res_evs, 2, fd[1], EPOLLOUT)) {
118 events_matched++;
119 events &= ~EPOLLOUT;
120 }
121
122 if (res != events_matched) {
123 tst_res(TFAIL,
124 "epoll_wait() returned unexpected events");
125 goto end;
126 }
127 }
128
129 tst_res(TPASS, "epoll_ctl() succeeds with op %i", opt);
130
131 end:
132 SAFE_READ(1, fd[0], read_buf, sizeof(write_buf));
133 }
134
opera_epoll_ctl(int opt,int fd,struct epoll_event * epvs)135 static void opera_epoll_ctl(int opt, int fd, struct epoll_event *epvs)
136 {
137 TEST(epoll_ctl(epfd, opt, fd, epvs));
138 if (TST_RET == -1)
139 tst_brk(TBROK | TTERRNO, "epoll_ctl() fails with op %i", opt);
140 }
141
verify_epoll_ctl(void)142 static void verify_epoll_ctl(void)
143 {
144 opera_epoll_ctl(EPOLL_CTL_ADD, fd[0], &events[0]);
145 opera_epoll_ctl(EPOLL_CTL_ADD, fd[1], &events[2]);
146 check_epoll_ctl(EPOLL_CTL_ADD, 1);
147 opera_epoll_ctl(EPOLL_CTL_MOD, fd[1], &events[1]);
148 check_epoll_ctl(EPOLL_CTL_MOD, 2);
149 opera_epoll_ctl(EPOLL_CTL_DEL, fd[1], &events[1]);
150 check_epoll_ctl(EPOLL_CTL_DEL, 1);
151 opera_epoll_ctl(EPOLL_CTL_DEL, fd[0], &events[0]);
152 }
153
154 static struct tst_test test = {
155 .setup = setup,
156 .cleanup = cleanup,
157 .test_all = verify_epoll_ctl,
158 };
159