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 <limits.h> 26*cc02d7e2SAndroid Build Coastguard Worker 27*cc02d7e2SAndroid Build Coastguard Worker#include <netinet/in.h> 28*cc02d7e2SAndroid Build Coastguard Worker 29*cc02d7e2SAndroid Build Coastguard Worker#include <grpc/grpc.h> 30*cc02d7e2SAndroid Build Coastguard Worker#include <grpc/impl/codegen/sync.h> 31*cc02d7e2SAndroid Build Coastguard Worker#include <grpc/support/sync.h> 32*cc02d7e2SAndroid Build Coastguard Worker 33*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/address_utils/parse_address.h" 34*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/address_utils/sockaddr_utils.h" 35*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/event_engine/channel_args_endpoint_config.h" 36*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/iomgr/endpoint.h" 37*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/iomgr/resolve_address.h" 38*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/iomgr/tcp_client.h" 39*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/resource_quota/api.h" 40*cc02d7e2SAndroid Build Coastguard Worker#include "test/core/util/test_config.h" 41*cc02d7e2SAndroid Build Coastguard Worker 42*cc02d7e2SAndroid Build Coastguard Worker#include <chrono> 43*cc02d7e2SAndroid Build Coastguard Worker#include <future> 44*cc02d7e2SAndroid Build Coastguard Worker 45*cc02d7e2SAndroid Build Coastguard Workerstatic const int kConnectTimeout = 5; 46*cc02d7e2SAndroid Build Coastguard Workerstatic const int kWriteTimeout = 5; 47*cc02d7e2SAndroid Build Coastguard Workerstatic const int kReadTimeout = 5; 48*cc02d7e2SAndroid Build Coastguard Worker 49*cc02d7e2SAndroid Build Coastguard Workerstatic const int kBufferSize = 10000; 50*cc02d7e2SAndroid Build Coastguard Worker 51*cc02d7e2SAndroid Build Coastguard Workerstatic const int kRunLoopTimeout = 1; 52*cc02d7e2SAndroid Build Coastguard Worker 53*cc02d7e2SAndroid Build Coastguard Workerstatic void set_error_handle_promise(void *arg, grpc_error_handle error) { 54*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> *p = static_cast<std::promise<grpc_error_handle> *>(arg); 55*cc02d7e2SAndroid Build Coastguard Worker p->set_value(error); 56*cc02d7e2SAndroid Build Coastguard Worker} 57*cc02d7e2SAndroid Build Coastguard Worker 58*cc02d7e2SAndroid Build Coastguard Workerstatic void init_event_closure(grpc_closure *closure, 59*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> *error_handle) { 60*cc02d7e2SAndroid Build Coastguard Worker GRPC_CLOSURE_INIT(closure, set_error_handle_promise, static_cast<void *>(error_handle), 61*cc02d7e2SAndroid Build Coastguard Worker grpc_schedule_on_exec_ctx); 62*cc02d7e2SAndroid Build Coastguard Worker} 63*cc02d7e2SAndroid Build Coastguard Worker 64*cc02d7e2SAndroid Build Coastguard Workerstatic bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const char *buffer, 65*cc02d7e2SAndroid Build Coastguard Worker size_t buffer_len) { 66*cc02d7e2SAndroid Build Coastguard Worker if (slices->length != buffer_len) { 67*cc02d7e2SAndroid Build Coastguard Worker return false; 68*cc02d7e2SAndroid Build Coastguard Worker } 69*cc02d7e2SAndroid Build Coastguard Worker 70*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < slices->count; i++) { 71*cc02d7e2SAndroid Build Coastguard Worker grpc_slice slice = slices->slices[i]; 72*cc02d7e2SAndroid Build Coastguard Worker if (0 != memcmp(buffer, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice))) { 73*cc02d7e2SAndroid Build Coastguard Worker return false; 74*cc02d7e2SAndroid Build Coastguard Worker } 75*cc02d7e2SAndroid Build Coastguard Worker buffer += GRPC_SLICE_LENGTH(slice); 76*cc02d7e2SAndroid Build Coastguard Worker } 77*cc02d7e2SAndroid Build Coastguard Worker 78*cc02d7e2SAndroid Build Coastguard Worker return true; 79*cc02d7e2SAndroid Build Coastguard Worker} 80*cc02d7e2SAndroid Build Coastguard Worker 81*cc02d7e2SAndroid Build Coastguard Worker@interface CFStreamEndpointTests : XCTestCase 82*cc02d7e2SAndroid Build Coastguard Worker 83*cc02d7e2SAndroid Build Coastguard Worker@end 84*cc02d7e2SAndroid Build Coastguard Worker 85*cc02d7e2SAndroid Build Coastguard Worker@implementation CFStreamEndpointTests { 86*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint *ep_; 87*cc02d7e2SAndroid Build Coastguard Worker int svr_fd_; 88*cc02d7e2SAndroid Build Coastguard Worker} 89*cc02d7e2SAndroid Build Coastguard Worker 90*cc02d7e2SAndroid Build Coastguard Worker- (BOOL)waitForEvent:(std::future<grpc_error_handle> *)event timeout:(int)timeout { 91*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx::Get()->Flush(); 92*cc02d7e2SAndroid Build Coastguard Worker return event->wait_for(std::chrono::seconds(timeout)) != std::future_status::timeout; 93*cc02d7e2SAndroid Build Coastguard Worker} 94*cc02d7e2SAndroid Build Coastguard Worker 95*cc02d7e2SAndroid Build Coastguard Worker+ (void)setUp { 96*cc02d7e2SAndroid Build Coastguard Worker grpc_init(); 97*cc02d7e2SAndroid Build Coastguard Worker} 98*cc02d7e2SAndroid Build Coastguard Worker 99*cc02d7e2SAndroid Build Coastguard Worker+ (void)tearDown { 100*cc02d7e2SAndroid Build Coastguard Worker grpc_shutdown(); 101*cc02d7e2SAndroid Build Coastguard Worker} 102*cc02d7e2SAndroid Build Coastguard Worker 103*cc02d7e2SAndroid Build Coastguard Worker- (void)setUp { 104*cc02d7e2SAndroid Build Coastguard Worker self.continueAfterFailure = NO; 105*cc02d7e2SAndroid Build Coastguard Worker 106*cc02d7e2SAndroid Build Coastguard Worker // Set up CFStream connection before testing the endpoint 107*cc02d7e2SAndroid Build Coastguard Worker 108*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx; 109*cc02d7e2SAndroid Build Coastguard Worker 110*cc02d7e2SAndroid Build Coastguard Worker int svr_fd; 111*cc02d7e2SAndroid Build Coastguard Worker int r; 112*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> connected_promise; 113*cc02d7e2SAndroid Build Coastguard Worker grpc_closure done; 114*cc02d7e2SAndroid Build Coastguard Worker 115*cc02d7e2SAndroid Build Coastguard Worker gpr_log(GPR_DEBUG, "test_succeeds"); 116*cc02d7e2SAndroid Build Coastguard Worker 117*cc02d7e2SAndroid Build Coastguard Worker auto resolved_addr = grpc_core::StringToSockaddr("127.0.0.1:0"); 118*cc02d7e2SAndroid Build Coastguard Worker struct sockaddr_in *addr = reinterpret_cast<struct sockaddr_in *>(resolved_addr->addr); 119*cc02d7e2SAndroid Build Coastguard Worker 120*cc02d7e2SAndroid Build Coastguard Worker /* create a phony server */ 121*cc02d7e2SAndroid Build Coastguard Worker svr_fd = socket(AF_INET, SOCK_STREAM, 0); 122*cc02d7e2SAndroid Build Coastguard Worker XCTAssertGreaterThanOrEqual(svr_fd, 0); 123*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(bind(svr_fd, (struct sockaddr *)addr, (socklen_t)resolved_addr->len), 0); 124*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(listen(svr_fd, 1), 0); 125*cc02d7e2SAndroid Build Coastguard Worker 126*cc02d7e2SAndroid Build Coastguard Worker /* connect to it */ 127*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(getsockname(svr_fd, (struct sockaddr *)addr, (socklen_t *)&resolved_addr->len), 0); 128*cc02d7e2SAndroid Build Coastguard Worker init_event_closure(&done, &connected_promise); 129*cc02d7e2SAndroid Build Coastguard Worker auto args = 130*cc02d7e2SAndroid Build Coastguard Worker grpc_core::CoreConfiguration::Get().channel_args_preconditioning().PreconditionChannelArgs( 131*cc02d7e2SAndroid Build Coastguard Worker nullptr); 132*cc02d7e2SAndroid Build Coastguard Worker grpc_tcp_client_connect(&done, &ep_, nullptr, 133*cc02d7e2SAndroid Build Coastguard Worker grpc_event_engine::experimental::ChannelArgsEndpointConfig(args), 134*cc02d7e2SAndroid Build Coastguard Worker &*resolved_addr, grpc_core::Timestamp::InfFuture()); 135*cc02d7e2SAndroid Build Coastguard Worker 136*cc02d7e2SAndroid Build Coastguard Worker /* await the connection */ 137*cc02d7e2SAndroid Build Coastguard Worker do { 138*cc02d7e2SAndroid Build Coastguard Worker resolved_addr->len = sizeof(addr); 139*cc02d7e2SAndroid Build Coastguard Worker r = accept(svr_fd, reinterpret_cast<struct sockaddr *>(addr), 140*cc02d7e2SAndroid Build Coastguard Worker reinterpret_cast<socklen_t *>(&resolved_addr->len)); 141*cc02d7e2SAndroid Build Coastguard Worker } while (r == -1 && errno == EINTR); 142*cc02d7e2SAndroid Build Coastguard Worker XCTAssertGreaterThanOrEqual(r, 0, @"connection failed with return code %@ and errno %@", @(r), 143*cc02d7e2SAndroid Build Coastguard Worker @(errno)); 144*cc02d7e2SAndroid Build Coastguard Worker svr_fd_ = r; 145*cc02d7e2SAndroid Build Coastguard Worker 146*cc02d7e2SAndroid Build Coastguard Worker /* wait for the connection callback to finish */ 147*cc02d7e2SAndroid Build Coastguard Worker std::future<grpc_error_handle> connected_future = connected_promise.get_future(); 148*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([self waitForEvent:&connected_future timeout:kConnectTimeout], YES); 149*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(connected_future.get(), absl::OkStatus()); 150*cc02d7e2SAndroid Build Coastguard Worker} 151*cc02d7e2SAndroid Build Coastguard Worker 152*cc02d7e2SAndroid Build Coastguard Worker- (void)tearDown { 153*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx; 154*cc02d7e2SAndroid Build Coastguard Worker close(svr_fd_); 155*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_destroy(ep_); 156*cc02d7e2SAndroid Build Coastguard Worker} 157*cc02d7e2SAndroid Build Coastguard Worker 158*cc02d7e2SAndroid Build Coastguard Worker- (void)testReadWrite { 159*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx; 160*cc02d7e2SAndroid Build Coastguard Worker 161*cc02d7e2SAndroid Build Coastguard Worker grpc_closure read_done; 162*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer read_slices; 163*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer read_one_slice; 164*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> write_promise; 165*cc02d7e2SAndroid Build Coastguard Worker grpc_closure write_done; 166*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer write_slices; 167*cc02d7e2SAndroid Build Coastguard Worker 168*cc02d7e2SAndroid Build Coastguard Worker grpc_slice slice; 169*cc02d7e2SAndroid Build Coastguard Worker char write_buffer[kBufferSize]; 170*cc02d7e2SAndroid Build Coastguard Worker char read_buffer[kBufferSize]; 171*cc02d7e2SAndroid Build Coastguard Worker size_t recv_size = 0; 172*cc02d7e2SAndroid Build Coastguard Worker 173*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_init(&write_slices); 174*cc02d7e2SAndroid Build Coastguard Worker slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize); 175*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_add(&write_slices, slice); 176*cc02d7e2SAndroid Build Coastguard Worker init_event_closure(&write_done, &write_promise); 177*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_write(ep_, &write_slices, &write_done, nullptr, /*max_frame_size=*/INT_MAX); 178*cc02d7e2SAndroid Build Coastguard Worker 179*cc02d7e2SAndroid Build Coastguard Worker std::future<grpc_error_handle> write_future = write_promise.get_future(); 180*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([self waitForEvent:&write_future timeout:kWriteTimeout], YES); 181*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(write_future.get(), absl::OkStatus()); 182*cc02d7e2SAndroid Build Coastguard Worker 183*cc02d7e2SAndroid Build Coastguard Worker while (recv_size < kBufferSize) { 184*cc02d7e2SAndroid Build Coastguard Worker ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0); 185*cc02d7e2SAndroid Build Coastguard Worker XCTAssertGreaterThanOrEqual(size, 0); 186*cc02d7e2SAndroid Build Coastguard Worker recv_size += size; 187*cc02d7e2SAndroid Build Coastguard Worker } 188*cc02d7e2SAndroid Build Coastguard Worker 189*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(recv_size, kBufferSize); 190*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(memcmp(read_buffer, write_buffer, kBufferSize), 0); 191*cc02d7e2SAndroid Build Coastguard Worker ssize_t send_size = send(svr_fd_, read_buffer, kBufferSize, 0); 192*cc02d7e2SAndroid Build Coastguard Worker XCTAssertGreaterThanOrEqual(send_size, 0); 193*cc02d7e2SAndroid Build Coastguard Worker 194*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_init(&read_slices); 195*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_init(&read_one_slice); 196*cc02d7e2SAndroid Build Coastguard Worker while (read_slices.length < kBufferSize) { 197*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> read_promise; 198*cc02d7e2SAndroid Build Coastguard Worker init_event_closure(&read_done, &read_promise); 199*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_read(ep_, &read_one_slice, &read_done, /*urgent=*/false, 200*cc02d7e2SAndroid Build Coastguard Worker /*min_progress_size=*/1); 201*cc02d7e2SAndroid Build Coastguard Worker std::future<grpc_error_handle> read_future = read_promise.get_future(); 202*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([self waitForEvent:&read_future timeout:kReadTimeout], YES); 203*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(read_future.get(), absl::OkStatus()); 204*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_move_into(&read_one_slice, &read_slices); 205*cc02d7e2SAndroid Build Coastguard Worker XCTAssertLessThanOrEqual(read_slices.length, kBufferSize); 206*cc02d7e2SAndroid Build Coastguard Worker } 207*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(compare_slice_buffer_with_buffer(&read_slices, read_buffer, kBufferSize)); 208*cc02d7e2SAndroid Build Coastguard Worker 209*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_shutdown(ep_, absl::OkStatus()); 210*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_reset_and_unref(&read_slices); 211*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_reset_and_unref(&write_slices); 212*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_reset_and_unref(&read_one_slice); 213*cc02d7e2SAndroid Build Coastguard Worker} 214*cc02d7e2SAndroid Build Coastguard Worker 215*cc02d7e2SAndroid Build Coastguard Worker- (void)testShutdownBeforeRead { 216*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx; 217*cc02d7e2SAndroid Build Coastguard Worker 218*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> read_promise; 219*cc02d7e2SAndroid Build Coastguard Worker grpc_closure read_done; 220*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer read_slices; 221*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> write_promise; 222*cc02d7e2SAndroid Build Coastguard Worker grpc_closure write_done; 223*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer write_slices; 224*cc02d7e2SAndroid Build Coastguard Worker 225*cc02d7e2SAndroid Build Coastguard Worker grpc_slice slice; 226*cc02d7e2SAndroid Build Coastguard Worker char write_buffer[kBufferSize]; 227*cc02d7e2SAndroid Build Coastguard Worker char read_buffer[kBufferSize]; 228*cc02d7e2SAndroid Build Coastguard Worker size_t recv_size = 0; 229*cc02d7e2SAndroid Build Coastguard Worker 230*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_init(&read_slices); 231*cc02d7e2SAndroid Build Coastguard Worker init_event_closure(&read_done, &read_promise); 232*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_read(ep_, &read_slices, &read_done, /*urgent=*/false, 233*cc02d7e2SAndroid Build Coastguard Worker /*min_progress_size=*/1); 234*cc02d7e2SAndroid Build Coastguard Worker 235*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_init(&write_slices); 236*cc02d7e2SAndroid Build Coastguard Worker slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize); 237*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_add(&write_slices, slice); 238*cc02d7e2SAndroid Build Coastguard Worker init_event_closure(&write_done, &write_promise); 239*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_write(ep_, &write_slices, &write_done, nullptr, /*max_frame_size=*/INT_MAX); 240*cc02d7e2SAndroid Build Coastguard Worker 241*cc02d7e2SAndroid Build Coastguard Worker std::future<grpc_error_handle> write_future = write_promise.get_future(); 242*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([self waitForEvent:&write_future timeout:kWriteTimeout], YES); 243*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(write_future.get(), absl::OkStatus()); 244*cc02d7e2SAndroid Build Coastguard Worker 245*cc02d7e2SAndroid Build Coastguard Worker while (recv_size < kBufferSize) { 246*cc02d7e2SAndroid Build Coastguard Worker ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0); 247*cc02d7e2SAndroid Build Coastguard Worker XCTAssertGreaterThanOrEqual(size, 0); 248*cc02d7e2SAndroid Build Coastguard Worker recv_size += size; 249*cc02d7e2SAndroid Build Coastguard Worker } 250*cc02d7e2SAndroid Build Coastguard Worker 251*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(recv_size, kBufferSize); 252*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(memcmp(read_buffer, write_buffer, kBufferSize), 0); 253*cc02d7e2SAndroid Build Coastguard Worker 254*cc02d7e2SAndroid Build Coastguard Worker std::future<grpc_error_handle> read_future = read_promise.get_future(); 255*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([self waitForEvent:&read_future timeout:kReadTimeout], NO); 256*cc02d7e2SAndroid Build Coastguard Worker 257*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_shutdown(ep_, absl::OkStatus()); 258*cc02d7e2SAndroid Build Coastguard Worker 259*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx::Get()->Flush(); 260*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([self waitForEvent:&read_future timeout:kReadTimeout], YES); 261*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNotEqual(read_future.get(), absl::OkStatus()); 262*cc02d7e2SAndroid Build Coastguard Worker 263*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_reset_and_unref(&read_slices); 264*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_reset_and_unref(&write_slices); 265*cc02d7e2SAndroid Build Coastguard Worker} 266*cc02d7e2SAndroid Build Coastguard Worker 267*cc02d7e2SAndroid Build Coastguard Worker- (void)testRemoteClosed { 268*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx; 269*cc02d7e2SAndroid Build Coastguard Worker 270*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> read_promise; 271*cc02d7e2SAndroid Build Coastguard Worker grpc_closure read_done; 272*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer read_slices; 273*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> write_promise; 274*cc02d7e2SAndroid Build Coastguard Worker grpc_closure write_done; 275*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer write_slices; 276*cc02d7e2SAndroid Build Coastguard Worker 277*cc02d7e2SAndroid Build Coastguard Worker grpc_slice slice; 278*cc02d7e2SAndroid Build Coastguard Worker char write_buffer[kBufferSize]; 279*cc02d7e2SAndroid Build Coastguard Worker char read_buffer[kBufferSize]; 280*cc02d7e2SAndroid Build Coastguard Worker size_t recv_size = 0; 281*cc02d7e2SAndroid Build Coastguard Worker 282*cc02d7e2SAndroid Build Coastguard Worker init_event_closure(&read_done, &read_promise); 283*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_init(&read_slices); 284*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_read(ep_, &read_slices, &read_done, /*urgent=*/false, 285*cc02d7e2SAndroid Build Coastguard Worker /*min_progress_size=*/1); 286*cc02d7e2SAndroid Build Coastguard Worker 287*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_init(&write_slices); 288*cc02d7e2SAndroid Build Coastguard Worker slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize); 289*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_add(&write_slices, slice); 290*cc02d7e2SAndroid Build Coastguard Worker 291*cc02d7e2SAndroid Build Coastguard Worker init_event_closure(&write_done, &write_promise); 292*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_write(ep_, &write_slices, &write_done, nullptr, /*max_frame_size=*/INT_MAX); 293*cc02d7e2SAndroid Build Coastguard Worker 294*cc02d7e2SAndroid Build Coastguard Worker std::future<grpc_error_handle> write_future = write_promise.get_future(); 295*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([self waitForEvent:&write_future timeout:kWriteTimeout], YES); 296*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(write_future.get(), absl::OkStatus()); 297*cc02d7e2SAndroid Build Coastguard Worker 298*cc02d7e2SAndroid Build Coastguard Worker while (recv_size < kBufferSize) { 299*cc02d7e2SAndroid Build Coastguard Worker ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0); 300*cc02d7e2SAndroid Build Coastguard Worker XCTAssertGreaterThanOrEqual(size, 0); 301*cc02d7e2SAndroid Build Coastguard Worker recv_size += size; 302*cc02d7e2SAndroid Build Coastguard Worker } 303*cc02d7e2SAndroid Build Coastguard Worker 304*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(recv_size, kBufferSize); 305*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(memcmp(read_buffer, write_buffer, kBufferSize), 0); 306*cc02d7e2SAndroid Build Coastguard Worker 307*cc02d7e2SAndroid Build Coastguard Worker close(svr_fd_); 308*cc02d7e2SAndroid Build Coastguard Worker 309*cc02d7e2SAndroid Build Coastguard Worker std::future<grpc_error_handle> read_future = read_promise.get_future(); 310*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([self waitForEvent:&read_future timeout:kReadTimeout], YES); 311*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNotEqual(read_future.get(), absl::OkStatus()); 312*cc02d7e2SAndroid Build Coastguard Worker 313*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_shutdown(ep_, absl::OkStatus()); 314*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_reset_and_unref(&read_slices); 315*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_reset_and_unref(&write_slices); 316*cc02d7e2SAndroid Build Coastguard Worker} 317*cc02d7e2SAndroid Build Coastguard Worker 318*cc02d7e2SAndroid Build Coastguard Worker- (void)testRemoteReset { 319*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx; 320*cc02d7e2SAndroid Build Coastguard Worker 321*cc02d7e2SAndroid Build Coastguard Worker std::promise<grpc_error_handle> read_promise; 322*cc02d7e2SAndroid Build Coastguard Worker grpc_closure read_done; 323*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer read_slices; 324*cc02d7e2SAndroid Build Coastguard Worker 325*cc02d7e2SAndroid Build Coastguard Worker init_event_closure(&read_done, &read_promise); 326*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_init(&read_slices); 327*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_read(ep_, &read_slices, &read_done, /*urgent=*/false, 328*cc02d7e2SAndroid Build Coastguard Worker /*min_progress_size=*/1); 329*cc02d7e2SAndroid Build Coastguard Worker 330*cc02d7e2SAndroid Build Coastguard Worker struct linger so_linger; 331*cc02d7e2SAndroid Build Coastguard Worker so_linger.l_onoff = 1; 332*cc02d7e2SAndroid Build Coastguard Worker so_linger.l_linger = 0; 333*cc02d7e2SAndroid Build Coastguard Worker setsockopt(svr_fd_, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)); 334*cc02d7e2SAndroid Build Coastguard Worker 335*cc02d7e2SAndroid Build Coastguard Worker close(svr_fd_); 336*cc02d7e2SAndroid Build Coastguard Worker 337*cc02d7e2SAndroid Build Coastguard Worker std::future<grpc_error_handle> read_future = read_promise.get_future(); 338*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual([self waitForEvent:&read_future timeout:kReadTimeout], YES); 339*cc02d7e2SAndroid Build Coastguard Worker XCTAssertNotEqual(read_future.get(), absl::OkStatus()); 340*cc02d7e2SAndroid Build Coastguard Worker 341*cc02d7e2SAndroid Build Coastguard Worker grpc_endpoint_shutdown(ep_, absl::OkStatus()); 342*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_buffer_reset_and_unref(&read_slices); 343*cc02d7e2SAndroid Build Coastguard Worker} 344*cc02d7e2SAndroid Build Coastguard Worker 345*cc02d7e2SAndroid Build Coastguard Worker@end 346*cc02d7e2SAndroid Build Coastguard Worker 347*cc02d7e2SAndroid Build Coastguard Worker#else // GRPC_CFSTREAM 348*cc02d7e2SAndroid Build Coastguard Worker 349*cc02d7e2SAndroid Build Coastguard Worker// Phony test suite 350*cc02d7e2SAndroid Build Coastguard Worker@interface CFStreamEndpointTests : XCTestCase 351*cc02d7e2SAndroid Build Coastguard Worker@end 352*cc02d7e2SAndroid Build Coastguard Worker 353*cc02d7e2SAndroid Build Coastguard Worker@implementation CFStreamEndpointTests 354*cc02d7e2SAndroid Build Coastguard Worker- (void)setUp { 355*cc02d7e2SAndroid Build Coastguard Worker [super setUp]; 356*cc02d7e2SAndroid Build Coastguard Worker} 357*cc02d7e2SAndroid Build Coastguard Worker 358*cc02d7e2SAndroid Build Coastguard Worker- (void)tearDown { 359*cc02d7e2SAndroid Build Coastguard Worker [super tearDown]; 360*cc02d7e2SAndroid Build Coastguard Worker} 361*cc02d7e2SAndroid Build Coastguard Worker 362*cc02d7e2SAndroid Build Coastguard Worker@end 363*cc02d7e2SAndroid Build Coastguard Worker 364*cc02d7e2SAndroid Build Coastguard Worker#endif // GRPC_CFSTREAM 365