blob: c8f1f53dbb3277efbd26808799a17bf577e52a45 [file] [log] [blame]
ctiller18b49ab2014-12-09 14:39:16 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * Copyright 2015, Google Inc.
ctiller18b49ab2014-12-09 14:39:16 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "src/core/iomgr/tcp_client.h"
35
36#include <errno.h>
37#include <netinet/in.h>
38#include <string.h>
39#include <sys/socket.h>
40#include <unistd.h>
41
42#include "src/core/iomgr/iomgr.h"
Craig Tiller5d8fbe22015-01-21 16:33:54 -080043#include "src/core/iomgr/socket_utils_posix.h"
ctiller18b49ab2014-12-09 14:39:16 -080044#include <grpc/support/log.h>
45#include <grpc/support/time.h>
46
Craig Tiller32946d32015-01-15 11:37:30 -080047static gpr_timespec test_deadline(void) {
ctiller58393c22015-01-07 14:03:30 -080048 return gpr_time_add(gpr_now(), gpr_time_from_seconds(10));
ctiller18b49ab2014-12-09 14:39:16 -080049}
50
51static void must_succeed(void *arg, grpc_endpoint *tcp) {
52 GPR_ASSERT(tcp);
53 grpc_endpoint_shutdown(tcp);
54 grpc_endpoint_destroy(tcp);
55 gpr_event_set(arg, (void *)1);
56}
57
58static void must_fail(void *arg, grpc_endpoint *tcp) {
59 GPR_ASSERT(!tcp);
60 gpr_event_set(arg, (void *)1);
61}
62
Craig Tiller32946d32015-01-15 11:37:30 -080063void test_succeeds(void) {
ctiller18b49ab2014-12-09 14:39:16 -080064 struct sockaddr_in addr;
65 socklen_t addr_len = sizeof(addr);
66 int svr_fd;
67 int r;
68 gpr_event ev;
69
70 gpr_event_init(&ev);
71
72 memset(&addr, 0, sizeof(addr));
73 addr.sin_family = AF_INET;
74
75 /* create a dummy server */
76 svr_fd = socket(AF_INET, SOCK_STREAM, 0);
77 GPR_ASSERT(svr_fd >= 0);
78 GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len));
79 GPR_ASSERT(0 == listen(svr_fd, 1));
80
81 /* connect to it */
82 GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0);
83 grpc_tcp_client_connect(must_succeed, &ev, (struct sockaddr *)&addr, addr_len,
84 gpr_inf_future);
85
86 /* await the connection */
87 do {
88 addr_len = sizeof(addr);
89 r = accept(svr_fd, (struct sockaddr *)&addr, &addr_len);
90 } while (r == -1 && errno == EINTR);
91 GPR_ASSERT(r >= 0);
92 close(r);
93
94 /* wait for the connection callback to finish */
95 GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
96}
97
Craig Tiller32946d32015-01-15 11:37:30 -080098void test_fails(void) {
ctiller18b49ab2014-12-09 14:39:16 -080099 struct sockaddr_in addr;
100 socklen_t addr_len = sizeof(addr);
101 gpr_event ev;
102
103 gpr_event_init(&ev);
104
105 memset(&addr, 0, sizeof(addr));
106 addr.sin_family = AF_INET;
107
108 /* connect to a broken address */
109 grpc_tcp_client_connect(must_fail, &ev, (struct sockaddr *)&addr, addr_len,
110 gpr_inf_future);
111
112 /* wait for the connection callback to finish */
113 GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
114}
115
Craig Tiller32946d32015-01-15 11:37:30 -0800116void test_times_out(void) {
ctiller18b49ab2014-12-09 14:39:16 -0800117 struct sockaddr_in addr;
118 socklen_t addr_len = sizeof(addr);
119 int svr_fd;
120#define NUM_CLIENT_CONNECTS 10
121 int client_fd[NUM_CLIENT_CONNECTS];
122 int i;
123 int r;
124 gpr_event ev;
125 gpr_timespec connect_deadline;
126
127 gpr_event_init(&ev);
128
129 memset(&addr, 0, sizeof(addr));
130 addr.sin_family = AF_INET;
131
132 /* create a dummy server */
133 svr_fd = socket(AF_INET, SOCK_STREAM, 0);
134 GPR_ASSERT(svr_fd >= 0);
135 GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len));
136 GPR_ASSERT(0 == listen(svr_fd, 1));
137 /* Get its address */
138 GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0);
139
140 /* tie up the listen buffer, which is somewhat arbitrarily sized. */
141 for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) {
Craig Tiller5d8fbe22015-01-21 16:33:54 -0800142 client_fd[i] = socket(AF_INET, SOCK_STREAM, 0);
Yang Gao5fd0d292015-01-26 00:19:48 -0800143 grpc_set_socket_nonblocking(client_fd[i], 1);
ctiller18b49ab2014-12-09 14:39:16 -0800144 do {
145 r = connect(client_fd[i], (struct sockaddr *)&addr, addr_len);
146 } while (r == -1 && errno == EINTR);
147 GPR_ASSERT(r < 0);
148 GPR_ASSERT(errno == EWOULDBLOCK || errno == EINPROGRESS);
149 }
150
151 /* connect to dummy server address */
152
153 connect_deadline = gpr_time_add(gpr_now(), gpr_time_from_micros(1000000));
154
155 grpc_tcp_client_connect(must_fail, &ev, (struct sockaddr *)&addr, addr_len,
156 connect_deadline);
157 /* Make sure the event doesn't trigger early */
158 GPR_ASSERT(!gpr_event_wait(
159 &ev, gpr_time_add(gpr_now(), gpr_time_from_micros(500000))));
160 /* Now wait until it should have triggered */
161 sleep(1);
162
163 /* wait for the connection callback to finish */
164 GPR_ASSERT(gpr_event_wait(&ev, test_deadline()));
165 close(svr_fd);
166 for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) {
167 close(client_fd[i]);
168 }
169}
170
171int main(void) {
172 grpc_iomgr_init();
173 test_succeeds();
David Klempnerbaced4d2015-02-10 17:10:15 -0800174 gpr_log(GPR_ERROR, "End of first test");
ctiller18b49ab2014-12-09 14:39:16 -0800175 test_fails();
176 test_times_out();
177 grpc_iomgr_shutdown();
178 return 0;
Craig Tiller06059952015-02-18 08:34:56 -0800179}