blob: cf98c3d0e5587c0073ffd911503da58b351fa64b [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
Luc Nguyend28c2022022-05-12 18:58:577#include "base/metrics/field_trial.h"
Kevin McNee5e754b12021-08-18 21:59:308#include "base/threading/platform_thread.h"
Steven Holte5c6dd632017-07-19 23:25:499#include "components/variations/active_field_trials.h"
10#include "components/variations/synthetic_trial_registry.h"
Luc Nguyen69147e02022-01-24 20:32:1011#include "components/variations/synthetic_trials.h"
Steven Holte5c6dd632017-07-19 23:25:4912#include "testing/gtest/include/gtest/gtest.h"
Steven Holtef9d5ed62017-10-21 02:02:3013#include "third_party/metrics_proto/system_profile.pb.h"
Steven Holte5c6dd632017-07-19 23:25:4914
Luc Nguyend28c2022022-05-12 18:58:5715using ActiveGroup = base::FieldTrial::ActiveGroup;
16
Steven Holte5c6dd632017-07-19 23:25:4917namespace variations {
18
19namespace {
20
Luc Nguyend28c2022022-05-12 18:58:5721constexpr const char* kSuffix = "UKM";
22
23const ActiveGroup kFieldTrials[] = {{"Trial1", "Group1"},
24 {"Trial2", "Group2"},
25 {"Trial3", "Group3"}};
26const ActiveGroup kSyntheticFieldTrials[] = {{"Synthetic1", "SyntheticGroup1"},
27 {"Synthetic2", "SyntheticGroup2"}};
28
29ActiveGroupId ToActiveGroupId(ActiveGroup active_group,
30 std::string suffix = "");
31
32const ActiveGroupId kFieldTrialIds[] = {ToActiveGroupId(kFieldTrials[0]),
33 ToActiveGroupId(kFieldTrials[1]),
34 ToActiveGroupId(kFieldTrials[2])};
Luc Nguyen75a8bb2ee2022-05-04 20:53:5535const ActiveGroupId kAllTrialIds[] = {
Luc Nguyend28c2022022-05-12 18:58:5736 ToActiveGroupId(kFieldTrials[0]), ToActiveGroupId(kFieldTrials[1]),
37 ToActiveGroupId(kFieldTrials[2]), ToActiveGroupId(kSyntheticFieldTrials[0]),
38 ToActiveGroupId(kSyntheticFieldTrials[1])};
39const ActiveGroupId kAllTrialIdsWithSuffixes[] = {
40 ToActiveGroupId(kFieldTrials[0], kSuffix),
41 ToActiveGroupId(kFieldTrials[1], kSuffix),
42 ToActiveGroupId(kFieldTrials[2], kSuffix),
43 ToActiveGroupId(kSyntheticFieldTrials[0], kSuffix),
44 ToActiveGroupId(kSyntheticFieldTrials[1], kSuffix)};
Steven Holte5c6dd632017-07-19 23:25:4945
Caitlin Fischerd0cd0b92020-06-03 12:10:4846// Check that the field trials in |system_profile| correspond to |expected|.
Xi Han095f39342019-08-08 20:00:5447void CheckFieldTrialsInSystemProfile(
Caitlin Fischerd0cd0b92020-06-03 12:10:4848 const metrics::SystemProfileProto& system_profile,
49 const ActiveGroupId* expected) {
50 for (int i = 0; i < system_profile.field_trial_size(); ++i) {
Steven Holte5c6dd632017-07-19 23:25:4951 const metrics::SystemProfileProto::FieldTrial& field_trial =
52 system_profile.field_trial(i);
Caitlin Fischerd0cd0b92020-06-03 12:10:4853 EXPECT_EQ(expected[i].name, field_trial.name_id());
54 EXPECT_EQ(expected[i].group, field_trial.group_id());
Steven Holte5c6dd632017-07-19 23:25:4955 }
56}
57
Luc Nguyend28c2022022-05-12 18:58:5758ActiveGroupId ToActiveGroupId(ActiveGroup active_group, std::string suffix) {
59 return MakeActiveGroupId(active_group.trial_name + suffix,
60 active_group.group_name + suffix);
61}
62
Steven Holte5c6dd632017-07-19 23:25:4963} // namespace
64
65class FieldTrialsProviderTest : public ::testing::Test {
66 public:
Luc Nguyend28c2022022-05-12 18:58:5767 FieldTrialsProviderTest() = default;
68 ~FieldTrialsProviderTest() override = default;
Steven Holte5c6dd632017-07-19 23:25:4969
70 protected:
Luc Nguyend28c2022022-05-12 18:58:5771 void SetUp() override {
72 // Register the field trials.
73 for (const ActiveGroup& trial : kFieldTrials) {
74 base::FieldTrial* field_trial = base::FieldTrialList::CreateFieldTrial(
75 trial.trial_name, trial.group_name);
Steven Holtef1551602022-09-03 06:38:3876 // Call Activate() to finalize and mark the field trial as active.
77 field_trial->Activate();
Luc Nguyend28c2022022-05-12 18:58:5778 }
79 }
80
Steven Holte5c6dd632017-07-19 23:25:4981 // Register trials which should get recorded.
82 void RegisterExpectedSyntheticTrials() {
Luc Nguyend28c2022022-05-12 18:58:5783 for (const ActiveGroup& trial : kSyntheticFieldTrials) {
84 registry_.RegisterSyntheticFieldTrial(SyntheticTrialGroup(
85 trial.trial_name, trial.group_name,
86 /*annotation_mode=*/
87 variations::SyntheticTrialAnnotationMode::kNextLog));
Steven Holte5c6dd632017-07-19 23:25:4988 }
89 }
90 // Register trial which shouldn't get recorded.
91 void RegisterExtraSyntheticTrial() {
Luc Nguyen69147e02022-01-24 20:32:1092 registry_.RegisterSyntheticFieldTrial(SyntheticTrialGroup(
Luc Nguyen75a8bb2ee2022-05-04 20:53:5593 "ExtraSynthetic", "ExtraGroup",
Luc Nguyend28c2022022-05-12 18:58:5794 /*annotation_mode=*/
Luc Nguyen75a8bb2ee2022-05-04 20:53:5595 variations::SyntheticTrialAnnotationMode::kNextLog));
Steven Holte5c6dd632017-07-19 23:25:4996 }
97
98 // Waits until base::TimeTicks::Now() no longer equals |value|. This should
99 // take between 1-15ms per the documented resolution of base::TimeTicks.
100 void WaitUntilTimeChanges(const base::TimeTicks& value) {
101 while (base::TimeTicks::Now() == value) {
Peter Kastinge5a38ed2021-10-02 03:06:35102 base::PlatformThread::Sleep(base::Milliseconds(1));
Steven Holte5c6dd632017-07-19 23:25:49103 }
104 }
105
106 SyntheticTrialRegistry registry_;
107};
108
109TEST_F(FieldTrialsProviderTest, ProvideSyntheticTrials) {
Luc Nguyend28c2022022-05-12 18:58:57110 FieldTrialsProvider provider(&registry_, base::StringPiece());
Steven Holte5c6dd632017-07-19 23:25:49111
112 RegisterExpectedSyntheticTrials();
113 // Make sure these trials are older than the log.
114 WaitUntilTimeChanges(base::TimeTicks::Now());
115
Alexei Svitkine70c95022019-08-21 18:13:24116 // Get the current time and wait for it to change.
117 base::TimeTicks log_creation_time = base::TimeTicks::Now();
118
Steven Holte5c6dd632017-07-19 23:25:49119 // Make sure that the log is older than the trials that should be excluded.
Alexei Svitkine70c95022019-08-21 18:13:24120 WaitUntilTimeChanges(log_creation_time);
Steven Holte5c6dd632017-07-19 23:25:49121
122 RegisterExtraSyntheticTrial();
123
124 metrics::SystemProfileProto proto;
Alexei Svitkine70c95022019-08-21 18:13:24125 provider.ProvideSystemProfileMetricsWithLogCreationTime(log_creation_time,
126 &proto);
Xi Han095f39342019-08-08 20:00:54127
Daniel Cheng7b7aaecc2022-02-26 17:57:25128 EXPECT_EQ(std::size(kAllTrialIds),
Xi Han095f39342019-08-08 20:00:54129 static_cast<size_t>(proto.field_trial_size()));
Caitlin Fischerd0cd0b92020-06-03 12:10:48130 CheckFieldTrialsInSystemProfile(proto, kAllTrialIds);
Xi Han095f39342019-08-08 20:00:54131}
132
133TEST_F(FieldTrialsProviderTest, NoSyntheticTrials) {
Luc Nguyend28c2022022-05-12 18:58:57134 FieldTrialsProvider provider(nullptr, base::StringPiece());
Xi Han095f39342019-08-08 20:00:54135
136 metrics::SystemProfileProto proto;
Alexei Svitkine70c95022019-08-21 18:13:24137 provider.ProvideSystemProfileMetricsWithLogCreationTime(base::TimeTicks(),
138 &proto);
Xi Han095f39342019-08-08 20:00:54139
Daniel Cheng7b7aaecc2022-02-26 17:57:25140 EXPECT_EQ(std::size(kFieldTrialIds),
Xi Han095f39342019-08-08 20:00:54141 static_cast<size_t>(proto.field_trial_size()));
Caitlin Fischerd0cd0b92020-06-03 12:10:48142 CheckFieldTrialsInSystemProfile(proto, kFieldTrialIds);
143}
144
145TEST_F(FieldTrialsProviderTest, ProvideCurrentSessionData) {
146 metrics::ChromeUserMetricsExtension uma_log;
147 uma_log.system_profile();
148
149 // {1, 1} should not be in the resulting proto as ProvideCurrentSessionData()
150 // clears existing trials and sets the trials to be those determined by
151 // GetSyntheticFieldTrialsOlderThan() and GetFieldTrialIds().
152 metrics::SystemProfileProto::FieldTrial* trial =
153 uma_log.mutable_system_profile()->add_field_trial();
154 trial->set_name_id(1);
155 trial->set_group_id(1);
156
Luc Nguyend28c2022022-05-12 18:58:57157 FieldTrialsProvider provider(&registry_, base::StringPiece());
Caitlin Fischerd0cd0b92020-06-03 12:10:48158 RegisterExpectedSyntheticTrials();
159 WaitUntilTimeChanges(base::TimeTicks::Now());
160 provider.SetLogCreationTimeForTesting(base::TimeTicks::Now());
161
162 provider.ProvideCurrentSessionData(&uma_log);
163
Daniel Cheng7b7aaecc2022-02-26 17:57:25164 EXPECT_EQ(std::size(kAllTrialIds),
Caitlin Fischerd0cd0b92020-06-03 12:10:48165 static_cast<size_t>(uma_log.system_profile().field_trial_size()));
166 CheckFieldTrialsInSystemProfile(uma_log.system_profile(), kAllTrialIds);
Steven Holte5c6dd632017-07-19 23:25:49167}
168
Luc Nguyend28c2022022-05-12 18:58:57169TEST_F(FieldTrialsProviderTest, GetAndWriteFieldTrialsWithSuffixes) {
170 metrics::ChromeUserMetricsExtension uma_log;
171 uma_log.system_profile();
172
173 FieldTrialsProvider provider(&registry_, kSuffix);
174 RegisterExpectedSyntheticTrials();
175 WaitUntilTimeChanges(base::TimeTicks::Now());
176 provider.SetLogCreationTimeForTesting(base::TimeTicks::Now());
177
178 provider.ProvideCurrentSessionData(&uma_log);
179
180 EXPECT_EQ(std::size(kAllTrialIdsWithSuffixes),
181 static_cast<size_t>(uma_log.system_profile().field_trial_size()));
182 CheckFieldTrialsInSystemProfile(uma_log.system_profile(),
183 kAllTrialIdsWithSuffixes);
184}
185
Steven Holte5c6dd632017-07-19 23:25:49186} // namespace variations