1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2015 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 "sample_tree.h"
20*288bf522SAndroid Build Coastguard Worker #include "thread_tree.h"
21*288bf522SAndroid Build Coastguard Worker
22*288bf522SAndroid Build Coastguard Worker using namespace simpleperf;
23*288bf522SAndroid Build Coastguard Worker
24*288bf522SAndroid Build Coastguard Worker namespace {
25*288bf522SAndroid Build Coastguard Worker
26*288bf522SAndroid Build Coastguard Worker struct SampleEntry {
27*288bf522SAndroid Build Coastguard Worker int pid;
28*288bf522SAndroid Build Coastguard Worker int tid;
29*288bf522SAndroid Build Coastguard Worker const char* thread_comm;
30*288bf522SAndroid Build Coastguard Worker std::string dso_name;
31*288bf522SAndroid Build Coastguard Worker uint64_t map_start_addr;
32*288bf522SAndroid Build Coastguard Worker size_t sample_count;
33*288bf522SAndroid Build Coastguard Worker
SampleEntry__anonb7e208560111::SampleEntry34*288bf522SAndroid Build Coastguard Worker SampleEntry(int pid, int tid, const char* thread_comm, const std::string& dso_name,
35*288bf522SAndroid Build Coastguard Worker uint64_t map_start_addr, size_t sample_count = 1u)
36*288bf522SAndroid Build Coastguard Worker : pid(pid),
37*288bf522SAndroid Build Coastguard Worker tid(tid),
38*288bf522SAndroid Build Coastguard Worker thread_comm(thread_comm),
39*288bf522SAndroid Build Coastguard Worker dso_name(dso_name),
40*288bf522SAndroid Build Coastguard Worker map_start_addr(map_start_addr),
41*288bf522SAndroid Build Coastguard Worker sample_count(sample_count) {}
42*288bf522SAndroid Build Coastguard Worker };
43*288bf522SAndroid Build Coastguard Worker
44*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_VALUE_FUNCTION(TestComparePid, pid);
45*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_VALUE_FUNCTION(TestCompareTid, tid);
46*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_STRING_FUNCTION(TestCompareDsoName, dso_name.c_str());
47*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_VALUE_FUNCTION(TestCompareMapStartAddr, map_start_addr);
48*288bf522SAndroid Build Coastguard Worker
49*288bf522SAndroid Build Coastguard Worker class TestSampleComparator : public SampleComparator<SampleEntry> {
50*288bf522SAndroid Build Coastguard Worker public:
TestSampleComparator()51*288bf522SAndroid Build Coastguard Worker TestSampleComparator() {
52*288bf522SAndroid Build Coastguard Worker AddCompareFunction(TestComparePid);
53*288bf522SAndroid Build Coastguard Worker AddCompareFunction(TestCompareTid);
54*288bf522SAndroid Build Coastguard Worker AddCompareFunction(CompareComm);
55*288bf522SAndroid Build Coastguard Worker AddCompareFunction(TestCompareDsoName);
56*288bf522SAndroid Build Coastguard Worker AddCompareFunction(TestCompareMapStartAddr);
57*288bf522SAndroid Build Coastguard Worker }
58*288bf522SAndroid Build Coastguard Worker };
59*288bf522SAndroid Build Coastguard Worker
60*288bf522SAndroid Build Coastguard Worker class TestSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, int> {
61*288bf522SAndroid Build Coastguard Worker public:
TestSampleTreeBuilder(ThreadTree * thread_tree)62*288bf522SAndroid Build Coastguard Worker explicit TestSampleTreeBuilder(ThreadTree* thread_tree)
63*288bf522SAndroid Build Coastguard Worker : SampleTreeBuilder(TestSampleComparator()), thread_tree_(thread_tree) {}
64*288bf522SAndroid Build Coastguard Worker
AddSample(int pid,int tid,uint64_t ip,bool in_kernel)65*288bf522SAndroid Build Coastguard Worker void AddSample(int pid, int tid, uint64_t ip, bool in_kernel) {
66*288bf522SAndroid Build Coastguard Worker const ThreadEntry* thread = thread_tree_->FindThreadOrNew(pid, tid);
67*288bf522SAndroid Build Coastguard Worker const MapEntry* map = thread_tree_->FindMap(thread, ip, in_kernel);
68*288bf522SAndroid Build Coastguard Worker InsertSample(std::unique_ptr<SampleEntry>(
69*288bf522SAndroid Build Coastguard Worker new SampleEntry(pid, tid, thread->comm, map->dso->Path(), map->start_addr)));
70*288bf522SAndroid Build Coastguard Worker }
71*288bf522SAndroid Build Coastguard Worker
72*288bf522SAndroid Build Coastguard Worker protected:
CreateSample(const SampleRecord &,bool,int *)73*288bf522SAndroid Build Coastguard Worker SampleEntry* CreateSample(const SampleRecord&, bool, int*) override { return nullptr; }
CreateBranchSample(const SampleRecord &,const BranchStackItemType &)74*288bf522SAndroid Build Coastguard Worker SampleEntry* CreateBranchSample(const SampleRecord&, const BranchStackItemType&) override {
75*288bf522SAndroid Build Coastguard Worker return nullptr;
76*288bf522SAndroid Build Coastguard Worker };
CreateCallChainSample(const ThreadEntry *,const SampleEntry *,uint64_t,bool,const std::vector<SampleEntry * > &,const int &)77*288bf522SAndroid Build Coastguard Worker SampleEntry* CreateCallChainSample(const ThreadEntry*, const SampleEntry*, uint64_t, bool,
78*288bf522SAndroid Build Coastguard Worker const std::vector<SampleEntry*>&, const int&) override {
79*288bf522SAndroid Build Coastguard Worker return nullptr;
80*288bf522SAndroid Build Coastguard Worker }
GetThreadOfSample(SampleEntry *)81*288bf522SAndroid Build Coastguard Worker const ThreadEntry* GetThreadOfSample(SampleEntry*) override { return nullptr; }
GetPeriodForCallChain(const int &)82*288bf522SAndroid Build Coastguard Worker uint64_t GetPeriodForCallChain(const int&) override { return 0; }
MergeSample(SampleEntry * sample1,SampleEntry * sample2)83*288bf522SAndroid Build Coastguard Worker void MergeSample(SampleEntry* sample1, SampleEntry* sample2) override {
84*288bf522SAndroid Build Coastguard Worker sample1->sample_count += sample2->sample_count;
85*288bf522SAndroid Build Coastguard Worker }
86*288bf522SAndroid Build Coastguard Worker
87*288bf522SAndroid Build Coastguard Worker private:
88*288bf522SAndroid Build Coastguard Worker ThreadTree* thread_tree_;
89*288bf522SAndroid Build Coastguard Worker };
90*288bf522SAndroid Build Coastguard Worker
SampleMatchExpectation(const SampleEntry & sample,const SampleEntry & expected,bool * has_error)91*288bf522SAndroid Build Coastguard Worker static void SampleMatchExpectation(const SampleEntry& sample, const SampleEntry& expected,
92*288bf522SAndroid Build Coastguard Worker bool* has_error) {
93*288bf522SAndroid Build Coastguard Worker *has_error = true;
94*288bf522SAndroid Build Coastguard Worker ASSERT_EQ(expected.pid, sample.pid);
95*288bf522SAndroid Build Coastguard Worker ASSERT_EQ(expected.tid, sample.tid);
96*288bf522SAndroid Build Coastguard Worker ASSERT_STREQ(expected.thread_comm, sample.thread_comm);
97*288bf522SAndroid Build Coastguard Worker ASSERT_EQ(expected.dso_name, sample.dso_name);
98*288bf522SAndroid Build Coastguard Worker ASSERT_EQ(expected.map_start_addr, sample.map_start_addr);
99*288bf522SAndroid Build Coastguard Worker ASSERT_EQ(expected.sample_count, sample.sample_count);
100*288bf522SAndroid Build Coastguard Worker *has_error = false;
101*288bf522SAndroid Build Coastguard Worker }
102*288bf522SAndroid Build Coastguard Worker
CheckSamples(const std::vector<SampleEntry * > & samples,const std::vector<SampleEntry> & expected_samples)103*288bf522SAndroid Build Coastguard Worker static void CheckSamples(const std::vector<SampleEntry*>& samples,
104*288bf522SAndroid Build Coastguard Worker const std::vector<SampleEntry>& expected_samples) {
105*288bf522SAndroid Build Coastguard Worker ASSERT_EQ(samples.size(), expected_samples.size());
106*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < samples.size(); ++i) {
107*288bf522SAndroid Build Coastguard Worker bool has_error;
108*288bf522SAndroid Build Coastguard Worker SampleMatchExpectation(*samples[i], expected_samples[i], &has_error);
109*288bf522SAndroid Build Coastguard Worker ASSERT_FALSE(has_error) << "Error matching sample at pos " << i;
110*288bf522SAndroid Build Coastguard Worker }
111*288bf522SAndroid Build Coastguard Worker }
112*288bf522SAndroid Build Coastguard Worker } // namespace
113*288bf522SAndroid Build Coastguard Worker
114*288bf522SAndroid Build Coastguard Worker class SampleTreeTest : public testing::Test {
115*288bf522SAndroid Build Coastguard Worker protected:
SetUp()116*288bf522SAndroid Build Coastguard Worker virtual void SetUp() {
117*288bf522SAndroid Build Coastguard Worker thread_tree.SetThreadName(1, 1, "p1t1");
118*288bf522SAndroid Build Coastguard Worker thread_tree.SetThreadName(1, 11, "p1t11");
119*288bf522SAndroid Build Coastguard Worker thread_tree.SetThreadName(2, 2, "p2t2");
120*288bf522SAndroid Build Coastguard Worker thread_tree.AddThreadMap(1, 1, 1, 5, 0, "process1_thread1");
121*288bf522SAndroid Build Coastguard Worker thread_tree.AddThreadMap(1, 11, 6, 5, 0, "process1_thread1_map2");
122*288bf522SAndroid Build Coastguard Worker thread_tree.AddThreadMap(2, 2, 1, 20, 0, "process2_thread2");
123*288bf522SAndroid Build Coastguard Worker thread_tree.AddKernelMap(10, 20, 0, "kernel");
124*288bf522SAndroid Build Coastguard Worker sample_tree_builder.reset(new TestSampleTreeBuilder(&thread_tree));
125*288bf522SAndroid Build Coastguard Worker }
126*288bf522SAndroid Build Coastguard Worker
CheckSamples(const std::vector<SampleEntry> & expected_samples)127*288bf522SAndroid Build Coastguard Worker void CheckSamples(const std::vector<SampleEntry>& expected_samples) {
128*288bf522SAndroid Build Coastguard Worker ::CheckSamples(sample_tree_builder->GetSamples(), expected_samples);
129*288bf522SAndroid Build Coastguard Worker }
130*288bf522SAndroid Build Coastguard Worker
131*288bf522SAndroid Build Coastguard Worker ThreadTree thread_tree;
132*288bf522SAndroid Build Coastguard Worker std::unique_ptr<TestSampleTreeBuilder> sample_tree_builder;
133*288bf522SAndroid Build Coastguard Worker };
134*288bf522SAndroid Build Coastguard Worker
135*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(SampleTreeTest,ip_in_map)136*288bf522SAndroid Build Coastguard Worker TEST_F(SampleTreeTest, ip_in_map) {
137*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 1, false);
138*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 2, false);
139*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 5, false);
140*288bf522SAndroid Build Coastguard Worker std::vector<SampleEntry> expected_samples = {
141*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1", "process1_thread1", 1, 3),
142*288bf522SAndroid Build Coastguard Worker };
143*288bf522SAndroid Build Coastguard Worker CheckSamples(expected_samples);
144*288bf522SAndroid Build Coastguard Worker }
145*288bf522SAndroid Build Coastguard Worker
146*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(SampleTreeTest,different_pid)147*288bf522SAndroid Build Coastguard Worker TEST_F(SampleTreeTest, different_pid) {
148*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 1, false);
149*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(2, 2, 1, false);
150*288bf522SAndroid Build Coastguard Worker std::vector<SampleEntry> expected_samples = {
151*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1", "process1_thread1", 1, 1),
152*288bf522SAndroid Build Coastguard Worker SampleEntry(2, 2, "p2t2", "process2_thread2", 1, 1),
153*288bf522SAndroid Build Coastguard Worker };
154*288bf522SAndroid Build Coastguard Worker CheckSamples(expected_samples);
155*288bf522SAndroid Build Coastguard Worker }
156*288bf522SAndroid Build Coastguard Worker
157*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(SampleTreeTest,different_tid)158*288bf522SAndroid Build Coastguard Worker TEST_F(SampleTreeTest, different_tid) {
159*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 1, false);
160*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 11, 1, false);
161*288bf522SAndroid Build Coastguard Worker std::vector<SampleEntry> expected_samples = {
162*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1", "process1_thread1", 1, 1),
163*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 11, "p1t11", "process1_thread1", 1, 1),
164*288bf522SAndroid Build Coastguard Worker };
165*288bf522SAndroid Build Coastguard Worker CheckSamples(expected_samples);
166*288bf522SAndroid Build Coastguard Worker }
167*288bf522SAndroid Build Coastguard Worker
168*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(SampleTreeTest,different_comm)169*288bf522SAndroid Build Coastguard Worker TEST_F(SampleTreeTest, different_comm) {
170*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 1, false);
171*288bf522SAndroid Build Coastguard Worker thread_tree.SetThreadName(1, 1, "p1t1_comm2");
172*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 1, false);
173*288bf522SAndroid Build Coastguard Worker std::vector<SampleEntry> expected_samples = {
174*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1", "process1_thread1", 1, 1),
175*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1_comm2", "process1_thread1", 1, 1),
176*288bf522SAndroid Build Coastguard Worker };
177*288bf522SAndroid Build Coastguard Worker CheckSamples(expected_samples);
178*288bf522SAndroid Build Coastguard Worker }
179*288bf522SAndroid Build Coastguard Worker
180*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(SampleTreeTest,different_map)181*288bf522SAndroid Build Coastguard Worker TEST_F(SampleTreeTest, different_map) {
182*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 1, false);
183*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 6, false);
184*288bf522SAndroid Build Coastguard Worker std::vector<SampleEntry> expected_samples = {
185*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1", "process1_thread1", 1, 1),
186*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1", "process1_thread1_map2", 6, 1),
187*288bf522SAndroid Build Coastguard Worker };
188*288bf522SAndroid Build Coastguard Worker CheckSamples(expected_samples);
189*288bf522SAndroid Build Coastguard Worker }
190*288bf522SAndroid Build Coastguard Worker
191*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(SampleTreeTest,unmapped_sample)192*288bf522SAndroid Build Coastguard Worker TEST_F(SampleTreeTest, unmapped_sample) {
193*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 0, false);
194*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 31, false);
195*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 70, false);
196*288bf522SAndroid Build Coastguard Worker // Match the unknown map.
197*288bf522SAndroid Build Coastguard Worker std::vector<SampleEntry> expected_samples = {
198*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1", "unknown", 0, 3),
199*288bf522SAndroid Build Coastguard Worker };
200*288bf522SAndroid Build Coastguard Worker CheckSamples(expected_samples);
201*288bf522SAndroid Build Coastguard Worker }
202*288bf522SAndroid Build Coastguard Worker
203*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST_F(SampleTreeTest,map_kernel)204*288bf522SAndroid Build Coastguard Worker TEST_F(SampleTreeTest, map_kernel) {
205*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 10, true);
206*288bf522SAndroid Build Coastguard Worker sample_tree_builder->AddSample(1, 1, 10, false);
207*288bf522SAndroid Build Coastguard Worker std::vector<SampleEntry> expected_samples = {
208*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1", "kernel", 10, 1),
209*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "p1t1", "process1_thread1_map2", 6, 1),
210*288bf522SAndroid Build Coastguard Worker };
211*288bf522SAndroid Build Coastguard Worker CheckSamples(expected_samples);
212*288bf522SAndroid Build Coastguard Worker }
213*288bf522SAndroid Build Coastguard Worker
214*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST(sample_tree,overlapped_map)215*288bf522SAndroid Build Coastguard Worker TEST(sample_tree, overlapped_map) {
216*288bf522SAndroid Build Coastguard Worker ThreadTree thread_tree;
217*288bf522SAndroid Build Coastguard Worker TestSampleTreeBuilder sample_tree_builder(&thread_tree);
218*288bf522SAndroid Build Coastguard Worker thread_tree.SetThreadName(1, 1, "thread1");
219*288bf522SAndroid Build Coastguard Worker thread_tree.AddThreadMap(1, 1, 1, 10, 0, "map1"); // Add map 1.
220*288bf522SAndroid Build Coastguard Worker sample_tree_builder.AddSample(1, 1, 5, false); // Hit map 1.
221*288bf522SAndroid Build Coastguard Worker thread_tree.AddThreadMap(1, 1, 5, 20, 0, "map2"); // Add map 2.
222*288bf522SAndroid Build Coastguard Worker sample_tree_builder.AddSample(1, 1, 6, false); // Hit map 2.
223*288bf522SAndroid Build Coastguard Worker sample_tree_builder.AddSample(1, 1, 4, false); // Hit map 1.
224*288bf522SAndroid Build Coastguard Worker thread_tree.AddThreadMap(1, 1, 2, 7, 0, "map3"); // Add map 3.
225*288bf522SAndroid Build Coastguard Worker sample_tree_builder.AddSample(1, 1, 7, false); // Hit map 3.
226*288bf522SAndroid Build Coastguard Worker sample_tree_builder.AddSample(1, 1, 10, false); // Hit map 2.
227*288bf522SAndroid Build Coastguard Worker
228*288bf522SAndroid Build Coastguard Worker std::vector<SampleEntry> expected_samples = {
229*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "thread1", "map1", 1, 2),
230*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "thread1", "map2", 5, 1),
231*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "thread1", "map2", 9, 1),
232*288bf522SAndroid Build Coastguard Worker SampleEntry(1, 1, "thread1", "map3", 2, 1),
233*288bf522SAndroid Build Coastguard Worker };
234*288bf522SAndroid Build Coastguard Worker CheckSamples(sample_tree_builder.GetSamples(), expected_samples);
235*288bf522SAndroid Build Coastguard Worker }
236*288bf522SAndroid Build Coastguard Worker
237*288bf522SAndroid Build Coastguard Worker // @CddTest = 6.1/C-0-2
TEST(thread_tree,symbol_ULLONG_MAX)238*288bf522SAndroid Build Coastguard Worker TEST(thread_tree, symbol_ULLONG_MAX) {
239*288bf522SAndroid Build Coastguard Worker ThreadTree thread_tree;
240*288bf522SAndroid Build Coastguard Worker thread_tree.ShowIpForUnknownSymbol();
241*288bf522SAndroid Build Coastguard Worker ASSERT_TRUE(thread_tree.FindKernelSymbol(ULLONG_MAX) != nullptr);
242*288bf522SAndroid Build Coastguard Worker }
243