xref: /aosp_15_r20/external/grpc-grpc/test/cpp/server/load_reporter/load_reporter_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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 
19 #include "src/cpp/server/load_reporter/load_reporter.h"
20 
21 #include <set>
22 #include <vector>
23 
24 #include <gmock/gmock.h>
25 #include <gtest/gtest.h>
26 
27 #include "absl/memory/memory.h"
28 #include "opencensus/stats/testing/test_utils.h"
29 
30 #include <grpc/grpc.h>
31 #include <grpc/support/port_platform.h>
32 
33 #include "src/core/ext/filters/load_reporting/registered_opencensus_objects.h"
34 #include "src/core/lib/iomgr/exec_ctx.h"
35 #include "src/cpp/server/load_reporter/constants.h"
36 #include "test/core/util/port.h"
37 #include "test/core/util/test_config.h"
38 
39 namespace grpc {
40 namespace testing {
41 namespace {
42 
43 using ::grpc::lb::v1::LoadBalancingFeedback;
44 using ::grpc::load_reporter::CensusViewProvider;
45 using ::grpc::load_reporter::CpuStatsProvider;
46 using ::grpc::load_reporter::LoadReporter;
47 using ::opencensus::stats::ViewDescriptor;
48 using ::testing::DoubleNear;
49 using ::testing::Return;
50 
51 constexpr uint64_t kFeedbackSampleWindowSeconds = 5;
52 constexpr uint64_t kFetchAndSampleIntervalSeconds = 1;
53 constexpr uint64_t kNumFeedbackSamplesInWindow =
54     kFeedbackSampleWindowSeconds / kFetchAndSampleIntervalSeconds;
55 
56 class MockCensusViewProvider : public CensusViewProvider {
57  public:
58   MOCK_METHOD0(FetchViewData, CensusViewProvider::ViewDataMap());
59 
FindViewDescriptor(const std::string & view_name)60   const ViewDescriptor& FindViewDescriptor(const std::string& view_name) {
61     auto it = view_descriptor_map().find(view_name);
62     GPR_ASSERT(it != view_descriptor_map().end());
63     return it->second;
64   }
65 };
66 
67 class MockCpuStatsProvider : public CpuStatsProvider {
68  public:
69   MOCK_METHOD0(GetCpuStats, CpuStatsProvider::CpuStatsSample());
70 };
71 
72 class LoadReporterTest : public ::testing::Test {
73  public:
LoadReporterTest()74   LoadReporterTest() {}
75 
mock_census_view_provider()76   MockCensusViewProvider* mock_census_view_provider() {
77     return static_cast<MockCensusViewProvider*>(
78         load_reporter_->census_view_provider());
79   }
80 
PrepareCpuExpectation(size_t call_num)81   void PrepareCpuExpectation(size_t call_num) {
82     auto mock_cpu_stats_provider = static_cast<MockCpuStatsProvider*>(
83         load_reporter_->cpu_stats_provider());
84     ::testing::InSequence s;
85     for (size_t i = 0; i < call_num; ++i) {
86       EXPECT_CALL(*mock_cpu_stats_provider, GetCpuStats())
87           .WillOnce(Return(kCpuStatsSamples[i]))
88           .RetiresOnSaturation();
89     }
90   }
91 
92   CpuStatsProvider::CpuStatsSample initial_cpu_stats_{2, 20};
93   const std::vector<CpuStatsProvider::CpuStatsSample> kCpuStatsSamples = {
94       {13, 53},    {64, 96},     {245, 345},  {314, 785},
95       {874, 1230}, {1236, 2145}, {1864, 2974}};
96 
97   std::unique_ptr<LoadReporter> load_reporter_;
98 
99   const std::string kHostname1 = "kHostname1";
100   const std::string kHostname2 = "kHostname2";
101   const std::string kHostname3 = "kHostname3";
102   // Pad to the length of a valid LB ID.
103   const std::string kLbId1 = "kLbId111";
104   const std::string kLbId2 = "kLbId222";
105   const std::string kLbId3 = "kLbId333";
106   const std::string kLbId4 = "kLbId444";
107   const std::string kLoadKey1 = "kLoadKey1";
108   const std::string kLoadKey2 = "kLoadKey2";
109   const std::string kLoadKey3 = "kLoadKey3";
110   const std::string kLbTag1 = "kLbTag1";
111   const std::string kLbTag2 = "kLbTag2";
112   const std::string kLbToken1 = "kLbId111kLbTag1";
113   const std::string kLbToken2 = "kLbId222kLbTag2";
114   const std::string kUser1 = "kUser1";
115   const std::string kUser2 = "kUser2";
116   const std::string kUser3 = "kUser3";
117   const std::string kClientIp0 = "00";
118   const std::string kClientIp1 = "0800000001";
119   const std::string kClientIp2 = "3200000000000000000000000000000002";
120   const std::string kMetric1 = "kMetric1";
121   const std::string kMetric2 = "kMetric2";
122 
123  private:
SetUp()124   void SetUp() override {
125     // Access the measures to make them valid.
126     grpc::load_reporter::MeasureStartCount();
127     grpc::load_reporter::MeasureEndCount();
128     grpc::load_reporter::MeasureEndBytesSent();
129     grpc::load_reporter::MeasureEndBytesReceived();
130     grpc::load_reporter::MeasureEndLatencyMs();
131     grpc::load_reporter::MeasureOtherCallMetric();
132     // Set up the load reporter.
133     auto mock_cpu = new MockCpuStatsProvider();
134     auto mock_census = new MockCensusViewProvider();
135     // Prepare the initial CPU stats data. Note that the expectation should be
136     // set up before the load reporter is initialized, because CPU stats is
137     // sampled at that point.
138     EXPECT_CALL(*mock_cpu, GetCpuStats())
139         .WillOnce(Return(initial_cpu_stats_))
140         .RetiresOnSaturation();
141     load_reporter_ = std::make_unique<LoadReporter>(
142         kFeedbackSampleWindowSeconds,
143         std::unique_ptr<CensusViewProvider>(mock_census),
144         std::unique_ptr<CpuStatsProvider>(mock_cpu));
145   }
146 };
147 
148 class LbFeedbackTest : public LoadReporterTest {
149  public:
150   // Note that [start, start + count) of the fake samples (maybe plus the
151   // initial record) are in the window now.
VerifyLbFeedback(const LoadBalancingFeedback & lb_feedback,size_t start,size_t count)152   void VerifyLbFeedback(const LoadBalancingFeedback& lb_feedback, size_t start,
153                         size_t count) {
154     const CpuStatsProvider::CpuStatsSample* base =
155         start == 0 ? &initial_cpu_stats_ : &kCpuStatsSamples[start - 1];
156     double expected_cpu_util =
157         static_cast<double>(kCpuStatsSamples[start + count - 1].first -
158                             base->first) /
159         static_cast<double>(kCpuStatsSamples[start + count - 1].second -
160                             base->second);
161     ASSERT_THAT(static_cast<double>(lb_feedback.server_utilization()),
162                 DoubleNear(expected_cpu_util, 0.00001));
163     double qps_sum = 0, eps_sum = 0;
164     for (size_t i = 0; i < count; ++i) {
165       qps_sum += kQpsEpsSamples[start + i].first;
166       eps_sum += kQpsEpsSamples[start + i].second;
167     }
168     double expected_qps = qps_sum / count;
169     double expected_eps = eps_sum / count;
170     // TODO(juanlishen): The error is big because we use sleep(). It should be
171     // much smaller when we use fake clock.
172     ASSERT_THAT(static_cast<double>(lb_feedback.calls_per_second()),
173                 DoubleNear(expected_qps, expected_qps * 0.3));
174     ASSERT_THAT(static_cast<double>(lb_feedback.errors_per_second()),
175                 DoubleNear(expected_eps, expected_eps * 0.3));
176     gpr_log(GPR_INFO,
177             "Verified LB feedback matches the samples of index [%zu, %zu).",
178             start, start + count);
179   }
180 
181   const std::vector<std::pair<double, double>> kQpsEpsSamples = {
182       {546.1, 153.1},  {62.1, 54.1},   {578.1, 154.2}, {978.1, 645.1},
183       {1132.1, 846.4}, {531.5, 315.4}, {874.1, 324.9}};
184 };
185 
TEST_F(LbFeedbackTest,ZeroDuration)186 TEST_F(LbFeedbackTest, ZeroDuration) {
187   PrepareCpuExpectation(kCpuStatsSamples.size());
188   EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
189       .WillRepeatedly(
190           Return(grpc::load_reporter::CensusViewProvider::ViewDataMap()));
191   // Verify that divide-by-zero exception doesn't happen.
192   for (size_t i = 0; i < kCpuStatsSamples.size(); ++i) {
193     load_reporter_->FetchAndSample();
194   }
195   load_reporter_->GenerateLoadBalancingFeedback();
196 }
197 
TEST_F(LbFeedbackTest,Normal)198 TEST_F(LbFeedbackTest, Normal) {
199   // Prepare view data list using the <QPS, EPS> samples.
200   std::vector<CensusViewProvider::ViewDataMap> view_data_map_list;
201   for (const auto& p : LbFeedbackTest::kQpsEpsSamples) {
202     double qps = p.first;
203     double eps = p.second;
204     double ok_count = (qps - eps) * kFetchAndSampleIntervalSeconds;
205     double error_count = eps * kFetchAndSampleIntervalSeconds;
206     double ok_count_1 = ok_count / 3.0;
207     double ok_count_2 = ok_count - ok_count_1;
208     auto end_count_vd = ::opencensus::stats::testing::TestUtils::MakeViewData(
209         mock_census_view_provider()->FindViewDescriptor(
210             grpc::load_reporter::kViewEndCount),
211         {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
212            grpc::load_reporter::kCallStatusOk},
213           ok_count_1},
214          {{kClientIp0 + kLbToken1, kHostname1, kUser2,
215            grpc::load_reporter::kCallStatusOk},
216           ok_count_2},
217          {{kClientIp0 + kLbToken1, kHostname1, kUser1,
218            grpc::load_reporter::kCallStatusClientError},
219           error_count}});
220     // Values for other view data don't matter.
221     auto end_bytes_sent_vd =
222         ::opencensus::stats::testing::TestUtils::MakeViewData(
223             mock_census_view_provider()->FindViewDescriptor(
224                 grpc::load_reporter::kViewEndBytesSent),
225             {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
226                grpc::load_reporter::kCallStatusOk},
227               0},
228              {{kClientIp0 + kLbToken1, kHostname1, kUser2,
229                grpc::load_reporter::kCallStatusOk},
230               0},
231              {{kClientIp0 + kLbToken1, kHostname1, kUser1,
232                grpc::load_reporter::kCallStatusClientError},
233               0}});
234     auto end_bytes_received_vd =
235         ::opencensus::stats::testing::TestUtils::MakeViewData(
236             mock_census_view_provider()->FindViewDescriptor(
237                 grpc::load_reporter::kViewEndBytesReceived),
238             {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
239                grpc::load_reporter::kCallStatusOk},
240               0},
241              {{kClientIp0 + kLbToken1, kHostname1, kUser2,
242                grpc::load_reporter::kCallStatusOk},
243               0},
244              {{kClientIp0 + kLbToken1, kHostname1, kUser1,
245                grpc::load_reporter::kCallStatusClientError},
246               0}});
247     auto end_latency_vd = ::opencensus::stats::testing::TestUtils::MakeViewData(
248         mock_census_view_provider()->FindViewDescriptor(
249             grpc::load_reporter::kViewEndLatencyMs),
250         {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
251            grpc::load_reporter::kCallStatusOk},
252           0},
253          {{kClientIp0 + kLbToken1, kHostname1, kUser2,
254            grpc::load_reporter::kCallStatusOk},
255           0},
256          {{kClientIp0 + kLbToken1, kHostname1, kUser1,
257            grpc::load_reporter::kCallStatusClientError},
258           0}});
259     view_data_map_list.push_back(
260         {{::grpc::load_reporter::kViewEndCount, end_count_vd},
261          {::grpc::load_reporter::kViewEndBytesSent, end_bytes_sent_vd},
262          {::grpc::load_reporter::kViewEndBytesReceived, end_bytes_received_vd},
263          {::grpc::load_reporter::kViewEndLatencyMs, end_latency_vd}});
264   }
265   {
266     ::testing::InSequence s;
267     for (size_t i = 0; i < view_data_map_list.size(); ++i) {
268       EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
269           .WillOnce(Return(view_data_map_list[i]))
270           .RetiresOnSaturation();
271     }
272   }
273   PrepareCpuExpectation(kNumFeedbackSamplesInWindow + 2);
274   // When the load reporter is created, a trivial LB feedback record is added.
275   // But that's not enough for generating an LB feedback.
276   // Fetch some view data so that non-trivial LB feedback can be generated.
277   for (size_t i = 0; i < kNumFeedbackSamplesInWindow / 2; ++i) {
278     // TODO(juanlishen): Find some fake clock to speed up testing.
279     sleep(1);
280     load_reporter_->FetchAndSample();
281   }
282   VerifyLbFeedback(load_reporter_->GenerateLoadBalancingFeedback(), 0,
283                    kNumFeedbackSamplesInWindow / 2);
284   // Fetch more view data so that the feedback record window is just full (the
285   // initial record just falls out of the window).
286   for (size_t i = 0; i < (kNumFeedbackSamplesInWindow + 1) / 2; ++i) {
287     sleep(1);
288     load_reporter_->FetchAndSample();
289   }
290   VerifyLbFeedback(load_reporter_->GenerateLoadBalancingFeedback(), 0,
291                    kNumFeedbackSamplesInWindow);
292   // Further fetching will cause the old records to fall out of the window.
293   for (size_t i = 0; i < 2; ++i) {
294     sleep(1);
295     load_reporter_->FetchAndSample();
296   }
297   VerifyLbFeedback(load_reporter_->GenerateLoadBalancingFeedback(), 2,
298                    kNumFeedbackSamplesInWindow);
299 }
300 
301 using LoadReportTest = LoadReporterTest;
302 
TEST_F(LoadReportTest,BasicReport)303 TEST_F(LoadReportTest, BasicReport) {
304   // Make up the first view data map.
305   CensusViewProvider::ViewDataMap vdm1;
306   vdm1.emplace(
307       grpc::load_reporter::kViewStartCount,
308       ::opencensus::stats::testing::TestUtils::MakeViewData(
309           mock_census_view_provider()->FindViewDescriptor(
310               grpc::load_reporter::kViewStartCount),
311           {{{kClientIp1 + kLbToken1, kHostname1, kUser1}, 1234},
312            {{kClientIp2 + kLbToken1, kHostname1, kUser1}, 1225},
313            {{kClientIp0 + kLbToken1, kHostname1, kUser1}, 10},
314            {{kClientIp2 + kLbToken1, kHostname1, kUser2}, 464},
315            {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3}, 101},
316            {{kClientIp1 + kLbToken2, kHostname2, kUser3}, 17},
317            {{kClientIp2 + kLbId3 + kLbTag2, kHostname2, kUser3}, 23}}));
318   vdm1.emplace(grpc::load_reporter::kViewEndCount,
319                ::opencensus::stats::testing::TestUtils::MakeViewData(
320                    mock_census_view_provider()->FindViewDescriptor(
321                        grpc::load_reporter::kViewEndCount),
322                    {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
323                       grpc::load_reporter::kCallStatusOk},
324                      641},
325                     {{kClientIp2 + kLbToken1, kHostname1, kUser1,
326                       grpc::load_reporter::kCallStatusClientError},
327                      272},
328                     {{kClientIp2 + kLbToken1, kHostname1, kUser2,
329                       grpc::load_reporter::kCallStatusOk},
330                      996},
331                     {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
332                       grpc::load_reporter::kCallStatusClientError},
333                      34},
334                     {{kClientIp1 + kLbToken2, kHostname2, kUser2,
335                       grpc::load_reporter::kCallStatusOk},
336                      18}}));
337   vdm1.emplace(grpc::load_reporter::kViewEndBytesSent,
338                ::opencensus::stats::testing::TestUtils::MakeViewData(
339                    mock_census_view_provider()->FindViewDescriptor(
340                        grpc::load_reporter::kViewEndBytesSent),
341                    {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
342                       grpc::load_reporter::kCallStatusOk},
343                      8977},
344                     {{kClientIp2 + kLbToken1, kHostname1, kUser1,
345                       grpc::load_reporter::kCallStatusClientError},
346                      266},
347                     {{kClientIp2 + kLbToken1, kHostname1, kUser2,
348                       grpc::load_reporter::kCallStatusOk},
349                      1276},
350                     {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
351                       grpc::load_reporter::kCallStatusClientError},
352                      77823},
353                     {{kClientIp1 + kLbToken2, kHostname2, kUser2,
354                       grpc::load_reporter::kCallStatusOk},
355                      48}}));
356   vdm1.emplace(grpc::load_reporter::kViewEndBytesReceived,
357                ::opencensus::stats::testing::TestUtils::MakeViewData(
358                    mock_census_view_provider()->FindViewDescriptor(
359                        grpc::load_reporter::kViewEndBytesReceived),
360                    {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
361                       grpc::load_reporter::kCallStatusOk},
362                      2341},
363                     {{kClientIp2 + kLbToken1, kHostname1, kUser1,
364                       grpc::load_reporter::kCallStatusClientError},
365                      466},
366                     {{kClientIp2 + kLbToken1, kHostname1, kUser2,
367                       grpc::load_reporter::kCallStatusOk},
368                      518},
369                     {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
370                       grpc::load_reporter::kCallStatusClientError},
371                      81},
372                     {{kClientIp1 + kLbToken2, kHostname2, kUser2,
373                       grpc::load_reporter::kCallStatusOk},
374                      27}}));
375   vdm1.emplace(grpc::load_reporter::kViewEndLatencyMs,
376                ::opencensus::stats::testing::TestUtils::MakeViewData(
377                    mock_census_view_provider()->FindViewDescriptor(
378                        grpc::load_reporter::kViewEndLatencyMs),
379                    {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
380                       grpc::load_reporter::kCallStatusOk},
381                      3.14},
382                     {{kClientIp2 + kLbToken1, kHostname1, kUser1,
383                       grpc::load_reporter::kCallStatusClientError},
384                      5.26},
385                     {{kClientIp2 + kLbToken1, kHostname1, kUser2,
386                       grpc::load_reporter::kCallStatusOk},
387                      45.4},
388                     {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
389                       grpc::load_reporter::kCallStatusClientError},
390                      4.4},
391                     {{kClientIp1 + kLbToken2, kHostname2, kUser2,
392                       grpc::load_reporter::kCallStatusOk},
393                      2348.0}}));
394   vdm1.emplace(
395       grpc::load_reporter::kViewOtherCallMetricCount,
396       ::opencensus::stats::testing::TestUtils::MakeViewData(
397           mock_census_view_provider()->FindViewDescriptor(
398               grpc::load_reporter::kViewOtherCallMetricCount),
399           {{{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1},
400            {{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1},
401            {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
402             1}}));
403   vdm1.emplace(
404       grpc::load_reporter::kViewOtherCallMetricValue,
405       ::opencensus::stats::testing::TestUtils::MakeViewData(
406           mock_census_view_provider()->FindViewDescriptor(
407               grpc::load_reporter::kViewOtherCallMetricValue),
408           {{{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1.2},
409            {{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1.2},
410            {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
411             3.2}}));
412   // Make up the second view data map.
413   CensusViewProvider::ViewDataMap vdm2;
414   vdm2.emplace(
415       grpc::load_reporter::kViewStartCount,
416       ::opencensus::stats::testing::TestUtils::MakeViewData(
417           mock_census_view_provider()->FindViewDescriptor(
418               grpc::load_reporter::kViewStartCount),
419           {{{kClientIp2 + kLbToken1, kHostname1, kUser1}, 3},
420            {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3}, 778}}));
421   vdm2.emplace(grpc::load_reporter::kViewEndCount,
422                ::opencensus::stats::testing::TestUtils::MakeViewData(
423                    mock_census_view_provider()->FindViewDescriptor(
424                        grpc::load_reporter::kViewEndCount),
425                    {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
426                       grpc::load_reporter::kCallStatusOk},
427                      24},
428                     {{kClientIp1 + kLbToken2, kHostname2, kUser3,
429                       grpc::load_reporter::kCallStatusClientError},
430                      546}}));
431   vdm2.emplace(grpc::load_reporter::kViewEndBytesSent,
432                ::opencensus::stats::testing::TestUtils::MakeViewData(
433                    mock_census_view_provider()->FindViewDescriptor(
434                        grpc::load_reporter::kViewEndBytesSent),
435                    {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
436                       grpc::load_reporter::kCallStatusOk},
437                      747},
438                     {{kClientIp1 + kLbToken2, kHostname2, kUser3,
439                       grpc::load_reporter::kCallStatusClientError},
440                      229}}));
441   vdm2.emplace(grpc::load_reporter::kViewEndBytesReceived,
442                ::opencensus::stats::testing::TestUtils::MakeViewData(
443                    mock_census_view_provider()->FindViewDescriptor(
444                        grpc::load_reporter::kViewEndBytesReceived),
445                    {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
446                       grpc::load_reporter::kCallStatusOk},
447                      173},
448                     {{kClientIp1 + kLbToken2, kHostname2, kUser3,
449                       grpc::load_reporter::kCallStatusClientError},
450                      438}}));
451   vdm2.emplace(grpc::load_reporter::kViewEndLatencyMs,
452                ::opencensus::stats::testing::TestUtils::MakeViewData(
453                    mock_census_view_provider()->FindViewDescriptor(
454                        grpc::load_reporter::kViewEndLatencyMs),
455                    {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
456                       grpc::load_reporter::kCallStatusOk},
457                      187},
458                     {{kClientIp1 + kLbToken2, kHostname2, kUser3,
459                       grpc::load_reporter::kCallStatusClientError},
460                      34}}));
461   vdm2.emplace(
462       grpc::load_reporter::kViewOtherCallMetricCount,
463       ::opencensus::stats::testing::TestUtils::MakeViewData(
464           mock_census_view_provider()->FindViewDescriptor(
465               grpc::load_reporter::kViewOtherCallMetricCount),
466           {{{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric1}, 1},
467            {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
468             1}}));
469   vdm2.emplace(
470       grpc::load_reporter::kViewOtherCallMetricValue,
471       ::opencensus::stats::testing::TestUtils::MakeViewData(
472           mock_census_view_provider()->FindViewDescriptor(
473               grpc::load_reporter::kViewOtherCallMetricValue),
474           {{{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric1}, 9.6},
475            {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
476             5.7}}));
477   // Set up mock expectation.
478   EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
479       .WillOnce(Return(vdm1))
480       .WillOnce(Return(vdm2));
481   PrepareCpuExpectation(2);
482   // Start testing.
483   load_reporter_->ReportStreamCreated(kHostname1, kLbId1, kLoadKey1);
484   load_reporter_->ReportStreamCreated(kHostname2, kLbId2, kLoadKey2);
485   load_reporter_->ReportStreamCreated(kHostname2, kLbId3, kLoadKey3);
486   // First fetch.
487   load_reporter_->FetchAndSample();
488   load_reporter_->GenerateLoads(kHostname1, kLbId1);
489   gpr_log(GPR_INFO, "First load generated.");
490   // Second fetch.
491   load_reporter_->FetchAndSample();
492   load_reporter_->GenerateLoads(kHostname2, kLbId2);
493   gpr_log(GPR_INFO, "Second load generated.");
494   // TODO(juanlishen): Verify the data.
495 }
496 
497 }  // namespace
498 }  // namespace testing
499 }  // namespace grpc
500 
main(int argc,char ** argv)501 int main(int argc, char** argv) {
502   grpc::testing::TestEnvironment env(&argc, argv);
503   ::testing::InitGoogleTest(&argc, argv);
504   return RUN_ALL_TESTS();
505 }
506