xref: /aosp_15_r20/external/grpc-grpc/src/objective-c/tests/CppCronetTests/CppCronetEnd2EndTests.mm (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1*cc02d7e2SAndroid Build Coastguard Worker/*
2*cc02d7e2SAndroid Build Coastguard Worker *
3*cc02d7e2SAndroid Build Coastguard Worker * Copyright 2019 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 <Cronet/Cronet.h>
20*cc02d7e2SAndroid Build Coastguard Worker#import <XCTest/XCTest.h>
21*cc02d7e2SAndroid Build Coastguard Worker
22*cc02d7e2SAndroid Build Coastguard Worker#import <grpc/grpc_cronet.h>
23*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/client_context.h>
24*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/create_channel.h>
25*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/resource_quota.h>
26*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/security/cronet_credentials.h>
27*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/server_builder.h>
28*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/server_context.h>
29*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/support/client_interceptor.h>
30*cc02d7e2SAndroid Build Coastguard Worker#import <grpcpp/support/config.h>
31*cc02d7e2SAndroid Build Coastguard Worker#import "src/proto/grpc/testing/echo.grpc.pb.h"
32*cc02d7e2SAndroid Build Coastguard Worker
33*cc02d7e2SAndroid Build Coastguard Worker#import "TestHelper.h"
34*cc02d7e2SAndroid Build Coastguard Worker#import "test/core/end2end/data/ssl_test_data.h"
35*cc02d7e2SAndroid Build Coastguard Worker
36*cc02d7e2SAndroid Build Coastguard Worker#import <map>
37*cc02d7e2SAndroid Build Coastguard Worker#import <sstream>
38*cc02d7e2SAndroid Build Coastguard Worker#import <thread>
39*cc02d7e2SAndroid Build Coastguard Worker#import <vector>
40*cc02d7e2SAndroid Build Coastguard Worker
41*cc02d7e2SAndroid Build Coastguard Workerusing namespace grpc::testing;
42*cc02d7e2SAndroid Build Coastguard Workerusing grpc::ClientContext;
43*cc02d7e2SAndroid Build Coastguard Workerusing grpc::ServerContext;
44*cc02d7e2SAndroid Build Coastguard Workerusing grpc::Status;
45*cc02d7e2SAndroid Build Coastguard Workerusing std::chrono::system_clock;
46*cc02d7e2SAndroid Build Coastguard Worker
47*cc02d7e2SAndroid Build Coastguard Worker@interface CppCronetEnd2EndTests : XCTestCase
48*cc02d7e2SAndroid Build Coastguard Worker
49*cc02d7e2SAndroid Build Coastguard Worker@end
50*cc02d7e2SAndroid Build Coastguard Worker
51*cc02d7e2SAndroid Build Coastguard Worker@implementation CppCronetEnd2EndTests {
52*cc02d7e2SAndroid Build Coastguard Worker  std::unique_ptr<grpc::Server> _server;
53*cc02d7e2SAndroid Build Coastguard Worker  TestServiceImpl _service;
54*cc02d7e2SAndroid Build Coastguard Worker  TestServiceImpl _foo_service;
55*cc02d7e2SAndroid Build Coastguard Worker}
56*cc02d7e2SAndroid Build Coastguard Worker
57*cc02d7e2SAndroid Build Coastguard Worker// The setUp() function is run before the test cases run and only run once
58*cc02d7e2SAndroid Build Coastguard Worker+ (void)setUp {
59*cc02d7e2SAndroid Build Coastguard Worker  [super setUp];
60*cc02d7e2SAndroid Build Coastguard Worker  configureCronet();
61*cc02d7e2SAndroid Build Coastguard Worker}
62*cc02d7e2SAndroid Build Coastguard Worker
63*cc02d7e2SAndroid Build Coastguard Worker- (void)startServer {
64*cc02d7e2SAndroid Build Coastguard Worker  if (_server) {
65*cc02d7e2SAndroid Build Coastguard Worker    // server is already running
66*cc02d7e2SAndroid Build Coastguard Worker    return;
67*cc02d7e2SAndroid Build Coastguard Worker  }
68*cc02d7e2SAndroid Build Coastguard Worker
69*cc02d7e2SAndroid Build Coastguard Worker  grpc::ServerBuilder builder;
70*cc02d7e2SAndroid Build Coastguard Worker  grpc::SslServerCredentialsOptions ssl_opts;
71*cc02d7e2SAndroid Build Coastguard Worker
72*cc02d7e2SAndroid Build Coastguard Worker  ssl_opts.pem_root_certs = "";
73*cc02d7e2SAndroid Build Coastguard Worker  grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key, test_server1_cert};
74*cc02d7e2SAndroid Build Coastguard Worker  ssl_opts.pem_key_cert_pairs.push_back(pkcp);
75*cc02d7e2SAndroid Build Coastguard Worker  auto server_creds = SslServerCredentials(ssl_opts);
76*cc02d7e2SAndroid Build Coastguard Worker  builder.AddListeningPort("localhost:5000", server_creds);
77*cc02d7e2SAndroid Build Coastguard Worker  builder.RegisterService(&_service);
78*cc02d7e2SAndroid Build Coastguard Worker  builder.RegisterService("foo.test.youtube.com", &_foo_service);
79*cc02d7e2SAndroid Build Coastguard Worker  _server = builder.BuildAndStart();
80*cc02d7e2SAndroid Build Coastguard Worker}
81*cc02d7e2SAndroid Build Coastguard Worker
82*cc02d7e2SAndroid Build Coastguard Worker- (void)stopServer {
83*cc02d7e2SAndroid Build Coastguard Worker  _server.reset();
84*cc02d7e2SAndroid Build Coastguard Worker}
85*cc02d7e2SAndroid Build Coastguard Worker
86*cc02d7e2SAndroid Build Coastguard Worker- (void)restartServer {
87*cc02d7e2SAndroid Build Coastguard Worker  [self stopServer];
88*cc02d7e2SAndroid Build Coastguard Worker  [self startServer];
89*cc02d7e2SAndroid Build Coastguard Worker}
90*cc02d7e2SAndroid Build Coastguard Worker
91*cc02d7e2SAndroid Build Coastguard Worker- (void)setUp {
92*cc02d7e2SAndroid Build Coastguard Worker  [self startServer];
93*cc02d7e2SAndroid Build Coastguard Worker}
94*cc02d7e2SAndroid Build Coastguard Worker
95*cc02d7e2SAndroid Build Coastguard Worker- (void)sendRPCWithStub:(EchoTestService::Stub*)stub
96*cc02d7e2SAndroid Build Coastguard Worker                numRPCs:(int)num_rpcs
97*cc02d7e2SAndroid Build Coastguard Worker     withBinaryMetadata:(BOOL)with_binary_metadata {
98*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
99*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
100*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello hello hello hello");
101*cc02d7e2SAndroid Build Coastguard Worker
102*cc02d7e2SAndroid Build Coastguard Worker  for (int i = 0; i < num_rpcs; ++i) {
103*cc02d7e2SAndroid Build Coastguard Worker    ClientContext context;
104*cc02d7e2SAndroid Build Coastguard Worker    if (with_binary_metadata) {
105*cc02d7e2SAndroid Build Coastguard Worker      char bytes[8] = {'\0', '\1', '\2', '\3', '\4', '\5', '\6', static_cast<char>(i)};
106*cc02d7e2SAndroid Build Coastguard Worker      context.AddMetadata("custom-bin", std::string(bytes, 8));
107*cc02d7e2SAndroid Build Coastguard Worker    }
108*cc02d7e2SAndroid Build Coastguard Worker    context.set_compression_algorithm(GRPC_COMPRESS_GZIP);
109*cc02d7e2SAndroid Build Coastguard Worker    Status s = stub->Echo(&context, request, &response);
110*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertEqual(response.message(), request.message());
111*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertTrue(s.ok());
112*cc02d7e2SAndroid Build Coastguard Worker  }
113*cc02d7e2SAndroid Build Coastguard Worker}
114*cc02d7e2SAndroid Build Coastguard Worker
115*cc02d7e2SAndroid Build Coastguard Worker- (std::shared_ptr<::grpc::Channel>)getChannel {
116*cc02d7e2SAndroid Build Coastguard Worker  stream_engine* cronetEngine = [Cronet getGlobalEngine];
117*cc02d7e2SAndroid Build Coastguard Worker  auto cronetChannelCredentials = grpc::CronetChannelCredentials(cronetEngine);
118*cc02d7e2SAndroid Build Coastguard Worker  grpc::ChannelArguments args;
119*cc02d7e2SAndroid Build Coastguard Worker  args.SetSslTargetNameOverride("foo.test.google.fr");
120*cc02d7e2SAndroid Build Coastguard Worker  args.SetUserAgentPrefix("custom_prefix");
121*cc02d7e2SAndroid Build Coastguard Worker  args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test");
122*cc02d7e2SAndroid Build Coastguard Worker  auto channel = grpc::CreateCustomChannel("127.0.0.1:5000", cronetChannelCredentials, args);
123*cc02d7e2SAndroid Build Coastguard Worker  return channel;
124*cc02d7e2SAndroid Build Coastguard Worker}
125*cc02d7e2SAndroid Build Coastguard Worker
126*cc02d7e2SAndroid Build Coastguard Worker- (std::shared_ptr<::grpc::Channel>)getChannelWithInterceptors:
127*cc02d7e2SAndroid Build Coastguard Worker    (std::vector<std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>>)creators {
128*cc02d7e2SAndroid Build Coastguard Worker  stream_engine* cronetEngine = [Cronet getGlobalEngine];
129*cc02d7e2SAndroid Build Coastguard Worker  auto cronetChannelCredentials = grpc::CronetChannelCredentials(cronetEngine);
130*cc02d7e2SAndroid Build Coastguard Worker  grpc::ChannelArguments args;
131*cc02d7e2SAndroid Build Coastguard Worker  args.SetSslTargetNameOverride("foo.test.google.fr");
132*cc02d7e2SAndroid Build Coastguard Worker  args.SetUserAgentPrefix("custom_prefix");
133*cc02d7e2SAndroid Build Coastguard Worker  args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test");
134*cc02d7e2SAndroid Build Coastguard Worker  auto channel = grpc::experimental::CreateCustomChannelWithInterceptors(
135*cc02d7e2SAndroid Build Coastguard Worker      "127.0.01:5000", cronetChannelCredentials, args, std::move(creators));
136*cc02d7e2SAndroid Build Coastguard Worker  return channel;
137*cc02d7e2SAndroid Build Coastguard Worker}
138*cc02d7e2SAndroid Build Coastguard Worker
139*cc02d7e2SAndroid Build Coastguard Worker- (std::unique_ptr<EchoTestService::Stub>)getStub {
140*cc02d7e2SAndroid Build Coastguard Worker  auto channel = [self getChannel];
141*cc02d7e2SAndroid Build Coastguard Worker  auto stub = EchoTestService::NewStub(channel);
142*cc02d7e2SAndroid Build Coastguard Worker  return stub;
143*cc02d7e2SAndroid Build Coastguard Worker}
144*cc02d7e2SAndroid Build Coastguard Worker
145*cc02d7e2SAndroid Build Coastguard Worker- (void)testUserAgent {
146*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
147*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
148*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
149*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello");
150*cc02d7e2SAndroid Build Coastguard Worker  request.mutable_param()->set_echo_metadata(true);
151*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
152*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
153*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
154*cc02d7e2SAndroid Build Coastguard Worker  const auto& trailing_metadata = context.GetServerTrailingMetadata();
155*cc02d7e2SAndroid Build Coastguard Worker  auto iter = trailing_metadata.find("user-agent");
156*cc02d7e2SAndroid Build Coastguard Worker  XCTAssert(iter->second.starts_with("custom_prefix grpc-c++"));
157*cc02d7e2SAndroid Build Coastguard Worker}
158*cc02d7e2SAndroid Build Coastguard Worker
159*cc02d7e2SAndroid Build Coastguard Worker- (void)testMultipleRPCs {
160*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
161*cc02d7e2SAndroid Build Coastguard Worker  std::vector<std::thread> threads;
162*cc02d7e2SAndroid Build Coastguard Worker  threads.reserve(10);
163*cc02d7e2SAndroid Build Coastguard Worker  for (int i = 0; i < 10; ++i) {
164*cc02d7e2SAndroid Build Coastguard Worker    threads.emplace_back(
165*cc02d7e2SAndroid Build Coastguard Worker        [self, &stub]() { [self sendRPCWithStub:stub.get() numRPCs:10 withBinaryMetadata:NO]; });
166*cc02d7e2SAndroid Build Coastguard Worker  }
167*cc02d7e2SAndroid Build Coastguard Worker  for (int i = 0; i < 10; ++i) {
168*cc02d7e2SAndroid Build Coastguard Worker    threads[i].join();
169*cc02d7e2SAndroid Build Coastguard Worker  }
170*cc02d7e2SAndroid Build Coastguard Worker}
171*cc02d7e2SAndroid Build Coastguard Worker
172*cc02d7e2SAndroid Build Coastguard Worker- (void)testMultipleRPCsWithBinaryMetadata {
173*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
174*cc02d7e2SAndroid Build Coastguard Worker  std::vector<std::thread> threads;
175*cc02d7e2SAndroid Build Coastguard Worker  threads.reserve(10);
176*cc02d7e2SAndroid Build Coastguard Worker  for (int i = 0; i < 10; ++i) {
177*cc02d7e2SAndroid Build Coastguard Worker    threads.emplace_back(
178*cc02d7e2SAndroid Build Coastguard Worker        [self, &stub]() { [self sendRPCWithStub:stub.get() numRPCs:10 withBinaryMetadata:YES]; });
179*cc02d7e2SAndroid Build Coastguard Worker  }
180*cc02d7e2SAndroid Build Coastguard Worker  for (int i = 0; i < 10; ++i) {
181*cc02d7e2SAndroid Build Coastguard Worker    threads[i].join();
182*cc02d7e2SAndroid Build Coastguard Worker  }
183*cc02d7e2SAndroid Build Coastguard Worker}
184*cc02d7e2SAndroid Build Coastguard Worker
185*cc02d7e2SAndroid Build Coastguard Worker- (void)testEmptyBinaryMetadata {
186*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
187*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
188*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello hello hello hello");
189*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
190*cc02d7e2SAndroid Build Coastguard Worker  context.AddMetadata("custom-bin", "");
191*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
192*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
193*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
194*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
195*cc02d7e2SAndroid Build Coastguard Worker}
196*cc02d7e2SAndroid Build Coastguard Worker
197*cc02d7e2SAndroid Build Coastguard Worker- (void)testReconnectChannel {
198*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
199*cc02d7e2SAndroid Build Coastguard Worker  [self sendRPCWithStub:stub.get() numRPCs:1 withBinaryMetadata:NO];
200*cc02d7e2SAndroid Build Coastguard Worker
201*cc02d7e2SAndroid Build Coastguard Worker  [self restartServer];
202*cc02d7e2SAndroid Build Coastguard Worker  [self sendRPCWithStub:stub.get() numRPCs:1 withBinaryMetadata:NO];
203*cc02d7e2SAndroid Build Coastguard Worker}
204*cc02d7e2SAndroid Build Coastguard Worker
205*cc02d7e2SAndroid Build Coastguard Worker- (void)testRequestStreamOneRequest {
206*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
207*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
208*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
209*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
210*cc02d7e2SAndroid Build Coastguard Worker  auto stream = stub->RequestStream(&context, &response);
211*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("hello");
212*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
213*cc02d7e2SAndroid Build Coastguard Worker  stream->WritesDone();
214*cc02d7e2SAndroid Build Coastguard Worker  Status s = stream->Finish();
215*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
216*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
217*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(context.debug_error_string().empty());
218*cc02d7e2SAndroid Build Coastguard Worker}
219*cc02d7e2SAndroid Build Coastguard Worker
220*cc02d7e2SAndroid Build Coastguard Worker- (void)testRequestStreamOneRequestWithCoalescingApi {
221*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
222*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
223*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
224*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
225*cc02d7e2SAndroid Build Coastguard Worker  context.set_initial_metadata_corked(true);
226*cc02d7e2SAndroid Build Coastguard Worker  auto stream = stub->RequestStream(&context, &response);
227*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("hello");
228*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
229*cc02d7e2SAndroid Build Coastguard Worker  stream->WritesDone();
230*cc02d7e2SAndroid Build Coastguard Worker  Status s = stream->Finish();
231*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
232*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
233*cc02d7e2SAndroid Build Coastguard Worker}
234*cc02d7e2SAndroid Build Coastguard Worker
235*cc02d7e2SAndroid Build Coastguard Worker- (void)testRequestStreamTwoRequests {
236*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
237*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
238*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
239*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
240*cc02d7e2SAndroid Build Coastguard Worker  auto stream = stub->RequestStream(&context, &response);
241*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("hello");
242*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
243*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
244*cc02d7e2SAndroid Build Coastguard Worker  stream->WritesDone();
245*cc02d7e2SAndroid Build Coastguard Worker  Status s = stream->Finish();
246*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), "hellohello");
247*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
248*cc02d7e2SAndroid Build Coastguard Worker}
249*cc02d7e2SAndroid Build Coastguard Worker
250*cc02d7e2SAndroid Build Coastguard Worker- (void)testResponseStream {
251*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
252*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
253*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
254*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
255*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("hello");
256*cc02d7e2SAndroid Build Coastguard Worker
257*cc02d7e2SAndroid Build Coastguard Worker  auto stream = stub->ResponseStream(&context, request);
258*cc02d7e2SAndroid Build Coastguard Worker  for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) {
259*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertTrue(stream->Read(&response));
260*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertEqual(response.message(), request.message() + std::to_string(i));
261*cc02d7e2SAndroid Build Coastguard Worker  }
262*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertFalse(stream->Read(&response));
263*cc02d7e2SAndroid Build Coastguard Worker
264*cc02d7e2SAndroid Build Coastguard Worker  Status s = stream->Finish();
265*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
266*cc02d7e2SAndroid Build Coastguard Worker}
267*cc02d7e2SAndroid Build Coastguard Worker
268*cc02d7e2SAndroid Build Coastguard Worker- (void)testBidiStream {
269*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
270*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
271*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
272*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
273*cc02d7e2SAndroid Build Coastguard Worker  std::string msg("hello");
274*cc02d7e2SAndroid Build Coastguard Worker
275*cc02d7e2SAndroid Build Coastguard Worker  auto stream = stub->BidiStream(&context);
276*cc02d7e2SAndroid Build Coastguard Worker
277*cc02d7e2SAndroid Build Coastguard Worker  for (int i = 0; i < kServerDefaultResponseStreamsToSend; ++i) {
278*cc02d7e2SAndroid Build Coastguard Worker    request.set_message(msg + std::to_string(i));
279*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertTrue(stream->Write(request));
280*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertTrue(stream->Read(&response));
281*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertEqual(response.message(), request.message());
282*cc02d7e2SAndroid Build Coastguard Worker  }
283*cc02d7e2SAndroid Build Coastguard Worker
284*cc02d7e2SAndroid Build Coastguard Worker  stream->WritesDone();
285*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertFalse(stream->Read(&response));
286*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertFalse(stream->Read(&response));
287*cc02d7e2SAndroid Build Coastguard Worker
288*cc02d7e2SAndroid Build Coastguard Worker  Status s = stream->Finish();
289*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
290*cc02d7e2SAndroid Build Coastguard Worker}
291*cc02d7e2SAndroid Build Coastguard Worker
292*cc02d7e2SAndroid Build Coastguard Worker- (void)testBidiStreamWithCoalescingApi {
293*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
294*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
295*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
296*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
297*cc02d7e2SAndroid Build Coastguard Worker  context.AddMetadata(kServerFinishAfterNReads, "3");
298*cc02d7e2SAndroid Build Coastguard Worker  context.set_initial_metadata_corked(true);
299*cc02d7e2SAndroid Build Coastguard Worker  std::string msg("hello");
300*cc02d7e2SAndroid Build Coastguard Worker
301*cc02d7e2SAndroid Build Coastguard Worker  auto stream = stub->BidiStream(&context);
302*cc02d7e2SAndroid Build Coastguard Worker
303*cc02d7e2SAndroid Build Coastguard Worker  request.set_message(msg + "0");
304*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
305*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Read(&response));
306*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
307*cc02d7e2SAndroid Build Coastguard Worker
308*cc02d7e2SAndroid Build Coastguard Worker  request.set_message(msg + "1");
309*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
310*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Read(&response));
311*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
312*cc02d7e2SAndroid Build Coastguard Worker
313*cc02d7e2SAndroid Build Coastguard Worker  request.set_message(msg + "2");
314*cc02d7e2SAndroid Build Coastguard Worker  stream->WriteLast(request, grpc::WriteOptions());
315*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Read(&response));
316*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
317*cc02d7e2SAndroid Build Coastguard Worker
318*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertFalse(stream->Read(&response));
319*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertFalse(stream->Read(&response));
320*cc02d7e2SAndroid Build Coastguard Worker
321*cc02d7e2SAndroid Build Coastguard Worker  Status s = stream->Finish();
322*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
323*cc02d7e2SAndroid Build Coastguard Worker}
324*cc02d7e2SAndroid Build Coastguard Worker
325*cc02d7e2SAndroid Build Coastguard Worker- (void)testCancelBeforeStart {
326*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
327*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
328*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
329*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
330*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("hello");
331*cc02d7e2SAndroid Build Coastguard Worker  context.TryCancel();
332*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
333*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual("", response.message());
334*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(grpc::StatusCode::CANCELLED, s.error_code());
335*cc02d7e2SAndroid Build Coastguard Worker}
336*cc02d7e2SAndroid Build Coastguard Worker
337*cc02d7e2SAndroid Build Coastguard Worker- (void)testClientCancelsRequestStream {
338*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
339*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
340*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
341*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
342*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("hello");
343*cc02d7e2SAndroid Build Coastguard Worker
344*cc02d7e2SAndroid Build Coastguard Worker  auto stream = stub->RequestStream(&context, &response);
345*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
346*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
347*cc02d7e2SAndroid Build Coastguard Worker
348*cc02d7e2SAndroid Build Coastguard Worker  context.TryCancel();
349*cc02d7e2SAndroid Build Coastguard Worker
350*cc02d7e2SAndroid Build Coastguard Worker  Status s = stream->Finish();
351*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(grpc::StatusCode::CANCELLED, s.error_code());
352*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), "");
353*cc02d7e2SAndroid Build Coastguard Worker}
354*cc02d7e2SAndroid Build Coastguard Worker
355*cc02d7e2SAndroid Build Coastguard Worker- (void)testClientCancelsResponseStream {
356*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
357*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
358*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
359*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
360*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("hello");
361*cc02d7e2SAndroid Build Coastguard Worker
362*cc02d7e2SAndroid Build Coastguard Worker  auto stream = stub->ResponseStream(&context, request);
363*cc02d7e2SAndroid Build Coastguard Worker
364*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Read(&response));
365*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message() + "0");
366*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Read(&response));
367*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message() + "1");
368*cc02d7e2SAndroid Build Coastguard Worker
369*cc02d7e2SAndroid Build Coastguard Worker  context.TryCancel();
370*cc02d7e2SAndroid Build Coastguard Worker
371*cc02d7e2SAndroid Build Coastguard Worker  // The cancellation races with responses, so there might be zero or
372*cc02d7e2SAndroid Build Coastguard Worker  // one responses pending, read till failure
373*cc02d7e2SAndroid Build Coastguard Worker
374*cc02d7e2SAndroid Build Coastguard Worker  if (stream->Read(&response)) {
375*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertEqual(response.message(), request.message() + "2");
376*cc02d7e2SAndroid Build Coastguard Worker    // Since we have cancelled, we expect the next attempt to read to fail
377*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertFalse(stream->Read(&response));
378*cc02d7e2SAndroid Build Coastguard Worker  }
379*cc02d7e2SAndroid Build Coastguard Worker}
380*cc02d7e2SAndroid Build Coastguard Worker
381*cc02d7e2SAndroid Build Coastguard Worker- (void)testlClientCancelsBidiStream {
382*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
383*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
384*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
385*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
386*cc02d7e2SAndroid Build Coastguard Worker  std::string msg("hello");
387*cc02d7e2SAndroid Build Coastguard Worker
388*cc02d7e2SAndroid Build Coastguard Worker  auto stream = stub->BidiStream(&context);
389*cc02d7e2SAndroid Build Coastguard Worker
390*cc02d7e2SAndroid Build Coastguard Worker  request.set_message(msg + "0");
391*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
392*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Read(&response));
393*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
394*cc02d7e2SAndroid Build Coastguard Worker
395*cc02d7e2SAndroid Build Coastguard Worker  request.set_message(msg + "1");
396*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(stream->Write(request));
397*cc02d7e2SAndroid Build Coastguard Worker
398*cc02d7e2SAndroid Build Coastguard Worker  context.TryCancel();
399*cc02d7e2SAndroid Build Coastguard Worker
400*cc02d7e2SAndroid Build Coastguard Worker  // The cancellation races with responses, so there might be zero or
401*cc02d7e2SAndroid Build Coastguard Worker  // one responses pending, read till failure
402*cc02d7e2SAndroid Build Coastguard Worker
403*cc02d7e2SAndroid Build Coastguard Worker  if (stream->Read(&response)) {
404*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertEqual(response.message(), request.message());
405*cc02d7e2SAndroid Build Coastguard Worker    // Since we have cancelled, we expect the next attempt to read to fail
406*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertFalse(stream->Read(&response));
407*cc02d7e2SAndroid Build Coastguard Worker  }
408*cc02d7e2SAndroid Build Coastguard Worker
409*cc02d7e2SAndroid Build Coastguard Worker  Status s = stream->Finish();
410*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(grpc::StatusCode::CANCELLED, s.error_code());
411*cc02d7e2SAndroid Build Coastguard Worker}
412*cc02d7e2SAndroid Build Coastguard Worker
413*cc02d7e2SAndroid Build Coastguard Worker- (void)testNonExistingService {
414*cc02d7e2SAndroid Build Coastguard Worker  auto channel = [self getChannel];
415*cc02d7e2SAndroid Build Coastguard Worker  auto stub = grpc::testing::UnimplementedEchoService::NewStub(channel);
416*cc02d7e2SAndroid Build Coastguard Worker
417*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
418*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
419*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello");
420*cc02d7e2SAndroid Build Coastguard Worker
421*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
422*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Unimplemented(&context, request, &response);
423*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(grpc::StatusCode::UNIMPLEMENTED, s.error_code());
424*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual("", s.error_message());
425*cc02d7e2SAndroid Build Coastguard Worker}
426*cc02d7e2SAndroid Build Coastguard Worker
427*cc02d7e2SAndroid Build Coastguard Worker- (void)testBinaryTrailer {
428*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
429*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
430*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
431*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
432*cc02d7e2SAndroid Build Coastguard Worker
433*cc02d7e2SAndroid Build Coastguard Worker  request.mutable_param()->set_echo_metadata(true);
434*cc02d7e2SAndroid Build Coastguard Worker  DebugInfo* info = request.mutable_param()->mutable_debug_info();
435*cc02d7e2SAndroid Build Coastguard Worker  info->add_stack_entries("stack_entry_1");
436*cc02d7e2SAndroid Build Coastguard Worker  info->add_stack_entries("stack_entry_2");
437*cc02d7e2SAndroid Build Coastguard Worker  info->add_stack_entries("stack_entry_3");
438*cc02d7e2SAndroid Build Coastguard Worker  info->set_detail("detailed debug info");
439*cc02d7e2SAndroid Build Coastguard Worker  std::string expected_string = info->SerializeAsString();
440*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello");
441*cc02d7e2SAndroid Build Coastguard Worker
442*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
443*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertFalse(s.ok());
444*cc02d7e2SAndroid Build Coastguard Worker  auto trailers = context.GetServerTrailingMetadata();
445*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(1u, trailers.count(kDebugInfoTrailerKey));
446*cc02d7e2SAndroid Build Coastguard Worker  auto iter = trailers.find(kDebugInfoTrailerKey);
447*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(expected_string, iter->second);
448*cc02d7e2SAndroid Build Coastguard Worker  // Parse the returned trailer into a DebugInfo proto.
449*cc02d7e2SAndroid Build Coastguard Worker  DebugInfo returned_info;
450*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(returned_info.ParseFromString(ToString(iter->second)));
451*cc02d7e2SAndroid Build Coastguard Worker}
452*cc02d7e2SAndroid Build Coastguard Worker
453*cc02d7e2SAndroid Build Coastguard Worker- (void)testExpectError {
454*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
455*cc02d7e2SAndroid Build Coastguard Worker  std::vector<ErrorStatus> expected_status;
456*cc02d7e2SAndroid Build Coastguard Worker  expected_status.emplace_back();
457*cc02d7e2SAndroid Build Coastguard Worker  expected_status.back().set_code(13);  // INTERNAL
458*cc02d7e2SAndroid Build Coastguard Worker  // No Error message or details
459*cc02d7e2SAndroid Build Coastguard Worker
460*cc02d7e2SAndroid Build Coastguard Worker  expected_status.emplace_back();
461*cc02d7e2SAndroid Build Coastguard Worker  expected_status.back().set_code(13);  // INTERNAL
462*cc02d7e2SAndroid Build Coastguard Worker  expected_status.back().set_error_message("text error message");
463*cc02d7e2SAndroid Build Coastguard Worker  expected_status.back().set_binary_error_details("text error details");
464*cc02d7e2SAndroid Build Coastguard Worker
465*cc02d7e2SAndroid Build Coastguard Worker  expected_status.emplace_back();
466*cc02d7e2SAndroid Build Coastguard Worker  expected_status.back().set_code(13);  // INTERNAL
467*cc02d7e2SAndroid Build Coastguard Worker  expected_status.back().set_error_message("text error message");
468*cc02d7e2SAndroid Build Coastguard Worker  expected_status.back().set_binary_error_details("\x0\x1\x2\x3\x4\x5\x6\x8\x9\xA\xB");
469*cc02d7e2SAndroid Build Coastguard Worker
470*cc02d7e2SAndroid Build Coastguard Worker  for (auto iter = expected_status.begin(); iter != expected_status.end(); ++iter) {
471*cc02d7e2SAndroid Build Coastguard Worker    EchoRequest request;
472*cc02d7e2SAndroid Build Coastguard Worker    EchoResponse response;
473*cc02d7e2SAndroid Build Coastguard Worker    ClientContext context;
474*cc02d7e2SAndroid Build Coastguard Worker    request.set_message("Hello");
475*cc02d7e2SAndroid Build Coastguard Worker    auto* error = request.mutable_param()->mutable_expected_error();
476*cc02d7e2SAndroid Build Coastguard Worker    error->set_code(iter->code());
477*cc02d7e2SAndroid Build Coastguard Worker    error->set_error_message(iter->error_message());
478*cc02d7e2SAndroid Build Coastguard Worker    error->set_binary_error_details(iter->binary_error_details());
479*cc02d7e2SAndroid Build Coastguard Worker
480*cc02d7e2SAndroid Build Coastguard Worker    Status s = stub->Echo(&context, request, &response);
481*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertFalse(s.ok());
482*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertEqual(iter->code(), s.error_code());
483*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertEqual(iter->error_message(), s.error_message());
484*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertEqual(iter->binary_error_details(), s.error_details());
485*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertTrue(context.debug_error_string().find("created") != std::string::npos);
486*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertTrue(context.debug_error_string().find("file") != std::string::npos);
487*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertTrue(context.debug_error_string().find("line") != std::string::npos);
488*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertTrue(context.debug_error_string().find("status") != std::string::npos);
489*cc02d7e2SAndroid Build Coastguard Worker    XCTAssertTrue(context.debug_error_string().find("13") != std::string::npos);
490*cc02d7e2SAndroid Build Coastguard Worker  }
491*cc02d7e2SAndroid Build Coastguard Worker}
492*cc02d7e2SAndroid Build Coastguard Worker
493*cc02d7e2SAndroid Build Coastguard Worker- (void)testRpcDeadlineExpires {
494*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
495*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
496*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
497*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello");
498*cc02d7e2SAndroid Build Coastguard Worker  request.mutable_param()->set_skip_cancelled_check(true);
499*cc02d7e2SAndroid Build Coastguard Worker  // Let server sleep for 40 ms first to guarantee expiry.
500*cc02d7e2SAndroid Build Coastguard Worker  request.mutable_param()->set_server_sleep_us(40 * 1000);
501*cc02d7e2SAndroid Build Coastguard Worker
502*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
503*cc02d7e2SAndroid Build Coastguard Worker  std::chrono::system_clock::time_point deadline =
504*cc02d7e2SAndroid Build Coastguard Worker      std::chrono::system_clock::now() + std::chrono::milliseconds(1);
505*cc02d7e2SAndroid Build Coastguard Worker  context.set_deadline(deadline);
506*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
507*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(grpc::StatusCode::DEADLINE_EXCEEDED, s.error_code());
508*cc02d7e2SAndroid Build Coastguard Worker}
509*cc02d7e2SAndroid Build Coastguard Worker
510*cc02d7e2SAndroid Build Coastguard Worker- (void)testRpcLongDeadline {
511*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
512*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
513*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
514*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello");
515*cc02d7e2SAndroid Build Coastguard Worker
516*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
517*cc02d7e2SAndroid Build Coastguard Worker  std::chrono::system_clock::time_point deadline =
518*cc02d7e2SAndroid Build Coastguard Worker      std::chrono::system_clock::now() + std::chrono::hours(1);
519*cc02d7e2SAndroid Build Coastguard Worker  context.set_deadline(deadline);
520*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
521*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
522*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
523*cc02d7e2SAndroid Build Coastguard Worker}
524*cc02d7e2SAndroid Build Coastguard Worker
525*cc02d7e2SAndroid Build Coastguard Worker- (void)testEchoDeadlineForNoDeadlineRpc {
526*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
527*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
528*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
529*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello");
530*cc02d7e2SAndroid Build Coastguard Worker  request.mutable_param()->set_echo_deadline(true);
531*cc02d7e2SAndroid Build Coastguard Worker
532*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
533*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
534*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
535*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
536*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.param().request_deadline(), gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec);
537*cc02d7e2SAndroid Build Coastguard Worker}
538*cc02d7e2SAndroid Build Coastguard Worker
539*cc02d7e2SAndroid Build Coastguard Worker- (void)testEchoDeadline {
540*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
541*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
542*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
543*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello");
544*cc02d7e2SAndroid Build Coastguard Worker  request.mutable_param()->set_echo_deadline(true);
545*cc02d7e2SAndroid Build Coastguard Worker
546*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
547*cc02d7e2SAndroid Build Coastguard Worker  std::chrono::system_clock::time_point deadline =
548*cc02d7e2SAndroid Build Coastguard Worker      std::chrono::system_clock::now() + std::chrono::seconds(100);
549*cc02d7e2SAndroid Build Coastguard Worker  context.set_deadline(deadline);
550*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
551*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(response.message(), request.message());
552*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
553*cc02d7e2SAndroid Build Coastguard Worker  gpr_timespec sent_deadline;
554*cc02d7e2SAndroid Build Coastguard Worker  grpc::Timepoint2Timespec(deadline, &sent_deadline);
555*cc02d7e2SAndroid Build Coastguard Worker  // We want to allow some reasonable error given:
556*cc02d7e2SAndroid Build Coastguard Worker  // - request_deadline() only has 1sec resolution so the best we can do is +-1
557*cc02d7e2SAndroid Build Coastguard Worker  // - if sent_deadline.tv_nsec is very close to the next second's boundary we
558*cc02d7e2SAndroid Build Coastguard Worker  // can end up being off by 2 in one direction.
559*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertLessThanOrEqual(response.param().request_deadline() - sent_deadline.tv_sec, 2);
560*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertGreaterThanOrEqual(response.param().request_deadline() - sent_deadline.tv_sec, -1);
561*cc02d7e2SAndroid Build Coastguard Worker  NSLog(@"request deadline: %d sent_deadline: %d", response.param().request_deadline(),
562*cc02d7e2SAndroid Build Coastguard Worker        sent_deadline.tv_sec);
563*cc02d7e2SAndroid Build Coastguard Worker}
564*cc02d7e2SAndroid Build Coastguard Worker
565*cc02d7e2SAndroid Build Coastguard Worker- (void)testPeer {
566*cc02d7e2SAndroid Build Coastguard Worker  auto stub = [self getStub];
567*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
568*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
569*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello");
570*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
571*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
572*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
573*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(CheckIsLocalhost(context.peer()));
574*cc02d7e2SAndroid Build Coastguard Worker}
575*cc02d7e2SAndroid Build Coastguard Worker
576*cc02d7e2SAndroid Build Coastguard Worker- (void)testClientInterceptor {
577*cc02d7e2SAndroid Build Coastguard Worker  PhonyInterceptor::Reset();
578*cc02d7e2SAndroid Build Coastguard Worker  std::vector<std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>> creators;
579*cc02d7e2SAndroid Build Coastguard Worker  // Add 20 phony interceptors
580*cc02d7e2SAndroid Build Coastguard Worker  for (auto i = 0; i < 20; i++) {
581*cc02d7e2SAndroid Build Coastguard Worker    creators.push_back(std::unique_ptr<PhonyInterceptorFactory>(new PhonyInterceptorFactory()));
582*cc02d7e2SAndroid Build Coastguard Worker  }
583*cc02d7e2SAndroid Build Coastguard Worker  auto channel = [self getChannelWithInterceptors:std::move(creators)];
584*cc02d7e2SAndroid Build Coastguard Worker  auto stub = EchoTestService::NewStub(channel);
585*cc02d7e2SAndroid Build Coastguard Worker
586*cc02d7e2SAndroid Build Coastguard Worker  EchoRequest request;
587*cc02d7e2SAndroid Build Coastguard Worker  EchoResponse response;
588*cc02d7e2SAndroid Build Coastguard Worker  ClientContext context;
589*cc02d7e2SAndroid Build Coastguard Worker  request.set_message("Hello");
590*cc02d7e2SAndroid Build Coastguard Worker  Status s = stub->Echo(&context, request, &response);
591*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertTrue(s.ok());
592*cc02d7e2SAndroid Build Coastguard Worker  XCTAssertEqual(PhonyInterceptor::GetNumTimesRun(), 20);
593*cc02d7e2SAndroid Build Coastguard Worker}
594*cc02d7e2SAndroid Build Coastguard Worker
595*cc02d7e2SAndroid Build Coastguard Worker@end
596