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