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