xref: /aosp_15_r20/external/grpc-grpc/test/cpp/interop/stress_interop_client.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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 // is % allowed in string
17 //
18 
19 #include "test/cpp/interop/stress_interop_client.h"
20 
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 #include "absl/strings/str_format.h"
26 
27 #include <grpc/support/log.h>
28 #include <grpcpp/create_channel.h>
29 
30 #include "src/core/lib/gprpp/crash.h"
31 #include "test/cpp/interop/interop_client.h"
32 #include "test/cpp/util/metrics_server.h"
33 
34 namespace grpc {
35 namespace testing {
36 
37 using std::pair;
38 using std::vector;
39 
WeightedRandomTestSelector(const vector<pair<TestCaseType,int>> & tests)40 WeightedRandomTestSelector::WeightedRandomTestSelector(
41     const vector<pair<TestCaseType, int>>& tests)
42     : tests_(tests) {
43   total_weight_ = 0;
44   for (auto it = tests.begin(); it != tests.end(); it++) {
45     total_weight_ += it->second;
46   }
47 }
48 
49 // Returns a weighted-randomly selected test case based on the test weights
50 // passed in the constructror
GetNextTest() const51 TestCaseType WeightedRandomTestSelector::GetNextTest() const {
52   int random = 0;
53   TestCaseType selected_test = UNKNOWN_TEST;
54 
55   // Get a random number from [0 to the total_weight - 1]
56   random = rand() % total_weight_;
57 
58   int weight_sofar = 0;
59   for (auto it = tests_.begin(); it != tests_.end(); it++) {
60     weight_sofar += it->second;
61     if (random < weight_sofar) {
62       selected_test = it->first;
63       break;
64     }
65   }
66 
67   // It is a bug in the logic if no test is selected at this point
68   GPR_ASSERT(selected_test != UNKNOWN_TEST);
69   return selected_test;
70 }
71 
StressTestInteropClient(int test_id,const std::string & server_address,ChannelCreationFunc channel_creation_func,const WeightedRandomTestSelector & test_selector,long test_duration_secs,long sleep_duration_ms,bool do_not_abort_on_transient_failures)72 StressTestInteropClient::StressTestInteropClient(
73     int test_id, const std::string& server_address,
74     ChannelCreationFunc channel_creation_func,
75     const WeightedRandomTestSelector& test_selector, long test_duration_secs,
76     long sleep_duration_ms, bool do_not_abort_on_transient_failures)
77     : test_id_(test_id),
78       server_address_(server_address),
79       channel_creation_func_(std::move(channel_creation_func)),
80       interop_client_(new InteropClient(channel_creation_func_, false,
81                                         do_not_abort_on_transient_failures)),
82       test_selector_(test_selector),
83       test_duration_secs_(test_duration_secs),
84       sleep_duration_ms_(sleep_duration_ms) {}
85 
MainLoop(const std::shared_ptr<QpsGauge> & qps_gauge)86 void StressTestInteropClient::MainLoop(
87     const std::shared_ptr<QpsGauge>& qps_gauge) {
88   gpr_log(GPR_INFO, "Running test %d. ServerAddr: %s", test_id_,
89           server_address_.c_str());
90 
91   gpr_timespec test_end_time;
92   if (test_duration_secs_ < 0) {
93     test_end_time = gpr_inf_future(GPR_CLOCK_REALTIME);
94   } else {
95     test_end_time =
96         gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
97                      gpr_time_from_seconds(test_duration_secs_, GPR_TIMESPAN));
98   }
99 
100   qps_gauge->Reset();
101 
102   while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), test_end_time) < 0) {
103     // Select the test case to execute based on the weights and execute it
104     TestCaseType test_case = test_selector_.GetNextTest();
105     gpr_log(GPR_DEBUG, "%d - Executing the test case %d", test_id_, test_case);
106     RunTest(test_case);
107 
108     qps_gauge->Incr();
109 
110     // Sleep between successive calls if needed
111     if (sleep_duration_ms_ > 0) {
112       gpr_timespec sleep_time =
113           gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
114                        gpr_time_from_millis(sleep_duration_ms_, GPR_TIMESPAN));
115       gpr_sleep_until(sleep_time);
116     }
117   }
118 }
119 
RunTest(TestCaseType test_case)120 bool StressTestInteropClient::RunTest(TestCaseType test_case) {
121   bool is_success = false;
122   switch (test_case) {
123     case EMPTY_UNARY: {
124       is_success = interop_client_->DoEmpty();
125       break;
126     }
127     case LARGE_UNARY: {
128       is_success = interop_client_->DoLargeUnary();
129       break;
130     }
131     case CLIENT_COMPRESSED_UNARY: {
132       is_success = interop_client_->DoClientCompressedUnary();
133       break;
134     }
135     case CLIENT_COMPRESSED_STREAMING: {
136       is_success = interop_client_->DoClientCompressedStreaming();
137       break;
138     }
139     case CLIENT_STREAMING: {
140       is_success = interop_client_->DoRequestStreaming();
141       break;
142     }
143     case SERVER_STREAMING: {
144       is_success = interop_client_->DoResponseStreaming();
145       break;
146     }
147     case SERVER_COMPRESSED_UNARY: {
148       is_success = interop_client_->DoServerCompressedUnary();
149       break;
150     }
151     case SERVER_COMPRESSED_STREAMING: {
152       is_success = interop_client_->DoServerCompressedStreaming();
153       break;
154     }
155     case SLOW_CONSUMER: {
156       is_success = interop_client_->DoResponseStreamingWithSlowConsumer();
157       break;
158     }
159     case HALF_DUPLEX: {
160       is_success = interop_client_->DoHalfDuplex();
161       break;
162     }
163     case PING_PONG: {
164       is_success = interop_client_->DoPingPong();
165       break;
166     }
167     case CANCEL_AFTER_BEGIN: {
168       is_success = interop_client_->DoCancelAfterBegin();
169       break;
170     }
171     case CANCEL_AFTER_FIRST_RESPONSE: {
172       is_success = interop_client_->DoCancelAfterFirstResponse();
173       break;
174     }
175     case TIMEOUT_ON_SLEEPING_SERVER: {
176       is_success = interop_client_->DoTimeoutOnSleepingServer();
177       break;
178     }
179     case EMPTY_STREAM: {
180       is_success = interop_client_->DoEmptyStream();
181       break;
182     }
183     case STATUS_CODE_AND_MESSAGE: {
184       is_success = interop_client_->DoStatusWithMessage();
185       break;
186     }
187     case CUSTOM_METADATA: {
188       is_success = interop_client_->DoCustomMetadata();
189       break;
190     }
191     default: {
192       grpc_core::Crash(absl::StrFormat("Invalid test case (%d)", test_case));
193       break;
194     }
195   }
196 
197   return is_success;
198 }
199 
200 }  // namespace testing
201 }  // namespace grpc
202