181 lines · cpp
1//===- unittests/Support/DataAccessProfTest.cpp2//----------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#include "llvm/ProfileData/DataAccessProf.h"11#include "llvm/Support/raw_ostream.h"12#include "llvm/Testing/Support/SupportHelpers.h"13#include "gmock/gmock.h"14#include "gtest/gtest.h"15 16namespace llvm {17namespace memprof {18namespace {19 20using ::llvm::StringRef;21using llvm::ValueIs;22using ::testing::ElementsAre;23using ::testing::Field;24using ::testing::HasSubstr;25using ::testing::IsEmpty;26 27static std::string ErrorToString(Error E) {28 std::string ErrMsg;29 llvm::raw_string_ostream OS(ErrMsg);30 llvm::logAllUnhandledErrors(std::move(E), OS);31 return ErrMsg;32}33 34// Test the various scenarios when DataAccessProfData should return error on35// invalid input.36TEST(MemProf, DataAccessProfileError) {37 // Returns error if the input symbol name is empty.38 DataAccessProfData Data;39 EXPECT_THAT(ErrorToString(Data.setDataAccessProfile("", 100)),40 HasSubstr("Empty symbol name"));41 42 // Returns error when the same symbol gets added twice.43 ASSERT_FALSE(Data.setDataAccessProfile("foo", 100));44 EXPECT_THAT(ErrorToString(Data.setDataAccessProfile("foo", 100)),45 HasSubstr("Duplicate symbol or string literal added"));46 47 // Returns error when the same string content hash gets added twice.48 ASSERT_FALSE(Data.setDataAccessProfile((uint64_t)135246, 1000));49 EXPECT_THAT(ErrorToString(Data.setDataAccessProfile((uint64_t)135246, 1000)),50 HasSubstr("Duplicate symbol or string literal added"));51}52 53// Test the following operations on DataAccessProfData:54// - Profile record look up.55// - Serialization and de-serialization.56TEST(MemProf, DataAccessProfile) {57 using internal::DataAccessProfRecordRef;58 using internal::SourceLocationRef;59 DataAccessProfData Data;60 61 // In the bool conversion, Error is true if it's in a failure state and false62 // if it's in an accept state. Use ASSERT_FALSE or EXPECT_FALSE for no error.63 ASSERT_FALSE(Data.setDataAccessProfile("foo.llvm.123", 100));64 ASSERT_FALSE(Data.addKnownSymbolWithoutSamples((uint64_t)789));65 ASSERT_FALSE(Data.addKnownSymbolWithoutSamples("sym2"));66 ASSERT_FALSE(Data.setDataAccessProfile("bar.__uniq.321", 123,67 {68 SourceLocation{"file2", 3},69 }));70 ASSERT_FALSE(Data.addKnownSymbolWithoutSamples("sym1"));71 ASSERT_FALSE(Data.addKnownSymbolWithoutSamples((uint64_t)678));72 ASSERT_FALSE(Data.setDataAccessProfile(73 (uint64_t)135246, 1000,74 {SourceLocation{"file1", 1}, SourceLocation{"file2", 2}}));75 76 {77 // Test that symbol names and file names are stored in the input order.78 EXPECT_THAT(79 llvm::to_vector(llvm::make_first_range(Data.getStrToIndexMapRef())),80 ElementsAre("foo", "sym2", "bar.__uniq.321", "file2", "sym1", "file1"));81 EXPECT_THAT(Data.getKnownColdSymbols(), ElementsAre("sym2", "sym1"));82 EXPECT_THAT(Data.getKnownColdHashes(), ElementsAre(789, 678));83 84 // Look up profiles.85 EXPECT_TRUE(Data.isKnownColdSymbol((uint64_t)789));86 EXPECT_TRUE(Data.isKnownColdSymbol((uint64_t)678));87 EXPECT_TRUE(Data.isKnownColdSymbol("sym2"));88 EXPECT_TRUE(Data.isKnownColdSymbol("sym1"));89 90 EXPECT_EQ(Data.getProfileRecord("non-existence"), std::nullopt);91 EXPECT_EQ(Data.getProfileRecord((uint64_t)789987), std::nullopt);92 93 EXPECT_THAT(94 Data.getProfileRecord("foo.llvm.123"),95 ValueIs(96 AllOf(Field(&DataAccessProfRecord::SymHandle,97 testing::VariantWith<std::string>(testing::Eq("foo"))),98 Field(&DataAccessProfRecord::Locations, IsEmpty()))));99 EXPECT_THAT(100 Data.getProfileRecord("bar.__uniq.321"),101 ValueIs(AllOf(102 Field(&DataAccessProfRecord::SymHandle,103 testing::VariantWith<std::string>(104 testing::Eq("bar.__uniq.321"))),105 Field(&DataAccessProfRecord::Locations,106 ElementsAre(AllOf(Field(&SourceLocation::FileName, "file2"),107 Field(&SourceLocation::Line, 3)))))));108 EXPECT_THAT(109 Data.getProfileRecord((uint64_t)135246),110 ValueIs(AllOf(111 Field(&DataAccessProfRecord::SymHandle,112 testing::VariantWith<uint64_t>(testing::Eq(135246))),113 Field(&DataAccessProfRecord::Locations,114 ElementsAre(AllOf(Field(&SourceLocation::FileName, "file1"),115 Field(&SourceLocation::Line, 1)),116 AllOf(Field(&SourceLocation::FileName, "file2"),117 Field(&SourceLocation::Line, 2)))))));118 }119 120 // Tests serialization and de-serialization.121 DataAccessProfData deserializedData;122 {123 std::string serializedData;124 llvm::raw_string_ostream OS(serializedData);125 llvm::ProfOStream POS(OS);126 127 EXPECT_FALSE(Data.serialize(POS));128 129 const unsigned char *p =130 reinterpret_cast<const unsigned char *>(serializedData.data());131 ASSERT_THAT(llvm::to_vector(llvm::make_first_range(132 deserializedData.getStrToIndexMapRef())),133 IsEmpty());134 EXPECT_FALSE(deserializedData.deserialize(p));135 136 EXPECT_THAT(137 llvm::to_vector(138 llvm::make_first_range(deserializedData.getStrToIndexMapRef())),139 ElementsAre("foo", "sym2", "bar.__uniq.321", "file2", "sym1", "file1"));140 EXPECT_THAT(deserializedData.getKnownColdSymbols(),141 ElementsAre("sym2", "sym1"));142 EXPECT_THAT(deserializedData.getKnownColdHashes(), ElementsAre(789, 678));143 144 // Look up profiles after deserialization.145 EXPECT_TRUE(deserializedData.isKnownColdSymbol((uint64_t)789));146 EXPECT_TRUE(deserializedData.isKnownColdSymbol((uint64_t)678));147 EXPECT_TRUE(deserializedData.isKnownColdSymbol("sym2"));148 EXPECT_TRUE(deserializedData.isKnownColdSymbol("sym1"));149 150 auto Records =151 llvm::to_vector(llvm::make_second_range(deserializedData.getRecords()));152 153 EXPECT_THAT(154 Records,155 ElementsAre(156 AllOf(Field(&DataAccessProfRecordRef::SymbolID, 0),157 Field(&DataAccessProfRecordRef::AccessCount, 100),158 Field(&DataAccessProfRecordRef::IsStringLiteral, false),159 Field(&DataAccessProfRecordRef::Locations, IsEmpty())),160 AllOf(Field(&DataAccessProfRecordRef::SymbolID, 2),161 Field(&DataAccessProfRecordRef::AccessCount, 123),162 Field(&DataAccessProfRecordRef::IsStringLiteral, false),163 Field(&DataAccessProfRecordRef::Locations,164 ElementsAre(165 AllOf(Field(&SourceLocationRef::FileName, "file2"),166 Field(&SourceLocationRef::Line, 3))))),167 AllOf(Field(&DataAccessProfRecordRef::SymbolID, 135246),168 Field(&DataAccessProfRecordRef::AccessCount, 1000),169 Field(&DataAccessProfRecordRef::IsStringLiteral, true),170 Field(&DataAccessProfRecordRef::Locations,171 ElementsAre(172 AllOf(Field(&SourceLocationRef::FileName, "file1"),173 Field(&SourceLocationRef::Line, 1)),174 AllOf(Field(&SourceLocationRef::FileName, "file2"),175 Field(&SourceLocationRef::Line, 2)))))));176 }177}178} // namespace179} // namespace memprof180} // namespace llvm181