1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "metrics.h"
18
19 #include "base/macros.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include "metrics_test.h"
23
24 #pragma clang diagnostic push
25 #pragma clang diagnostic error "-Wconversion"
26
27 namespace art {
28 namespace metrics {
29
30 using test::CounterValue;
31 using test::GetBuckets;
32 using test::TestBackendBase;
33
34 class MetricsTest : public testing::Test {};
35
TEST_F(MetricsTest,SimpleCounter)36 TEST_F(MetricsTest, SimpleCounter) {
37 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
38
39 EXPECT_EQ(0u, CounterValue(test_counter));
40
41 test_counter.AddOne();
42 EXPECT_EQ(1u, CounterValue(test_counter));
43
44 test_counter.Add(5);
45 EXPECT_EQ(6u, CounterValue(test_counter));
46 }
47
TEST_F(MetricsTest,CounterTimer)48 TEST_F(MetricsTest, CounterTimer) {
49 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
50 {
51 AutoTimer timer{&test_counter};
52 // Sleep for 2µs so the counter will be greater than 0.
53 NanoSleep(2'000);
54 }
55 EXPECT_GT(CounterValue(test_counter), 0u);
56 }
57
TEST_F(MetricsTest,CounterTimerExplicitStop)58 TEST_F(MetricsTest, CounterTimerExplicitStop) {
59 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
60 AutoTimer timer{&test_counter};
61 // Sleep for 2µs so the counter will be greater than 0.
62 NanoSleep(2'000);
63 timer.Stop();
64 EXPECT_GT(CounterValue(test_counter), 0u);
65 }
66
TEST_F(MetricsTest,CounterTimerExplicitStart)67 TEST_F(MetricsTest, CounterTimerExplicitStart) {
68 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
69 {
70 AutoTimer timer{&test_counter, /*autostart=*/false};
71 // Sleep for 2µs so the counter will be greater than 0.
72 NanoSleep(2'000);
73 }
74 EXPECT_EQ(CounterValue(test_counter), 0u);
75
76 {
77 AutoTimer timer{&test_counter, /*autostart=*/false};
78 timer.Start();
79 // Sleep for 2µs so the counter will be greater than 0.
80 NanoSleep(2'000);
81 }
82 EXPECT_GT(CounterValue(test_counter), 0u);
83 }
84
TEST_F(MetricsTest,CounterTimerExplicitStartStop)85 TEST_F(MetricsTest, CounterTimerExplicitStartStop) {
86 MetricsCounter<DatumId::kClassVerificationTotalTime> test_counter;
87 AutoTimer timer{&test_counter, /*autostart=*/false};
88 // Sleep for 2µs so the counter will be greater than 0.
89 timer.Start();
90 NanoSleep(2'000);
91 timer.Stop();
92 EXPECT_GT(CounterValue(test_counter), 0u);
93 }
94
TEST_F(MetricsTest,AccumulatorMetric)95 TEST_F(MetricsTest, AccumulatorMetric) {
96 MetricsAccumulator<DatumId::kClassLoadingTotalTime, uint64_t, std::max> accumulator;
97
98 std::vector<std::thread> threads;
99
100 constexpr uint64_t kMaxValue = 100;
101
102 for (uint64_t i = 0; i <= kMaxValue; i++) {
103 threads.emplace_back(std::thread{[&accumulator, i]() { accumulator.Add(i); }});
104 }
105
106 for (auto& thread : threads) {
107 thread.join();
108 }
109
110 EXPECT_EQ(CounterValue(accumulator), kMaxValue);
111 }
112
TEST_F(MetricsTest,AverageMetric)113 TEST_F(MetricsTest, AverageMetric) {
114 MetricsAverage<DatumId::kClassLoadingTotalTime, uint64_t> avg;
115
116 std::vector<std::thread> threads;
117
118 constexpr uint64_t kMaxValue = 100;
119
120 for (uint64_t i = 0; i <= kMaxValue; i++) {
121 threads.emplace_back(std::thread{[&avg, i]() { avg.Add(i); }});
122 }
123
124 for (auto& thread : threads) {
125 thread.join();
126 }
127
128 EXPECT_EQ(CounterValue(avg), (kMaxValue + 1) / 2);
129 }
130
TEST_F(MetricsTest,DatumName)131 TEST_F(MetricsTest, DatumName) {
132 EXPECT_EQ("ClassVerificationTotalTime", DatumName(DatumId::kClassVerificationTotalTime));
133 }
134
TEST_F(MetricsTest,SimpleHistogramTest)135 TEST_F(MetricsTest, SimpleHistogramTest) {
136 MetricsHistogram<DatumId::kYoungGcCollectionTime, 5, 0, 100> histogram;
137
138 // bucket 0: 0-19
139 histogram.Add(10);
140
141 // bucket 1: 20-39
142 histogram.Add(20);
143 histogram.Add(25);
144
145 // bucket 2: 40-59
146 histogram.Add(56);
147 histogram.Add(57);
148 histogram.Add(58);
149 histogram.Add(59);
150
151 // bucket 3: 60-79
152 histogram.Add(70);
153 histogram.Add(70);
154 histogram.Add(70);
155
156 // bucket 4: 80-99
157 // leave this bucket empty
158
159 std::vector<uint32_t> buckets{GetBuckets(histogram)};
160 EXPECT_EQ(1u, buckets[0u]);
161 EXPECT_EQ(2u, buckets[1u]);
162 EXPECT_EQ(4u, buckets[2u]);
163 EXPECT_EQ(3u, buckets[3u]);
164 EXPECT_EQ(0u, buckets[4u]);
165 }
166
167 // Make sure values added outside the range of the histogram go into the first or last bucket.
TEST_F(MetricsTest,HistogramOutOfRangeTest)168 TEST_F(MetricsTest, HistogramOutOfRangeTest) {
169 MetricsHistogram<DatumId::kYoungGcCollectionTime, 2, 0, 100> histogram;
170
171 // bucket 0: 0-49
172 histogram.Add(-500);
173
174 // bucket 1: 50-99
175 histogram.Add(250);
176 histogram.Add(1000);
177
178 std::vector<uint32_t> buckets{GetBuckets(histogram)};
179 EXPECT_EQ(1u, buckets[0u]);
180 EXPECT_EQ(2u, buckets[1u]);
181 }
182
183 // Test adding values to ArtMetrics and reporting them through a test backend.
TEST_F(MetricsTest,ArtMetricsReport)184 TEST_F(MetricsTest, ArtMetricsReport) {
185 ArtMetrics metrics;
186
187 // Collect some data
188 static constexpr uint64_t verification_time = 42;
189 metrics.ClassVerificationTotalTime()->Add(verification_time);
190 // Add a negative value so we are guaranteed that it lands in the first bucket.
191 metrics.YoungGcCollectionTime()->Add(-5);
192
193 // Report and check the data
194 class TestBackend : public TestBackendBase {
195 public:
196 ~TestBackend() {
197 EXPECT_TRUE(found_counter_);
198 EXPECT_TRUE(found_histogram_);
199 }
200
201 void ReportCounter(DatumId counter_type, uint64_t value) override {
202 switch (counter_type) {
203 case DatumId::kClassVerificationTotalTime:
204 EXPECT_EQ(value, verification_time)
205 << "Unexpected value for counter " << DatumName(counter_type);
206 found_counter_ = true;
207 break;
208 case DatumId::kTimeElapsedDelta:
209 // TimeElapsedData can be greater than 0 if the test takes more than 1ms to run
210 EXPECT_GE(value, 0u) << "Unexpected value for counter " << DatumName(counter_type);
211 break;
212 default:
213 EXPECT_EQ(value, 0u) << "Unexpected value for counter " << DatumName(counter_type);
214 }
215 }
216
217 void ReportHistogram(DatumId histogram_type,
218 int64_t,
219 int64_t,
220 const std::vector<uint32_t>& buckets) override {
221 if (histogram_type == DatumId::kYoungGcCollectionTime) {
222 EXPECT_EQ(buckets[0], 1u) << "Unexpected value for bucket 0 for histogram "
223 << DatumName(histogram_type);
224 for (size_t i = 1; i < buckets.size(); ++i) {
225 EXPECT_EQ(buckets[i], 0u) << "Unexpected value for bucket " << i << " for histogram "
226 << DatumName(histogram_type);
227 }
228 found_histogram_ = true;
229 } else {
230 for (size_t i = 0; i < buckets.size(); ++i) {
231 EXPECT_EQ(buckets[i], 0u) << "Unexpected value for bucket " << i << " for histogram "
232 << DatumName(histogram_type);
233 }
234 }
235 }
236
237 private:
238 bool found_counter_{false};
239 bool found_histogram_{false};
240 } backend;
241
242 metrics.ReportAllMetricsAndResetValueMetrics({&backend});
243 }
244
TEST_F(MetricsTest,HistogramTimer)245 TEST_F(MetricsTest, HistogramTimer) {
246 MetricsHistogram<DatumId::kYoungGcCollectionTime, 1, 0, 100> test_histogram;
247 {
248 AutoTimer timer{&test_histogram};
249 // Sleep for 2µs so the counter will be greater than 0.
250 NanoSleep(2'000);
251 }
252
253 EXPECT_GT(GetBuckets(test_histogram)[0], 0u);
254 }
255
256 // Makes sure all defined metrics are included when dumping through StreamBackend.
TEST_F(MetricsTest,StreamBackendDumpAllMetrics)257 TEST_F(MetricsTest, StreamBackendDumpAllMetrics) {
258 ArtMetrics metrics;
259 StringBackend backend(std::make_unique<TextFormatter>());
260
261 metrics.ReportAllMetricsAndResetValueMetrics({&backend});
262
263 // Make sure the resulting string lists all the metrics.
264 const std::string result = backend.GetAndResetBuffer();
265 #define METRIC(name, type, ...) \
266 EXPECT_NE(result.find(DatumName(DatumId::k##name)), std::string::npos);
267 ART_METRICS(METRIC);
268 #undef METRIC
269 }
270
TEST_F(MetricsTest,ResetMetrics)271 TEST_F(MetricsTest, ResetMetrics) {
272 ArtMetrics metrics;
273
274 // Add something to each of the metrics.
275 #define METRIC(name, type, ...) metrics.name()->Add(42);
276 ART_METRICS(METRIC)
277 #undef METRIC
278
279 class NonZeroBackend : public TestBackendBase {
280 public:
281 void ReportCounter(DatumId counter_type, uint64_t value) override {
282 EXPECT_NE(value, 0u) << "Unexpected value for counter " << DatumName(counter_type);
283 }
284
285 void ReportHistogram(DatumId histogram_type,
286 [[maybe_unused]] int64_t minimum_value,
287 [[maybe_unused]] int64_t maximum_value,
288 const std::vector<uint32_t>& buckets) override {
289 bool nonzero = false;
290 for (const auto value : buckets) {
291 nonzero |= (value != 0u);
292 }
293 EXPECT_TRUE(nonzero) << "Unexpected value for histogram " << DatumName(histogram_type);
294 }
295 } non_zero_backend;
296
297 // Make sure the metrics all have a nonzero value.
298 metrics.ReportAllMetricsAndResetValueMetrics({&non_zero_backend});
299
300 // Reset the metrics and make sure they are all zero again
301 metrics.Reset();
302
303 class ZeroBackend : public TestBackendBase {
304 public:
305 void ReportCounter(DatumId counter_type, uint64_t value) override {
306 if (counter_type == DatumId::kTimeElapsedDelta) {
307 // TimeElapsedData can be greater than 0 if the test takes more than 1ms to run
308 EXPECT_GE(value, 0u) << "Unexpected value for counter " << DatumName(counter_type);
309 } else {
310 EXPECT_EQ(value, 0u) << "Unexpected value for counter " << DatumName(counter_type);
311 }
312 }
313
314 void ReportHistogram([[maybe_unused]] DatumId histogram_type,
315 [[maybe_unused]] int64_t minimum_value,
316 [[maybe_unused]] int64_t maximum_value,
317 const std::vector<uint32_t>& buckets) override {
318 for (const auto value : buckets) {
319 EXPECT_EQ(value, 0u) << "Unexpected value for histogram " << DatumName(histogram_type);
320 }
321 }
322 } zero_backend;
323
324 metrics.ReportAllMetricsAndResetValueMetrics({&zero_backend});
325 }
326
TEST_F(MetricsTest,KeepEventMetricsResetValueMetricsAfterReporting)327 TEST_F(MetricsTest, KeepEventMetricsResetValueMetricsAfterReporting) {
328 ArtMetrics metrics;
329
330 // Add something to each of the metrics.
331 #define METRIC(name, type, ...) metrics.name()->Add(42);
332 ART_METRICS(METRIC)
333 #undef METRIC
334
335 class FirstBackend : public TestBackendBase {
336 public:
337 void ReportCounter(DatumId counter_type, uint64_t value) override {
338 EXPECT_NE(value, 0u) << "Unexpected value for counter " << DatumName(counter_type);
339 }
340
341 void ReportHistogram(DatumId histogram_type,
342 [[maybe_unused]] int64_t minimum_value,
343 [[maybe_unused]] int64_t maximum_value,
344 const std::vector<uint32_t>& buckets) override {
345 EXPECT_NE(buckets[0], 0u) << "Unexpected value for bucket 0 for histogram "
346 << DatumName(histogram_type);
347 for (size_t i = 1; i < buckets.size(); i++) {
348 EXPECT_EQ(buckets[i], 0u) << "Unexpected value for bucket " << i << " for histogram "
349 << DatumName(histogram_type);
350 }
351 }
352 } first_backend;
353
354 // Make sure the metrics all have a nonzero value, and they are not reset between backends.
355 metrics.ReportAllMetricsAndResetValueMetrics({&first_backend, &first_backend});
356
357 // After reporting, the Value Metrics should have been reset.
358 class SecondBackend : public TestBackendBase {
359 public:
360 void ReportCounter(DatumId datum_id, uint64_t value) override {
361 switch (datum_id) {
362 // Value metrics - expected to have been reset
363 #define CHECK_METRIC(name, ...) case DatumId::k##name:
364 ART_VALUE_METRICS(CHECK_METRIC)
365 #undef CHECK_METRIC
366 if (datum_id == DatumId::kTimeElapsedDelta) {
367 // TimeElapsedData can be greater than 0 if the test takes more than 1ms to run
368 EXPECT_GE(value, 0u) << "Unexpected value for counter " << DatumName(datum_id);
369 } else {
370 EXPECT_EQ(value, 0u) << "Unexpected value for counter " << DatumName(datum_id);
371 }
372 return;
373
374 // Event metrics - expected to have retained their previous value
375 #define CHECK_METRIC(name, ...) case DatumId::k##name:
376 ART_EVENT_METRICS(CHECK_METRIC)
377 #undef CHECK_METRIC
378 EXPECT_NE(value, 0u) << "Unexpected value for metric " << DatumName(datum_id);
379 return;
380
381 default:
382 // unknown metric - it should not be possible to reach this path
383 FAIL();
384 UNREACHABLE();
385 }
386 }
387
388 // All histograms are event metrics.
389 void ReportHistogram([[maybe_unused]] DatumId histogram_type,
390 [[maybe_unused]] int64_t minimum_value,
391 [[maybe_unused]] int64_t maximum_value,
392 const std::vector<uint32_t>& buckets) override {
393 EXPECT_NE(buckets[0], 0u) << "Unexpected value for bucket 0 for histogram "
394 << DatumName(histogram_type);
395 for (size_t i = 1; i < buckets.size(); i++) {
396 EXPECT_EQ(buckets[i], 0u) << "Unexpected value for bucket " << i << " for histogram "
397 << DatumName(histogram_type);
398 }
399 }
400 } second_backend;
401
402 metrics.ReportAllMetricsAndResetValueMetrics({&second_backend});
403 }
404
TEST(TextFormatterTest,ReportMetrics_WithBuckets)405 TEST(TextFormatterTest, ReportMetrics_WithBuckets) {
406 TextFormatter text_formatter;
407 SessionData session_data{
408 .session_id = 1000,
409 .uid = 50,
410 .compilation_reason = CompilationReason::kInstall,
411 .compiler_filter = CompilerFilterReporting::kSpeed,
412 };
413
414 text_formatter.FormatBeginReport(200, session_data);
415 text_formatter.FormatReportCounter(DatumId::kFullGcCount, 1u);
416 text_formatter.FormatReportHistogram(DatumId::kFullGcCollectionTime, 50, 200, {2, 4, 7, 1});
417 text_formatter.FormatEndReport();
418
419 const std::string result = text_formatter.GetAndResetBuffer();
420 ASSERT_EQ(result,
421 "\n*** ART internal metrics ***\n"
422 " Metadata:\n"
423 " timestamp_since_start_ms: 200\n"
424 " session_id: 1000\n"
425 " uid: 50\n"
426 " compilation_reason: install\n"
427 " compiler_filter: speed\n"
428 " Metrics:\n"
429 " FullGcCount: count = 1\n"
430 " FullGcCollectionTime: range = 50...200, buckets: 2,4,7,1\n"
431 "*** Done dumping ART internal metrics ***\n");
432 }
433
TEST(TextFormatterTest,ReportMetrics_NoBuckets)434 TEST(TextFormatterTest, ReportMetrics_NoBuckets) {
435 TextFormatter text_formatter;
436 SessionData session_data{
437 .session_id = 500,
438 .uid = 15,
439 .compilation_reason = CompilationReason::kCmdLine,
440 .compiler_filter = CompilerFilterReporting::kExtract,
441 };
442
443 text_formatter.FormatBeginReport(400, session_data);
444 text_formatter.FormatReportHistogram(DatumId::kFullGcCollectionTime, 10, 20, {});
445 text_formatter.FormatEndReport();
446
447 std::string result = text_formatter.GetAndResetBuffer();
448 ASSERT_EQ(result,
449 "\n*** ART internal metrics ***\n"
450 " Metadata:\n"
451 " timestamp_since_start_ms: 400\n"
452 " session_id: 500\n"
453 " uid: 15\n"
454 " compilation_reason: cmdline\n"
455 " compiler_filter: extract\n"
456 " Metrics:\n"
457 " FullGcCollectionTime: range = 10...20, no buckets\n"
458 "*** Done dumping ART internal metrics ***\n");
459 }
460
TEST(TextFormatterTest,BeginReport_NoSessionData)461 TEST(TextFormatterTest, BeginReport_NoSessionData) {
462 TextFormatter text_formatter;
463 std::optional<SessionData> empty_session_data;
464
465 text_formatter.FormatBeginReport(100, empty_session_data);
466 text_formatter.FormatEndReport();
467
468 std::string result = text_formatter.GetAndResetBuffer();
469 ASSERT_EQ(result,
470 "\n*** ART internal metrics ***\n"
471 " Metadata:\n"
472 " timestamp_since_start_ms: 100\n"
473 " Metrics:\n"
474 "*** Done dumping ART internal metrics ***\n");
475 }
476
TEST(TextFormatterTest,GetAndResetBuffer_ActuallyResetsBuffer)477 TEST(TextFormatterTest, GetAndResetBuffer_ActuallyResetsBuffer) {
478 TextFormatter text_formatter;
479 std::optional<SessionData> empty_session_data;
480
481 text_formatter.FormatBeginReport(200, empty_session_data);
482 text_formatter.FormatReportCounter(DatumId::kFullGcCount, 1u);
483 text_formatter.FormatEndReport();
484
485 std::string result = text_formatter.GetAndResetBuffer();
486 ASSERT_EQ(result,
487 "\n*** ART internal metrics ***\n"
488 " Metadata:\n"
489 " timestamp_since_start_ms: 200\n"
490 " Metrics:\n"
491 " FullGcCount: count = 1\n"
492 "*** Done dumping ART internal metrics ***\n");
493
494 text_formatter.FormatBeginReport(300, empty_session_data);
495 text_formatter.FormatReportCounter(DatumId::kFullGcCount, 5u);
496 text_formatter.FormatEndReport();
497
498 result = text_formatter.GetAndResetBuffer();
499 ASSERT_EQ(result,
500 "\n*** ART internal metrics ***\n"
501 " Metadata:\n"
502 " timestamp_since_start_ms: 300\n"
503 " Metrics:\n"
504 " FullGcCount: count = 5\n"
505 "*** Done dumping ART internal metrics ***\n");
506 }
507
TEST(XmlFormatterTest,ReportMetrics_WithBuckets)508 TEST(XmlFormatterTest, ReportMetrics_WithBuckets) {
509 XmlFormatter xml_formatter;
510 SessionData session_data{
511 .session_id = 123,
512 .uid = 456,
513 .compilation_reason = CompilationReason::kFirstBoot,
514 .compiler_filter = CompilerFilterReporting::kSpace,
515 };
516
517 xml_formatter.FormatBeginReport(250, session_data);
518 xml_formatter.FormatReportCounter(DatumId::kYoungGcCount, 3u);
519 xml_formatter.FormatReportHistogram(DatumId::kYoungGcCollectionTime, 300, 600, {1, 5, 3});
520 xml_formatter.FormatEndReport();
521
522 const std::string result = xml_formatter.GetAndResetBuffer();
523 ASSERT_EQ(result,
524 "<art_runtime_metrics>"
525 "<version>1.0</version>"
526 "<metadata>"
527 "<timestamp_since_start_ms>250</timestamp_since_start_ms>"
528 "<session_id>123</session_id>"
529 "<uid>456</uid>"
530 "<compilation_reason>first-boot</compilation_reason>"
531 "<compiler_filter>space</compiler_filter>"
532 "</metadata>"
533 "<metrics>"
534 "<YoungGcCount>"
535 "<counter_type>count</counter_type>"
536 "<value>3</value>"
537 "</YoungGcCount>"
538 "<YoungGcCollectionTime>"
539 "<counter_type>histogram</counter_type>"
540 "<minimum_value>300</minimum_value>"
541 "<maximum_value>600</maximum_value>"
542 "<buckets>"
543 "<bucket>1</bucket>"
544 "<bucket>5</bucket>"
545 "<bucket>3</bucket>"
546 "</buckets>"
547 "</YoungGcCollectionTime>"
548 "</metrics>"
549 "</art_runtime_metrics>");
550 }
551
TEST(XmlFormatterTest,ReportMetrics_NoBuckets)552 TEST(XmlFormatterTest, ReportMetrics_NoBuckets) {
553 XmlFormatter xml_formatter;
554 SessionData session_data{
555 .session_id = 234,
556 .uid = 345,
557 .compilation_reason = CompilationReason::kFirstBoot,
558 .compiler_filter = CompilerFilterReporting::kSpace,
559 };
560
561 xml_formatter.FormatBeginReport(160, session_data);
562 xml_formatter.FormatReportCounter(DatumId::kYoungGcCount, 4u);
563 xml_formatter.FormatReportHistogram(DatumId::kYoungGcCollectionTime, 20, 40, {});
564 xml_formatter.FormatEndReport();
565
566 const std::string result = xml_formatter.GetAndResetBuffer();
567 ASSERT_EQ(result,
568 "<art_runtime_metrics>"
569 "<version>1.0</version>"
570 "<metadata>"
571 "<timestamp_since_start_ms>160</timestamp_since_start_ms>"
572 "<session_id>234</session_id>"
573 "<uid>345</uid>"
574 "<compilation_reason>first-boot</compilation_reason>"
575 "<compiler_filter>space</compiler_filter>"
576 "</metadata>"
577 "<metrics>"
578 "<YoungGcCount>"
579 "<counter_type>count</counter_type>"
580 "<value>4</value>"
581 "</YoungGcCount>"
582 "<YoungGcCollectionTime>"
583 "<counter_type>histogram</counter_type>"
584 "<minimum_value>20</minimum_value>"
585 "<maximum_value>40</maximum_value>"
586 "<buckets/>"
587 "</YoungGcCollectionTime>"
588 "</metrics>"
589 "</art_runtime_metrics>");
590 }
591
TEST(XmlFormatterTest,BeginReport_NoSessionData)592 TEST(XmlFormatterTest, BeginReport_NoSessionData) {
593 XmlFormatter xml_formatter;
594 std::optional<SessionData> empty_session_data;
595
596 xml_formatter.FormatBeginReport(100, empty_session_data);
597 xml_formatter.FormatReportCounter(DatumId::kYoungGcCount, 3u);
598 xml_formatter.FormatEndReport();
599
600 std::string result = xml_formatter.GetAndResetBuffer();
601 ASSERT_EQ(result,
602 "<art_runtime_metrics>"
603 "<version>1.0</version>"
604 "<metadata>"
605 "<timestamp_since_start_ms>100</timestamp_since_start_ms>"
606 "</metadata>"
607 "<metrics>"
608 "<YoungGcCount>"
609 "<counter_type>count</counter_type>"
610 "<value>3</value>"
611 "</YoungGcCount>"
612 "</metrics>"
613 "</art_runtime_metrics>");
614 }
615
TEST(XmlFormatterTest,GetAndResetBuffer_ActuallyResetsBuffer)616 TEST(XmlFormatterTest, GetAndResetBuffer_ActuallyResetsBuffer) {
617 XmlFormatter xml_formatter;
618 std::optional<SessionData> empty_session_data;
619
620 xml_formatter.FormatBeginReport(200, empty_session_data);
621 xml_formatter.FormatReportCounter(DatumId::kFullGcCount, 1u);
622 xml_formatter.FormatEndReport();
623
624 std::string result = xml_formatter.GetAndResetBuffer();
625 ASSERT_EQ(result,
626 "<art_runtime_metrics>"
627 "<version>1.0</version>"
628 "<metadata>"
629 "<timestamp_since_start_ms>200</timestamp_since_start_ms>"
630 "</metadata>"
631 "<metrics>"
632 "<FullGcCount>"
633 "<counter_type>count</counter_type>"
634 "<value>1</value>"
635 "</FullGcCount>"
636 "</metrics>"
637 "</art_runtime_metrics>");
638
639 xml_formatter.FormatBeginReport(300, empty_session_data);
640 xml_formatter.FormatReportCounter(DatumId::kFullGcCount, 5u);
641 xml_formatter.FormatEndReport();
642
643 result = xml_formatter.GetAndResetBuffer();
644 ASSERT_EQ(result,
645 "<art_runtime_metrics>"
646 "<version>1.0</version>"
647 "<metadata>"
648 "<timestamp_since_start_ms>300</timestamp_since_start_ms>"
649 "</metadata>"
650 "<metrics>"
651 "<FullGcCount>"
652 "<counter_type>count</counter_type>"
653 "<value>5</value>"
654 "</FullGcCount>"
655 "</metrics>"
656 "</art_runtime_metrics>");
657 }
658
TEST(CompilerFilterReportingTest,FromName)659 TEST(CompilerFilterReportingTest, FromName) {
660 ASSERT_EQ(CompilerFilterReportingFromName("error"), CompilerFilterReporting::kError);
661 ASSERT_EQ(CompilerFilterReportingFromName("unknown"), CompilerFilterReporting::kUnknown);
662 ASSERT_EQ(CompilerFilterReportingFromName("assume-verified"),
663 CompilerFilterReporting::kAssumeVerified);
664 ASSERT_EQ(CompilerFilterReportingFromName("extract"), CompilerFilterReporting::kExtract);
665 ASSERT_EQ(CompilerFilterReportingFromName("verify"), CompilerFilterReporting::kVerify);
666 ASSERT_EQ(CompilerFilterReportingFromName("space-profile"),
667 CompilerFilterReporting::kSpaceProfile);
668 ASSERT_EQ(CompilerFilterReportingFromName("space"), CompilerFilterReporting::kSpace);
669 ASSERT_EQ(CompilerFilterReportingFromName("speed-profile"),
670 CompilerFilterReporting::kSpeedProfile);
671 ASSERT_EQ(CompilerFilterReportingFromName("speed"), CompilerFilterReporting::kSpeed);
672 ASSERT_EQ(CompilerFilterReportingFromName("everything-profile"),
673 CompilerFilterReporting::kEverythingProfile);
674 ASSERT_EQ(CompilerFilterReportingFromName("everything"), CompilerFilterReporting::kEverything);
675 ASSERT_EQ(CompilerFilterReportingFromName("run-from-apk"), CompilerFilterReporting::kRunFromApk);
676 ASSERT_EQ(CompilerFilterReportingFromName("run-from-apk-fallback"),
677 CompilerFilterReporting::kRunFromApkFallback);
678 }
679
TEST(CompilerFilterReportingTest,Name)680 TEST(CompilerFilterReportingTest, Name) {
681 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kError), "error");
682 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kUnknown), "unknown");
683 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kAssumeVerified),
684 "assume-verified");
685 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kExtract), "extract");
686 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kVerify), "verify");
687 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpaceProfile), "space-profile");
688 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpace), "space");
689 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpeedProfile), "speed-profile");
690 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kSpeed), "speed");
691 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kEverythingProfile),
692 "everything-profile");
693 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kEverything), "everything");
694 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kRunFromApk), "run-from-apk");
695 ASSERT_EQ(CompilerFilterReportingName(CompilerFilterReporting::kRunFromApkFallback),
696 "run-from-apk-fallback");
697 }
698
TEST(CompilerReason,FromName)699 TEST(CompilerReason, FromName) {
700 ASSERT_EQ(CompilationReasonFromName("unknown"), CompilationReason::kUnknown);
701 ASSERT_EQ(CompilationReasonFromName("first-boot"), CompilationReason::kFirstBoot);
702 ASSERT_EQ(CompilationReasonFromName("boot-after-ota"), CompilationReason::kBootAfterOTA);
703 ASSERT_EQ(CompilationReasonFromName("post-boot"), CompilationReason::kPostBoot);
704 ASSERT_EQ(CompilationReasonFromName("install"), CompilationReason::kInstall);
705 ASSERT_EQ(CompilationReasonFromName("install-fast"), CompilationReason::kInstallFast);
706 ASSERT_EQ(CompilationReasonFromName("install-bulk"), CompilationReason::kInstallBulk);
707 ASSERT_EQ(CompilationReasonFromName("install-bulk-secondary"),
708 CompilationReason::kInstallBulkSecondary);
709 ASSERT_EQ(CompilationReasonFromName("install-bulk-downgraded"),
710 CompilationReason::kInstallBulkDowngraded);
711 ASSERT_EQ(CompilationReasonFromName("install-bulk-secondary-downgraded"),
712 CompilationReason::kInstallBulkSecondaryDowngraded);
713 ASSERT_EQ(CompilationReasonFromName("bg-dexopt"), CompilationReason::kBgDexopt);
714 ASSERT_EQ(CompilationReasonFromName("ab-ota"), CompilationReason::kABOTA);
715 ASSERT_EQ(CompilationReasonFromName("inactive"), CompilationReason::kInactive);
716 ASSERT_EQ(CompilationReasonFromName("shared"), CompilationReason::kShared);
717 ASSERT_EQ(CompilationReasonFromName("install-with-dex-metadata"),
718 CompilationReason::kInstallWithDexMetadata);
719 ASSERT_EQ(CompilationReasonFromName("prebuilt"), CompilationReason::kPrebuilt);
720 ASSERT_EQ(CompilationReasonFromName("cmdline"), CompilationReason::kCmdLine);
721 ASSERT_EQ(CompilationReasonFromName("error"), CompilationReason::kError);
722 ASSERT_EQ(CompilationReasonFromName("vdex"), CompilationReason::kVdex);
723 ASSERT_EQ(CompilationReasonFromName("boot-after-mainline-update"),
724 CompilationReason::kBootAfterMainlineUpdate);
725 }
726
TEST(CompilerReason,Name)727 TEST(CompilerReason, Name) {
728 ASSERT_EQ(CompilationReasonName(CompilationReason::kUnknown), "unknown");
729 ASSERT_EQ(CompilationReasonName(CompilationReason::kFirstBoot), "first-boot");
730 ASSERT_EQ(CompilationReasonName(CompilationReason::kBootAfterOTA), "boot-after-ota");
731 ASSERT_EQ(CompilationReasonName(CompilationReason::kPostBoot), "post-boot");
732 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstall), "install");
733 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallFast), "install-fast");
734 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulk), "install-bulk");
735 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkSecondary),
736 "install-bulk-secondary");
737 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkDowngraded),
738 "install-bulk-downgraded");
739 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallBulkSecondaryDowngraded),
740 "install-bulk-secondary-downgraded");
741 ASSERT_EQ(CompilationReasonName(CompilationReason::kBgDexopt), "bg-dexopt");
742 ASSERT_EQ(CompilationReasonName(CompilationReason::kABOTA), "ab-ota");
743 ASSERT_EQ(CompilationReasonName(CompilationReason::kInactive), "inactive");
744 ASSERT_EQ(CompilationReasonName(CompilationReason::kShared), "shared");
745 ASSERT_EQ(CompilationReasonName(CompilationReason::kInstallWithDexMetadata),
746 "install-with-dex-metadata");
747 ASSERT_EQ(CompilationReasonName(CompilationReason::kPrebuilt), "prebuilt");
748 ASSERT_EQ(CompilationReasonName(CompilationReason::kCmdLine), "cmdline");
749 ASSERT_EQ(CompilationReasonName(CompilationReason::kError), "error");
750 ASSERT_EQ(CompilationReasonName(CompilationReason::kVdex), "vdex");
751 ASSERT_EQ(CompilationReasonName(CompilationReason::kBootAfterMainlineUpdate),
752 "boot-after-mainline-update");
753 }
754 } // namespace metrics
755 } // namespace art
756
757 #pragma clang diagnostic pop // -Wconversion
758