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