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/impl/codegen/sync.h> 28#include <grpc/support/sync.h> 29 30#include "src/core/lib/iomgr/endpoint.h" 31#include "src/core/lib/iomgr/resolve_address.h" 32#include "src/core/lib/iomgr/tcp_client.h" 33#include "test/core/util/test_config.h" 34 35// static int g_connections_complete = 0; 36static gpr_mu g_mu; 37static int g_connections_complete = 0; 38static grpc_endpoint* g_connecting = nullptr; 39 40static void finish_connection() { 41 gpr_mu_lock(&g_mu); 42 g_connections_complete++; 43 gpr_mu_unlock(&g_mu); 44} 45 46static void must_succeed(void* arg, grpc_error* error) { 47 GPR_ASSERT(g_connecting != nullptr); 48 GPR_ASSERT(error == GRPC_ERROR_NONE); 49 grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called")); 50 grpc_endpoint_destroy(g_connecting); 51 g_connecting = nullptr; 52 finish_connection(); 53} 54 55static void must_fail(void* arg, grpc_error* error) { 56 GPR_ASSERT(g_connecting == nullptr); 57 GPR_ASSERT(error != GRPC_ERROR_NONE); 58 const char* error_str = grpc_error_string(error); 59 NSLog(@"%s", error_str); 60 finish_connection(); 61} 62 63@interface CFStreamClientTests : XCTestCase 64 65@end 66 67@implementation CFStreamClientTests 68 69+ (void)setUp { 70 grpc_init(); 71 gpr_mu_init(&g_mu); 72} 73 74+ (void)tearDown { 75 grpc_shutdown(); 76} 77 78- (void)testSucceeds { 79 grpc_resolved_address resolved_addr; 80 struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr); 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 memset(&resolved_addr, 0, sizeof(resolved_addr)); 90 resolved_addr.len = sizeof(struct sockaddr_in); 91 addr->sin_family = AF_INET; 92 93 /* create a dummy 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 grpc_tcp_client_connect(&done, &g_connecting, nullptr, nullptr, &resolved_addr, 107 GRPC_MILLIS_INF_FUTURE); 108 109 /* await the connection */ 110 do { 111 resolved_addr.len = sizeof(addr); 112 r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr), 113 reinterpret_cast<socklen_t*>(&resolved_addr.len)); 114 } while (r == -1 && errno == EINTR); 115 GPR_ASSERT(r >= 0); 116 close(r); 117 118 grpc_core::ExecCtx::Get()->Flush(); 119 120 /* wait for the connection callback to finish */ 121 gpr_mu_lock(&g_mu); 122 NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5]; 123 while (connections_complete_before == g_connections_complete) { 124 gpr_mu_unlock(&g_mu); 125 [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline]; 126 gpr_mu_lock(&g_mu); 127 } 128 XCTAssertGreaterThan(g_connections_complete, connections_complete_before); 129 130 gpr_mu_unlock(&g_mu); 131} 132 133- (void)testFails { 134 grpc_core::ExecCtx exec_ctx; 135 136 grpc_resolved_address resolved_addr; 137 struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr); 138 int connections_complete_before; 139 grpc_closure done; 140 int svr_fd; 141 142 gpr_log(GPR_DEBUG, "test_fails"); 143 144 memset(&resolved_addr, 0, sizeof(resolved_addr)); 145 resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in)); 146 addr->sin_family = AF_INET; 147 148 svr_fd = socket(AF_INET, SOCK_STREAM, 0); 149 GPR_ASSERT(svr_fd >= 0); 150 GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len)); 151 GPR_ASSERT(0 == listen(svr_fd, 1)); 152 GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr.len) == 0); 153 close(svr_fd); 154 155 gpr_mu_lock(&g_mu); 156 connections_complete_before = g_connections_complete; 157 gpr_mu_unlock(&g_mu); 158 159 /* connect to a broken address */ 160 GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx); 161 grpc_tcp_client_connect(&done, &g_connecting, nullptr, nullptr, &resolved_addr, 162 GRPC_MILLIS_INF_FUTURE); 163 164 grpc_core::ExecCtx::Get()->Flush(); 165 166 /* wait for the connection callback to finish */ 167 gpr_mu_lock(&g_mu); 168 NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5]; 169 while (g_connections_complete == connections_complete_before) { 170 gpr_mu_unlock(&g_mu); 171 [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline]; 172 gpr_mu_lock(&g_mu); 173 } 174 175 XCTAssertGreaterThan(g_connections_complete, connections_complete_before); 176 177 gpr_mu_unlock(&g_mu); 178} 179 180@end 181 182#else // GRPC_CFSTREAM 183 184// Dummy test suite 185@interface CFStreamClientTests : XCTestCase 186 187@end 188 189@implementation CFStreamClientTests 190 191- (void)setUp { 192 [super setUp]; 193} 194 195- (void)tearDown { 196 [super tearDown]; 197} 198 199@end 200 201#endif // GRPC_CFSTREAM 202