|
| 1 | +#include "test.h" |
| 2 | +#include <arpa/inet.h> |
| 3 | +#include <errno.h> |
| 4 | +#include <fcntl.h> |
| 5 | +#include <netdb.h> |
| 6 | +#include <netinet/in.h> |
| 7 | +#include <poll.h> |
| 8 | +#include <stdio.h> |
| 9 | +#include <stdlib.h> |
| 10 | +#include <string.h> |
| 11 | +#include <sys/socket.h> |
| 12 | +#include <unistd.h> |
| 13 | + |
| 14 | +#define TEST(c) \ |
| 15 | + do { \ |
| 16 | + errno = 0; \ |
| 17 | + if (!(c)) \ |
| 18 | + t_error("%s failed (errno = %d)\n", #c, errno); \ |
| 19 | + } while (0) |
| 20 | + |
| 21 | +int main() { |
| 22 | + char buf[10]; |
| 23 | + int listener_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); |
| 24 | + |
| 25 | + // Setup a listener bound to port 0 to have the OS assign us one. |
| 26 | + struct sockaddr_in server_address; |
| 27 | + socklen_t server_address_len = sizeof(server_address); |
| 28 | + server_address.sin_family = AF_INET; |
| 29 | + server_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 30 | + server_address.sin_port = 0; |
| 31 | + TEST(bind(listener_fd, (struct sockaddr *)&server_address, |
| 32 | + sizeof(server_address)) != -1); |
| 33 | + TEST(getsockname(listener_fd, (struct sockaddr *)&server_address, |
| 34 | + &server_address_len) != -1); |
| 35 | + TEST(listen(listener_fd, 1) != -1); |
| 36 | + |
| 37 | + // Connect a client to our server |
| 38 | + int client_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); |
| 39 | + TEST(client_fd != -1); |
| 40 | + TEST(connect(client_fd, (struct sockaddr *)&server_address, |
| 41 | + server_address_len) != -1 || |
| 42 | + errno == EINPROGRESS); |
| 43 | + |
| 44 | + // Wait for the client to be writable, signaling the connection is there. |
| 45 | + struct pollfd client, listener; |
| 46 | + client.fd = client_fd; |
| 47 | + client.events = POLLWRNORM; |
| 48 | + TEST(poll(&client, 1, -1) == 1); |
| 49 | + |
| 50 | + // Various ways of seeing that this isn't at EOF yet. |
| 51 | + TEST(read(client_fd, buf, sizeof(buf)) == -1 && errno == EWOULDBLOCK); |
| 52 | + client.events = POLLRDNORM; |
| 53 | + TEST(poll(&client, 1, 0) == 0); |
| 54 | + TEST(read(client_fd, buf, sizeof(buf)) == -1 && errno == EWOULDBLOCK); |
| 55 | + |
| 56 | + // Accept the socket on the listener, then immediately close it. |
| 57 | + int server_fd; |
| 58 | + listener.fd = listener_fd; |
| 59 | + listener.events = POLLRDNORM; |
| 60 | + TEST(poll(&listener, 1, -1) == 1); |
| 61 | + TEST((server_fd = accept(listener_fd, NULL, NULL)) != -1); |
| 62 | + TEST(close(server_fd) != -1); |
| 63 | + |
| 64 | + // Test to make sure that the client is now at EOF. |
| 65 | + TEST(poll(&client, 1, -1) == 1); |
| 66 | + TEST(read(client_fd, buf, sizeof(buf)) == 0); |
| 67 | + TEST(read(client_fd, buf, sizeof(buf)) == 0); |
| 68 | + |
| 69 | + return t_status; |
| 70 | +} |
0 commit comments