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 <grpc/impl/codegen/port_platform.h>
20
21 #include <set>
22 #include <vector>
23
24 #include <gmock/gmock.h>
25 #include <grpc/grpc.h>
26 #include <gtest/gtest.h>
27
28 #include "src/core/ext/filters/load_reporting/registered_opencensus_objects.h"
29 #include "src/core/lib/iomgr/exec_ctx.h"
30 #include "src/cpp/server/load_reporter/constants.h"
31 #include "src/cpp/server/load_reporter/load_reporter.h"
32 #include "test/core/util/port.h"
33 #include "test/core/util/test_config.h"
34
35 #include "opencensus/stats/testing/test_utils.h"
36
37 namespace grpc {
38 namespace testing {
39 namespace {
40
41 using ::grpc::lb::v1::LoadBalancingFeedback;
42 using ::grpc::load_reporter::CensusViewProvider;
43 using ::grpc::load_reporter::CpuStatsProvider;
44 using ::grpc::load_reporter::LoadReporter;
45 using ::opencensus::stats::View;
46 using ::opencensus::stats::ViewData;
47 using ::opencensus::stats::ViewDataImpl;
48 using ::opencensus::stats::ViewDescriptor;
49 using ::testing::DoubleNear;
50 using ::testing::Return;
51
52 constexpr uint64_t kFeedbackSampleWindowSeconds = 5;
53 constexpr uint64_t kFetchAndSampleIntervalSeconds = 1;
54 constexpr uint64_t kNumFeedbackSamplesInWindow =
55 kFeedbackSampleWindowSeconds / kFetchAndSampleIntervalSeconds;
56
57 class MockCensusViewProvider : public CensusViewProvider {
58 public:
59 MOCK_METHOD0(FetchViewData, CensusViewProvider::ViewDataMap());
60
FindViewDescriptor(const grpc::string & view_name)61 const ::opencensus::stats::ViewDescriptor& FindViewDescriptor(
62 const grpc::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:
LoadReporterTest()76 LoadReporterTest() {}
77
mock_census_view_provider()78 MockCensusViewProvider* mock_census_view_provider() {
79 return static_cast<MockCensusViewProvider*>(
80 load_reporter_->census_view_provider());
81 }
82
PrepareCpuExpectation(size_t call_num)83 void PrepareCpuExpectation(size_t call_num) {
84 auto mock_cpu_stats_provider = static_cast<MockCpuStatsProvider*>(
85 load_reporter_->cpu_stats_provider());
86 ::testing::InSequence s;
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 grpc::string kHostname1 = "kHostname1";
102 const grpc::string kHostname2 = "kHostname2";
103 const grpc::string kHostname3 = "kHostname3";
104 // Pad to the length of a valid LB ID.
105 const grpc::string kLbId1 = "kLbId111";
106 const grpc::string kLbId2 = "kLbId222";
107 const grpc::string kLbId3 = "kLbId333";
108 const grpc::string kLbId4 = "kLbId444";
109 const grpc::string kLoadKey1 = "kLoadKey1";
110 const grpc::string kLoadKey2 = "kLoadKey2";
111 const grpc::string kLoadKey3 = "kLoadKey3";
112 const grpc::string kLbTag1 = "kLbTag1";
113 const grpc::string kLbTag2 = "kLbTag2";
114 const grpc::string kLbToken1 = "kLbId111kLbTag1";
115 const grpc::string kLbToken2 = "kLbId222kLbTag2";
116 const grpc::string kUser1 = "kUser1";
117 const grpc::string kUser2 = "kUser2";
118 const grpc::string kUser3 = "kUser3";
119 const grpc::string kClientIp0 = "00";
120 const grpc::string kClientIp1 = "0800000001";
121 const grpc::string kClientIp2 = "3200000000000000000000000000000002";
122 const grpc::string kMetric1 = "kMetric1";
123 const grpc::string kMetric2 = "kMetric2";
124
125 private:
SetUp()126 void SetUp() override {
127 // Access the measures to make them valid.
128 ::grpc::load_reporter::MeasureStartCount();
129 ::grpc::load_reporter::MeasureEndCount();
130 ::grpc::load_reporter::MeasureEndBytesSent();
131 ::grpc::load_reporter::MeasureEndBytesReceived();
132 ::grpc::load_reporter::MeasureEndLatencyMs();
133 ::grpc::load_reporter::MeasureOtherCallMetric();
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_ = std::unique_ptr<LoadReporter>(
144 new LoadReporter(kFeedbackSampleWindowSeconds,
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.
VerifyLbFeedback(const LoadBalancingFeedback & lb_feedback,size_t start,size_t count)154 void VerifyLbFeedback(const LoadBalancingFeedback& lb_feedback, size_t start,
155 size_t count) {
156 const CpuStatsProvider::CpuStatsSample* base =
157 start == 0 ? &initial_cpu_stats_ : &kCpuStatsSamples[start - 1];
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.05));
176 ASSERT_THAT(static_cast<double>(lb_feedback.errors_per_second()),
177 DoubleNear(expected_eps, expected_eps * 0.05));
178 gpr_log(GPR_INFO,
179 "Verified LB feedback matches the samples of index [%lu, %lu).",
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
TEST_F(LbFeedbackTest,ZeroDuration)188 TEST_F(LbFeedbackTest, ZeroDuration) {
189 PrepareCpuExpectation(kCpuStatsSamples.size());
190 EXPECT_CALL(*mock_census_view_provider(), FetchViewData())
191 .WillRepeatedly(
192 Return(::grpc::load_reporter::CensusViewProvider::ViewDataMap()));
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
TEST_F(LbFeedbackTest,Normal)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(
212 ::grpc::load_reporter::kViewEndCount),
213 {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
214 ::grpc::load_reporter::kCallStatusOk},
215 ok_count_1},
216 {{kClientIp0 + kLbToken1, kHostname1, kUser2,
217 ::grpc::load_reporter::kCallStatusOk},
218 ok_count_2},
219 {{kClientIp0 + kLbToken1, kHostname1, kUser1,
220 ::grpc::load_reporter::kCallStatusClientError},
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(
226 ::grpc::load_reporter::kViewEndBytesSent),
227 {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
228 ::grpc::load_reporter::kCallStatusOk},
229 0},
230 {{kClientIp0 + kLbToken1, kHostname1, kUser2,
231 ::grpc::load_reporter::kCallStatusOk},
232 0},
233 {{kClientIp0 + kLbToken1, kHostname1, kUser1,
234 ::grpc::load_reporter::kCallStatusClientError},
235 0}});
236 auto end_bytes_received_vd =
237 ::opencensus::stats::testing::TestUtils::MakeViewData(
238 mock_census_view_provider()->FindViewDescriptor(
239 ::grpc::load_reporter::kViewEndBytesReceived),
240 {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
241 ::grpc::load_reporter::kCallStatusOk},
242 0},
243 {{kClientIp0 + kLbToken1, kHostname1, kUser2,
244 ::grpc::load_reporter::kCallStatusOk},
245 0},
246 {{kClientIp0 + kLbToken1, kHostname1, kUser1,
247 ::grpc::load_reporter::kCallStatusClientError},
248 0}});
249 auto end_latency_vd = ::opencensus::stats::testing::TestUtils::MakeViewData(
250 mock_census_view_provider()->FindViewDescriptor(
251 ::grpc::load_reporter::kViewEndLatencyMs),
252 {{{kClientIp0 + kLbToken1, kHostname1, kUser1,
253 ::grpc::load_reporter::kCallStatusOk},
254 0},
255 {{kClientIp0 + kLbToken1, kHostname1, kUser2,
256 ::grpc::load_reporter::kCallStatusOk},
257 0},
258 {{kClientIp0 + kLbToken1, kHostname1, kUser1,
259 ::grpc::load_reporter::kCallStatusClientError},
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 {
268 ::testing::InSequence s;
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
TEST_F(LoadReportTest,BasicReport)305 TEST_F(LoadReportTest, BasicReport) {
306 // Make up the first view data map.
307 CensusViewProvider::ViewDataMap vdm1;
308 vdm1.emplace(
309 ::grpc::load_reporter::kViewStartCount,
310 ::opencensus::stats::testing::TestUtils::MakeViewData(
311 mock_census_view_provider()->FindViewDescriptor(
312 ::grpc::load_reporter::kViewStartCount),
313 {{{kClientIp1 + kLbToken1, kHostname1, kUser1}, 1234},
314 {{kClientIp2 + kLbToken1, kHostname1, kUser1}, 1225},
315 {{kClientIp0 + kLbToken1, kHostname1, kUser1}, 10},
316 {{kClientIp2 + kLbToken1, kHostname1, kUser2}, 464},
317 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3}, 101},
318 {{kClientIp1 + kLbToken2, kHostname2, kUser3}, 17},
319 {{kClientIp2 + kLbId3 + kLbTag2, kHostname2, kUser3}, 23}}));
320 vdm1.emplace(::grpc::load_reporter::kViewEndCount,
321 ::opencensus::stats::testing::TestUtils::MakeViewData(
322 mock_census_view_provider()->FindViewDescriptor(
323 ::grpc::load_reporter::kViewEndCount),
324 {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
325 ::grpc::load_reporter::kCallStatusOk},
326 641},
327 {{kClientIp2 + kLbToken1, kHostname1, kUser1,
328 ::grpc::load_reporter::kCallStatusClientError},
329 272},
330 {{kClientIp2 + kLbToken1, kHostname1, kUser2,
331 ::grpc::load_reporter::kCallStatusOk},
332 996},
333 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
334 ::grpc::load_reporter::kCallStatusClientError},
335 34},
336 {{kClientIp1 + kLbToken2, kHostname2, kUser2,
337 ::grpc::load_reporter::kCallStatusOk},
338 18}}));
339 vdm1.emplace(::grpc::load_reporter::kViewEndBytesSent,
340 ::opencensus::stats::testing::TestUtils::MakeViewData(
341 mock_census_view_provider()->FindViewDescriptor(
342 ::grpc::load_reporter::kViewEndBytesSent),
343 {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
344 ::grpc::load_reporter::kCallStatusOk},
345 8977},
346 {{kClientIp2 + kLbToken1, kHostname1, kUser1,
347 ::grpc::load_reporter::kCallStatusClientError},
348 266},
349 {{kClientIp2 + kLbToken1, kHostname1, kUser2,
350 ::grpc::load_reporter::kCallStatusOk},
351 1276},
352 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
353 ::grpc::load_reporter::kCallStatusClientError},
354 77823},
355 {{kClientIp1 + kLbToken2, kHostname2, kUser2,
356 ::grpc::load_reporter::kCallStatusOk},
357 48}}));
358 vdm1.emplace(::grpc::load_reporter::kViewEndBytesReceived,
359 ::opencensus::stats::testing::TestUtils::MakeViewData(
360 mock_census_view_provider()->FindViewDescriptor(
361 ::grpc::load_reporter::kViewEndBytesReceived),
362 {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
363 ::grpc::load_reporter::kCallStatusOk},
364 2341},
365 {{kClientIp2 + kLbToken1, kHostname1, kUser1,
366 ::grpc::load_reporter::kCallStatusClientError},
367 466},
368 {{kClientIp2 + kLbToken1, kHostname1, kUser2,
369 ::grpc::load_reporter::kCallStatusOk},
370 518},
371 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
372 ::grpc::load_reporter::kCallStatusClientError},
373 81},
374 {{kClientIp1 + kLbToken2, kHostname2, kUser2,
375 ::grpc::load_reporter::kCallStatusOk},
376 27}}));
377 vdm1.emplace(::grpc::load_reporter::kViewEndLatencyMs,
378 ::opencensus::stats::testing::TestUtils::MakeViewData(
379 mock_census_view_provider()->FindViewDescriptor(
380 ::grpc::load_reporter::kViewEndLatencyMs),
381 {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
382 ::grpc::load_reporter::kCallStatusOk},
383 3.14},
384 {{kClientIp2 + kLbToken1, kHostname1, kUser1,
385 ::grpc::load_reporter::kCallStatusClientError},
386 5.26},
387 {{kClientIp2 + kLbToken1, kHostname1, kUser2,
388 ::grpc::load_reporter::kCallStatusOk},
389 45.4},
390 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3,
391 ::grpc::load_reporter::kCallStatusClientError},
392 4.4},
393 {{kClientIp1 + kLbToken2, kHostname2, kUser2,
394 ::grpc::load_reporter::kCallStatusOk},
395 2348.0}}));
396 vdm1.emplace(
397 ::grpc::load_reporter::kViewOtherCallMetricCount,
398 ::opencensus::stats::testing::TestUtils::MakeViewData(
399 mock_census_view_provider()->FindViewDescriptor(
400 ::grpc::load_reporter::kViewOtherCallMetricCount),
401 {{{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1},
402 {{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1},
403 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
404 1}}));
405 vdm1.emplace(
406 ::grpc::load_reporter::kViewOtherCallMetricValue,
407 ::opencensus::stats::testing::TestUtils::MakeViewData(
408 mock_census_view_provider()->FindViewDescriptor(
409 ::grpc::load_reporter::kViewOtherCallMetricValue),
410 {{{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1.2},
411 {{kClientIp1 + kLbToken1, kHostname1, kUser2, kMetric1}, 1.2},
412 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
413 3.2}}));
414 // Make up the second view data map.
415 CensusViewProvider::ViewDataMap vdm2;
416 vdm2.emplace(
417 ::grpc::load_reporter::kViewStartCount,
418 ::opencensus::stats::testing::TestUtils::MakeViewData(
419 mock_census_view_provider()->FindViewDescriptor(
420 ::grpc::load_reporter::kViewStartCount),
421 {{{kClientIp2 + kLbToken1, kHostname1, kUser1}, 3},
422 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3}, 778}}));
423 vdm2.emplace(::grpc::load_reporter::kViewEndCount,
424 ::opencensus::stats::testing::TestUtils::MakeViewData(
425 mock_census_view_provider()->FindViewDescriptor(
426 ::grpc::load_reporter::kViewEndCount),
427 {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
428 ::grpc::load_reporter::kCallStatusOk},
429 24},
430 {{kClientIp1 + kLbToken2, kHostname2, kUser3,
431 ::grpc::load_reporter::kCallStatusClientError},
432 546}}));
433 vdm2.emplace(::grpc::load_reporter::kViewEndBytesSent,
434 ::opencensus::stats::testing::TestUtils::MakeViewData(
435 mock_census_view_provider()->FindViewDescriptor(
436 ::grpc::load_reporter::kViewEndBytesSent),
437 {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
438 ::grpc::load_reporter::kCallStatusOk},
439 747},
440 {{kClientIp1 + kLbToken2, kHostname2, kUser3,
441 ::grpc::load_reporter::kCallStatusClientError},
442 229}}));
443 vdm2.emplace(::grpc::load_reporter::kViewEndBytesReceived,
444 ::opencensus::stats::testing::TestUtils::MakeViewData(
445 mock_census_view_provider()->FindViewDescriptor(
446 ::grpc::load_reporter::kViewEndBytesReceived),
447 {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
448 ::grpc::load_reporter::kCallStatusOk},
449 173},
450 {{kClientIp1 + kLbToken2, kHostname2, kUser3,
451 ::grpc::load_reporter::kCallStatusClientError},
452 438}}));
453 vdm2.emplace(::grpc::load_reporter::kViewEndLatencyMs,
454 ::opencensus::stats::testing::TestUtils::MakeViewData(
455 mock_census_view_provider()->FindViewDescriptor(
456 ::grpc::load_reporter::kViewEndLatencyMs),
457 {{{kClientIp1 + kLbToken1, kHostname1, kUser1,
458 ::grpc::load_reporter::kCallStatusOk},
459 187},
460 {{kClientIp1 + kLbToken2, kHostname2, kUser3,
461 ::grpc::load_reporter::kCallStatusClientError},
462 34}}));
463 vdm2.emplace(
464 ::grpc::load_reporter::kViewOtherCallMetricCount,
465 ::opencensus::stats::testing::TestUtils::MakeViewData(
466 mock_census_view_provider()->FindViewDescriptor(
467 ::grpc::load_reporter::kViewOtherCallMetricCount),
468 {{{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric1}, 1},
469 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
470 1}}));
471 vdm2.emplace(
472 ::grpc::load_reporter::kViewOtherCallMetricValue,
473 ::opencensus::stats::testing::TestUtils::MakeViewData(
474 mock_census_view_provider()->FindViewDescriptor(
475 ::grpc::load_reporter::kViewOtherCallMetricValue),
476 {{{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric1}, 9.6},
477 {{kClientIp1 + kLbId2 + kLbTag1, kHostname2, kUser3, kMetric2},
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
main(int argc,char ** argv)503 int main(int argc, char** argv) {
504 grpc_test_init(argc, argv);
505 ::testing::InitGoogleTest(&argc, argv);
506 return RUN_ALL_TESTS();
507 }
508