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