load_reporter_test.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2018 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 
20 
22 
23 #include <set>
24 #include <vector>
25 
26 #include <gmock/gmock.h>
27 #include <gtest/gtest.h>
28 
29 #include "absl/memory/memory.h"
30 #include "opencensus/stats/testing/test_utils.h"
31 
32 #include <grpc/grpc.h>
33 
37 #include "test/core/util/port.h"
39 
40 namespace grpc {
41 namespace testing {
42 namespace {
43 
44 using ::grpc::lb::v1::LoadBalancingFeedback;
45 using ::grpc::load_reporter::CensusViewProvider;
46 using ::grpc::load_reporter::CpuStatsProvider;
47 using ::grpc::load_reporter::LoadReporter;
48 using ::opencensus::stats::ViewDescriptor;
51 
54 constexpr uint64_t kNumFeedbackSamplesInWindow =
56 
57 class MockCensusViewProvider : public CensusViewProvider {
58  public:
59  MOCK_METHOD0(FetchViewData, CensusViewProvider::ViewDataMap());
60 
61  const ::opencensus::stats::ViewDescriptor& FindViewDescriptor(
62  const std::string& view_name) {
63  auto it = view_descriptor_map().find(view_name);
64  GPR_ASSERT(it != view_descriptor_map().end());
65  return it->second;
66  }
67 };
68 
69 class MockCpuStatsProvider : public CpuStatsProvider {
70  public:
71  MOCK_METHOD0(GetCpuStats, CpuStatsProvider::CpuStatsSample());
72 };
73 
74 class LoadReporterTest : public ::testing::Test {
75  public:
76  LoadReporterTest() {}
77 
78  MockCensusViewProvider* mock_census_view_provider() {
79  return static_cast<MockCensusViewProvider*>(
80  load_reporter_->census_view_provider());
81  }
82 
83  void PrepareCpuExpectation(size_t call_num) {
84  auto mock_cpu_stats_provider = static_cast<MockCpuStatsProvider*>(
85  load_reporter_->cpu_stats_provider());
87  for (size_t i = 0; i < call_num; ++i) {
88  EXPECT_CALL(*mock_cpu_stats_provider, GetCpuStats())
89  .WillOnce(Return(kCpuStatsSamples[i]))
90  .RetiresOnSaturation();
91  }
92  }
93 
94  CpuStatsProvider::CpuStatsSample initial_cpu_stats_{2, 20};
95  const std::vector<CpuStatsProvider::CpuStatsSample> kCpuStatsSamples = {
96  {13, 53}, {64, 96}, {245, 345}, {314, 785},
97  {874, 1230}, {1236, 2145}, {1864, 2974}};
98 
99  std::unique_ptr<LoadReporter> load_reporter_;
100 
101  const std::string kHostname1 = "kHostname1";
102  const std::string kHostname2 = "kHostname2";
103  const std::string kHostname3 = "kHostname3";
104  // Pad to the length of a valid LB ID.
105  const std::string kLbId1 = "kLbId111";
106  const std::string kLbId2 = "kLbId222";
107  const std::string kLbId3 = "kLbId333";
108  const std::string kLbId4 = "kLbId444";
109  const std::string kLoadKey1 = "kLoadKey1";
110  const std::string kLoadKey2 = "kLoadKey2";
111  const std::string kLoadKey3 = "kLoadKey3";
112  const std::string kLbTag1 = "kLbTag1";
113  const std::string kLbTag2 = "kLbTag2";
114  const std::string kLbToken1 = "kLbId111kLbTag1";
115  const std::string kLbToken2 = "kLbId222kLbTag2";
116  const std::string kUser1 = "kUser1";
117  const std::string kUser2 = "kUser2";
118  const std::string kUser3 = "kUser3";
119  const std::string kClientIp0 = "00";
120  const std::string kClientIp1 = "0800000001";
121  const std::string kClientIp2 = "3200000000000000000000000000000002";
122  const std::string kMetric1 = "kMetric1";
123  const std::string kMetric2 = "kMetric2";
124 
125  private:
126  void SetUp() override {
127  // Access the measures to make them valid.
134  // Set up the load reporter.
135  auto mock_cpu = new MockCpuStatsProvider();
136  auto mock_census = new MockCensusViewProvider();
137  // Prepare the initial CPU stats data. Note that the expectation should be
138  // set up before the load reporter is initialized, because CPU stats is
139  // sampled at that point.
140  EXPECT_CALL(*mock_cpu, GetCpuStats())
141  .WillOnce(Return(initial_cpu_stats_))
142  .RetiresOnSaturation();
143  load_reporter_ = absl::make_unique<LoadReporter>(
145  std::unique_ptr<CensusViewProvider>(mock_census),
146  std::unique_ptr<CpuStatsProvider>(mock_cpu));
147  }
148 };
149 
150 class LbFeedbackTest : public LoadReporterTest {
151  public:
152  // Note that [start, start + count) of the fake samples (maybe plus the
153  // initial record) are in the window now.
154  void VerifyLbFeedback(const LoadBalancingFeedback& lb_feedback, size_t start,
155  size_t count) {
156  const CpuStatsProvider::CpuStatsSample* base =
158  double expected_cpu_util =
159  static_cast<double>(kCpuStatsSamples[start + count - 1].first -
160  base->first) /
161  static_cast<double>(kCpuStatsSamples[start + count - 1].second -
162  base->second);
163  ASSERT_THAT(static_cast<double>(lb_feedback.server_utilization()),
164  DoubleNear(expected_cpu_util, 0.00001));
165  double qps_sum = 0, eps_sum = 0;
166  for (size_t i = 0; i < count; ++i) {
167  qps_sum += kQpsEpsSamples[start + i].first;
168  eps_sum += kQpsEpsSamples[start + i].second;
169  }
170  double expected_qps = qps_sum / count;
171  double expected_eps = eps_sum / count;
172  // TODO(juanlishen): The error is big because we use sleep(). It should be
173  // much smaller when we use fake clock.
174  ASSERT_THAT(static_cast<double>(lb_feedback.calls_per_second()),
175  DoubleNear(expected_qps, expected_qps * 0.3));
176  ASSERT_THAT(static_cast<double>(lb_feedback.errors_per_second()),
177  DoubleNear(expected_eps, expected_eps * 0.3));
179  "Verified LB feedback matches the samples of index [%zu, %zu).",
180  start, start + count);
181  }
182 
183  const std::vector<std::pair<double, double>> kQpsEpsSamples = {
184  {546.1, 153.1}, {62.1, 54.1}, {578.1, 154.2}, {978.1, 645.1},
185  {1132.1, 846.4}, {531.5, 315.4}, {874.1, 324.9}};
186 };
187 
188 TEST_F(LbFeedbackTest, ZeroDuration) {
189  PrepareCpuExpectation(kCpuStatsSamples.size());
190  EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
191  .WillRepeatedly(
193  // Verify that divide-by-zero exception doesn't happen.
194  for (size_t i = 0; i < kCpuStatsSamples.size(); ++i) {
195  load_reporter_->FetchAndSample();
196  }
197  load_reporter_->GenerateLoadBalancingFeedback();
198 }
199 
200 TEST_F(LbFeedbackTest, Normal) {
201  // Prepare view data list using the <QPS, EPS> samples.
202  std::vector<CensusViewProvider::ViewDataMap> view_data_map_list;
203  for (const auto& p : LbFeedbackTest::kQpsEpsSamples) {
204  double qps = p.first;
205  double eps = p.second;
206  double ok_count = (qps - eps) * kFetchAndSampleIntervalSeconds;
207  double error_count = eps * kFetchAndSampleIntervalSeconds;
208  double ok_count_1 = ok_count / 3.0;
209  double ok_count_2 = ok_count - ok_count_1;
210  auto end_count_vd = ::opencensus::stats::testing::TestUtils::MakeViewData(
211  mock_census_view_provider()->FindViewDescriptor(
215  ok_count_1},
218  ok_count_2},
221  error_count}});
222  // Values for other view data don't matter.
223  auto end_bytes_sent_vd =
224  ::opencensus::stats::testing::TestUtils::MakeViewData(
225  mock_census_view_provider()->FindViewDescriptor(
229  0},
232  0},
235  0}});
236  auto end_bytes_received_vd =
237  ::opencensus::stats::testing::TestUtils::MakeViewData(
238  mock_census_view_provider()->FindViewDescriptor(
242  0},
245  0},
248  0}});
249  auto end_latency_vd = ::opencensus::stats::testing::TestUtils::MakeViewData(
250  mock_census_view_provider()->FindViewDescriptor(
254  0},
257  0},
260  0}});
261  view_data_map_list.push_back(
262  {{::grpc::load_reporter::kViewEndCount, end_count_vd},
263  {::grpc::load_reporter::kViewEndBytesSent, end_bytes_sent_vd},
264  {::grpc::load_reporter::kViewEndBytesReceived, end_bytes_received_vd},
265  {::grpc::load_reporter::kViewEndLatencyMs, end_latency_vd}});
266  }
267  {
269  for (size_t i = 0; i < view_data_map_list.size(); ++i) {
270  EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
271  .WillOnce(Return(view_data_map_list[i]))
272  .RetiresOnSaturation();
273  }
274  }
275  PrepareCpuExpectation(kNumFeedbackSamplesInWindow + 2);
276  // When the load reporter is created, a trivial LB feedback record is added.
277  // But that's not enough for generating an LB feedback.
278  // Fetch some view data so that non-trivial LB feedback can be generated.
279  for (size_t i = 0; i < kNumFeedbackSamplesInWindow / 2; ++i) {
280  // TODO(juanlishen): Find some fake clock to speed up testing.
281  sleep(1);
282  load_reporter_->FetchAndSample();
283  }
284  VerifyLbFeedback(load_reporter_->GenerateLoadBalancingFeedback(), 0,
285  kNumFeedbackSamplesInWindow / 2);
286  // Fetch more view data so that the feedback record window is just full (the
287  // initial record just falls out of the window).
288  for (size_t i = 0; i < (kNumFeedbackSamplesInWindow + 1) / 2; ++i) {
289  sleep(1);
290  load_reporter_->FetchAndSample();
291  }
292  VerifyLbFeedback(load_reporter_->GenerateLoadBalancingFeedback(), 0,
293  kNumFeedbackSamplesInWindow);
294  // Further fetching will cause the old records to fall out of the window.
295  for (size_t i = 0; i < 2; ++i) {
296  sleep(1);
297  load_reporter_->FetchAndSample();
298  }
299  VerifyLbFeedback(load_reporter_->GenerateLoadBalancingFeedback(), 2,
300  kNumFeedbackSamplesInWindow);
301 }
302 
303 using LoadReportTest = LoadReporterTest;
304 
305 TEST_F(LoadReportTest, BasicReport) {
306  // Make up the first view data map.
307  CensusViewProvider::ViewDataMap vdm1;
308  vdm1.emplace(
310  ::opencensus::stats::testing::TestUtils::MakeViewData(
311  mock_census_view_provider()->FindViewDescriptor(
313  {{{kClientIp1 + kLbToken1, kHostname1, kUser1}, 1234},
314  {{kClientIp2 + kLbToken1, kHostname1, kUser1}, 1225},
316  {{kClientIp2 + kLbToken1, kHostname1, kUser2}, 464},
317  {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3}, 101},
319  {{kClientIp2 + kLbId3 + kLbTag2, kHostname2, kUser3}, 23}}));
321  ::opencensus::stats::testing::TestUtils::MakeViewData(
322  mock_census_view_provider()->FindViewDescriptor(
326  641},
329  272},
332  996},
335  34},
338  18}}));
340  ::opencensus::stats::testing::TestUtils::MakeViewData(
341  mock_census_view_provider()->FindViewDescriptor(
345  8977},
348  266},
351  1276},
354  77823},
357  48}}));
359  ::opencensus::stats::testing::TestUtils::MakeViewData(
360  mock_census_view_provider()->FindViewDescriptor(
364  2341},
367  466},
370  518},
373  81},
376  27}}));
378  ::opencensus::stats::testing::TestUtils::MakeViewData(
379  mock_census_view_provider()->FindViewDescriptor(
383  3.14},
386  5.26},
389  45.4},
392  4.4},
395  2348.0}}));
396  vdm1.emplace(
398  ::opencensus::stats::testing::TestUtils::MakeViewData(
399  mock_census_view_provider()->FindViewDescriptor(
404  1}}));
405  vdm1.emplace(
407  ::opencensus::stats::testing::TestUtils::MakeViewData(
408  mock_census_view_provider()->FindViewDescriptor(
413  3.2}}));
414  // Make up the second view data map.
415  CensusViewProvider::ViewDataMap vdm2;
416  vdm2.emplace(
418  ::opencensus::stats::testing::TestUtils::MakeViewData(
419  mock_census_view_provider()->FindViewDescriptor(
422  {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3}, 778}}));
424  ::opencensus::stats::testing::TestUtils::MakeViewData(
425  mock_census_view_provider()->FindViewDescriptor(
429  24},
432  546}}));
434  ::opencensus::stats::testing::TestUtils::MakeViewData(
435  mock_census_view_provider()->FindViewDescriptor(
439  747},
442  229}}));
444  ::opencensus::stats::testing::TestUtils::MakeViewData(
445  mock_census_view_provider()->FindViewDescriptor(
449  173},
452  438}}));
454  ::opencensus::stats::testing::TestUtils::MakeViewData(
455  mock_census_view_provider()->FindViewDescriptor(
459  187},
462  34}}));
463  vdm2.emplace(
465  ::opencensus::stats::testing::TestUtils::MakeViewData(
466  mock_census_view_provider()->FindViewDescriptor(
470  1}}));
471  vdm2.emplace(
473  ::opencensus::stats::testing::TestUtils::MakeViewData(
474  mock_census_view_provider()->FindViewDescriptor(
478  5.7}}));
479  // Set up mock expectation.
480  EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
481  .WillOnce(Return(vdm1))
482  .WillOnce(Return(vdm2));
483  PrepareCpuExpectation(2);
484  // Start testing.
485  load_reporter_->ReportStreamCreated(kHostname1, kLbId1, kLoadKey1);
486  load_reporter_->ReportStreamCreated(kHostname2, kLbId2, kLoadKey2);
487  load_reporter_->ReportStreamCreated(kHostname2, kLbId3, kLoadKey3);
488  // First fetch.
489  load_reporter_->FetchAndSample();
490  load_reporter_->GenerateLoads(kHostname1, kLbId1);
491  gpr_log(GPR_INFO, "First load generated.");
492  // Second fetch.
493  load_reporter_->FetchAndSample();
494  load_reporter_->GenerateLoads(kHostname2, kLbId2);
495  gpr_log(GPR_INFO, "Second load generated.");
496  // TODO(juanlishen): Verify the data.
497 }
498 
499 } // namespace
500 } // namespace testing
501 } // namespace grpc
502 
503 int main(int argc, char** argv) {
504  grpc::testing::TestEnvironment env(&argc, argv);
505  ::testing::InitGoogleTest(&argc, argv);
506  return RUN_ALL_TESTS();
507 }
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
testing
Definition: aws_request_signer_test.cc:25
grpc::load_reporter::kViewEndCount
constexpr char kViewEndCount[]
Definition: src/cpp/server/load_reporter/constants.h:72
kHostname1
const std::string kHostname1
Definition: load_reporter_test.cc:101
regen-readme.it
it
Definition: regen-readme.py:15
port.h
generate.env
env
Definition: generate.py:37
absl::ZeroDuration
constexpr Duration ZeroDuration()
Definition: third_party/abseil-cpp/absl/time/time.h:308
grpc
Definition: grpcpp/alarm.h:33
kUser1
const std::string kUser1
Definition: load_reporter_test.cc:116
testing::DoubleNear
internal::FloatingEqMatcher< double > DoubleNear(double rhs, double max_abs_error)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8647
testing::Return
internal::ReturnAction< R > Return(R value)
Definition: bloaty/third_party/googletest/googlemock/include/gmock/gmock-actions.h:1004
grpc::load_reporter::MeasureEndLatencyMs
inline ::opencensus::stats::MeasureInt64 MeasureEndLatencyMs()
Definition: registered_opencensus_objects.h:67
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
kHostname3
const std::string kHostname3
Definition: load_reporter_test.cc:103
absl::FormatConversionChar::s
@ s
xds_manager.p
p
Definition: xds_manager.py:60
second
StrT second
Definition: cxa_demangle.cpp:4885
kLbToken2
const std::string kLbToken2
Definition: load_reporter_test.cc:115
kClientIp2
const std::string kClientIp2
Definition: load_reporter_test.cc:121
grpc::load_reporter::kFeedbackSampleWindowSeconds
constexpr uint32_t kFeedbackSampleWindowSeconds
Definition: src/cpp/server/load_reporter/constants.h:37
MOCK_METHOD0
#define MOCK_METHOD0(m,...)
Definition: bloaty/third_party/googletest/googlemock/include/gmock/gmock-generated-function-mockers.h:599
grpc::load_reporter::CensusViewProvider::ViewDataMap
std::unordered_map< std::string, ::opencensus::stats::ViewData > ViewDataMap
Definition: load_reporter.h:56
kMetric1
const std::string kMetric1
Definition: load_reporter_test.cc:122
kLbId2
const std::string kLbId2
Definition: load_reporter_test.cc:106
testing::Test
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:402
main
int main(int argc, char **argv)
Definition: load_reporter_test.cc:503
kHostname2
const std::string kHostname2
Definition: load_reporter_test.cc:102
kLbTag1
const std::string kLbTag1
Definition: load_reporter_test.cc:112
load_reporter.h
kLbId1
const std::string kLbId1
Definition: load_reporter_test.cc:105
start
static uint64_t start
Definition: benchmark-pound.c:74
kLoadKey3
const std::string kLoadKey3
Definition: load_reporter_test.cc:111
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
grpc::load_reporter::kViewOtherCallMetricValue
constexpr char kViewOtherCallMetricValue[]
Definition: src/cpp/server/load_reporter/constants.h:78
grpc::load_reporter::kViewEndBytesReceived
constexpr char kViewEndBytesReceived[]
Definition: src/cpp/server/load_reporter/constants.h:74
ASSERT_THAT
#define ASSERT_THAT(value, matcher)
grpc::load_reporter::kFetchAndSampleIntervalSeconds
constexpr uint32_t kFetchAndSampleIntervalSeconds
Definition: src/cpp/server/load_reporter/constants.h:38
grpc::load_reporter::kViewStartCount
constexpr char kViewStartCount[]
Definition: src/cpp/server/load_reporter/constants.h:71
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
testing::InSequence
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:9838
grpc.h
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
kQpsEpsSamples
const std::vector< std::pair< double, double > > kQpsEpsSamples
Definition: load_reporter_test.cc:183
kLoadKey2
const std::string kLoadKey2
Definition: load_reporter_test.cc:110
gen_synthetic_protos.base
base
Definition: gen_synthetic_protos.py:31
kLbTag2
const std::string kLbTag2
Definition: load_reporter_test.cc:113
RUN_ALL_TESTS
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2471
grpc::load_reporter::MeasureEndBytesReceived
inline ::opencensus::stats::MeasureInt64 MeasureEndBytesReceived()
Definition: registered_opencensus_objects.h:59
EXPECT_CALL
#define EXPECT_CALL(obj, call)
grpc::load_reporter::kViewOtherCallMetricCount
constexpr char kViewOtherCallMetricCount[]
Definition: src/cpp/server/load_reporter/constants.h:76
grpc::load_reporter::kCallStatusOk
constexpr char kCallStatusOk[]
Definition: src/cpp/server/load_reporter/constants.h:48
test_config.h
constants.h
testing::InitGoogleTest
GTEST_API_ void InitGoogleTest(int *argc, char **argv)
Definition: bloaty/third_party/googletest/googletest/src/gtest.cc:6106
kMetric2
const std::string kMetric2
Definition: load_reporter_test.cc:123
grpc::testing::TEST_F
TEST_F(ChannelArgumentsTest, SetInt)
Definition: channel_arguments_test.cc:134
grpc::load_reporter::MeasureStartCount
inline ::opencensus::stats::MeasureInt64 MeasureStartCount()
Definition: registered_opencensus_objects.h:38
grpc::load_reporter::kCallStatusClientError
constexpr char kCallStatusClientError[]
Definition: src/cpp/server/load_reporter/constants.h:50
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
registered_opencensus_objects.h
grpc::load_reporter::MeasureEndBytesSent
inline ::opencensus::stats::MeasureInt64 MeasureEndBytesSent()
Definition: registered_opencensus_objects.h:52
kUser3
const std::string kUser3
Definition: load_reporter_test.cc:118
port_platform.h
grpc::load_reporter::kViewEndLatencyMs
constexpr char kViewEndLatencyMs[]
Definition: src/cpp/server/load_reporter/constants.h:75
kUser2
const std::string kUser2
Definition: load_reporter_test.cc:117
grpc::load_reporter::MeasureEndCount
inline ::opencensus::stats::MeasureInt64 MeasureEndCount()
Definition: registered_opencensus_objects.h:45
grpc::testing::TestEnvironment
Definition: test/core/util/test_config.h:54
exec_ctx.h
kLbToken1
const std::string kLbToken1
Definition: load_reporter_test.cc:114
initial_cpu_stats_
CpuStatsProvider::CpuStatsSample initial_cpu_stats_
Definition: load_reporter_test.cc:94
kLbId3
const std::string kLbId3
Definition: load_reporter_test.cc:107
kCpuStatsSamples
const std::vector< CpuStatsProvider::CpuStatsSample > kCpuStatsSamples
Definition: load_reporter_test.cc:95
grpc::load_reporter::MeasureOtherCallMetric
inline ::opencensus::stats::MeasureDouble MeasureOtherCallMetric()
Definition: registered_opencensus_objects.h:74
kLbId4
const std::string kLbId4
Definition: load_reporter_test.cc:108
grpc::load_reporter::kViewEndBytesSent
constexpr char kViewEndBytesSent[]
Definition: src/cpp/server/load_reporter/constants.h:73
kLoadKey1
const std::string kLoadKey1
Definition: load_reporter_test.cc:109
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
load_reporter_
std::unique_ptr< LoadReporter > load_reporter_
Definition: load_reporter_test.cc:99
kClientIp1
const std::string kClientIp1
Definition: load_reporter_test.cc:120
kClientIp0
const std::string kClientIp0
Definition: load_reporter_test.cc:119


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:16