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