]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/regression/poll/sockpoll.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / regression / poll / sockpoll.c
1 /* $FreeBSD$ */
2
3 #include <sys/poll.h>
4 #include <sys/socket.h>
5 #include <sys/stat.h>
6
7 #include <err.h>
8 #include <fcntl.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13
14 static const char *
15 decode_events(int events)
16 {
17         char *ncresult;
18         const char *result;
19
20         switch (events) {
21         case POLLIN:
22                 result = "POLLIN";
23                 break;
24         case POLLOUT:
25                 result = "POLLOUT";
26                 break;
27         case POLLIN | POLLOUT:
28                 result = "POLLIN | POLLOUT";
29                 break;
30         case POLLHUP:
31                 result = "POLLHUP";
32                 break;
33         case POLLIN | POLLHUP:
34                 result = "POLLIN | POLLHUP";
35                 break;
36         case POLLOUT | POLLHUP:
37                 result = "POLLOUT | POLLHUP";
38                 break;
39         case POLLIN | POLLOUT | POLLHUP:
40                 result = "POLLIN | POLLOUT | POLLHUP";
41                 break;
42         default:
43                 asprintf(&ncresult, "%#x", events);
44                 result = ncresult;
45                 break;
46         }
47         return (result);
48 }
49
50 static void
51 report(int num, const char *state, int expected, int got)
52 {
53         if (expected == got)
54                 printf("ok %-2d    ", num);
55         else
56                 printf("not ok %-2d", num);
57         printf(" state %s: expected %s; got %s\n",
58             state, decode_events(expected), decode_events(got));
59         fflush(stdout);
60 }
61
62 static int
63 set_nonblocking(int sck)
64 {
65         int flags;
66
67         flags = fcntl(sck, F_GETFL, 0);
68         flags |= O_NONBLOCK;
69
70         if (fcntl(sck, F_SETFL, flags))
71                 return -1;
72
73         return 0;
74 }
75
76 static char largeblock[1048576]; /* should be more than AF_UNIX sockbuf size */
77 static int fd[2];
78 static struct pollfd pfd0;
79 static struct pollfd pfd1;
80
81 void
82 setup(void)
83 {
84         if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0)
85                 err(1, "socketpair");
86         if (set_nonblocking(fd[0]) == -1)
87                 err(1, "fcntl");
88         if (set_nonblocking(fd[1]) == -1)
89                 err(1, "fcntl");
90         pfd0.fd = fd[0];
91         pfd0.events = POLLIN | POLLOUT;
92         pfd1.fd = fd[1];
93         pfd1.events = POLLIN | POLLOUT;
94 }
95
96 int
97 main(void)
98 {
99         int num;
100
101         num = 1;
102         printf("1..18\n");
103         fflush(stdout);
104
105         /* Large write with close */
106         setup();
107         if (poll(&pfd0, 1, 0) == -1)
108                 err(1, "poll");
109         report(num++, "initial 0", POLLOUT, pfd0.revents);
110         if (poll(&pfd1, 1, 0) == -1)
111                 err(1, "poll");
112         report(num++, "initial 1", POLLOUT, pfd1.revents);
113         if (write(fd[0], largeblock, sizeof(largeblock)) == -1)
114                 err(1, "write");
115         if (poll(&pfd0, 1, 0) == -1)
116                 err(1, "poll");
117         report(num++, "after large write", 0, pfd0.revents);
118         if (poll(&pfd1, 1, 0) == -1)
119                 err(1, "poll");
120         report(num++, "other side after large write", POLLIN | POLLOUT, pfd1.revents);
121         close(fd[0]);
122         if (poll(&pfd1, 1, 0) == -1)
123                 err(1, "poll");
124         report(num++, "other side after close", POLLIN | POLLHUP, pfd1.revents);
125         if (read(fd[1], largeblock, sizeof(largeblock)) == -1)
126                 err(1, "read");
127         if (poll(&pfd1, 1, 0) == -1)
128                 err(1, "poll");
129         report(num++, "other side after reading input", POLLHUP, pfd1.revents);
130         close(fd[1]);
131
132         /* With shutdown(SHUT_WR) */
133         setup();
134         if (shutdown(fd[0], SHUT_WR) == -1)
135                 err(1, "shutdown");
136         if (poll(&pfd0, 1, 0) == -1)
137                 err(1, "poll");
138         report(num++, "after shutdown(SHUT_WR)", POLLOUT, pfd0.revents);
139         if (poll(&pfd1, 1, 0) == -1)
140                 err(1, "poll");
141         report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
142         switch (read(fd[1], largeblock, sizeof(largeblock))) {
143                 case 0:
144                         break;
145                 case -1:
146                         err(1, "read after other side shutdown");
147                         break;
148                 default:
149                         errx(1, "kernel made up data that was never written");
150         }
151         if (poll(&pfd1, 1, 0) == -1)
152                 err(1, "poll");
153         report(num++, "other side after reading EOF", POLLIN | POLLOUT, pfd1.revents);
154         if (write(fd[1], largeblock, sizeof(largeblock)) == -1)
155                 err(1, "write");
156         if (poll(&pfd0, 1, 0) == -1)
157                 err(1, "poll");
158         report(num++, "after data from other side", POLLIN | POLLOUT, pfd0.revents);
159         if (poll(&pfd1, 1, 0) == -1)
160                 err(1, "poll");
161         report(num++, "after writing", POLLIN, pfd1.revents);
162         if (shutdown(fd[1], SHUT_WR) == -1)
163                 err(1, "shutdown second");
164         if (poll(&pfd0, 1, 0) == -1)
165                 err(1, "poll");
166         report(num++, "after second shutdown", POLLIN | POLLHUP, pfd0.revents);
167         if (poll(&pfd1, 1, 0) == -1)
168                 err(1, "poll");
169         report(num++, "after second shutdown", POLLHUP, pfd1.revents);
170         close(fd[0]);
171         if (poll(&pfd1, 1, 0) == -1)
172                 err(1, "poll");
173         report(num++, "after close", POLLHUP, pfd1.revents);
174         close(fd[1]);
175
176         /*
177          * With shutdown(SHUT_RD)
178          * Note that shutdown(SHUT_WR) is passed to the peer, but
179          * shutdown(SHUT_RD) is not.
180          */
181         setup();
182         if (shutdown(fd[0], SHUT_RD) == -1)
183                 err(1, "shutdown");
184         if (poll(&pfd0, 1, 0) == -1)
185                 err(1, "poll");
186         report(num++, "after shutdown(SHUT_RD)", POLLIN | POLLOUT, pfd0.revents);
187         if (poll(&pfd1, 1, 0) == -1)
188                 err(1, "poll");
189         report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents);
190         if (shutdown(fd[0], SHUT_WR) == -1)
191                 err(1, "shutdown");
192         if (poll(&pfd0, 1, 0) == -1)
193                 err(1, "poll");
194         report(num++, "after shutdown(SHUT_WR)", POLLHUP, pfd0.revents);
195         if (poll(&pfd1, 1, 0) == -1)
196                 err(1, "poll");
197         report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
198         close(fd[0]);
199         close(fd[1]);
200
201         return (0);
202 }