tcp_client_posix_test.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
21 
22 // This test won't work except with posix sockets enabled
23 #ifdef GRPC_POSIX_SOCKET_TCP_CLIENT
24 
25 #include <errno.h>
26 #include <netinet/in.h>
27 #include <string.h>
28 #include <sys/socket.h>
29 #include <unistd.h>
30 
31 #include <grpc/grpc.h>
32 #include <grpc/support/alloc.h>
33 #include <grpc/support/log.h>
34 #include <grpc/support/time.h>
35 
43 
44 static grpc_pollset_set* g_pollset_set;
45 static gpr_mu* g_mu;
46 static grpc_pollset* g_pollset;
47 static int g_connections_complete = 0;
48 static grpc_endpoint* g_connecting = nullptr;
49 
53 }
54 
55 static void finish_connection() {
57  g_connections_complete++;
59  GPR_ASSERT(
60  GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(g_pollset, nullptr)));
61 
63 }
64 
65 static void must_succeed(void* /*arg*/, grpc_error_handle error) {
66  GPR_ASSERT(g_connecting != nullptr);
69  "must_succeed called"));
70  grpc_endpoint_destroy(g_connecting);
71  g_connecting = nullptr;
72  finish_connection();
73 }
74 
75 static void must_fail(void* /*arg*/, grpc_error_handle error) {
76  GPR_ASSERT(g_connecting == nullptr);
78  finish_connection();
79 }
80 
81 void test_succeeds(void) {
82  gpr_log(GPR_ERROR, "---- starting test_succeeds() ----");
83  grpc_resolved_address resolved_addr;
84  struct sockaddr_in* addr =
85  reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
86  int svr_fd;
87  int r;
88  int connections_complete_before;
91 
92  memset(&resolved_addr, 0, sizeof(resolved_addr));
93  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
94  addr->sin_family = AF_INET;
95 
96  /* create a phony server */
97  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
98  GPR_ASSERT(svr_fd >= 0);
99  GPR_ASSERT(
100  0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len));
101  GPR_ASSERT(0 == listen(svr_fd, 1));
102 
103  gpr_mu_lock(g_mu);
104  connections_complete_before = g_connections_complete;
106 
107  /* connect to it */
108  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr,
109  (socklen_t*)&resolved_addr.len) == 0);
110  GRPC_CLOSURE_INIT(&done, must_succeed, nullptr, grpc_schedule_on_exec_ctx);
113  .PreconditionChannelArgs(nullptr)
114  .ToC();
115  int64_t connection_handle = grpc_tcp_client_connect(
116  &done, &g_connecting, g_pollset_set, args, &resolved_addr,
119  /* await the connection */
120  do {
121  resolved_addr.len = static_cast<socklen_t>(sizeof(addr));
122  r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr),
123  reinterpret_cast<socklen_t*>(&resolved_addr.len));
124  } while (r == -1 && errno == EINTR);
125  GPR_ASSERT(r >= 0);
126  close(r);
127 
128  gpr_mu_lock(g_mu);
129 
130  while (g_connections_complete == connections_complete_before) {
131  grpc_pollset_worker* worker = nullptr;
133  "pollset_work",
139  gpr_mu_lock(g_mu);
140  }
141 
143 
144  // A cancellation attempt should fail because connect already succeeded.
145  GPR_ASSERT(grpc_tcp_client_cancel_connect(connection_handle) == false);
146 
147  gpr_log(GPR_ERROR, "---- finished test_succeeds() ----");
148 }
149 
150 void test_fails(void) {
151  gpr_log(GPR_ERROR, "---- starting test_fails() ----");
152  grpc_resolved_address resolved_addr;
153  struct sockaddr_in* addr =
154  reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
155  int connections_complete_before;
158 
159  memset(&resolved_addr, 0, sizeof(resolved_addr));
160  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
161  addr->sin_family = AF_INET;
162 
163  gpr_mu_lock(g_mu);
164  connections_complete_before = g_connections_complete;
166 
167  /* connect to a broken address */
168  GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
169  int64_t connection_handle = grpc_tcp_client_connect(
170  &done, &g_connecting, g_pollset_set, nullptr, &resolved_addr,
172  gpr_mu_lock(g_mu);
173 
174  /* wait for the connection callback to finish */
175  while (g_connections_complete == connections_complete_before) {
176  grpc_pollset_worker* worker = nullptr;
177  grpc_core::Timestamp polling_deadline = test_deadline();
178  switch (grpc_timer_check(&polling_deadline)) {
179  case GRPC_TIMERS_FIRED:
180  break;
182  polling_deadline = grpc_core::Timestamp::ProcessEpoch();
186  "pollset_work",
187  grpc_pollset_work(g_pollset, &worker, polling_deadline)));
188  break;
189  }
192  gpr_mu_lock(g_mu);
193  }
194 
196 
197  // A cancellation attempt should fail because connect already failed.
198  GPR_ASSERT(grpc_tcp_client_cancel_connect(connection_handle) == false);
199 
200  gpr_log(GPR_ERROR, "---- finished test_fails() ----");
201 }
202 
203 void test_connect_cancellation_succeeds(void) {
204  gpr_log(GPR_ERROR, "---- starting test_connect_cancellation_succeeds() ----");
205  grpc_resolved_address resolved_addr;
206  struct sockaddr_in* addr =
207  reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
208  int svr_fd;
211 
212  memset(&resolved_addr, 0, sizeof(resolved_addr));
213  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
214  addr->sin_family = AF_INET;
215 
216  /* create a phony server */
217  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
218  GPR_ASSERT(svr_fd >= 0);
219  GPR_ASSERT(
220  0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len));
221  GPR_ASSERT(0 == listen(svr_fd, 1));
222 
223  // connect to it. accept() is not called on the bind socket. So the connection
224  // should appear to be stuck giving ample time to try to cancel it.
225  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr,
226  (socklen_t*)&resolved_addr.len) == 0);
227  GRPC_CLOSURE_INIT(&done, must_succeed, nullptr, grpc_schedule_on_exec_ctx);
230  .PreconditionChannelArgs(nullptr)
231  .ToC();
232  int64_t connection_handle = grpc_tcp_client_connect(
233  &done, &g_connecting, g_pollset_set, args, &resolved_addr,
236  GPR_ASSERT(connection_handle > 0);
237  GPR_ASSERT(grpc_tcp_client_cancel_connect(connection_handle) == true);
238  close(svr_fd);
239  gpr_log(GPR_ERROR, "---- finished test_connect_cancellation_succeeds() ----");
240 }
241 
242 void test_fails_bad_addr_no_leak(void) {
243  gpr_log(GPR_ERROR, "---- starting test_fails_bad_addr_no_leak() ----");
244  grpc_resolved_address resolved_addr;
245  struct sockaddr_in* addr =
246  reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
247  int connections_complete_before;
250  memset(&resolved_addr, 0, sizeof(resolved_addr));
251  resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
252  // force `grpc_tcp_client_prepare_fd` to fail. contrived, but effective.
253  addr->sin_family = AF_IPX;
254  gpr_mu_lock(g_mu);
255  connections_complete_before = g_connections_complete;
257  // connect to an invalid address.
258  GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
259  grpc_tcp_client_connect(&done, &g_connecting, g_pollset_set, nullptr,
260  &resolved_addr, grpc_core::Timestamp::InfFuture());
261  gpr_mu_lock(g_mu);
262  while (g_connections_complete == connections_complete_before) {
263  grpc_pollset_worker* worker = nullptr;
264  grpc_core::Timestamp polling_deadline = test_deadline();
265  switch (grpc_timer_check(&polling_deadline)) {
266  case GRPC_TIMERS_FIRED:
267  break;
269  polling_deadline = grpc_core::Timestamp::ProcessEpoch();
273  "pollset_work",
274  grpc_pollset_work(g_pollset, &worker, polling_deadline)));
275  break;
276  }
279  gpr_mu_lock(g_mu);
280  }
282  gpr_log(GPR_ERROR, "---- finished test_fails_bad_addr_no_leak() ----");
283 }
284 
285 static void destroy_pollset(void* p, grpc_error_handle /*error*/) {
286  grpc_pollset_destroy(static_cast<grpc_pollset*>(p));
287 }
288 
289 int main(int argc, char** argv) {
290  grpc_closure destroyed;
291  grpc::testing::TestEnvironment env(&argc, argv);
292  grpc_init();
293 
294  {
296  g_pollset_set = grpc_pollset_set_create();
299  grpc_pollset_set_add_pollset(g_pollset_set, g_pollset);
300 
301  test_succeeds();
302  test_connect_cancellation_succeeds();
303  test_fails();
304  test_fails_bad_addr_no_leak();
305  grpc_pollset_set_destroy(g_pollset_set);
307  grpc_schedule_on_exec_ctx);
308  grpc_pollset_shutdown(g_pollset, &destroyed);
309  }
310 
311  grpc_shutdown();
313  return 0;
314 }
315 
316 #else /* GRPC_POSIX_SOCKET_TCP_CLIENT */
317 
318 int main(int argc, char** argv) { return 1; }
319 
320 #endif /* GRPC_POSIX_SOCKET_CLIENT */
grpc_pollset_worker
struct grpc_pollset_worker grpc_pollset_worker
Definition: pollset.h:39
GRPC_CLOSURE_INIT
#define GRPC_CLOSURE_INIT(closure, cb, cb_arg, scheduler)
Definition: closure.h:115
grpc_pollset_size
size_t grpc_pollset_size(void)
Definition: pollset.cc:56
iomgr.h
gpr_mu_unlock
GPRAPI void gpr_mu_unlock(gpr_mu *mu)
grpc_timeout_seconds_to_deadline
gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s)
Definition: test/core/util/test_config.cc:81
log.h
generate.env
env
Definition: generate.py:37
memset
return memset(p, 0, total)
GRPC_TIMERS_NOT_CHECKED
@ GRPC_TIMERS_NOT_CHECKED
Definition: iomgr/timer.h:56
grpc_pollset_set
struct grpc_pollset_set grpc_pollset_set
Definition: iomgr_fwd.h:23
string.h
grpc_pollset_set_create
grpc_pollset_set * grpc_pollset_set_create()
Definition: pollset_set.cc:29
grpc_core::Timestamp
Definition: src/core/lib/gprpp/time.h:62
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
error
grpc_error_handle error
Definition: retry_filter.cc:499
grpc_resolved_address
Definition: resolved_address.h:34
grpc_pollset_work
grpc_error_handle grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker **worker, grpc_core::Timestamp deadline)
Definition: pollset.cc:45
GRPC_LOG_IF_ERROR
#define GRPC_LOG_IF_ERROR(what, error)
Definition: error.h:398
time.h
grpc_tcp_client_connect
int64_t grpc_tcp_client_connect(grpc_closure *on_connect, grpc_endpoint **endpoint, grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args, const grpc_resolved_address *addr, grpc_core::Timestamp deadline)
Definition: tcp_client.cc:25
grpc_timer_check
grpc_timer_check_result grpc_timer_check(grpc_core::Timestamp *next)
Definition: iomgr/timer.cc:38
xds_manager.p
p
Definition: xds_manager.py:60
g_pollset
static grpc_pollset * g_pollset
Definition: endpoint_pair_test.cc:31
grpc_channel_args
Definition: grpc_types.h:132
gen_build_yaml.struct
def struct(**kwargs)
Definition: test/core/end2end/gen_build_yaml.py:30
grpc_pollset_init
void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu)
Definition: pollset.cc:33
gpr_zalloc
GPRAPI void * gpr_zalloc(size_t size)
Definition: alloc.cc:40
GRPC_TIMERS_FIRED
@ GRPC_TIMERS_FIRED
Definition: iomgr/timer.h:58
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
grpc_core::CoreConfiguration::Get
static const CoreConfiguration & Get()
Definition: core_configuration.h:82
grpc_core::ExecCtx::Flush
bool Flush()
Definition: exec_ctx.cc:69
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
worker
Definition: worker.py:1
grpc.h
grpc_pollset_set_destroy
void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set)
Definition: pollset_set.cc:33
pollset_set.h
done
struct tab * done
Definition: bloaty/third_party/zlib/examples/enough.c:176
grpc_core::ChannelArgs::ToC
const grpc_channel_args * ToC() const
Definition: channel_args.cc:94
grpc_channel_args_destroy
void grpc_channel_args_destroy(grpc_channel_args *a)
Definition: channel_args.cc:360
main
int main(int argc, char **argv)
Definition: tcp_client_posix_test.cc:318
time.h
close
#define close
Definition: test-fs.c:48
gpr_mu_lock
GPRAPI void gpr_mu_lock(gpr_mu *mu)
grpc_resolved_address::len
socklen_t len
Definition: resolved_address.h:36
grpc_endpoint_shutdown
void grpc_endpoint_shutdown(grpc_endpoint *ep, grpc_error_handle why)
Definition: endpoint.cc:49
GRPC_TIMERS_CHECKED_AND_EMPTY
@ GRPC_TIMERS_CHECKED_AND_EMPTY
Definition: iomgr/timer.h:57
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
grpc_endpoint_destroy
void grpc_endpoint_destroy(grpc_endpoint *ep)
Definition: endpoint.cc:53
grpc_pollset_kick
grpc_error_handle grpc_pollset_kick(grpc_pollset *pollset, grpc_pollset_worker *specific_worker)
Definition: pollset.cc:51
grpc_core::CoreConfiguration::channel_args_preconditioning
const ChannelArgsPreconditioning & channel_args_preconditioning() const
Definition: core_configuration.h:139
grpc_core::Timestamp::ProcessEpoch
static constexpr Timestamp ProcessEpoch()
Definition: src/core/lib/gprpp/time.h:77
grpc_core::ExecCtx
Definition: exec_ctx.h:97
tcp_client.h
GRPC_ERROR_CREATE_FROM_STATIC_STRING
#define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc)
Definition: error.h:291
test_config.h
g_mu
static gpr_mu g_mu
Definition: iomgr.cc:55
destroy_pollset
static void destroy_pollset(void *p, grpc_error_handle)
Definition: google_default_credentials.cc:199
test_succeeds
static void test_succeeds(grpc_core::ResolverFactory *factory, const char *string)
Definition: dns_resolver_test.cc:39
gpr_mu
pthread_mutex_t gpr_mu
Definition: impl/codegen/sync_posix.h:47
test_fails
static void test_fails(grpc_core::ResolverFactory *factory, const char *string)
Definition: dns_resolver_test.cc:58
port.h
exec_ctx
grpc_core::ExecCtx exec_ctx
Definition: end2end_binder_transport_test.cc:75
http2_test_server.listen
def listen(endpoint, test_case)
Definition: http2_test_server.py:87
grpc_pollset_shutdown
void grpc_pollset_shutdown(grpc_pollset *pollset, grpc_closure *closure)
Definition: pollset.cc:37
alloc.h
fix_build_deps.r
r
Definition: fix_build_deps.py:491
grpc::testing::TestEnvironment
Definition: test/core/util/test_config.h:54
socket_utils_posix.h
timer.h
test_server.socket
socket
Definition: test_server.py:65
grpc_core::Timestamp::InfFuture
static constexpr Timestamp InfFuture()
Definition: src/core/lib/gprpp/time.h:79
grpc_init
GRPCAPI void grpc_init(void)
Definition: init.cc:146
grpc_error
Definition: error_internal.h:42
grpc_core::Timestamp::FromTimespecRoundUp
static Timestamp FromTimespecRoundUp(gpr_timespec t)
Definition: src/core/lib/gprpp/time.cc:136
test_deadline
static gpr_timespec test_deadline(void)
Definition: dns_resolver_cooldown_test.cc:143
grpc_pollset
Definition: bm_cq_multiple_threads.cc:37
ABSL_FALLTHROUGH_INTENDED
#define ABSL_FALLTHROUGH_INTENDED
Definition: abseil-cpp/absl/base/attributes.h:641
grpc_pollset_destroy
void grpc_pollset_destroy(grpc_pollset *pollset)
Definition: pollset.cc:41
grpc_closure
Definition: closure.h:56
grpc_pollset_set_add_pollset
void grpc_pollset_set_add_pollset(grpc_pollset_set *pollset_set, grpc_pollset *pollset)
Definition: pollset_set.cc:37
grpc_resolved_address::addr
char addr[GRPC_MAX_SOCKADDR_SIZE]
Definition: resolved_address.h:35
grpc_endpoint
Definition: endpoint.h:105
grpc_shutdown
GRPCAPI void grpc_shutdown(void)
Definition: init.cc:209
addr
struct sockaddr_in addr
Definition: libuv/docs/code/tcp-echo-server/main.c:10
grpc_core::ChannelArgsPreconditioning::PreconditionChannelArgs
ChannelArgs PreconditionChannelArgs(const grpc_channel_args *args) const
Definition: channel_args_preconditioning.cc:34
errno.h
grpc_core::ExecCtx::Get
static ExecCtx * Get()
Definition: exec_ctx.h:205
grpc_tcp_client_cancel_connect
bool grpc_tcp_client_cancel_connect(int64_t connection_handle)
Definition: tcp_client.cc:35
GRPC_ERROR_IS_NONE
#define GRPC_ERROR_IS_NONE(err)
Definition: error.h:241
api.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:29