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