Home | History | Annotate | Download | only in interop
      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 
     45 Http2Client::ServiceStub::ServiceStub(const std::shared_ptr<Channel>& channel)
     46     : channel_(std::move(channel)) {
     47   stub_ = TestService::NewStub(channel);
     48 }
     49 
     50 TestService::Stub* Http2Client::ServiceStub::Get() { return stub_.get(); }
     51 
     52 Http2Client::Http2Client(const std::shared_ptr<Channel>& channel)
     53     : serviceStub_(channel),
     54       channel_(std::move(channel)),
     55       defaultRequest_(BuildDefaultRequest()) {}
     56 
     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 
     67 Status Http2Client::SendUnaryCall(SimpleResponse* response) {
     68   ClientContext context;
     69   return serviceStub_.Get()->UnaryCall(&context, defaultRequest_, response);
     70 }
     71 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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