1 /*
2 *
3 * Copyright 2016 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 <gflags/gflags.h>
22 #include <grpc/support/alloc.h>
23 #include <grpc/support/log.h>
24 #include <grpcpp/channel.h>
25 #include <grpcpp/client_context.h>
26
27 #include "src/core/lib/transport/byte_stream.h"
28 #include "src/proto/grpc/testing/messages.pb.h"
29 #include "src/proto/grpc/testing/test.grpc.pb.h"
30 #include "test/cpp/interop/http2_client.h"
31
32 #include "src/core/lib/gpr/string.h"
33 #include "src/core/lib/gpr/useful.h"
34 #include "test/cpp/util/create_test_channel.h"
35 #include "test/cpp/util/test_config.h"
36
37 namespace grpc {
38 namespace testing {
39
40 namespace {
41 const int kLargeRequestSize = 271828;
42 const int kLargeResponseSize = 314159;
43 } // namespace
44
ServiceStub(const std::shared_ptr<Channel> & channel)45 Http2Client::ServiceStub::ServiceStub(const std::shared_ptr<Channel>& channel)
46 : channel_(std::move(channel)) {
47 stub_ = TestService::NewStub(channel);
48 }
49
Get()50 TestService::Stub* Http2Client::ServiceStub::Get() { return stub_.get(); }
51
Http2Client(const std::shared_ptr<Channel> & channel)52 Http2Client::Http2Client(const std::shared_ptr<Channel>& channel)
53 : serviceStub_(channel),
54 channel_(std::move(channel)),
55 defaultRequest_(BuildDefaultRequest()) {}
56
AssertStatusCode(const Status & s,StatusCode expected_code)57 bool Http2Client::AssertStatusCode(const Status& s, StatusCode expected_code) {
58 if (s.error_code() == expected_code) {
59 return true;
60 }
61
62 gpr_log(GPR_ERROR, "Error status code: %d (expected: %d), message: %s",
63 s.error_code(), expected_code, s.error_message().c_str());
64 abort();
65 }
66
SendUnaryCall(SimpleResponse * response)67 Status Http2Client::SendUnaryCall(SimpleResponse* response) {
68 ClientContext context;
69 return serviceStub_.Get()->UnaryCall(&context, defaultRequest_, response);
70 }
71
BuildDefaultRequest()72 SimpleRequest Http2Client::BuildDefaultRequest() {
73 SimpleRequest request;
74 request.set_response_size(kLargeResponseSize);
75 grpc::string payload(kLargeRequestSize, '\0');
76 request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
77 return request;
78 }
79
DoRstAfterHeader()80 bool Http2Client::DoRstAfterHeader() {
81 gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after header");
82
83 SimpleResponse response;
84 AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::INTERNAL);
85 GPR_ASSERT(!response.has_payload()); // no data should be received
86
87 gpr_log(GPR_DEBUG, "Done testing reset stream after header");
88 return true;
89 }
90
DoRstAfterData()91 bool Http2Client::DoRstAfterData() {
92 gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after data");
93
94 SimpleResponse response;
95 AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::INTERNAL);
96 // There is no guarantee that data would be received.
97
98 gpr_log(GPR_DEBUG, "Done testing reset stream after data");
99 return true;
100 }
101
DoRstDuringData()102 bool Http2Client::DoRstDuringData() {
103 gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream during data");
104
105 SimpleResponse response;
106 AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::INTERNAL);
107 GPR_ASSERT(!response.has_payload()); // no data should be received
108
109 gpr_log(GPR_DEBUG, "Done testing reset stream during data");
110 return true;
111 }
112
DoGoaway()113 bool Http2Client::DoGoaway() {
114 gpr_log(GPR_DEBUG, "Sending two RPCs and expecting goaway");
115 SimpleResponse response;
116 AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
117 GPR_ASSERT(response.payload().body() ==
118 grpc::string(kLargeResponseSize, '\0'));
119
120 // Sleep for one second to give time for client to receive goaway frame.
121 gpr_timespec sleep_time = gpr_time_add(
122 gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(1, GPR_TIMESPAN));
123 gpr_sleep_until(sleep_time);
124
125 response.Clear();
126 AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
127 GPR_ASSERT(response.payload().body() ==
128 grpc::string(kLargeResponseSize, '\0'));
129 gpr_log(GPR_DEBUG, "Done testing goaway");
130 return true;
131 }
132
DoPing()133 bool Http2Client::DoPing() {
134 gpr_log(GPR_DEBUG, "Sending RPC and expecting ping");
135 SimpleResponse response;
136 AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
137 GPR_ASSERT(response.payload().body() ==
138 grpc::string(kLargeResponseSize, '\0'));
139 gpr_log(GPR_DEBUG, "Done testing ping");
140 return true;
141 }
142
MaxStreamsWorker(const std::shared_ptr<grpc::Channel> & channel)143 void Http2Client::MaxStreamsWorker(
144 const std::shared_ptr<grpc::Channel>& channel) {
145 SimpleResponse response;
146 AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
147 GPR_ASSERT(response.payload().body() ==
148 grpc::string(kLargeResponseSize, '\0'));
149 }
150
DoMaxStreams()151 bool Http2Client::DoMaxStreams() {
152 gpr_log(GPR_DEBUG, "Testing max streams");
153
154 // Make an initial call on the channel to ensure the server's max streams
155 // setting is received
156 SimpleResponse response;
157 AssertStatusCode(SendUnaryCall(&response), grpc::StatusCode::OK);
158 GPR_ASSERT(response.payload().body() ==
159 grpc::string(kLargeResponseSize, '\0'));
160
161 std::vector<std::thread> test_threads;
162
163 for (int i = 0; i < 10; i++) {
164 test_threads.emplace_back(
165 std::thread(&Http2Client::MaxStreamsWorker, this, channel_));
166 }
167
168 for (auto it = test_threads.begin(); it != test_threads.end(); it++) {
169 it->join();
170 }
171
172 gpr_log(GPR_DEBUG, "Done testing max streams");
173 return true;
174 }
175
176 } // namespace testing
177 } // namespace grpc
178
179 DEFINE_int32(server_port, 0, "Server port.");
180 DEFINE_string(server_host, "localhost", "Server host to connect to");
181 DEFINE_string(test_case, "rst_after_header",
182 "Configure different test cases. Valid options are:\n\n"
183 "goaway\n"
184 "max_streams\n"
185 "ping\n"
186 "rst_after_data\n"
187 "rst_after_header\n"
188 "rst_during_data\n");
189
main(int argc,char ** argv)190 int main(int argc, char** argv) {
191 grpc::testing::InitTest(&argc, &argv, true);
192 GPR_ASSERT(FLAGS_server_port);
193 const int host_port_buf_size = 1024;
194 char host_port[host_port_buf_size];
195 snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
196 FLAGS_server_port);
197 std::shared_ptr<grpc::Channel> channel =
198 grpc::CreateTestChannel(host_port, grpc::testing::INSECURE);
199 GPR_ASSERT(channel->WaitForConnected(gpr_time_add(
200 gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(300, GPR_TIMESPAN))));
201 grpc::testing::Http2Client client(channel);
202 gpr_log(GPR_INFO, "Testing case: %s", FLAGS_test_case.c_str());
203 int ret = 0;
204 if (FLAGS_test_case == "rst_after_header") {
205 client.DoRstAfterHeader();
206 } else if (FLAGS_test_case == "rst_after_data") {
207 client.DoRstAfterData();
208 } else if (FLAGS_test_case == "rst_during_data") {
209 client.DoRstDuringData();
210 } else if (FLAGS_test_case == "goaway") {
211 client.DoGoaway();
212 } else if (FLAGS_test_case == "ping") {
213 client.DoPing();
214 } else if (FLAGS_test_case == "max_streams") {
215 client.DoMaxStreams();
216 } else {
217 const char* testcases[] = {
218 "goaway", "max_streams", "ping",
219 "rst_after_data", "rst_after_header", "rst_during_data"};
220 char* joined_testcases =
221 gpr_strjoin_sep(testcases, GPR_ARRAY_SIZE(testcases), "\n", nullptr);
222
223 gpr_log(GPR_ERROR, "Unsupported test case %s. Valid options are\n%s",
224 FLAGS_test_case.c_str(), joined_testcases);
225 gpr_free(joined_testcases);
226 ret = 1;
227 }
228
229 return ret;
230 }
231