a2f790374786c06e998d75800eeea8caaf6b5880
[platform/upstream/grpc.git] / test / cpp / interop / client.cc
1 /*
2  *
3  * Copyright 2015 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 <grpc/grpc.h>
20 #include <grpc/support/alloc.h>
21 #include <grpc/support/log.h>
22 #include <grpcpp/channel.h>
23 #include <grpcpp/client_context.h>
24
25 #include <memory>
26 #include <unordered_map>
27
28 #include "absl/flags/flag.h"
29 #include "src/core/lib/gpr/string.h"
30 #include "test/core/util/test_config.h"
31 #include "test/cpp/interop/client_helper.h"
32 #include "test/cpp/interop/interop_client.h"
33 #include "test/cpp/util/test_config.h"
34
35 ABSL_FLAG(bool, use_alts, false,
36           "Whether to use alts. Enable alts will disable tls.");
37 ABSL_FLAG(bool, use_tls, false, "Whether to use tls.");
38 ABSL_FLAG(std::string, custom_credentials_type, "",
39           "User provided credentials type.");
40 ABSL_FLAG(bool, use_test_ca, false, "False to use SSL roots for google");
41 ABSL_FLAG(int32_t, server_port, 0, "Server port.");
42 ABSL_FLAG(std::string, server_host, "localhost", "Server host to connect to");
43 ABSL_FLAG(std::string, server_host_override, "",
44           "Override the server host which is sent in HTTP header");
45 ABSL_FLAG(
46     std::string, test_case, "large_unary",
47     "Configure different test cases. Valid options are:\n\n"
48     "all : all test cases;\n"
49
50     // TODO(veblush): Replace the help message with the following full message
51     // once Abseil fixes the flag-help compiler error on Windows. (b/171659833)
52     /*
53     "cancel_after_begin : cancel stream after starting it;\n"
54     "cancel_after_first_response: cancel on first response;\n"
55     "channel_soak: sends 'soak_iterations' rpcs, rebuilds channel each time;\n"
56     "client_compressed_streaming : compressed request streaming with "
57     "client_compressed_unary : single compressed request;\n"
58     "client_streaming : request streaming with single response;\n"
59     "compute_engine_creds: large_unary with compute engine auth;\n"
60     "custom_metadata: server will echo custom metadata;\n"
61     "empty_stream : bi-di stream with no request/response;\n"
62     "empty_unary : empty (zero bytes) request and response;\n"
63     "google_default_credentials: large unary using GDC;\n"
64     "half_duplex : half-duplex streaming;\n"
65     "jwt_token_creds: large_unary with JWT token auth;\n"
66     "large_unary : single request and (large) response;\n"
67     "long_lived_channel: sends large_unary rpcs over a long-lived channel;\n"
68     "oauth2_auth_token: raw oauth2 access token auth;\n"
69     "per_rpc_creds: raw oauth2 access token on a single rpc;\n"
70     "ping_pong : full-duplex streaming;\n"
71     "response streaming;\n"
72     "rpc_soak: 'sends soak_iterations' large_unary rpcs;\n"
73     "server_compressed_streaming : single request with compressed "
74     "server_compressed_unary : single compressed response;\n"
75     "server_streaming : single request with response streaming;\n"
76     "slow_consumer : single request with response streaming with "
77     "slow client consumer;\n"
78     "special_status_message: verify Unicode and whitespace in status message;\n"
79     "status_code_and_message: verify status code & message;\n"
80     "timeout_on_sleeping_server: deadline exceeds on stream;\n"
81     "unimplemented_method: client calls an unimplemented method;\n"
82     "unimplemented_service: client calls an unimplemented service;\n"
83     */
84 );
85 ABSL_FLAG(std::string, default_service_account, "",
86           "Email of GCE default service account");
87 ABSL_FLAG(std::string, service_account_key_file, "",
88           "Path to service account json key file.");
89 ABSL_FLAG(std::string, oauth_scope, "", "Scope for OAuth tokens.");
90 ABSL_FLAG(bool, do_not_abort_on_transient_failures, false,
91           "If set to 'true', abort() is not called in case of transient "
92           "failures (i.e failures that are temporary and will likely go away "
93           "on retrying; like a temporary connection failure) and an error "
94           "message is printed instead. Note that this flag just controls "
95           "whether abort() is called or not. It does not control whether the "
96           "test is retried in case of transient failures (and currently the "
97           "interop tests are not retried even if this flag is set to true)");
98 ABSL_FLAG(int32_t, soak_iterations, 1000,
99           "The number of iterations to use for the two soak tests; rpc_soak "
100           "and channel_soak.");
101 ABSL_FLAG(int32_t, soak_max_failures, 0,
102           "The number of iterations in soak tests that are allowed to fail "
103           "(either due to non-OK status code or exceeding the "
104           "per-iteration max acceptable latency).");
105 ABSL_FLAG(int32_t, soak_per_iteration_max_acceptable_latency_ms, 0,
106           "The number of milliseconds a single iteration in the two soak "
107           "tests (rpc_soak and channel_soak) should take.");
108 ABSL_FLAG(int32_t, soak_overall_timeout_seconds, 0,
109           "The overall number of seconds after which a soak test should "
110           "stop and fail, if the desired number of iterations have not yet "
111           "completed.");
112 ABSL_FLAG(int32_t, iteration_interval, 10,
113           "The interval in seconds between rpcs. This is used by "
114           "long_connection test");
115 ABSL_FLAG(std::string, additional_metadata, "",
116           "Additional metadata to send in each request, as a "
117           "semicolon-separated list of key:value pairs.");
118
119 using grpc::testing::CreateChannelForTestCase;
120 using grpc::testing::GetServiceAccountJsonKey;
121 using grpc::testing::UpdateActions;
122
123 namespace {
124
125 // Parse the contents of FLAGS_additional_metadata into a map. Allow
126 // alphanumeric characters and dashes in keys, and any character but semicolons
127 // in values. Convert keys to lowercase. On failure, log an error and return
128 // false.
129 bool ParseAdditionalMetadataFlag(
130     const std::string& flag,
131     std::multimap<std::string, std::string>* additional_metadata) {
132   size_t start_pos = 0;
133   while (start_pos < flag.length()) {
134     size_t colon_pos = flag.find(':', start_pos);
135     if (colon_pos == std::string::npos) {
136       gpr_log(GPR_ERROR,
137               "Couldn't parse metadata flag: extra characters at end of flag");
138       return false;
139     }
140     size_t semicolon_pos = flag.find(';', colon_pos);
141
142     std::string key = flag.substr(start_pos, colon_pos - start_pos);
143     std::string value =
144         flag.substr(colon_pos + 1, semicolon_pos - colon_pos - 1);
145
146     constexpr char alphanum_and_hyphen[] =
147         "-0123456789"
148         "abcdefghijklmnopqrstuvwxyz"
149         "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
150     if (key.find_first_not_of(alphanum_and_hyphen) != std::string::npos) {
151       gpr_log(GPR_ERROR,
152               "Couldn't parse metadata flag: key contains characters other "
153               "than alphanumeric and hyphens: %s",
154               key.c_str());
155       return false;
156     }
157
158     // Convert to lowercase.
159     for (char& c : key) {
160       if (c >= 'A' && c <= 'Z') {
161         c += ('a' - 'A');
162       }
163     }
164
165     gpr_log(GPR_INFO, "Adding additional metadata with key %s and value %s",
166             key.c_str(), value.c_str());
167     additional_metadata->insert({key, value});
168
169     if (semicolon_pos == std::string::npos) {
170       break;
171     } else {
172       start_pos = semicolon_pos + 1;
173     }
174   }
175
176   return true;
177 }
178
179 }  // namespace
180
181 int main(int argc, char** argv) {
182   grpc::testing::TestEnvironment env(argc, argv);
183   grpc::testing::InitTest(&argc, &argv, true);
184   gpr_log(GPR_INFO, "Testing these cases: %s",
185           absl::GetFlag(FLAGS_test_case).c_str());
186   int ret = 0;
187
188   grpc::testing::ChannelCreationFunc channel_creation_func;
189   std::string test_case = absl::GetFlag(FLAGS_test_case);
190   if (absl::GetFlag(FLAGS_additional_metadata).empty()) {
191     channel_creation_func = [test_case]() {
192       return CreateChannelForTestCase(test_case);
193     };
194   } else {
195     std::multimap<std::string, std::string> additional_metadata;
196     if (!ParseAdditionalMetadataFlag(absl::GetFlag(FLAGS_additional_metadata),
197                                      &additional_metadata)) {
198       return 1;
199     }
200
201     channel_creation_func = [test_case, additional_metadata]() {
202       std::vector<std::unique_ptr<
203           grpc::experimental::ClientInterceptorFactoryInterface>>
204           factories;
205       factories.emplace_back(
206           new grpc::testing::AdditionalMetadataInterceptorFactory(
207               additional_metadata));
208       return CreateChannelForTestCase(test_case, std::move(factories));
209     };
210   }
211
212   grpc::testing::InteropClient client(
213       channel_creation_func, true,
214       absl::GetFlag(FLAGS_do_not_abort_on_transient_failures));
215
216   std::unordered_map<std::string, std::function<bool()>> actions;
217   actions["empty_unary"] =
218       std::bind(&grpc::testing::InteropClient::DoEmpty, &client);
219   actions["large_unary"] =
220       std::bind(&grpc::testing::InteropClient::DoLargeUnary, &client);
221   actions["server_compressed_unary"] = std::bind(
222       &grpc::testing::InteropClient::DoServerCompressedUnary, &client);
223   actions["client_compressed_unary"] = std::bind(
224       &grpc::testing::InteropClient::DoClientCompressedUnary, &client);
225   actions["client_streaming"] =
226       std::bind(&grpc::testing::InteropClient::DoRequestStreaming, &client);
227   actions["server_streaming"] =
228       std::bind(&grpc::testing::InteropClient::DoResponseStreaming, &client);
229   actions["server_compressed_streaming"] = std::bind(
230       &grpc::testing::InteropClient::DoServerCompressedStreaming, &client);
231   actions["client_compressed_streaming"] = std::bind(
232       &grpc::testing::InteropClient::DoClientCompressedStreaming, &client);
233   actions["slow_consumer"] = std::bind(
234       &grpc::testing::InteropClient::DoResponseStreamingWithSlowConsumer,
235       &client);
236   actions["half_duplex"] =
237       std::bind(&grpc::testing::InteropClient::DoHalfDuplex, &client);
238   actions["ping_pong"] =
239       std::bind(&grpc::testing::InteropClient::DoPingPong, &client);
240   actions["cancel_after_begin"] =
241       std::bind(&grpc::testing::InteropClient::DoCancelAfterBegin, &client);
242   actions["cancel_after_first_response"] = std::bind(
243       &grpc::testing::InteropClient::DoCancelAfterFirstResponse, &client);
244   actions["timeout_on_sleeping_server"] = std::bind(
245       &grpc::testing::InteropClient::DoTimeoutOnSleepingServer, &client);
246   actions["empty_stream"] =
247       std::bind(&grpc::testing::InteropClient::DoEmptyStream, &client);
248   actions["pick_first_unary"] =
249       std::bind(&grpc::testing::InteropClient::DoPickFirstUnary, &client);
250   if (absl::GetFlag(FLAGS_use_tls)) {
251     actions["compute_engine_creds"] =
252         std::bind(&grpc::testing::InteropClient::DoComputeEngineCreds, &client,
253                   absl::GetFlag(FLAGS_default_service_account),
254                   absl::GetFlag(FLAGS_oauth_scope));
255     actions["jwt_token_creds"] =
256         std::bind(&grpc::testing::InteropClient::DoJwtTokenCreds, &client,
257                   GetServiceAccountJsonKey());
258     actions["oauth2_auth_token"] =
259         std::bind(&grpc::testing::InteropClient::DoOauth2AuthToken, &client,
260                   absl::GetFlag(FLAGS_default_service_account),
261                   absl::GetFlag(FLAGS_oauth_scope));
262     actions["per_rpc_creds"] =
263         std::bind(&grpc::testing::InteropClient::DoPerRpcCreds, &client,
264                   GetServiceAccountJsonKey());
265   }
266   if (absl::GetFlag(FLAGS_custom_credentials_type) ==
267       "google_default_credentials") {
268     actions["google_default_credentials"] =
269         std::bind(&grpc::testing::InteropClient::DoGoogleDefaultCredentials,
270                   &client, absl::GetFlag(FLAGS_default_service_account));
271   }
272   actions["status_code_and_message"] =
273       std::bind(&grpc::testing::InteropClient::DoStatusWithMessage, &client);
274   actions["special_status_message"] =
275       std::bind(&grpc::testing::InteropClient::DoSpecialStatusMessage, &client);
276   actions["custom_metadata"] =
277       std::bind(&grpc::testing::InteropClient::DoCustomMetadata, &client);
278   actions["unimplemented_method"] =
279       std::bind(&grpc::testing::InteropClient::DoUnimplementedMethod, &client);
280   actions["unimplemented_service"] =
281       std::bind(&grpc::testing::InteropClient::DoUnimplementedService, &client);
282   actions["cacheable_unary"] =
283       std::bind(&grpc::testing::InteropClient::DoCacheableUnary, &client);
284   actions["channel_soak"] = std::bind(
285       &grpc::testing::InteropClient::DoChannelSoakTest, &client,
286       absl::GetFlag(FLAGS_soak_iterations),
287       absl::GetFlag(FLAGS_soak_max_failures),
288       absl::GetFlag(FLAGS_soak_per_iteration_max_acceptable_latency_ms),
289       absl::GetFlag(FLAGS_soak_overall_timeout_seconds));
290   actions["rpc_soak"] = std::bind(
291       &grpc::testing::InteropClient::DoRpcSoakTest, &client,
292       absl::GetFlag(FLAGS_soak_iterations),
293       absl::GetFlag(FLAGS_soak_max_failures),
294       absl::GetFlag(FLAGS_soak_per_iteration_max_acceptable_latency_ms),
295       absl::GetFlag(FLAGS_soak_overall_timeout_seconds));
296   actions["long_lived_channel"] =
297       std::bind(&grpc::testing::InteropClient::DoLongLivedChannelTest, &client,
298                 absl::GetFlag(FLAGS_soak_iterations),
299                 absl::GetFlag(FLAGS_iteration_interval));
300
301   UpdateActions(&actions);
302
303   if (absl::GetFlag(FLAGS_test_case) == "all") {
304     for (const auto& action : actions) {
305       action.second();
306     }
307   } else if (actions.find(absl::GetFlag(FLAGS_test_case)) != actions.end()) {
308     actions.find(absl::GetFlag(FLAGS_test_case))->second();
309   } else {
310     std::string test_cases;
311     for (const auto& action : actions) {
312       if (!test_cases.empty()) test_cases += "\n";
313       test_cases += action.first;
314     }
315     gpr_log(GPR_ERROR, "Unsupported test case %s. Valid options are\n%s",
316             absl::GetFlag(FLAGS_test_case).c_str(), test_cases.c_str());
317     ret = 1;
318   }
319
320   return ret;
321 }