1*cc02d7e2SAndroid Build Coastguard Worker/* 2*cc02d7e2SAndroid Build Coastguard Worker * 3*cc02d7e2SAndroid Build Coastguard Worker * Copyright 2017 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 <sstream> 22*cc02d7e2SAndroid Build Coastguard Worker 23*cc02d7e2SAndroid Build Coastguard Worker#include <grpc/grpc.h> 24*cc02d7e2SAndroid Build Coastguard Worker#include <grpc/support/time.h> 25*cc02d7e2SAndroid Build Coastguard Worker#include <grpcpp/channel.h> 26*cc02d7e2SAndroid Build Coastguard Worker#include <grpcpp/client_context.h> 27*cc02d7e2SAndroid Build Coastguard Worker#include <grpcpp/create_channel.h> 28*cc02d7e2SAndroid Build Coastguard Worker#include <grpcpp/generic/async_generic_service.h> 29*cc02d7e2SAndroid Build Coastguard Worker#include <grpcpp/generic/generic_stub.h> 30*cc02d7e2SAndroid Build Coastguard Worker#include <grpcpp/server.h> 31*cc02d7e2SAndroid Build Coastguard Worker#include <grpcpp/server_builder.h> 32*cc02d7e2SAndroid Build Coastguard Worker#include <grpcpp/server_context.h> 33*cc02d7e2SAndroid Build Coastguard Worker#include <grpcpp/support/slice.h> 34*cc02d7e2SAndroid Build Coastguard Worker 35*cc02d7e2SAndroid Build Coastguard Worker#include "src/core/lib/gprpp/thd.h" 36*cc02d7e2SAndroid Build Coastguard Worker#include "test/core/util/port.h" 37*cc02d7e2SAndroid Build Coastguard Worker#include "test/core/util/test_config.h" 38*cc02d7e2SAndroid Build Coastguard Worker 39*cc02d7e2SAndroid Build Coastguard Workerusing std::chrono::system_clock; 40*cc02d7e2SAndroid Build Coastguard Workerusing namespace grpc; 41*cc02d7e2SAndroid Build Coastguard Worker 42*cc02d7e2SAndroid Build Coastguard Workervoid* tag(int i) { return (void*)(intptr_t)i; } 43*cc02d7e2SAndroid Build Coastguard Worker 44*cc02d7e2SAndroid Build Coastguard Workerstatic grpc_slice merge_slices(grpc_slice* slices, size_t nslices) { 45*cc02d7e2SAndroid Build Coastguard Worker size_t i; 46*cc02d7e2SAndroid Build Coastguard Worker size_t len = 0; 47*cc02d7e2SAndroid Build Coastguard Worker uint8_t* cursor; 48*cc02d7e2SAndroid Build Coastguard Worker grpc_slice out; 49*cc02d7e2SAndroid Build Coastguard Worker 50*cc02d7e2SAndroid Build Coastguard Worker for (i = 0; i < nslices; i++) { 51*cc02d7e2SAndroid Build Coastguard Worker len += GRPC_SLICE_LENGTH(slices[i]); 52*cc02d7e2SAndroid Build Coastguard Worker } 53*cc02d7e2SAndroid Build Coastguard Worker 54*cc02d7e2SAndroid Build Coastguard Worker out = grpc_slice_malloc(len); 55*cc02d7e2SAndroid Build Coastguard Worker cursor = GRPC_SLICE_START_PTR(out); 56*cc02d7e2SAndroid Build Coastguard Worker 57*cc02d7e2SAndroid Build Coastguard Worker for (i = 0; i < nslices; i++) { 58*cc02d7e2SAndroid Build Coastguard Worker memcpy(cursor, GRPC_SLICE_START_PTR(slices[i]), GRPC_SLICE_LENGTH(slices[i])); 59*cc02d7e2SAndroid Build Coastguard Worker cursor += GRPC_SLICE_LENGTH(slices[i]); 60*cc02d7e2SAndroid Build Coastguard Worker } 61*cc02d7e2SAndroid Build Coastguard Worker 62*cc02d7e2SAndroid Build Coastguard Worker return out; 63*cc02d7e2SAndroid Build Coastguard Worker} 64*cc02d7e2SAndroid Build Coastguard Worker 65*cc02d7e2SAndroid Build Coastguard Workerint byte_buffer_eq_string(ByteBuffer* bb, const char* str) { 66*cc02d7e2SAndroid Build Coastguard Worker int res; 67*cc02d7e2SAndroid Build Coastguard Worker 68*cc02d7e2SAndroid Build Coastguard Worker std::vector<Slice> slices; 69*cc02d7e2SAndroid Build Coastguard Worker bb->Dump(&slices); 70*cc02d7e2SAndroid Build Coastguard Worker grpc_slice* c_slices = new grpc_slice[slices.size()]; 71*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < slices.size(); i++) { 72*cc02d7e2SAndroid Build Coastguard Worker c_slices[i] = slices[i].c_slice(); 73*cc02d7e2SAndroid Build Coastguard Worker } 74*cc02d7e2SAndroid Build Coastguard Worker grpc_slice a = merge_slices(c_slices, slices.size()); 75*cc02d7e2SAndroid Build Coastguard Worker grpc_slice b = grpc_slice_from_copied_string(str); 76*cc02d7e2SAndroid Build Coastguard Worker res = (GRPC_SLICE_LENGTH(a) == GRPC_SLICE_LENGTH(b)) && 77*cc02d7e2SAndroid Build Coastguard Worker (0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b), GRPC_SLICE_LENGTH(a))); 78*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_unref(a); 79*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_unref(b); 80*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < slices.size(); i++) { 81*cc02d7e2SAndroid Build Coastguard Worker grpc_slice_unref(c_slices[i]); 82*cc02d7e2SAndroid Build Coastguard Worker } 83*cc02d7e2SAndroid Build Coastguard Worker delete[] c_slices; 84*cc02d7e2SAndroid Build Coastguard Worker 85*cc02d7e2SAndroid Build Coastguard Worker return res; 86*cc02d7e2SAndroid Build Coastguard Worker} 87*cc02d7e2SAndroid Build Coastguard Worker 88*cc02d7e2SAndroid Build Coastguard Worker@interface GenericTest : XCTestCase 89*cc02d7e2SAndroid Build Coastguard Worker 90*cc02d7e2SAndroid Build Coastguard Worker@end 91*cc02d7e2SAndroid Build Coastguard Worker 92*cc02d7e2SAndroid Build Coastguard Worker@implementation GenericTest { 93*cc02d7e2SAndroid Build Coastguard Worker std::string server_host_; 94*cc02d7e2SAndroid Build Coastguard Worker CompletionQueue cli_cq_; 95*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<ServerCompletionQueue> srv_cq_; 96*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<GenericStub> generic_stub_; 97*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<Server> server_; 98*cc02d7e2SAndroid Build Coastguard Worker AsyncGenericService generic_service_; 99*cc02d7e2SAndroid Build Coastguard Worker std::ostringstream server_address_; 100*cc02d7e2SAndroid Build Coastguard Worker} 101*cc02d7e2SAndroid Build Coastguard Worker 102*cc02d7e2SAndroid Build Coastguard Worker- (void)verify_ok:(grpc::CompletionQueue*)cq i:(int)i expect_ok:(bool)expect_ok { 103*cc02d7e2SAndroid Build Coastguard Worker bool ok; 104*cc02d7e2SAndroid Build Coastguard Worker void* got_tag; 105*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(cq->Next(&got_tag, &ok)); 106*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(expect_ok, ok); 107*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(tag(i), got_tag); 108*cc02d7e2SAndroid Build Coastguard Worker} 109*cc02d7e2SAndroid Build Coastguard Worker 110*cc02d7e2SAndroid Build Coastguard Worker- (void)server_ok:(int)i { 111*cc02d7e2SAndroid Build Coastguard Worker [self verify_ok:srv_cq_.get() i:i expect_ok:true]; 112*cc02d7e2SAndroid Build Coastguard Worker} 113*cc02d7e2SAndroid Build Coastguard Worker- (void)client_ok:(int)i { 114*cc02d7e2SAndroid Build Coastguard Worker [self verify_ok:&cli_cq_ i:i expect_ok:true]; 115*cc02d7e2SAndroid Build Coastguard Worker} 116*cc02d7e2SAndroid Build Coastguard Worker- (void)server_fail:(int)i { 117*cc02d7e2SAndroid Build Coastguard Worker [self verify_ok:srv_cq_.get() i:i expect_ok:false]; 118*cc02d7e2SAndroid Build Coastguard Worker} 119*cc02d7e2SAndroid Build Coastguard Worker- (void)client_fail:(int)i { 120*cc02d7e2SAndroid Build Coastguard Worker [self verify_ok:&cli_cq_ i:i expect_ok:false]; 121*cc02d7e2SAndroid Build Coastguard Worker} 122*cc02d7e2SAndroid Build Coastguard Worker 123*cc02d7e2SAndroid Build Coastguard Worker- (void)setUp { 124*cc02d7e2SAndroid Build Coastguard Worker [super setUp]; 125*cc02d7e2SAndroid Build Coastguard Worker 126*cc02d7e2SAndroid Build Coastguard Worker server_host_ = "localhost"; 127*cc02d7e2SAndroid Build Coastguard Worker int port = grpc_pick_unused_port_or_die(); 128*cc02d7e2SAndroid Build Coastguard Worker server_address_ << server_host_ << ":" << port; 129*cc02d7e2SAndroid Build Coastguard Worker // Setup server 130*cc02d7e2SAndroid Build Coastguard Worker ServerBuilder builder; 131*cc02d7e2SAndroid Build Coastguard Worker builder.AddListeningPort(server_address_.str(), InsecureServerCredentials()); 132*cc02d7e2SAndroid Build Coastguard Worker builder.RegisterAsyncGenericService(&generic_service_); 133*cc02d7e2SAndroid Build Coastguard Worker // Include a second call to RegisterAsyncGenericService to make sure that 134*cc02d7e2SAndroid Build Coastguard Worker // we get an error in the log, since it is not allowed to have 2 async 135*cc02d7e2SAndroid Build Coastguard Worker // generic services 136*cc02d7e2SAndroid Build Coastguard Worker builder.RegisterAsyncGenericService(&generic_service_); 137*cc02d7e2SAndroid Build Coastguard Worker srv_cq_ = builder.AddCompletionQueue(); 138*cc02d7e2SAndroid Build Coastguard Worker server_ = builder.BuildAndStart(); 139*cc02d7e2SAndroid Build Coastguard Worker} 140*cc02d7e2SAndroid Build Coastguard Worker 141*cc02d7e2SAndroid Build Coastguard Worker- (void)tearDown { 142*cc02d7e2SAndroid Build Coastguard Worker // Put teardown code here. This method is called after the invocation of each test method in the 143*cc02d7e2SAndroid Build Coastguard Worker // class. 144*cc02d7e2SAndroid Build Coastguard Worker server_->Shutdown(); 145*cc02d7e2SAndroid Build Coastguard Worker void* ignored_tag; 146*cc02d7e2SAndroid Build Coastguard Worker bool ignored_ok; 147*cc02d7e2SAndroid Build Coastguard Worker cli_cq_.Shutdown(); 148*cc02d7e2SAndroid Build Coastguard Worker srv_cq_->Shutdown(); 149*cc02d7e2SAndroid Build Coastguard Worker while (cli_cq_.Next(&ignored_tag, &ignored_ok)) 150*cc02d7e2SAndroid Build Coastguard Worker ; 151*cc02d7e2SAndroid Build Coastguard Worker while (srv_cq_->Next(&ignored_tag, &ignored_ok)) 152*cc02d7e2SAndroid Build Coastguard Worker ; 153*cc02d7e2SAndroid Build Coastguard Worker [super tearDown]; 154*cc02d7e2SAndroid Build Coastguard Worker} 155*cc02d7e2SAndroid Build Coastguard Worker 156*cc02d7e2SAndroid Build Coastguard Worker- (void)ResetStub { 157*cc02d7e2SAndroid Build Coastguard Worker std::shared_ptr<Channel> channel = 158*cc02d7e2SAndroid Build Coastguard Worker CreateChannel(server_address_.str(), InsecureChannelCredentials()); 159*cc02d7e2SAndroid Build Coastguard Worker generic_stub_.reset(new GenericStub(channel)); 160*cc02d7e2SAndroid Build Coastguard Worker} 161*cc02d7e2SAndroid Build Coastguard Worker 162*cc02d7e2SAndroid Build Coastguard Worker- (void)SendRpc:(int)num_rpcs { 163*cc02d7e2SAndroid Build Coastguard Worker [self SendRpc:num_rpcs check_deadline:false deadline:gpr_inf_future(GPR_CLOCK_MONOTONIC)]; 164*cc02d7e2SAndroid Build Coastguard Worker} 165*cc02d7e2SAndroid Build Coastguard Worker 166*cc02d7e2SAndroid Build Coastguard Worker- (void)SendRpc:(int)num_rpcs check_deadline:(bool)check_deadline deadline:(gpr_timespec)deadline { 167*cc02d7e2SAndroid Build Coastguard Worker const std::string kMethodName("/grpc.cpp.test.util.EchoTestService/Echo"); 168*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < num_rpcs; i++) { 169*cc02d7e2SAndroid Build Coastguard Worker Status recv_status; 170*cc02d7e2SAndroid Build Coastguard Worker 171*cc02d7e2SAndroid Build Coastguard Worker ClientContext cli_ctx; 172*cc02d7e2SAndroid Build Coastguard Worker GenericServerContext srv_ctx; 173*cc02d7e2SAndroid Build Coastguard Worker GenericServerAsyncReaderWriter stream(&srv_ctx); 174*cc02d7e2SAndroid Build Coastguard Worker 175*cc02d7e2SAndroid Build Coastguard Worker // The string needs to be long enough to test heap-based slice. 176*cc02d7e2SAndroid Build Coastguard Worker /*send_request.set_message("Hello world. Hello world. Hello world.");*/ 177*cc02d7e2SAndroid Build Coastguard Worker 178*cc02d7e2SAndroid Build Coastguard Worker if (check_deadline) { 179*cc02d7e2SAndroid Build Coastguard Worker cli_ctx.set_deadline(deadline); 180*cc02d7e2SAndroid Build Coastguard Worker } 181*cc02d7e2SAndroid Build Coastguard Worker 182*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<GenericClientAsyncReaderWriter> call = 183*cc02d7e2SAndroid Build Coastguard Worker generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1)); 184*cc02d7e2SAndroid Build Coastguard Worker [self client_ok:1]; 185*cc02d7e2SAndroid Build Coastguard Worker Slice send_slice = Slice("hello world", 11); 186*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<ByteBuffer> send_buffer = 187*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<ByteBuffer>(new ByteBuffer(&send_slice, 1)); 188*cc02d7e2SAndroid Build Coastguard Worker call->Write(*send_buffer, tag(2)); 189*cc02d7e2SAndroid Build Coastguard Worker // Send ByteBuffer can be destroyed after calling Write. 190*cc02d7e2SAndroid Build Coastguard Worker send_buffer.reset(); 191*cc02d7e2SAndroid Build Coastguard Worker [self client_ok:2]; 192*cc02d7e2SAndroid Build Coastguard Worker call->WritesDone(tag(3)); 193*cc02d7e2SAndroid Build Coastguard Worker [self client_ok:3]; 194*cc02d7e2SAndroid Build Coastguard Worker 195*cc02d7e2SAndroid Build Coastguard Worker generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), srv_cq_.get(), tag(4)); 196*cc02d7e2SAndroid Build Coastguard Worker 197*cc02d7e2SAndroid Build Coastguard Worker [self verify_ok:srv_cq_.get() i:4 expect_ok:true]; 198*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(server_host_, srv_ctx.host().substr(0, server_host_.length())); 199*cc02d7e2SAndroid Build Coastguard Worker XCTAssertEqual(kMethodName, srv_ctx.method()); 200*cc02d7e2SAndroid Build Coastguard Worker 201*cc02d7e2SAndroid Build Coastguard Worker if (check_deadline) { 202*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(gpr_time_similar(deadline, srv_ctx.raw_deadline(), 203*cc02d7e2SAndroid Build Coastguard Worker gpr_time_from_millis(1000, GPR_TIMESPAN))); 204*cc02d7e2SAndroid Build Coastguard Worker } 205*cc02d7e2SAndroid Build Coastguard Worker 206*cc02d7e2SAndroid Build Coastguard Worker ByteBuffer recv_buffer; 207*cc02d7e2SAndroid Build Coastguard Worker stream.Read(&recv_buffer, tag(5)); 208*cc02d7e2SAndroid Build Coastguard Worker [self server_ok:5]; 209*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(byte_buffer_eq_string(&recv_buffer, "hello world")); 210*cc02d7e2SAndroid Build Coastguard Worker 211*cc02d7e2SAndroid Build Coastguard Worker send_buffer = std::unique_ptr<ByteBuffer>(new ByteBuffer(recv_buffer)); 212*cc02d7e2SAndroid Build Coastguard Worker stream.Write(*send_buffer, tag(6)); 213*cc02d7e2SAndroid Build Coastguard Worker send_buffer.reset(); 214*cc02d7e2SAndroid Build Coastguard Worker [self server_ok:6]; 215*cc02d7e2SAndroid Build Coastguard Worker 216*cc02d7e2SAndroid Build Coastguard Worker stream.Finish(Status::OK, tag(7)); 217*cc02d7e2SAndroid Build Coastguard Worker [self server_ok:7]; 218*cc02d7e2SAndroid Build Coastguard Worker 219*cc02d7e2SAndroid Build Coastguard Worker recv_buffer.Clear(); 220*cc02d7e2SAndroid Build Coastguard Worker call->Read(&recv_buffer, tag(8)); 221*cc02d7e2SAndroid Build Coastguard Worker [self client_ok:8]; 222*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(byte_buffer_eq_string(&recv_buffer, "hello world")); 223*cc02d7e2SAndroid Build Coastguard Worker 224*cc02d7e2SAndroid Build Coastguard Worker call->Finish(&recv_status, tag(9)); 225*cc02d7e2SAndroid Build Coastguard Worker [self client_ok:9]; 226*cc02d7e2SAndroid Build Coastguard Worker 227*cc02d7e2SAndroid Build Coastguard Worker XCTAssertTrue(recv_status.ok()); 228*cc02d7e2SAndroid Build Coastguard Worker } 229*cc02d7e2SAndroid Build Coastguard Worker} 230*cc02d7e2SAndroid Build Coastguard Worker 231*cc02d7e2SAndroid Build Coastguard Worker- (void)testSimpleRpc { 232*cc02d7e2SAndroid Build Coastguard Worker [self ResetStub]; 233*cc02d7e2SAndroid Build Coastguard Worker [self SendRpc:1]; 234*cc02d7e2SAndroid Build Coastguard Worker} 235*cc02d7e2SAndroid Build Coastguard Worker 236*cc02d7e2SAndroid Build Coastguard Worker- (void)testSequentialRpcs { 237*cc02d7e2SAndroid Build Coastguard Worker [self ResetStub]; 238*cc02d7e2SAndroid Build Coastguard Worker [self SendRpc:10]; 239*cc02d7e2SAndroid Build Coastguard Worker} 240*cc02d7e2SAndroid Build Coastguard Worker 241*cc02d7e2SAndroid Build Coastguard Worker+ (void)setUp { 242*cc02d7e2SAndroid Build Coastguard Worker grpc_test_init(NULL, NULL); 243*cc02d7e2SAndroid Build Coastguard Worker} 244*cc02d7e2SAndroid Build Coastguard Worker 245*cc02d7e2SAndroid Build Coastguard Worker@end 246