1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/ukm/ukm_recorder_impl.h"
8 #include "base/metrics/ukm_source_id.h"
9 #include "services/metrics/public/cpp/ukm_builders.h"
10 #include "services/metrics/public/cpp/ukm_entry_builder.h"
11 #include "services/metrics/public/cpp/ukm_source.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/metrics_proto/ukm/report.pb.h"
19 class TestUkmRecorderImpl : public UkmRecorderImpl {
21 TestUkmRecorderImpl() {}
22 ~TestUkmRecorderImpl() override {}
24 void set_sampled_in(bool sampled_in) { sampled_in_ = sampled_in; }
26 size_t sampled_callback_count() { return sampled_callback_count_; }
30 bool ShouldRestrictToWhitelistedSourceIds() const override { return false; }
31 bool ShouldRestrictToWhitelistedEntries() const override { return false; }
32 bool IsSampledIn(int sampling_rate) override {
33 ++sampled_callback_count_;
38 bool sampled_in_ = true;
39 size_t sampled_callback_count_ = 0;
41 DISALLOW_COPY_AND_ASSIGN(TestUkmRecorderImpl);
46 class UkmRecorderImplTest : public testing::Test {
48 UkmRecorderImplTest() {
49 impl_.StoreWhitelistedEntries();
50 impl_.EnableRecording(/*extensions=*/true);
53 UkmRecorderImpl& impl() { return impl_; }
55 void set_sampled_in(bool sampled_in) { impl_.set_sampled_in(sampled_in); }
57 size_t sampled_callback_count() { return impl_.sampled_callback_count(); }
59 size_t source_sampling_count() { return impl_.source_event_sampling_.size(); }
61 void RecordNavigation(SourceId source_id,
62 const UkmSource::NavigationData& nav_data) {
63 impl_.RecordNavigation(source_id, nav_data);
66 void AddEntry(mojom::UkmEntryPtr entry) { impl_.AddEntry(std::move(entry)); }
68 void StoreRecordingsInReport(Report* report) {
69 impl_.StoreRecordingsInReport(report);
73 TestUkmRecorderImpl impl_;
75 DISALLOW_COPY_AND_ASSIGN(UkmRecorderImplTest);
78 TEST_F(UkmRecorderImplTest, PageSampling) {
79 SourceId page1_source =
80 ConvertToSourceId(101, base::UkmSourceId::Type::NAVIGATION_ID);
81 UkmSource::NavigationData page1_nav;
82 page1_nav.urls.push_back(GURL("https://www.google.com/"));
84 // First event always has to do sampled in/out callback.
85 RecordNavigation(page1_source, page1_nav);
86 AddEntry(builders::PageLoad(page1_source)
87 .SetDocumentTiming_NavigationToLoadEventFired(1000)
89 EXPECT_EQ(1U, sampled_callback_count());
91 // Second event will use what was already determined.
92 AddEntry(builders::PageLoad(page1_source)
93 .SetDocumentTiming_NavigationToLoadEventFired(2000)
95 EXPECT_EQ(1U, sampled_callback_count());
97 // Different event will again do the callback.
98 AddEntry(builders::Memory_Experimental(page1_source)
99 .SetCommandBuffer(3000)
101 EXPECT_EQ(2U, sampled_callback_count());
103 SourceId page2_source =
104 ConvertToSourceId(102, base::UkmSourceId::Type::NAVIGATION_ID);
105 UkmSource::NavigationData page2_nav;
106 page2_nav.urls.push_back(GURL("https://www.example.com/"));
108 // New page will again have to do sampling.
109 RecordNavigation(page2_source, page2_nav);
110 AddEntry(builders::PageLoad(page2_source)
111 .SetDocumentTiming_NavigationToLoadEventFired(1000)
113 EXPECT_EQ(3U, sampled_callback_count());
115 // First report won't clear this information.
116 EXPECT_EQ(2U, source_sampling_count());
118 StoreRecordingsInReport(&report);
119 EXPECT_EQ(2U, source_sampling_count());
121 // Second report will clear sampling info because they weren't modified.
122 StoreRecordingsInReport(&report);
123 EXPECT_EQ(0U, source_sampling_count());