blob: 7ddf2f59e26cb3d2593e9c6daac6cfe1ce26db10 [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2017 The Chromium Authors
Steven Holte5c6dd632017-07-19 23:25:492// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/metrics/field_trials_provider.h"
6
Arthur Sonzognib7c1fd512024-12-10 09:58:597#include <array>
Helmut Januschkaff1c3ec2024-04-25 19:38:328#include <string_view>
9
Arthur Sonzogni3250cb12024-12-10 16:04:0310#include "base/containers/span.h"
Luc Nguyend28c2022022-05-12 18:58:5711#include "base/metrics/field_trial.h"
Takashi Sakamotoba225e72023-03-16 14:09:0912#include "base/test/scoped_feature_list.h"
Kevin McNee5e754b12021-08-18 21:59:3013#include "base/threading/platform_thread.h"
Steven Holte5c6dd632017-07-19 23:25:4914#include "components/variations/active_field_trials.h"
15#include "components/variations/synthetic_trial_registry.h"
Luc Nguyen69147e02022-01-24 20:32:1016#include "components/variations/synthetic_trials.h"
Steven Holte5c6dd632017-07-19 23:25:4917#include "testing/gtest/include/gtest/gtest.h"
Steven Holtef9d5ed62017-10-21 02:02:3018#include "third_party/metrics_proto/system_profile.pb.h"
Steven Holte5c6dd632017-07-19 23:25:4919
Luc Nguyend28c2022022-05-12 18:58:5720using ActiveGroup = base::FieldTrial::ActiveGroup;
21
Steven Holte5c6dd632017-07-19 23:25:4922namespace variations {
23
24namespace {
25
Luc Nguyend28c2022022-05-12 18:58:5726constexpr const char* kSuffix = "UKM";
27
Arthur Sonzognib7c1fd512024-12-10 09:58:5928const auto kFieldTrials = std::to_array<ActiveGroup>({
29 {"Trial1", "Group1"},
30 {"Trial2", "Group2"},
31 {"Trial3", "Group3"},
32});
Arthur Sonzogni3250cb12024-12-10 16:04:0333const auto kSyntheticFieldTrials = std::to_array<ActiveGroup>({
34 {"Synthetic1", "SyntheticGroup1"},
35 {"Synthetic2", "SyntheticGroup2"},
36});
Luc Nguyend28c2022022-05-12 18:58:5737
38ActiveGroupId ToActiveGroupId(ActiveGroup active_group,
39 std::string suffix = "");
40
Arthur Sonzogni3250cb12024-12-10 16:04:0341const auto kFieldTrialIds = std::to_array<ActiveGroupId>({
42 ToActiveGroupId(kFieldTrials[0]),
43 ToActiveGroupId(kFieldTrials[1]),
44 ToActiveGroupId(kFieldTrials[2]),
45});
46const auto kAllTrialIds = std::to_array<ActiveGroupId>({
47 ToActiveGroupId(kFieldTrials[0]),
48 ToActiveGroupId(kFieldTrials[1]),
49 ToActiveGroupId(kFieldTrials[2]),
50 ToActiveGroupId(kSyntheticFieldTrials[0]),
51 ToActiveGroupId(kSyntheticFieldTrials[1]),
52});
53const auto kAllTrialIdsWithSuffixes = std::to_array<ActiveGroupId>({
Luc Nguyend28c2022022-05-12 18:58:5754 ToActiveGroupId(kFieldTrials[0], kSuffix),
55 ToActiveGroupId(kFieldTrials[1], kSuffix),
56 ToActiveGroupId(kFieldTrials[2], kSuffix),
57 ToActiveGroupId(kSyntheticFieldTrials[0], kSuffix),
Arthur Sonzogni3250cb12024-12-10 16:04:0358 ToActiveGroupId(kSyntheticFieldTrials[1], kSuffix),
59});
Steven Holte5c6dd632017-07-19 23:25:4960
Caitlin Fischerd0cd0b92020-06-03 12:10:4861// Check that the field trials in |system_profile| correspond to |expected|.
Xi Han095f39342019-08-08 20:00:5462void CheckFieldTrialsInSystemProfile(
Caitlin Fischerd0cd0b92020-06-03 12:10:4863 const metrics::SystemProfileProto& system_profile,
Arthur Sonzogni3250cb12024-12-10 16:04:0364 base::span<const ActiveGroupId> expected) {
Caitlin Fischerd0cd0b92020-06-03 12:10:4865 for (int i = 0; i < system_profile.field_trial_size(); ++i) {
Steven Holte5c6dd632017-07-19 23:25:4966 const metrics::SystemProfileProto::FieldTrial& field_trial =
67 system_profile.field_trial(i);
Caitlin Fischerd0cd0b92020-06-03 12:10:4868 EXPECT_EQ(expected[i].name, field_trial.name_id());
69 EXPECT_EQ(expected[i].group, field_trial.group_id());
Steven Holte5c6dd632017-07-19 23:25:4970 }
71}
72
Luc Nguyend28c2022022-05-12 18:58:5773ActiveGroupId ToActiveGroupId(ActiveGroup active_group, std::string suffix) {
74 return MakeActiveGroupId(active_group.trial_name + suffix,
75 active_group.group_name + suffix);
76}
77
Steven Holte5c6dd632017-07-19 23:25:4978} // namespace
79
80class FieldTrialsProviderTest : public ::testing::Test {
81 public:
Takashi Sakamotoba225e72023-03-16 14:09:0982 FieldTrialsProviderTest() { scope_.InitWithEmptyFeatureAndFieldTrialLists(); }
83
Luc Nguyend28c2022022-05-12 18:58:5784 ~FieldTrialsProviderTest() override = default;
Steven Holte5c6dd632017-07-19 23:25:4985
86 protected:
Luc Nguyend28c2022022-05-12 18:58:5787 void SetUp() override {
88 // Register the field trials.
89 for (const ActiveGroup& trial : kFieldTrials) {
90 base::FieldTrial* field_trial = base::FieldTrialList::CreateFieldTrial(
91 trial.trial_name, trial.group_name);
Steven Holtef1551602022-09-03 06:38:3892 // Call Activate() to finalize and mark the field trial as active.
93 field_trial->Activate();
Luc Nguyend28c2022022-05-12 18:58:5794 }
95 }
96
Steven Holte5c6dd632017-07-19 23:25:4997 // Register trials which should get recorded.
98 void RegisterExpectedSyntheticTrials() {
Luc Nguyend28c2022022-05-12 18:58:5799 for (const ActiveGroup& trial : kSyntheticFieldTrials) {
100 registry_.RegisterSyntheticFieldTrial(SyntheticTrialGroup(
101 trial.trial_name, trial.group_name,
102 /*annotation_mode=*/
103 variations::SyntheticTrialAnnotationMode::kNextLog));
Steven Holte5c6dd632017-07-19 23:25:49104 }
105 }
106 // Register trial which shouldn't get recorded.
107 void RegisterExtraSyntheticTrial() {
Luc Nguyen69147e02022-01-24 20:32:10108 registry_.RegisterSyntheticFieldTrial(SyntheticTrialGroup(
Luc Nguyen75a8bb2ee2022-05-04 20:53:55109 "ExtraSynthetic", "ExtraGroup",
Luc Nguyend28c2022022-05-12 18:58:57110 /*annotation_mode=*/
Luc Nguyen75a8bb2ee2022-05-04 20:53:55111 variations::SyntheticTrialAnnotationMode::kNextLog));
Steven Holte5c6dd632017-07-19 23:25:49112 }
113
114 // Waits until base::TimeTicks::Now() no longer equals |value|. This should
115 // take between 1-15ms per the documented resolution of base::TimeTicks.
116 void WaitUntilTimeChanges(const base::TimeTicks& value) {
117 while (base::TimeTicks::Now() == value) {
Peter Kastinge5a38ed2021-10-02 03:06:35118 base::PlatformThread::Sleep(base::Milliseconds(1));
Steven Holte5c6dd632017-07-19 23:25:49119 }
120 }
121
122 SyntheticTrialRegistry registry_;
Takashi Sakamotoba225e72023-03-16 14:09:09123 base::test::ScopedFeatureList scope_;
Steven Holte5c6dd632017-07-19 23:25:49124};
125
126TEST_F(FieldTrialsProviderTest, ProvideSyntheticTrials) {
Helmut Januschkaff1c3ec2024-04-25 19:38:32127 FieldTrialsProvider provider(&registry_, std::string_view());
Steven Holte5c6dd632017-07-19 23:25:49128
129 RegisterExpectedSyntheticTrials();
130 // Make sure these trials are older than the log.
131 WaitUntilTimeChanges(base::TimeTicks::Now());
132
Alexei Svitkine70c95022019-08-21 18:13:24133 // Get the current time and wait for it to change.
134 base::TimeTicks log_creation_time = base::TimeTicks::Now();
135
Steven Holte5c6dd632017-07-19 23:25:49136 // Make sure that the log is older than the trials that should be excluded.
Alexei Svitkine70c95022019-08-21 18:13:24137 WaitUntilTimeChanges(log_creation_time);
Steven Holte5c6dd632017-07-19 23:25:49138
139 RegisterExtraSyntheticTrial();
140
141 metrics::SystemProfileProto proto;
Alexei Svitkine70c95022019-08-21 18:13:24142 provider.ProvideSystemProfileMetricsWithLogCreationTime(log_creation_time,
143 &proto);
Xi Han095f39342019-08-08 20:00:54144
Daniel Cheng7b7aaecc2022-02-26 17:57:25145 EXPECT_EQ(std::size(kAllTrialIds),
Xi Han095f39342019-08-08 20:00:54146 static_cast<size_t>(proto.field_trial_size()));
Caitlin Fischerd0cd0b92020-06-03 12:10:48147 CheckFieldTrialsInSystemProfile(proto, kAllTrialIds);
Xi Han095f39342019-08-08 20:00:54148}
149
150TEST_F(FieldTrialsProviderTest, NoSyntheticTrials) {
Helmut Januschkaff1c3ec2024-04-25 19:38:32151 FieldTrialsProvider provider(nullptr, std::string_view());
Xi Han095f39342019-08-08 20:00:54152
153 metrics::SystemProfileProto proto;
Alexei Svitkine70c95022019-08-21 18:13:24154 provider.ProvideSystemProfileMetricsWithLogCreationTime(base::TimeTicks(),
155 &proto);
Xi Han095f39342019-08-08 20:00:54156
Daniel Cheng7b7aaecc2022-02-26 17:57:25157 EXPECT_EQ(std::size(kFieldTrialIds),
Xi Han095f39342019-08-08 20:00:54158 static_cast<size_t>(proto.field_trial_size()));
Caitlin Fischerd0cd0b92020-06-03 12:10:48159 CheckFieldTrialsInSystemProfile(proto, kFieldTrialIds);
160}
161
162TEST_F(FieldTrialsProviderTest, ProvideCurrentSessionData) {
163 metrics::ChromeUserMetricsExtension uma_log;
164 uma_log.system_profile();
165
166 // {1, 1} should not be in the resulting proto as ProvideCurrentSessionData()
167 // clears existing trials and sets the trials to be those determined by
168 // GetSyntheticFieldTrialsOlderThan() and GetFieldTrialIds().
169 metrics::SystemProfileProto::FieldTrial* trial =
170 uma_log.mutable_system_profile()->add_field_trial();
171 trial->set_name_id(1);
172 trial->set_group_id(1);
173
Helmut Januschkaff1c3ec2024-04-25 19:38:32174 FieldTrialsProvider provider(&registry_, std::string_view());
Caitlin Fischerd0cd0b92020-06-03 12:10:48175 RegisterExpectedSyntheticTrials();
176 WaitUntilTimeChanges(base::TimeTicks::Now());
177 provider.SetLogCreationTimeForTesting(base::TimeTicks::Now());
178
179 provider.ProvideCurrentSessionData(&uma_log);
180
Daniel Cheng7b7aaecc2022-02-26 17:57:25181 EXPECT_EQ(std::size(kAllTrialIds),
Caitlin Fischerd0cd0b92020-06-03 12:10:48182 static_cast<size_t>(uma_log.system_profile().field_trial_size()));
183 CheckFieldTrialsInSystemProfile(uma_log.system_profile(), kAllTrialIds);
Steven Holte5c6dd632017-07-19 23:25:49184}
185
Luc Nguyend28c2022022-05-12 18:58:57186TEST_F(FieldTrialsProviderTest, GetAndWriteFieldTrialsWithSuffixes) {
187 metrics::ChromeUserMetricsExtension uma_log;
188 uma_log.system_profile();
189
190 FieldTrialsProvider provider(&registry_, kSuffix);
191 RegisterExpectedSyntheticTrials();
192 WaitUntilTimeChanges(base::TimeTicks::Now());
193 provider.SetLogCreationTimeForTesting(base::TimeTicks::Now());
194
195 provider.ProvideCurrentSessionData(&uma_log);
196
197 EXPECT_EQ(std::size(kAllTrialIdsWithSuffixes),
198 static_cast<size_t>(uma_log.system_profile().field_trial_size()));
199 CheckFieldTrialsInSystemProfile(uma_log.system_profile(),
200 kAllTrialIdsWithSuffixes);
201}
202
Steven Holte5c6dd632017-07-19 23:25:49203} // namespace variations