• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
34 #include <gtest/gtest.h>
35 
36 namespace grpc {
37 namespace {
38 
TEST(ServerRequestCallTest,ShortDeadlineDoesNotCauseOkayFalse)39 TEST(ServerRequestCallTest, ShortDeadlineDoesNotCauseOkayFalse) {
40   std::mutex mu;
41   bool shutting_down = false;
42 
43   // grpc server config.
44   std::ostringstream s;
45   int p = grpc_pick_unused_port_or_die();
46   s << "[::1]:" << p;
47   const string address = s.str();
48   testing::EchoTestService::AsyncService service;
49   ServerBuilder builder;
50   builder.AddListeningPort(address, InsecureServerCredentials());
51   auto cq = builder.AddCompletionQueue();
52   builder.RegisterService(&service);
53   auto server = builder.BuildAndStart();
54 
55   // server thread.
56   std::thread t([address, &service, &cq, &mu, &shutting_down] {
57     for (int n = 0; true; n++) {
58       ServerContext ctx;
59       testing::EchoRequest req;
60       ServerAsyncResponseWriter<testing::EchoResponse> responder(&ctx);
61 
62       // if shutting down, don't enqueue a new request.
63       {
64         std::lock_guard<std::mutex> lock(mu);
65         if (!shutting_down) {
66           service.RequestEcho(&ctx, &req, &responder, cq.get(), cq.get(),
67                               (void*)1);
68         }
69       }
70 
71       bool ok;
72       void* tag;
73       if (!cq->Next(&tag, &ok)) {
74         break;
75       }
76 
77       EXPECT_EQ((void*)1, tag);
78       // If not shutting down, ok must be true for new requests.
79       {
80         std::lock_guard<std::mutex> lock(mu);
81         if (!shutting_down && !ok) {
82           gpr_log(GPR_INFO, "!ok on request %d", n);
83           abort();
84         }
85         if (shutting_down && !ok) {
86           // Failed connection due to shutdown, continue flushing the CQ.
87           continue;
88         }
89       }
90 
91       // Send a simple response after a small delay that would ensure the client
92       // deadline is exceeded.
93       gpr_log(GPR_INFO, "Got request %d", n);
94       testing::EchoResponse response;
95       response.set_message("foobar");
96       // A bit of sleep to make sure the deadline elapses.
97       gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
98                                    gpr_time_from_millis(50, GPR_TIMESPAN)));
99       {
100         std::lock_guard<std::mutex> lock(mu);
101         if (shutting_down) {
102           gpr_log(GPR_INFO,
103                   "shut down while processing call, not calling Finish()");
104           // Continue flushing the CQ.
105           continue;
106         }
107         gpr_log(GPR_INFO, "Finishing request %d", n);
108         responder.Finish(response, grpc::Status::OK, (void*)2);
109         if (!cq->Next(&tag, &ok)) {
110           break;
111         }
112         EXPECT_EQ((void*)2, tag);
113       }
114     }
115   });
116 
117   auto stub = testing::EchoTestService::NewStub(
118       CreateChannel(address, InsecureChannelCredentials()));
119 
120   for (int i = 0; i < 100; i++) {
121     gpr_log(GPR_INFO, "Sending %d.", i);
122     testing::EchoRequest request;
123 
124     /////////
125     // Comment out the following line to get ok=false due to invalid request.
126     // Otherwise, ok=false due to deadline being exceeded.
127     /////////
128     request.set_message("foobar");
129 
130     // A simple request with a short deadline. The server will always exceed the
131     // deadline, whether due to the sleep or because the server was unable to
132     // even fetch the request from the CQ before the deadline elapsed.
133     testing::EchoResponse response;
134     ::grpc::ClientContext ctx;
135     ctx.set_fail_fast(false);
136     ctx.set_deadline(std::chrono::system_clock::now() +
137                      std::chrono::milliseconds(1));
138     grpc::Status status = stub->Echo(&ctx, request, &response);
139     EXPECT_EQ(DEADLINE_EXCEEDED, status.error_code());
140     gpr_log(GPR_INFO, "Success.");
141   }
142   gpr_log(GPR_INFO, "Done sending RPCs.");
143 
144   // Shut down everything properly.
145   gpr_log(GPR_INFO, "Shutting down.");
146   {
147     std::lock_guard<std::mutex> lock(mu);
148     shutting_down = true;
149   }
150   server->Shutdown();
151   cq->Shutdown();
152   server->Wait();
153 
154   t.join();
155 }
156 
157 }  // namespace
158 }  // namespace grpc
159 
main(int argc,char ** argv)160 int main(int argc, char** argv) {
161   ::testing::InitGoogleTest(&argc, argv);
162   return RUN_ALL_TESTS();
163 }
164