xref: /aosp_15_r20/external/grpc-grpc/src/objective-c/tests/CFStreamTests/CFStreamClientTests.mm (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1*cc02d7e2SAndroid Build Coastguard Worker/*
2*cc02d7e2SAndroid Build Coastguard Worker *
3*cc02d7e2SAndroid Build Coastguard Worker * Copyright 2018 gRPC authors.
4*cc02d7e2SAndroid Build Coastguard Worker *
5*cc02d7e2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*cc02d7e2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*cc02d7e2SAndroid Build Coastguard Worker * You may obtain a copy of the License at
8*cc02d7e2SAndroid Build Coastguard Worker *
9*cc02d7e2SAndroid Build Coastguard Worker *     http://www.apache.org/licenses/LICENSE-2.0
10*cc02d7e2SAndroid Build Coastguard Worker *
11*cc02d7e2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*cc02d7e2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*cc02d7e2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*cc02d7e2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*cc02d7e2SAndroid Build Coastguard Worker * limitations under the License.
16*cc02d7e2SAndroid Build Coastguard Worker *
17*cc02d7e2SAndroid Build Coastguard Worker */
18*cc02d7e2SAndroid Build Coastguard Worker
19*cc02d7e2SAndroid Build Coastguard Worker#import <XCTest/XCTest.h>
20*cc02d7e2SAndroid Build Coastguard Worker
21*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/iomgr/port.h"
22*cc02d7e2SAndroid Build Coastguard Worker
23*cc02d7e2SAndroid Build Coastguard Worker#ifdef GRPC_CFSTREAM
24*cc02d7e2SAndroid Build Coastguard Worker
25*cc02d7e2SAndroid Build Coastguard Worker#include <netinet/in.h>
26*cc02d7e2SAndroid Build Coastguard Worker
27*cc02d7e2SAndroid Build Coastguard Worker#include <grpc/grpc.h>
28*cc02d7e2SAndroid Build Coastguard Worker#include <grpc/impl/codegen/sync.h>
29*cc02d7e2SAndroid Build Coastguard Worker#include <grpc/support/sync.h>
30*cc02d7e2SAndroid Build Coastguard Worker
31*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/address_utils/parse_address.h"
32*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/address_utils/sockaddr_utils.h"
33*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/event_engine/channel_args_endpoint_config.h"
34*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/iomgr/endpoint.h"
35*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/iomgr/resolve_address.h"
36*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/iomgr/tcp_client.h"
37*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/resource_quota/api.h"
38*cc02d7e2SAndroid Build Coastguard Worker#include "test/core/util/test_config.h"
39*cc02d7e2SAndroid Build Coastguard Worker
40*cc02d7e2SAndroid Build Coastguard Workerstatic gpr_mu g_mu;
41*cc02d7e2SAndroid Build Coastguard Workerstatic int g_connections_complete = 0;
42*cc02d7e2SAndroid Build Coastguard Workerstatic grpc_endpoint* g_connecting = nullptr;
43*cc02d7e2SAndroid Build Coastguard Worker
44*cc02d7e2SAndroid Build Coastguard Workerstatic void finish_connection() {
45*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_lock(&g_mu);
46*cc02d7e2SAndroid Build Coastguard Worker  g_connections_complete++;
47*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_unlock(&g_mu);
48*cc02d7e2SAndroid Build Coastguard Worker}
49*cc02d7e2SAndroid Build Coastguard Worker
50*cc02d7e2SAndroid Build Coastguard Workerstatic void must_succeed(void* arg, grpc_error_handle error) {
51*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(g_connecting != nullptr);
52*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(error.ok());
53*cc02d7e2SAndroid Build Coastguard Worker  grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE("must_succeed called"));
54*cc02d7e2SAndroid Build Coastguard Worker  grpc_endpoint_destroy(g_connecting);
55*cc02d7e2SAndroid Build Coastguard Worker  g_connecting = nullptr;
56*cc02d7e2SAndroid Build Coastguard Worker  finish_connection();
57*cc02d7e2SAndroid Build Coastguard Worker}
58*cc02d7e2SAndroid Build Coastguard Worker
59*cc02d7e2SAndroid Build Coastguard Workerstatic void must_fail(void* arg, grpc_error_handle error) {
60*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(g_connecting == nullptr);
61*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(!error.ok());
62*cc02d7e2SAndroid Build Coastguard Worker  NSLog(@"%s", grpc_core::StatusToString(error).c_str());
63*cc02d7e2SAndroid Build Coastguard Worker  finish_connection();
64*cc02d7e2SAndroid Build Coastguard Worker}
65*cc02d7e2SAndroid Build Coastguard Worker
66*cc02d7e2SAndroid Build Coastguard Worker@interface CFStreamClientTests : XCTestCase
67*cc02d7e2SAndroid Build Coastguard Worker
68*cc02d7e2SAndroid Build Coastguard Worker@end
69*cc02d7e2SAndroid Build Coastguard Worker
70*cc02d7e2SAndroid Build Coastguard Worker@implementation CFStreamClientTests
71*cc02d7e2SAndroid Build Coastguard Worker
72*cc02d7e2SAndroid Build Coastguard Worker+ (void)setUp {
73*cc02d7e2SAndroid Build Coastguard Worker  grpc_init();
74*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_init(&g_mu);
75*cc02d7e2SAndroid Build Coastguard Worker}
76*cc02d7e2SAndroid Build Coastguard Worker
77*cc02d7e2SAndroid Build Coastguard Worker+ (void)tearDown {
78*cc02d7e2SAndroid Build Coastguard Worker  grpc_shutdown();
79*cc02d7e2SAndroid Build Coastguard Worker}
80*cc02d7e2SAndroid Build Coastguard Worker
81*cc02d7e2SAndroid Build Coastguard Worker- (void)testSucceeds {
82*cc02d7e2SAndroid Build Coastguard Worker  int svr_fd;
83*cc02d7e2SAndroid Build Coastguard Worker  int r;
84*cc02d7e2SAndroid Build Coastguard Worker  int connections_complete_before;
85*cc02d7e2SAndroid Build Coastguard Worker  grpc_closure done;
86*cc02d7e2SAndroid Build Coastguard Worker  grpc_core::ExecCtx exec_ctx;
87*cc02d7e2SAndroid Build Coastguard Worker
88*cc02d7e2SAndroid Build Coastguard Worker  gpr_log(GPR_DEBUG, "test_succeeds");
89*cc02d7e2SAndroid Build Coastguard Worker
90*cc02d7e2SAndroid Build Coastguard Worker  auto resolved_addr = grpc_core::StringToSockaddr("127.0.0.1:0");
91*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(resolved_addr.ok());
92*cc02d7e2SAndroid Build Coastguard Worker  struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr->addr);
93*cc02d7e2SAndroid Build Coastguard Worker
94*cc02d7e2SAndroid Build Coastguard Worker  /* create a phony server */
95*cc02d7e2SAndroid Build Coastguard Worker  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
96*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(svr_fd >= 0);
97*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr->len));
98*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(0 == listen(svr_fd, 1));
99*cc02d7e2SAndroid Build Coastguard Worker
100*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_lock(&g_mu);
101*cc02d7e2SAndroid Build Coastguard Worker  connections_complete_before = g_connections_complete;
102*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_unlock(&g_mu);
103*cc02d7e2SAndroid Build Coastguard Worker
104*cc02d7e2SAndroid Build Coastguard Worker  /* connect to it */
105*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr->len) == 0);
106*cc02d7e2SAndroid Build Coastguard Worker  GRPC_CLOSURE_INIT(&done, must_succeed, nullptr, grpc_schedule_on_exec_ctx);
107*cc02d7e2SAndroid Build Coastguard Worker  auto args =
108*cc02d7e2SAndroid Build Coastguard Worker      grpc_core::CoreConfiguration::Get().channel_args_preconditioning().PreconditionChannelArgs(
109*cc02d7e2SAndroid Build Coastguard Worker          nullptr);
110*cc02d7e2SAndroid Build Coastguard Worker  grpc_tcp_client_connect(&done, &g_connecting, nullptr,
111*cc02d7e2SAndroid Build Coastguard Worker                          grpc_event_engine::experimental::ChannelArgsEndpointConfig(args),
112*cc02d7e2SAndroid Build Coastguard Worker                          &*resolved_addr, grpc_core::Timestamp::InfFuture());
113*cc02d7e2SAndroid Build Coastguard Worker
114*cc02d7e2SAndroid Build Coastguard Worker  /* await the connection */
115*cc02d7e2SAndroid Build Coastguard Worker  do {
116*cc02d7e2SAndroid Build Coastguard Worker    resolved_addr->len = sizeof(addr);
117*cc02d7e2SAndroid Build Coastguard Worker    r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr),
118*cc02d7e2SAndroid Build Coastguard Worker               reinterpret_cast<socklen_t*>(&resolved_addr->len));
119*cc02d7e2SAndroid Build Coastguard Worker  } while (r == -1 && errno == EINTR);
120*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(r >= 0);
121*cc02d7e2SAndroid Build Coastguard Worker  close(r);
122*cc02d7e2SAndroid Build Coastguard Worker
123*cc02d7e2SAndroid Build Coastguard Worker  grpc_core::ExecCtx::Get()->Flush();
124*cc02d7e2SAndroid Build Coastguard Worker
125*cc02d7e2SAndroid Build Coastguard Worker  /* wait for the connection callback to finish */
126*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_lock(&g_mu);
127*cc02d7e2SAndroid Build Coastguard Worker  NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
128*cc02d7e2SAndroid Build Coastguard Worker  while (connections_complete_before == g_connections_complete) {
129*cc02d7e2SAndroid Build Coastguard Worker    gpr_mu_unlock(&g_mu);
130*cc02d7e2SAndroid Build Coastguard Worker    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
131*cc02d7e2SAndroid Build Coastguard Worker    gpr_mu_lock(&g_mu);
132*cc02d7e2SAndroid Build Coastguard Worker  }
133*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
134*cc02d7e2SAndroid Build Coastguard Worker
135*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_unlock(&g_mu);
136*cc02d7e2SAndroid Build Coastguard Worker}
137*cc02d7e2SAndroid Build Coastguard Worker
138*cc02d7e2SAndroid Build Coastguard Worker- (void)testFails {
139*cc02d7e2SAndroid Build Coastguard Worker  grpc_core::ExecCtx exec_ctx;
140*cc02d7e2SAndroid Build Coastguard Worker
141*cc02d7e2SAndroid Build Coastguard Worker  int connections_complete_before;
142*cc02d7e2SAndroid Build Coastguard Worker  grpc_closure done;
143*cc02d7e2SAndroid Build Coastguard Worker  int svr_fd;
144*cc02d7e2SAndroid Build Coastguard Worker
145*cc02d7e2SAndroid Build Coastguard Worker  gpr_log(GPR_DEBUG, "test_fails");
146*cc02d7e2SAndroid Build Coastguard Worker
147*cc02d7e2SAndroid Build Coastguard Worker  auto resolved_addr = grpc_core::StringToSockaddr("127.0.0.1:0");
148*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(resolved_addr.ok());
149*cc02d7e2SAndroid Build Coastguard Worker  struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr->addr);
150*cc02d7e2SAndroid Build Coastguard Worker
151*cc02d7e2SAndroid Build Coastguard Worker  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
152*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(svr_fd >= 0);
153*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr->len));
154*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(0 == listen(svr_fd, 1));
155*cc02d7e2SAndroid Build Coastguard Worker  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr->len) == 0);
156*cc02d7e2SAndroid Build Coastguard Worker  close(svr_fd);
157*cc02d7e2SAndroid Build Coastguard Worker
158*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_lock(&g_mu);
159*cc02d7e2SAndroid Build Coastguard Worker  connections_complete_before = g_connections_complete;
160*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_unlock(&g_mu);
161*cc02d7e2SAndroid Build Coastguard Worker
162*cc02d7e2SAndroid Build Coastguard Worker  /* connect to a broken address */
163*cc02d7e2SAndroid Build Coastguard Worker  GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
164*cc02d7e2SAndroid Build Coastguard Worker  auto args =
165*cc02d7e2SAndroid Build Coastguard Worker      grpc_core::CoreConfiguration::Get().channel_args_preconditioning().PreconditionChannelArgs(
166*cc02d7e2SAndroid Build Coastguard Worker          nullptr);
167*cc02d7e2SAndroid Build Coastguard Worker  grpc_tcp_client_connect(&done, &g_connecting, nullptr,
168*cc02d7e2SAndroid Build Coastguard Worker                          grpc_event_engine::experimental::ChannelArgsEndpointConfig(args),
169*cc02d7e2SAndroid Build Coastguard Worker                          &*resolved_addr, grpc_core::Timestamp::InfFuture());
170*cc02d7e2SAndroid Build Coastguard Worker
171*cc02d7e2SAndroid Build Coastguard Worker  grpc_core::ExecCtx::Get()->Flush();
172*cc02d7e2SAndroid Build Coastguard Worker
173*cc02d7e2SAndroid Build Coastguard Worker  /* wait for the connection callback to finish */
174*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_lock(&g_mu);
175*cc02d7e2SAndroid Build Coastguard Worker  NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
176*cc02d7e2SAndroid Build Coastguard Worker  while (g_connections_complete == connections_complete_before) {
177*cc02d7e2SAndroid Build Coastguard Worker    gpr_mu_unlock(&g_mu);
178*cc02d7e2SAndroid Build Coastguard Worker    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
179*cc02d7e2SAndroid Build Coastguard Worker    gpr_mu_lock(&g_mu);
180*cc02d7e2SAndroid Build Coastguard Worker  }
181*cc02d7e2SAndroid Build Coastguard Worker
182*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
183*cc02d7e2SAndroid Build Coastguard Worker
184*cc02d7e2SAndroid Build Coastguard Worker  gpr_mu_unlock(&g_mu);
185*cc02d7e2SAndroid Build Coastguard Worker}
186*cc02d7e2SAndroid Build Coastguard Worker
187*cc02d7e2SAndroid Build Coastguard Worker@end
188*cc02d7e2SAndroid Build Coastguard Worker
189*cc02d7e2SAndroid Build Coastguard Worker#else  // GRPC_CFSTREAM
190*cc02d7e2SAndroid Build Coastguard Worker
191*cc02d7e2SAndroid Build Coastguard Worker// Phony test suite
192*cc02d7e2SAndroid Build Coastguard Worker@interface CFStreamClientTests : XCTestCase
193*cc02d7e2SAndroid Build Coastguard Worker
194*cc02d7e2SAndroid Build Coastguard Worker@end
195*cc02d7e2SAndroid Build Coastguard Worker
196*cc02d7e2SAndroid Build Coastguard Worker@implementation CFStreamClientTests
197*cc02d7e2SAndroid Build Coastguard Worker
198*cc02d7e2SAndroid Build Coastguard Worker- (void)setUp {
199*cc02d7e2SAndroid Build Coastguard Worker  [super setUp];
200*cc02d7e2SAndroid Build Coastguard Worker}
201*cc02d7e2SAndroid Build Coastguard Worker
202*cc02d7e2SAndroid Build Coastguard Worker- (void)tearDown {
203*cc02d7e2SAndroid Build Coastguard Worker  [super tearDown];
204*cc02d7e2SAndroid Build Coastguard Worker}
205*cc02d7e2SAndroid Build Coastguard Worker
206*cc02d7e2SAndroid Build Coastguard Worker@end
207*cc02d7e2SAndroid Build Coastguard Worker
208*cc02d7e2SAndroid Build Coastguard Worker#endif  // GRPC_CFSTREAM
209