xref: /aosp_15_r20/external/cronet/components/metrics/persistent_system_profile_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 The Chromium Authors
2 // 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/persistent_system_profile.h"
6 
7 #include <memory>
8 
9 #include "base/check_op.h"
10 #include "base/metrics/persistent_memory_allocator.h"
11 #include "base/rand_util.h"
12 #include "components/variations/hashing.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace metrics {
16 
17 class PersistentSystemProfileTest : public testing::Test {
18  public:
19   const int32_t kAllocatorMemorySize = 1 << 20;  // 1 MiB
20 
PersistentSystemProfileTest()21   PersistentSystemProfileTest() {}
22 
23   PersistentSystemProfileTest(const PersistentSystemProfileTest&) = delete;
24   PersistentSystemProfileTest& operator=(const PersistentSystemProfileTest&) =
25       delete;
26 
~PersistentSystemProfileTest()27   ~PersistentSystemProfileTest() override {}
28 
SetUp()29   void SetUp() override {
30     memory_allocator_ = std::make_unique<base::LocalPersistentMemoryAllocator>(
31         kAllocatorMemorySize, 0, "");
32     records_ = std::make_unique<PersistentSystemProfile::RecordAllocator>(
33         memory_allocator_.get());
34     persistent_profile_.RegisterPersistentAllocator(memory_allocator_.get());
35   }
36 
TearDown()37   void TearDown() override {
38     persistent_profile_.DeregisterPersistentAllocator(memory_allocator_.get());
39     records_.reset();
40     memory_allocator_.reset();
41   }
42 
WriteRecord(uint8_t type,const std::string & record)43   void WriteRecord(uint8_t type, const std::string& record) {
44     persistent_profile_.allocators_[0].Write(
45         static_cast<PersistentSystemProfile::RecordType>(type), record);
46   }
47 
ReadRecord(uint8_t * type,std::string * record)48   bool ReadRecord(uint8_t* type, std::string* record) {
49     PersistentSystemProfile::RecordType rec_type;
50 
51     bool success = records_->Read(&rec_type, record);
52     *type = rec_type;  // Convert to uint8_t for testing.
53     return success;
54   }
55 
memory_allocator()56   base::PersistentMemoryAllocator* memory_allocator() {
57     return memory_allocator_.get();
58   }
59 
persistent_profile()60   PersistentSystemProfile* persistent_profile() { return &persistent_profile_; }
61 
62  private:
63   PersistentSystemProfile persistent_profile_;
64   std::unique_ptr<base::PersistentMemoryAllocator> memory_allocator_;
65   std::unique_ptr<PersistentSystemProfile::RecordAllocator> records_;
66 };
67 
TEST_F(PersistentSystemProfileTest,Create)68 TEST_F(PersistentSystemProfileTest, Create) {
69   uint32_t type;
70   base::PersistentMemoryAllocator::Iterator iter(memory_allocator());
71   base::PersistentMemoryAllocator::Reference ref = iter.GetNext(&type);
72   DCHECK(ref);
73   DCHECK_NE(0U, type);
74 }
75 
TEST_F(PersistentSystemProfileTest,RecordSplitting)76 TEST_F(PersistentSystemProfileTest, RecordSplitting) {
77   const size_t kRecordSize = 100 << 10;  // 100 KiB
78   std::vector<char> buffer;
79   buffer.resize(kRecordSize);
80   base::RandBytes(&buffer[0], kRecordSize);
81 
82   WriteRecord(42, std::string(&buffer[0], kRecordSize));
83 
84   uint8_t type;
85   std::string record;
86   ASSERT_TRUE(ReadRecord(&type, &record));
87   EXPECT_EQ(42U, type);
88   ASSERT_EQ(kRecordSize, record.size());
89   for (size_t i = 0; i < kRecordSize; ++i)
90     EXPECT_EQ(buffer[i], record[i]);
91 }
92 
TEST_F(PersistentSystemProfileTest,ProfileStorage)93 TEST_F(PersistentSystemProfileTest, ProfileStorage) {
94   SystemProfileProto proto1;
95   SystemProfileProto::FieldTrial* trial = proto1.add_field_trial();
96   trial->set_name_id(123);
97   trial->set_group_id(456);
98 
99   persistent_profile()->SetSystemProfile(proto1, false);
100 
101   SystemProfileProto proto2;
102   ASSERT_TRUE(PersistentSystemProfile::HasSystemProfile(*memory_allocator()));
103   ASSERT_TRUE(
104       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &proto2));
105   ASSERT_EQ(1, proto2.field_trial_size());
106   EXPECT_EQ(123U, proto2.field_trial(0).name_id());
107   EXPECT_EQ(456U, proto2.field_trial(0).group_id());
108 
109   // Check that the profile can be overwritten by another incomplete profile.
110 
111   trial = proto1.add_field_trial();
112   trial->set_name_id(34);
113   trial->set_group_id(50);
114 
115   persistent_profile()->SetSystemProfile(proto1, false);
116 
117   ASSERT_TRUE(
118       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &proto2));
119   ASSERT_EQ(2, proto2.field_trial_size());
120   EXPECT_EQ(123U, proto2.field_trial(0).name_id());
121   EXPECT_EQ(456U, proto2.field_trial(0).group_id());
122   EXPECT_EQ(34U, proto2.field_trial(1).name_id());
123   EXPECT_EQ(50U, proto2.field_trial(1).group_id());
124 
125   // Check that the profile can be overwritten by a complete profile.
126 
127   trial = proto1.add_field_trial();
128   trial->set_name_id(78);
129   trial->set_group_id(90);
130 
131   persistent_profile()->SetSystemProfile(proto1, true);
132 
133   ASSERT_TRUE(
134       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &proto2));
135   ASSERT_EQ(3, proto2.field_trial_size());
136   EXPECT_EQ(123U, proto2.field_trial(0).name_id());
137   EXPECT_EQ(456U, proto2.field_trial(0).group_id());
138   EXPECT_EQ(34U, proto2.field_trial(1).name_id());
139   EXPECT_EQ(50U, proto2.field_trial(1).group_id());
140   EXPECT_EQ(78U, proto2.field_trial(2).name_id());
141   EXPECT_EQ(90U, proto2.field_trial(2).group_id());
142 
143   // Check that the profile won't be overwritten by a new non-complete profile.
144 
145   trial = proto1.add_field_trial();
146   trial->set_name_id(0xC0DE);
147   trial->set_group_id(0xFEED);
148 
149   persistent_profile()->SetSystemProfile(proto1, false);
150 
151   ASSERT_TRUE(
152       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &proto2));
153   ASSERT_EQ(3, proto2.field_trial_size());
154   EXPECT_EQ(123U, proto2.field_trial(0).name_id());
155   EXPECT_EQ(456U, proto2.field_trial(0).group_id());
156   EXPECT_EQ(34U, proto2.field_trial(1).name_id());
157   EXPECT_EQ(50U, proto2.field_trial(1).group_id());
158   EXPECT_EQ(78U, proto2.field_trial(2).name_id());
159   EXPECT_EQ(90U, proto2.field_trial(2).group_id());
160 }
161 
TEST_F(PersistentSystemProfileTest,ProfileExtensions)162 TEST_F(PersistentSystemProfileTest, ProfileExtensions) {
163   persistent_profile()->AddFieldTrial("sna", "foo");
164 
165   SystemProfileProto fetched;
166   ASSERT_FALSE(
167       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched));
168 
169   SystemProfileProto proto;
170   SystemProfileProto::FieldTrial* trial = proto.add_field_trial();
171   trial->set_name_id(123);
172   trial->set_group_id(456);
173 
174   // The system profile should now start fresh. In practice, field trials should
175   // already be properly updated in subsequent system profiles.
176   persistent_profile()->SetSystemProfile(proto, false);
177   ASSERT_TRUE(
178       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched));
179   ASSERT_EQ(1, fetched.field_trial_size());
180   EXPECT_EQ(123U, fetched.field_trial(0).name_id());
181   EXPECT_EQ(456U, fetched.field_trial(0).group_id());
182 
183   persistent_profile()->AddFieldTrial("foo", "bar");
184   ASSERT_TRUE(
185       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched));
186   ASSERT_EQ(2, fetched.field_trial_size());
187   EXPECT_EQ(123U, fetched.field_trial(0).name_id());
188   EXPECT_EQ(456U, fetched.field_trial(0).group_id());
189   EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(1).name_id());
190   EXPECT_EQ(variations::HashName("bar"), fetched.field_trial(1).group_id());
191 }
192 
TEST_F(PersistentSystemProfileTest,OverwriteFieldTrialsInProfile)193 TEST_F(PersistentSystemProfileTest, OverwriteFieldTrialsInProfile) {
194   // Set system profile with the field trial.
195   SystemProfileProto proto;
196   SystemProfileProto::FieldTrial* trial = proto.add_field_trial();
197   trial->set_name_id(variations::HashName("foo"));
198   trial->set_group_id(456);
199   persistent_profile()->SetSystemProfile(proto, false);
200 
201   // Overwrite the same trial with different group.
202   persistent_profile()->AddFieldTrial("foo", "bar");
203 
204   // The fetched profile should have the latest group name,
205   SystemProfileProto fetched;
206   ASSERT_TRUE(
207       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched));
208   ASSERT_EQ(1, fetched.field_trial_size());
209   EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(0).name_id());
210   EXPECT_EQ(variations::HashName("bar"), fetched.field_trial(0).group_id());
211 }
212 
TEST_F(PersistentSystemProfileTest,OverwriteFieldTrials)213 TEST_F(PersistentSystemProfileTest, OverwriteFieldTrials) {
214   // Set up a non-empty system profile.
215   SystemProfileProto proto;
216   proto.set_client_uuid("id");
217   persistent_profile()->SetSystemProfile(proto, false);
218 
219   // Set and overwrite the same trial with different group.
220   persistent_profile()->AddFieldTrial("foo", "bar");
221   persistent_profile()->AddFieldTrial("foo", "bar2");
222 
223   // The fetched profile should have the latest group name,
224   SystemProfileProto fetched;
225   ASSERT_TRUE(
226       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched));
227   ASSERT_EQ(1, fetched.field_trial_size());
228   EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(0).name_id());
229   EXPECT_EQ(variations::HashName("bar2"), fetched.field_trial(0).group_id());
230 }
231 
TEST_F(PersistentSystemProfileTest,DeleteFieldTrials)232 TEST_F(PersistentSystemProfileTest, DeleteFieldTrials) {
233   // Set up a non-empty system profile.
234   SystemProfileProto proto;
235   proto.set_client_uuid("id");
236   persistent_profile()->SetSystemProfile(proto, false);
237 
238   // Set and delete the trial.
239   persistent_profile()->AddFieldTrial("foo", "bar");
240   persistent_profile()->RemoveFieldTrial("foo");
241 
242   // The fetched profile should not have the deleted trial.
243   SystemProfileProto fetched;
244   ASSERT_TRUE(
245       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched));
246   ASSERT_EQ(0, fetched.field_trial_size());
247 
248   // Reset the trial and the fetched profile should have the latest group name.
249   persistent_profile()->AddFieldTrial("foo", "bar2");
250   ASSERT_TRUE(
251       PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched));
252   ASSERT_EQ(1, fetched.field_trial_size());
253   EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(0).name_id());
254   EXPECT_EQ(variations::HashName("bar2"), fetched.field_trial(0).group_id());
255 }
256 
257 }  // namespace metrics
258