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