• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 *
3 * Copyright 2018 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
19#import <XCTest/XCTest.h>
20
21#include "src/core/lib/iomgr/port.h"
22
23#ifdef GRPC_CFSTREAM
24
25#include <netinet/in.h>
26
27#include <grpc/grpc.h>
28#include <grpc/support/sync.h>
29
30#include "src/core/lib/address_utils/parse_address.h"
31#include "src/core/lib/address_utils/sockaddr_utils.h"
32#include "src/core/lib/event_engine/channel_args_endpoint_config.h"
33#include "src/core/lib/iomgr/endpoint.h"
34#include "src/core/lib/iomgr/resolve_address.h"
35#include "src/core/lib/iomgr/tcp_client.h"
36#include "src/core/lib/resource_quota/api.h"
37#include "test/core/util/test_config.h"
38
39static gpr_mu g_mu;
40static int g_connections_complete = 0;
41static grpc_endpoint* g_connecting = nullptr;
42
43static void finish_connection() {
44  gpr_mu_lock(&g_mu);
45  g_connections_complete++;
46  gpr_mu_unlock(&g_mu);
47}
48
49static void must_succeed(void* arg, grpc_error_handle error) {
50  GPR_ASSERT(g_connecting != nullptr);
51  GPR_ASSERT(error.ok());
52  grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE("must_succeed called"));
53  grpc_endpoint_destroy(g_connecting);
54  g_connecting = nullptr;
55  finish_connection();
56}
57
58static void must_fail(void* arg, grpc_error_handle error) {
59  GPR_ASSERT(g_connecting == nullptr);
60  GPR_ASSERT(!error.ok());
61  NSLog(@"%s", grpc_core::StatusToString(error).c_str());
62  finish_connection();
63}
64
65@interface CFStreamClientTests : XCTestCase
66
67@end
68
69@implementation CFStreamClientTests
70
71+ (void)setUp {
72  grpc_init();
73  gpr_mu_init(&g_mu);
74}
75
76+ (void)tearDown {
77  grpc_shutdown();
78}
79
80- (void)testSucceeds {
81  int svr_fd;
82  int r;
83  int connections_complete_before;
84  grpc_closure done;
85  grpc_core::ExecCtx exec_ctx;
86
87  gpr_log(GPR_DEBUG, "test_succeeds");
88
89  auto resolved_addr = grpc_core::StringToSockaddr("127.0.0.1:0");
90  GPR_ASSERT(resolved_addr.ok());
91  struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr->addr);
92
93  /* create a phony server */
94  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
95  GPR_ASSERT(svr_fd >= 0);
96  GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr->len));
97  GPR_ASSERT(0 == listen(svr_fd, 1));
98
99  gpr_mu_lock(&g_mu);
100  connections_complete_before = g_connections_complete;
101  gpr_mu_unlock(&g_mu);
102
103  /* connect to it */
104  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr->len) == 0);
105  GRPC_CLOSURE_INIT(&done, must_succeed, nullptr, grpc_schedule_on_exec_ctx);
106  auto args =
107      grpc_core::CoreConfiguration::Get().channel_args_preconditioning().PreconditionChannelArgs(
108          nullptr);
109  grpc_tcp_client_connect(&done, &g_connecting, nullptr,
110                          grpc_event_engine::experimental::ChannelArgsEndpointConfig(args),
111                          &*resolved_addr, grpc_core::Timestamp::InfFuture());
112
113  /* await the connection */
114  do {
115    resolved_addr->len = sizeof(addr);
116    r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr),
117               reinterpret_cast<socklen_t*>(&resolved_addr->len));
118  } while (r == -1 && errno == EINTR);
119  GPR_ASSERT(r >= 0);
120  close(r);
121
122  grpc_core::ExecCtx::Get()->Flush();
123
124  /* wait for the connection callback to finish */
125  gpr_mu_lock(&g_mu);
126  NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
127  while (connections_complete_before == g_connections_complete) {
128    gpr_mu_unlock(&g_mu);
129    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
130    gpr_mu_lock(&g_mu);
131  }
132  XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
133
134  gpr_mu_unlock(&g_mu);
135}
136
137- (void)testFails {
138  grpc_core::ExecCtx exec_ctx;
139
140  int connections_complete_before;
141  grpc_closure done;
142  int svr_fd;
143
144  gpr_log(GPR_DEBUG, "test_fails");
145
146  auto resolved_addr = grpc_core::StringToSockaddr("127.0.0.1:0");
147  GPR_ASSERT(resolved_addr.ok());
148  struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr->addr);
149
150  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
151  GPR_ASSERT(svr_fd >= 0);
152  GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr->len));
153  GPR_ASSERT(0 == listen(svr_fd, 1));
154  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr->len) == 0);
155  close(svr_fd);
156
157  gpr_mu_lock(&g_mu);
158  connections_complete_before = g_connections_complete;
159  gpr_mu_unlock(&g_mu);
160
161  /* connect to a broken address */
162  GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
163  auto args =
164      grpc_core::CoreConfiguration::Get().channel_args_preconditioning().PreconditionChannelArgs(
165          nullptr);
166  grpc_tcp_client_connect(&done, &g_connecting, nullptr,
167                          grpc_event_engine::experimental::ChannelArgsEndpointConfig(args),
168                          &*resolved_addr, grpc_core::Timestamp::InfFuture());
169
170  grpc_core::ExecCtx::Get()->Flush();
171
172  /* wait for the connection callback to finish */
173  gpr_mu_lock(&g_mu);
174  NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
175  while (g_connections_complete == connections_complete_before) {
176    gpr_mu_unlock(&g_mu);
177    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
178    gpr_mu_lock(&g_mu);
179  }
180
181  XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
182
183  gpr_mu_unlock(&g_mu);
184}
185
186@end
187
188#else  // GRPC_CFSTREAM
189
190// Phony test suite
191@interface CFStreamClientTests : XCTestCase
192
193@end
194
195@implementation CFStreamClientTests
196
197- (void)setUp {
198  [super setUp];
199}
200
201- (void)tearDown {
202  [super tearDown];
203}
204
205@end
206
207#endif  // GRPC_CFSTREAM
208