1 /*
2 *
3 * Copyright 2017 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <thread>
20
21 #include <grpcpp/impl/codegen/config.h>
22
23 #include <grpcpp/server.h>
24 #include <grpcpp/server_builder.h>
25
26 #include <grpcpp/create_channel.h>
27 #include <grpcpp/security/credentials.h>
28
29 #include <grpc/support/log.h>
30
31 #include "src/proto/grpc/testing/echo.grpc.pb.h"
32 #include "test/core/util/port.h"
33 #include "test/core/util/test_config.h"
34
35 #include <gtest/gtest.h>
36
37 namespace grpc {
38 namespace {
39
TEST(ServerRequestCallTest,ShortDeadlineDoesNotCauseOkayFalse)40 TEST(ServerRequestCallTest, ShortDeadlineDoesNotCauseOkayFalse) {
41 std::mutex mu;
42 bool shutting_down = false;
43
44 // grpc server config.
45 std::ostringstream s;
46 int p = grpc_pick_unused_port_or_die();
47 s << "[::1]:" << p;
48 const string address = s.str();
49 testing::EchoTestService::AsyncService service;
50 ServerBuilder builder;
51 builder.AddListeningPort(address, InsecureServerCredentials());
52 auto cq = builder.AddCompletionQueue();
53 builder.RegisterService(&service);
54 auto server = builder.BuildAndStart();
55
56 // server thread.
57 std::thread t([address, &service, &cq, &mu, &shutting_down] {
58 for (int n = 0; true; n++) {
59 ServerContext ctx;
60 testing::EchoRequest req;
61 ServerAsyncResponseWriter<testing::EchoResponse> responder(&ctx);
62
63 // if shutting down, don't enqueue a new request.
64 {
65 std::lock_guard<std::mutex> lock(mu);
66 if (!shutting_down) {
67 service.RequestEcho(&ctx, &req, &responder, cq.get(), cq.get(),
68 (void*)1);
69 }
70 }
71
72 bool ok;
73 void* tag;
74 if (!cq->Next(&tag, &ok)) {
75 break;
76 }
77
78 EXPECT_EQ((void*)1, tag);
79 // If not shutting down, ok must be true for new requests.
80 {
81 std::lock_guard<std::mutex> lock(mu);
82 if (!shutting_down && !ok) {
83 gpr_log(GPR_INFO, "!ok on request %d", n);
84 abort();
85 }
86 if (shutting_down && !ok) {
87 // Failed connection due to shutdown, continue flushing the CQ.
88 continue;
89 }
90 }
91
92 // Send a simple response after a small delay that would ensure the client
93 // deadline is exceeded.
94 gpr_log(GPR_INFO, "Got request %d", n);
95 testing::EchoResponse response;
96 response.set_message("foobar");
97 // A bit of sleep to make sure the deadline elapses.
98 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
99 gpr_time_from_millis(50, GPR_TIMESPAN)));
100 {
101 std::lock_guard<std::mutex> lock(mu);
102 if (shutting_down) {
103 gpr_log(GPR_INFO,
104 "shut down while processing call, not calling Finish()");
105 // Continue flushing the CQ.
106 continue;
107 }
108 gpr_log(GPR_INFO, "Finishing request %d", n);
109 responder.Finish(response, grpc::Status::OK, (void*)2);
110 if (!cq->Next(&tag, &ok)) {
111 break;
112 }
113 EXPECT_EQ((void*)2, tag);
114 }
115 }
116 });
117
118 auto stub = testing::EchoTestService::NewStub(
119 grpc::CreateChannel(address, InsecureChannelCredentials()));
120
121 for (int i = 0; i < 100; i++) {
122 gpr_log(GPR_INFO, "Sending %d.", i);
123 testing::EchoRequest request;
124
125 /////////
126 // Comment out the following line to get ok=false due to invalid request.
127 // Otherwise, ok=false due to deadline being exceeded.
128 /////////
129 request.set_message("foobar");
130
131 // A simple request with a short deadline. The server will always exceed the
132 // deadline, whether due to the sleep or because the server was unable to
133 // even fetch the request from the CQ before the deadline elapsed.
134 testing::EchoResponse response;
135 ::grpc::ClientContext ctx;
136 ctx.set_fail_fast(false);
137 ctx.set_deadline(std::chrono::system_clock::now() +
138 std::chrono::milliseconds(1));
139 grpc::Status status = stub->Echo(&ctx, request, &response);
140 EXPECT_EQ(DEADLINE_EXCEEDED, status.error_code());
141 gpr_log(GPR_INFO, "Success.");
142 }
143 gpr_log(GPR_INFO, "Done sending RPCs.");
144
145 // Shut down everything properly.
146 gpr_log(GPR_INFO, "Shutting down.");
147 {
148 std::lock_guard<std::mutex> lock(mu);
149 shutting_down = true;
150 }
151 server->Shutdown();
152 cq->Shutdown();
153 server->Wait();
154
155 t.join();
156 }
157
158 } // namespace
159 } // namespace grpc
160
main(int argc,char ** argv)161 int main(int argc, char** argv) {
162 grpc::testing::TestEnvironment env(argc, argv);
163 ::testing::InitGoogleTest(&argc, argv);
164 return RUN_ALL_TESTS();
165 }
166