• 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/test_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  CHECK(g_connecting != nullptr);
51  CHECK(error.ok());
52  grpc_endpoint_destroy(g_connecting);
53  g_connecting = nullptr;
54  finish_connection();
55}
56
57static void must_fail(void* arg, grpc_error_handle error) {
58  CHECK(g_connecting == nullptr);
59  CHECK(!error.ok());
60  NSLog(@"%s", grpc_core::StatusToString(error).c_str());
61  finish_connection();
62}
63
64@interface CFStreamClientTests : XCTestCase
65
66@end
67
68@implementation CFStreamClientTests
69
70+ (void)setUp {
71  grpc_init();
72  gpr_mu_init(&g_mu);
73}
74
75+ (void)tearDown {
76  grpc_shutdown();
77}
78
79- (void)testSucceeds {
80  int svr_fd;
81  int r;
82  int connections_complete_before;
83  grpc_closure done;
84  grpc_core::ExecCtx exec_ctx;
85
86  VLOG(2) << "test_succeeds";
87
88  auto resolved_addr = grpc_core::StringToSockaddr("127.0.0.1:0");
89  CHECK(resolved_addr.ok());
90  struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr->addr);
91
92  /* create a phony server */
93  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
94  CHECK(svr_fd >= 0);
95  CHECK(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr->len));
96  CHECK(0 == listen(svr_fd, 1));
97
98  gpr_mu_lock(&g_mu);
99  connections_complete_before = g_connections_complete;
100  gpr_mu_unlock(&g_mu);
101
102  /* connect to it */
103  CHECK(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr->len) == 0);
104  GRPC_CLOSURE_INIT(&done, must_succeed, nullptr, grpc_schedule_on_exec_ctx);
105  auto args =
106      grpc_core::CoreConfiguration::Get().channel_args_preconditioning().PreconditionChannelArgs(
107          nullptr);
108  grpc_tcp_client_connect(&done, &g_connecting, nullptr,
109                          grpc_event_engine::experimental::ChannelArgsEndpointConfig(args),
110                          &*resolved_addr, grpc_core::Timestamp::InfFuture());
111
112  /* await the connection */
113  do {
114    resolved_addr->len = sizeof(addr);
115    r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr),
116               reinterpret_cast<socklen_t*>(&resolved_addr->len));
117  } while (r == -1 && errno == EINTR);
118  CHECK(r >= 0);
119  close(r);
120
121  grpc_core::ExecCtx::Get()->Flush();
122
123  /* wait for the connection callback to finish */
124  gpr_mu_lock(&g_mu);
125  NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
126  while (connections_complete_before == g_connections_complete) {
127    gpr_mu_unlock(&g_mu);
128    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
129    gpr_mu_lock(&g_mu);
130  }
131  XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
132
133  gpr_mu_unlock(&g_mu);
134}
135
136- (void)testFails {
137  grpc_core::ExecCtx exec_ctx;
138
139  int connections_complete_before;
140  grpc_closure done;
141  int svr_fd;
142
143  VLOG(2) << "test_fails";
144
145  auto resolved_addr = grpc_core::StringToSockaddr("127.0.0.1:0");
146  CHECK(resolved_addr.ok());
147  struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr->addr);
148
149  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
150  CHECK(svr_fd >= 0);
151  CHECK(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr->len));
152  CHECK(0 == listen(svr_fd, 1));
153  CHECK(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr->len) == 0);
154  close(svr_fd);
155
156  gpr_mu_lock(&g_mu);
157  connections_complete_before = g_connections_complete;
158  gpr_mu_unlock(&g_mu);
159
160  /* connect to a broken address */
161  GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
162  auto args =
163      grpc_core::CoreConfiguration::Get().channel_args_preconditioning().PreconditionChannelArgs(
164          nullptr);
165  grpc_tcp_client_connect(&done, &g_connecting, nullptr,
166                          grpc_event_engine::experimental::ChannelArgsEndpointConfig(args),
167                          &*resolved_addr, grpc_core::Timestamp::InfFuture());
168
169  grpc_core::ExecCtx::Get()->Flush();
170
171  /* wait for the connection callback to finish */
172  gpr_mu_lock(&g_mu);
173  NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
174  while (g_connections_complete == connections_complete_before) {
175    gpr_mu_unlock(&g_mu);
176    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
177    gpr_mu_lock(&g_mu);
178  }
179
180  XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
181
182  gpr_mu_unlock(&g_mu);
183}
184
185@end
186
187#else  // GRPC_CFSTREAM
188
189// Phony test suite
190@interface CFStreamClientTests : XCTestCase
191
192@end
193
194@implementation CFStreamClientTests
195
196- (void)setUp {
197  [super setUp];
198}
199
200- (void)tearDown {
201  [super tearDown];
202}
203
204@end
205
206#endif  // GRPC_CFSTREAM
207