| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "platform/UkmTimeAggregator.h" |
| |
| #include "components/ukm/test_ukm_recorder.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace blink { |
| namespace { |
| |
| struct Timer { |
| static double GetTime() { return fake_time; } |
| static double fake_time; |
| }; |
| |
| double Timer::fake_time = 0; |
| |
| TEST(UkmTimeAggregatorTest, EmptyEventsNotRecorded) { |
| Timer::fake_time = 0; |
| auto original_time_function = SetTimeFunctionsForTesting(&Timer::GetTime); |
| |
| ukm::TestUkmRecorder recorder; |
| int64_t source_id = ukm::UkmRecorder::GetNewSourceID(); |
| std::unique_ptr<UkmTimeAggregator> aggregator( |
| new UkmTimeAggregator("event", source_id, &recorder, |
| {"metric1", "metric2"}, TimeDelta::FromSeconds(1))); |
| Timer::fake_time += 10.; |
| aggregator.reset(); |
| |
| EXPECT_EQ(recorder.sources_count(), 0u); |
| EXPECT_EQ(recorder.entries_count(), 0u); |
| SetTimeFunctionsForTesting(original_time_function); |
| } |
| |
| TEST(UkmTimeAggregatorTest, EventsRecordedPerSecond) { |
| Timer::fake_time = 0; |
| auto original_time_function = SetTimeFunctionsForTesting(&Timer::GetTime); |
| |
| ukm::TestUkmRecorder recorder; |
| int64_t source_id = ukm::UkmRecorder::GetNewSourceID(); |
| std::unique_ptr<UkmTimeAggregator> aggregator( |
| new UkmTimeAggregator("event", source_id, &recorder, |
| {"metric1", "metric2"}, TimeDelta::FromSeconds(1))); |
| // Have 100 events 99ms each; if the records are recorded once per second, we |
| // should expect 9 records to be recorded while the timer ticks. 0-1, 1-2, |
| // ..., 8-9 seconds. |
| for (int i = 0; i < 100; ++i) { |
| auto timer = aggregator->GetScopedTimer(i % 2); |
| Timer::fake_time += 0.099; |
| } |
| |
| EXPECT_EQ(recorder.entries_count(), 9u); |
| |
| // Once we reset, we record any remaining samples into one more entry, for a |
| // total of 10. |
| aggregator.reset(); |
| |
| EXPECT_EQ(recorder.entries_count(), 10u); |
| auto entries = recorder.GetEntriesByName("event"); |
| EXPECT_EQ(entries.size(), 10u); |
| |
| for (auto* entry : entries) { |
| EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "metric1.Average")); |
| const int64_t* metric1_average = |
| ukm::TestUkmRecorder::GetEntryMetric(entry, "metric1.Average"); |
| EXPECT_NEAR(*metric1_average / 1e6, 0.099, 0.0001); |
| |
| EXPECT_TRUE( |
| ukm::TestUkmRecorder::EntryHasMetric(entry, "metric1.WorstCase")); |
| const int64_t* metric1_worst = |
| ukm::TestUkmRecorder::GetEntryMetric(entry, "metric1.WorstCase"); |
| EXPECT_NEAR(*metric1_worst / 1e6, 0.099, 0.0001); |
| |
| EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "metric2.Average")); |
| const int64_t* metric2_average = |
| ukm::TestUkmRecorder::GetEntryMetric(entry, "metric2.Average"); |
| EXPECT_NEAR(*metric2_average / 1e6, 0.099, 0.0001); |
| |
| EXPECT_TRUE( |
| ukm::TestUkmRecorder::EntryHasMetric(entry, "metric2.WorstCase")); |
| const int64_t* metric2_worst = |
| ukm::TestUkmRecorder::GetEntryMetric(entry, "metric2.WorstCase"); |
| EXPECT_NEAR(*metric2_worst / 1e6, 0.099, 0.0001); |
| } |
| |
| SetTimeFunctionsForTesting(original_time_function); |
| } |
| |
| TEST(UkmTimeAggregatorTest, EventsAveragedCorrectly) { |
| Timer::fake_time = 0; |
| auto original_time_function = SetTimeFunctionsForTesting(&Timer::GetTime); |
| |
| ukm::TestUkmRecorder recorder; |
| int64_t source_id = ukm::UkmRecorder::GetNewSourceID(); |
| std::unique_ptr<UkmTimeAggregator> aggregator(new UkmTimeAggregator( |
| "event", source_id, &recorder, {"metric1", "metric2"}, |
| TimeDelta::FromSeconds(10000))); |
| // 1, 2, and 3 seconds. |
| for (int i = 1; i <= 3; ++i) { |
| auto timer = aggregator->GetScopedTimer(0); |
| Timer::fake_time += i; |
| } |
| |
| // 3, 3, 3, and then 1 outside of the loop. |
| for (int i = 0; i < 3; ++i) { |
| auto timer = aggregator->GetScopedTimer(1); |
| Timer::fake_time += 3.; |
| } |
| { |
| auto timer = aggregator->GetScopedTimer(1); |
| Timer::fake_time += 1.; |
| } |
| |
| aggregator.reset(); |
| auto entries = recorder.GetEntriesByName("event"); |
| EXPECT_EQ(entries.size(), 1u); |
| auto* entry = entries[0]; |
| |
| EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "metric1.Average")); |
| const int64_t* metric1_average = |
| ukm::TestUkmRecorder::GetEntryMetric(entry, "metric1.Average"); |
| // metric1 (1, 2, 3) average is 2 |
| EXPECT_NEAR(*metric1_average / 1e6, 2.0, 0.0001); |
| |
| EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "metric1.WorstCase")); |
| const int64_t* metric1_worst = |
| ukm::TestUkmRecorder::GetEntryMetric(entry, "metric1.WorstCase"); |
| // metric1 (1, 2, 3) worst case is 3 |
| EXPECT_NEAR(*metric1_worst / 1e6, 3.0, 0.0001); |
| |
| EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "metric2.Average")); |
| const int64_t* metric2_average = |
| ukm::TestUkmRecorder::GetEntryMetric(entry, "metric2.Average"); |
| // metric1 (3, 3, 3, 1) average is 2.5 |
| EXPECT_NEAR(*metric2_average / 1e6, 2.5, 0.0001); |
| |
| EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "metric2.WorstCase")); |
| const int64_t* metric2_worst = |
| ukm::TestUkmRecorder::GetEntryMetric(entry, "metric2.WorstCase"); |
| // metric1 (3, 3, 3, 1) worst case is 3 |
| EXPECT_NEAR(*metric2_worst / 1e6, 3.0, 0.0001); |
| |
| SetTimeFunctionsForTesting(original_time_function); |
| } |
| |
| } // namespace |
| } // namespace blink |