| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 | /* * * Copyright 2017 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */#import <XCTest/XCTest.h>#include <sstream>#include <grpc/grpc.h>#include <grpc/support/time.h>#include <grpcpp/channel.h>#include <grpcpp/client_context.h>#include <grpcpp/create_channel.h>#include <grpcpp/generic/async_generic_service.h>#include <grpcpp/generic/generic_stub.h>#include <grpcpp/server.h>#include <grpcpp/server_builder.h>#include <grpcpp/server_context.h>#include <grpcpp/support/slice.h>#include "src/core/lib/gprpp/thd.h"#include "test/core/util/port.h"#include "test/core/util/test_config.h"using std::chrono::system_clock;using namespace grpc;void* tag(int i) { return (void*)(intptr_t)i; }static grpc_slice merge_slices(grpc_slice* slices, size_t nslices) {  size_t i;  size_t len = 0;  uint8_t* cursor;  grpc_slice out;  for (i = 0; i < nslices; i++) {    len += GRPC_SLICE_LENGTH(slices[i]);  }  out = grpc_slice_malloc(len);  cursor = GRPC_SLICE_START_PTR(out);  for (i = 0; i < nslices; i++) {    memcpy(cursor, GRPC_SLICE_START_PTR(slices[i]), GRPC_SLICE_LENGTH(slices[i]));    cursor += GRPC_SLICE_LENGTH(slices[i]);  }  return out;}int byte_buffer_eq_string(ByteBuffer* bb, const char* str) {  int res;  std::vector<Slice> slices;  bb->Dump(&slices);  grpc_slice* c_slices = new grpc_slice[slices.size()];  for (int i = 0; i < slices.size(); i++) {    c_slices[i] = slices[i].c_slice();  }  grpc_slice a = merge_slices(c_slices, slices.size());  grpc_slice b = grpc_slice_from_copied_string(str);  res = (GRPC_SLICE_LENGTH(a) == GRPC_SLICE_LENGTH(b)) &&        (0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b), GRPC_SLICE_LENGTH(a)));  grpc_slice_unref(a);  grpc_slice_unref(b);  for (int i = 0; i < slices.size(); i++) {    grpc_slice_unref(c_slices[i]);  }  delete[] c_slices;  return res;}@interface GenericTest : XCTestCase@end@implementation GenericTest {  grpc::string server_host_;  CompletionQueue cli_cq_;  std::unique_ptr<ServerCompletionQueue> srv_cq_;  std::unique_ptr<GenericStub> generic_stub_;  std::unique_ptr<Server> server_;  AsyncGenericService generic_service_;  std::ostringstream server_address_;}- (void)verify_ok:(grpc::CompletionQueue*)cq i:(int)i expect_ok:(bool)expect_ok {  bool ok;  void* got_tag;  XCTAssertTrue(cq->Next(&got_tag, &ok));  XCTAssertEqual(expect_ok, ok);  XCTAssertEqual(tag(i), got_tag);}- (void)server_ok:(int)i {  [self verify_ok:srv_cq_.get() i:i expect_ok:true];}- (void)client_ok:(int)i {  [self verify_ok:&cli_cq_ i:i expect_ok:true];}- (void)server_fail:(int)i {  [self verify_ok:srv_cq_.get() i:i expect_ok:false];}- (void)client_fail:(int)i {  [self verify_ok:&cli_cq_ i:i expect_ok:false];}- (void)setUp {  [super setUp];  server_host_ = "localhost";  int port = grpc_pick_unused_port_or_die();  server_address_ << server_host_ << ":" << port;  // Setup server  ServerBuilder builder;  builder.AddListeningPort(server_address_.str(), InsecureServerCredentials());  builder.RegisterAsyncGenericService(&generic_service_);  // Include a second call to RegisterAsyncGenericService to make sure that  // we get an error in the log, since it is not allowed to have 2 async  // generic services  builder.RegisterAsyncGenericService(&generic_service_);  srv_cq_ = builder.AddCompletionQueue();  server_ = builder.BuildAndStart();}- (void)tearDown {  // Put teardown code here. This method is called after the invocation of each test method in the  // class.  server_->Shutdown();  void* ignored_tag;  bool ignored_ok;  cli_cq_.Shutdown();  srv_cq_->Shutdown();  while (cli_cq_.Next(&ignored_tag, &ignored_ok))    ;  while (srv_cq_->Next(&ignored_tag, &ignored_ok))    ;  [super tearDown];}- (void)ResetStub {  std::shared_ptr<Channel> channel =      CreateChannel(server_address_.str(), InsecureChannelCredentials());  generic_stub_.reset(new GenericStub(channel));}- (void)SendRpc:(int)num_rpcs {  [self SendRpc:num_rpcs check_deadline:false deadline:gpr_inf_future(GPR_CLOCK_MONOTONIC)];}- (void)SendRpc:(int)num_rpcs check_deadline:(bool)check_deadline deadline:(gpr_timespec)deadline {  const grpc::string kMethodName("/grpc.cpp.test.util.EchoTestService/Echo");  for (int i = 0; i < num_rpcs; i++) {    Status recv_status;    ClientContext cli_ctx;    GenericServerContext srv_ctx;    GenericServerAsyncReaderWriter stream(&srv_ctx);    // The string needs to be long enough to test heap-based slice.    /*send_request.set_message("Hello world. Hello world. Hello world.");*/    if (check_deadline) {      cli_ctx.set_deadline(deadline);    }    std::unique_ptr<GenericClientAsyncReaderWriter> call =        generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1));    [self client_ok:1];    Slice send_slice = Slice("hello world", 11);    std::unique_ptr<ByteBuffer> send_buffer =        std::unique_ptr<ByteBuffer>(new ByteBuffer(&send_slice, 1));    call->Write(*send_buffer, tag(2));    // Send ByteBuffer can be destroyed after calling Write.    send_buffer.reset();    [self client_ok:2];    call->WritesDone(tag(3));    [self client_ok:3];    generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), srv_cq_.get(), tag(4));    [self verify_ok:srv_cq_.get() i:4 expect_ok:true];    XCTAssertEqual(server_host_, srv_ctx.host().substr(0, server_host_.length()));    XCTAssertEqual(kMethodName, srv_ctx.method());    if (check_deadline) {      XCTAssertTrue(gpr_time_similar(deadline, srv_ctx.raw_deadline(),                                     gpr_time_from_millis(1000, GPR_TIMESPAN)));    }    ByteBuffer recv_buffer;    stream.Read(&recv_buffer, tag(5));    [self server_ok:5];    XCTAssertTrue(byte_buffer_eq_string(&recv_buffer, "hello world"));    send_buffer = std::unique_ptr<ByteBuffer>(new ByteBuffer(recv_buffer));    stream.Write(*send_buffer, tag(6));    send_buffer.reset();    [self server_ok:6];    stream.Finish(Status::OK, tag(7));    [self server_ok:7];    recv_buffer.Clear();    call->Read(&recv_buffer, tag(8));    [self client_ok:8];    XCTAssertTrue(byte_buffer_eq_string(&recv_buffer, "hello world"));    call->Finish(&recv_status, tag(9));    [self client_ok:9];    XCTAssertTrue(recv_status.ok());  }}- (void)testSimpleRpc {  [self ResetStub];  [self SendRpc:1];}- (void)testSequentialRpcs {  [self ResetStub];  [self SendRpc:10];}+ (void)setUp {  grpc_test_init(0, NULL);}@end
 |