| // Copyright 2017 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 "components/metrics/persistent_system_profile.h" |
| |
| #include <memory> |
| |
| #include "base/logging.h" |
| #include "base/metrics/persistent_memory_allocator.h" |
| #include "base/rand_util.h" |
| #include "components/variations/hashing.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace metrics { |
| |
| class PersistentSystemProfileTest : public testing::Test { |
| public: |
| const int32_t kAllocatorMemorySize = 1 << 20; // 1 MiB |
| |
| PersistentSystemProfileTest() {} |
| ~PersistentSystemProfileTest() override {} |
| |
| void SetUp() override { |
| memory_allocator_ = std::make_unique<base::LocalPersistentMemoryAllocator>( |
| kAllocatorMemorySize, 0, ""); |
| records_ = std::make_unique<PersistentSystemProfile::RecordAllocator>( |
| memory_allocator_.get()); |
| persistent_profile_.RegisterPersistentAllocator(memory_allocator_.get()); |
| } |
| |
| void TearDown() override { |
| persistent_profile_.DeregisterPersistentAllocator(memory_allocator_.get()); |
| records_.reset(); |
| memory_allocator_.reset(); |
| } |
| |
| void WriteRecord(uint8_t type, const std::string& record) { |
| persistent_profile_.allocators_[0].Write( |
| static_cast<PersistentSystemProfile::RecordType>(type), record); |
| } |
| |
| bool ReadRecord(uint8_t* type, std::string* record) { |
| PersistentSystemProfile::RecordType rec_type; |
| |
| bool success = records_->Read(&rec_type, record); |
| *type = rec_type; // Convert to uint8_t for testing. |
| return success; |
| } |
| |
| base::PersistentMemoryAllocator* memory_allocator() { |
| return memory_allocator_.get(); |
| } |
| |
| PersistentSystemProfile* persistent_profile() { return &persistent_profile_; } |
| |
| private: |
| PersistentSystemProfile persistent_profile_; |
| std::unique_ptr<base::PersistentMemoryAllocator> memory_allocator_; |
| std::unique_ptr<PersistentSystemProfile::RecordAllocator> records_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PersistentSystemProfileTest); |
| }; |
| |
| TEST_F(PersistentSystemProfileTest, Create) { |
| uint32_t type; |
| base::PersistentMemoryAllocator::Iterator iter(memory_allocator()); |
| base::PersistentMemoryAllocator::Reference ref = iter.GetNext(&type); |
| DCHECK(ref); |
| DCHECK_NE(0U, type); |
| } |
| |
| TEST_F(PersistentSystemProfileTest, RecordSplitting) { |
| const size_t kRecordSize = 100 << 10; // 100 KiB |
| std::vector<char> buffer; |
| buffer.resize(kRecordSize); |
| base::RandBytes(&buffer[0], kRecordSize); |
| |
| WriteRecord(42, std::string(&buffer[0], kRecordSize)); |
| |
| uint8_t type; |
| std::string record; |
| ASSERT_TRUE(ReadRecord(&type, &record)); |
| EXPECT_EQ(42U, type); |
| ASSERT_EQ(kRecordSize, record.size()); |
| for (size_t i = 0; i < kRecordSize; ++i) |
| EXPECT_EQ(buffer[i], record[i]); |
| } |
| |
| TEST_F(PersistentSystemProfileTest, ProfileStorage) { |
| SystemProfileProto proto1; |
| SystemProfileProto::FieldTrial* trial = proto1.add_field_trial(); |
| trial->set_name_id(123); |
| trial->set_group_id(456); |
| |
| persistent_profile()->SetSystemProfile(proto1, false); |
| |
| SystemProfileProto proto2; |
| ASSERT_TRUE(PersistentSystemProfile::HasSystemProfile(*memory_allocator())); |
| ASSERT_TRUE( |
| PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &proto2)); |
| ASSERT_EQ(1, proto2.field_trial_size()); |
| EXPECT_EQ(123U, proto2.field_trial(0).name_id()); |
| EXPECT_EQ(456U, proto2.field_trial(0).group_id()); |
| |
| // Check that the profile can be overwritten. |
| |
| trial = proto1.add_field_trial(); |
| trial->set_name_id(78); |
| trial->set_group_id(90); |
| |
| persistent_profile()->SetSystemProfile(proto1, true); |
| |
| ASSERT_TRUE( |
| PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &proto2)); |
| ASSERT_EQ(2, proto2.field_trial_size()); |
| EXPECT_EQ(123U, proto2.field_trial(0).name_id()); |
| EXPECT_EQ(456U, proto2.field_trial(0).group_id()); |
| EXPECT_EQ(78U, proto2.field_trial(1).name_id()); |
| EXPECT_EQ(90U, proto2.field_trial(1).group_id()); |
| |
| // Check that the profile won't be overwritten by a new non-complete profile. |
| |
| trial = proto1.add_field_trial(); |
| trial->set_name_id(0xC0DE); |
| trial->set_group_id(0xFEED); |
| |
| persistent_profile()->SetSystemProfile(proto1, false); |
| |
| ASSERT_TRUE( |
| PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &proto2)); |
| ASSERT_EQ(2, proto2.field_trial_size()); |
| EXPECT_EQ(123U, proto2.field_trial(0).name_id()); |
| EXPECT_EQ(456U, proto2.field_trial(0).group_id()); |
| EXPECT_EQ(78U, proto2.field_trial(1).name_id()); |
| EXPECT_EQ(90U, proto2.field_trial(1).group_id()); |
| } |
| |
| TEST_F(PersistentSystemProfileTest, ProfileExtensions) { |
| persistent_profile()->AddFieldTrial("sna", "foo"); |
| |
| SystemProfileProto fetched; |
| ASSERT_FALSE( |
| PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched)); |
| |
| SystemProfileProto proto; |
| SystemProfileProto::FieldTrial* trial = proto.add_field_trial(); |
| trial->set_name_id(123); |
| trial->set_group_id(456); |
| |
| persistent_profile()->SetSystemProfile(proto, false); |
| ASSERT_TRUE( |
| PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched)); |
| ASSERT_EQ(2, fetched.field_trial_size()); |
| EXPECT_EQ(123U, fetched.field_trial(0).name_id()); |
| EXPECT_EQ(456U, fetched.field_trial(0).group_id()); |
| EXPECT_EQ(variations::HashName("sna"), fetched.field_trial(1).name_id()); |
| EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(1).group_id()); |
| |
| persistent_profile()->AddFieldTrial("foo", "bar"); |
| ASSERT_TRUE( |
| PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &fetched)); |
| ASSERT_EQ(3, fetched.field_trial_size()); |
| EXPECT_EQ(123U, fetched.field_trial(0).name_id()); |
| EXPECT_EQ(456U, fetched.field_trial(0).group_id()); |
| EXPECT_EQ(variations::HashName("sna"), fetched.field_trial(1).name_id()); |
| EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(1).group_id()); |
| EXPECT_EQ(variations::HashName("foo"), fetched.field_trial(2).name_id()); |
| EXPECT_EQ(variations::HashName("bar"), fetched.field_trial(2).group_id()); |
| } |
| |
| } // namespace metrics |