1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #include "BranchListFile.h"
20*288bf522SAndroid Build Coastguard Worker #include "get_test_data.h"
21*288bf522SAndroid Build Coastguard Worker
22*288bf522SAndroid Build Coastguard Worker using namespace simpleperf;
23*288bf522SAndroid Build Coastguard Worker
24*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST(BranchListFile,etm_branch_to_proto_string)25*288bf522SAndroid Build Coastguard Worker TEST(BranchListFile, etm_branch_to_proto_string) {
26*288bf522SAndroid Build Coastguard Worker std::vector<bool> branch;
27*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < 100; i++) {
28*288bf522SAndroid Build Coastguard Worker branch.push_back(i % 2 == 0);
29*288bf522SAndroid Build Coastguard Worker std::string s = ETMBranchToProtoString(branch);
30*288bf522SAndroid Build Coastguard Worker for (size_t j = 0; j <= i; j++) {
31*288bf522SAndroid Build Coastguard Worker bool b = s[j >> 3] & (1 << (j & 7));
32*288bf522SAndroid Build Coastguard Worker ASSERT_EQ(b, branch[j]);
33*288bf522SAndroid Build Coastguard Worker }
34*288bf522SAndroid Build Coastguard Worker std::vector<bool> branch2 = ProtoStringToETMBranch(s, branch.size());
35*288bf522SAndroid Build Coastguard Worker ASSERT_EQ(branch, branch2);
36*288bf522SAndroid Build Coastguard Worker }
37*288bf522SAndroid Build Coastguard Worker }
38*288bf522SAndroid Build Coastguard Worker
IsETMDataEqual(ETMBinaryMap & data1,ETMBinaryMap & data2)39*288bf522SAndroid Build Coastguard Worker static bool IsETMDataEqual(ETMBinaryMap& data1, ETMBinaryMap& data2) {
40*288bf522SAndroid Build Coastguard Worker if (data1.size() != data2.size()) {
41*288bf522SAndroid Build Coastguard Worker return false;
42*288bf522SAndroid Build Coastguard Worker }
43*288bf522SAndroid Build Coastguard Worker for (const auto& [key, binary1] : data1) {
44*288bf522SAndroid Build Coastguard Worker auto it = data2.find(key);
45*288bf522SAndroid Build Coastguard Worker if (it == data2.end()) {
46*288bf522SAndroid Build Coastguard Worker return false;
47*288bf522SAndroid Build Coastguard Worker }
48*288bf522SAndroid Build Coastguard Worker ETMBinary& binary2 = it->second;
49*288bf522SAndroid Build Coastguard Worker if (binary1.dso_type != binary2.dso_type) {
50*288bf522SAndroid Build Coastguard Worker return false;
51*288bf522SAndroid Build Coastguard Worker }
52*288bf522SAndroid Build Coastguard Worker const UnorderedETMBranchMap& branch_map1 = binary1.branch_map;
53*288bf522SAndroid Build Coastguard Worker const UnorderedETMBranchMap& branch_map2 = binary2.branch_map;
54*288bf522SAndroid Build Coastguard Worker if (branch_map1.size() != branch_map2.size()) {
55*288bf522SAndroid Build Coastguard Worker return false;
56*288bf522SAndroid Build Coastguard Worker }
57*288bf522SAndroid Build Coastguard Worker for (const auto& [addr, b_map1] : branch_map1) {
58*288bf522SAndroid Build Coastguard Worker auto it2 = branch_map2.find(addr);
59*288bf522SAndroid Build Coastguard Worker if (it2 == branch_map2.end()) {
60*288bf522SAndroid Build Coastguard Worker return false;
61*288bf522SAndroid Build Coastguard Worker }
62*288bf522SAndroid Build Coastguard Worker const auto& b_map2 = it2->second;
63*288bf522SAndroid Build Coastguard Worker if (b_map1.size() != b_map2.size()) {
64*288bf522SAndroid Build Coastguard Worker return false;
65*288bf522SAndroid Build Coastguard Worker }
66*288bf522SAndroid Build Coastguard Worker for (const auto& [branch, count1] : b_map1) {
67*288bf522SAndroid Build Coastguard Worker auto it3 = b_map2.find(branch);
68*288bf522SAndroid Build Coastguard Worker if (it3 == b_map2.end()) {
69*288bf522SAndroid Build Coastguard Worker return false;
70*288bf522SAndroid Build Coastguard Worker }
71*288bf522SAndroid Build Coastguard Worker if (count1 != it3->second) {
72*288bf522SAndroid Build Coastguard Worker return false;
73*288bf522SAndroid Build Coastguard Worker }
74*288bf522SAndroid Build Coastguard Worker }
75*288bf522SAndroid Build Coastguard Worker }
76*288bf522SAndroid Build Coastguard Worker }
77*288bf522SAndroid Build Coastguard Worker return true;
78*288bf522SAndroid Build Coastguard Worker }
79*288bf522SAndroid Build Coastguard Worker
IsLBRDataEqual(const LBRData & data1,const LBRData & data2)80*288bf522SAndroid Build Coastguard Worker static bool IsLBRDataEqual(const LBRData& data1, const LBRData& data2) {
81*288bf522SAndroid Build Coastguard Worker if (data1.samples.size() != data2.samples.size()) {
82*288bf522SAndroid Build Coastguard Worker return false;
83*288bf522SAndroid Build Coastguard Worker }
84*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < data1.samples.size(); i++) {
85*288bf522SAndroid Build Coastguard Worker const LBRSample& sample1 = data1.samples[i];
86*288bf522SAndroid Build Coastguard Worker const LBRSample& sample2 = data2.samples[i];
87*288bf522SAndroid Build Coastguard Worker if (sample1.binary_id != sample2.binary_id) {
88*288bf522SAndroid Build Coastguard Worker return false;
89*288bf522SAndroid Build Coastguard Worker }
90*288bf522SAndroid Build Coastguard Worker if (sample1.vaddr_in_file != sample2.vaddr_in_file) {
91*288bf522SAndroid Build Coastguard Worker return false;
92*288bf522SAndroid Build Coastguard Worker }
93*288bf522SAndroid Build Coastguard Worker if (sample1.branches.size() != sample2.branches.size()) {
94*288bf522SAndroid Build Coastguard Worker return false;
95*288bf522SAndroid Build Coastguard Worker }
96*288bf522SAndroid Build Coastguard Worker for (size_t j = 0; j < sample1.branches.size(); j++) {
97*288bf522SAndroid Build Coastguard Worker const LBRBranch& b1 = sample1.branches[j];
98*288bf522SAndroid Build Coastguard Worker const LBRBranch& b2 = sample2.branches[j];
99*288bf522SAndroid Build Coastguard Worker if (b1.from_binary_id != b2.from_binary_id || b1.to_binary_id != b2.to_binary_id ||
100*288bf522SAndroid Build Coastguard Worker b1.from_vaddr_in_file != b2.from_vaddr_in_file ||
101*288bf522SAndroid Build Coastguard Worker b1.to_vaddr_in_file != b2.to_vaddr_in_file) {
102*288bf522SAndroid Build Coastguard Worker return false;
103*288bf522SAndroid Build Coastguard Worker }
104*288bf522SAndroid Build Coastguard Worker }
105*288bf522SAndroid Build Coastguard Worker }
106*288bf522SAndroid Build Coastguard Worker return data1.binaries == data2.binaries;
107*288bf522SAndroid Build Coastguard Worker }
108*288bf522SAndroid Build Coastguard Worker
109*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST(BranchListProtoReaderWriter,smoke)110*288bf522SAndroid Build Coastguard Worker TEST(BranchListProtoReaderWriter, smoke) {
111*288bf522SAndroid Build Coastguard Worker ETMBinaryMap etm_data;
112*288bf522SAndroid Build Coastguard Worker ETMBinary& binary = etm_data[BinaryKey("fake_binary", BuildId())];
113*288bf522SAndroid Build Coastguard Worker binary.dso_type = DSO_ELF_FILE;
114*288bf522SAndroid Build Coastguard Worker UnorderedETMBranchMap& branch_map = binary.branch_map;
115*288bf522SAndroid Build Coastguard Worker for (size_t addr = 0; addr <= 1024; addr++) {
116*288bf522SAndroid Build Coastguard Worker auto& b_map = branch_map[addr];
117*288bf522SAndroid Build Coastguard Worker std::vector<bool> branch1 = {true};
118*288bf522SAndroid Build Coastguard Worker b_map[branch1] = 1;
119*288bf522SAndroid Build Coastguard Worker std::vector<bool> branch2 = {true, false};
120*288bf522SAndroid Build Coastguard Worker b_map[branch2] = 2;
121*288bf522SAndroid Build Coastguard Worker }
122*288bf522SAndroid Build Coastguard Worker LBRData lbr_data;
123*288bf522SAndroid Build Coastguard Worker lbr_data.binaries.emplace_back(BinaryKey("binary1", BuildId()));
124*288bf522SAndroid Build Coastguard Worker lbr_data.binaries.emplace_back(BinaryKey("binary2", BuildId()));
125*288bf522SAndroid Build Coastguard Worker for (uint64_t from_addr = 0; from_addr <= 10; from_addr++) {
126*288bf522SAndroid Build Coastguard Worker for (uint64_t to_addr = 100; to_addr <= 110; to_addr++) {
127*288bf522SAndroid Build Coastguard Worker LBRBranch branch = {0, 1, from_addr, to_addr};
128*288bf522SAndroid Build Coastguard Worker LBRSample sample = {0, from_addr, {branch}};
129*288bf522SAndroid Build Coastguard Worker lbr_data.samples.emplace_back(sample);
130*288bf522SAndroid Build Coastguard Worker }
131*288bf522SAndroid Build Coastguard Worker }
132*288bf522SAndroid Build Coastguard Worker
133*288bf522SAndroid Build Coastguard Worker TemporaryFile tmpfile;
134*288bf522SAndroid Build Coastguard Worker close(tmpfile.fd);
135*288bf522SAndroid Build Coastguard Worker for (size_t max_branches_per_message : {100, 100000000}) {
136*288bf522SAndroid Build Coastguard Worker for (bool compress : {false, true}) {
137*288bf522SAndroid Build Coastguard Worker auto writer =
138*288bf522SAndroid Build Coastguard Worker BranchListProtoWriter::CreateForFile(tmpfile.path, compress, max_branches_per_message);
139*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(writer);
140*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(writer->Write(etm_data));
141*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(writer->Write(lbr_data));
142*288bf522SAndroid Build Coastguard Worker writer = nullptr;
143*288bf522SAndroid Build Coastguard Worker auto reader = BranchListProtoReader::CreateForFile(tmpfile.path);
144*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(reader);
145*288bf522SAndroid Build Coastguard Worker ETMBinaryMap new_etm_data;
146*288bf522SAndroid Build Coastguard Worker LBRData new_lbr_data;
147*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(reader->Read(new_etm_data, new_lbr_data));
148*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(IsETMDataEqual(etm_data, new_etm_data));
149*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(IsLBRDataEqual(lbr_data, new_lbr_data));
150*288bf522SAndroid Build Coastguard Worker }
151*288bf522SAndroid Build Coastguard Worker }
152*288bf522SAndroid Build Coastguard Worker }
153*288bf522SAndroid Build Coastguard Worker
154*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST(BranchListProtoReaderWriter,read_old_branch_list_file)155*288bf522SAndroid Build Coastguard Worker TEST(BranchListProtoReaderWriter, read_old_branch_list_file) {
156*288bf522SAndroid Build Coastguard Worker std::string path = GetTestData("etm/old_branch_list.data");
157*288bf522SAndroid Build Coastguard Worker auto reader = BranchListProtoReader::CreateForFile(path);
158*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(reader);
159*288bf522SAndroid Build Coastguard Worker ETMBinaryMap etm_data;
160*288bf522SAndroid Build Coastguard Worker LBRData lbr_data;
161*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(reader->Read(etm_data, lbr_data));
162*288bf522SAndroid Build Coastguard Worker ASSERT_EQ(etm_data.size(), 1u);
163*288bf522SAndroid Build Coastguard Worker }
164