1#!/usr/bin/env python3 2# 3# Copyright (C) 2021 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17from simpleperf_report_lib import ReportLib 18from . test_utils import TestBase, TestHelper 19 20 21class TestReportLib(TestBase): 22 def setUp(self): 23 super(TestReportLib, self).setUp() 24 self.report_lib = ReportLib() 25 self.report_lib.SetRecordFile(TestHelper.testdata_path('perf_with_symbols.data')) 26 27 def tearDown(self): 28 self.report_lib.Close() 29 super(TestReportLib, self).tearDown() 30 31 def test_build_id(self): 32 build_id = self.report_lib.GetBuildIdForPath('/data/t2') 33 self.assertEqual(build_id, '0x70f1fe24500fc8b0d9eb477199ca1ca21acca4de') 34 35 def test_symbol(self): 36 found_func2 = False 37 while self.report_lib.GetNextSample(): 38 symbol = self.report_lib.GetSymbolOfCurrentSample() 39 if symbol.symbol_name == 'func2(int, int)': 40 found_func2 = True 41 self.assertEqual(symbol.symbol_addr, 0x4004ed) 42 self.assertEqual(symbol.symbol_len, 0x14) 43 self.assertTrue(found_func2) 44 45 def test_sample(self): 46 found_sample = False 47 while self.report_lib.GetNextSample(): 48 sample = self.report_lib.GetCurrentSample() 49 if sample.ip == 0x4004ff and sample.time == 7637889424953: 50 found_sample = True 51 self.assertEqual(sample.pid, 15926) 52 self.assertEqual(sample.tid, 15926) 53 self.assertEqual(sample.thread_comm, 't2') 54 self.assertEqual(sample.cpu, 5) 55 self.assertEqual(sample.period, 694614) 56 event = self.report_lib.GetEventOfCurrentSample() 57 self.assertEqual(event.name, 'cpu-cycles') 58 callchain = self.report_lib.GetCallChainOfCurrentSample() 59 self.assertEqual(callchain.nr, 0) 60 self.assertTrue(found_sample) 61 62 def test_meta_info(self): 63 self.report_lib.SetRecordFile(TestHelper.testdata_path('perf_with_trace_offcpu.data')) 64 meta_info = self.report_lib.MetaInfo() 65 self.assertTrue("simpleperf_version" in meta_info) 66 self.assertEqual(meta_info["system_wide_collection"], "false") 67 self.assertEqual(meta_info["trace_offcpu"], "true") 68 self.assertEqual(meta_info["event_type_info"], "cpu-cycles,0,0\nsched:sched_switch,2,47") 69 self.assertTrue("product_props" in meta_info) 70 71 def test_event_name_from_meta_info(self): 72 self.report_lib.SetRecordFile(TestHelper.testdata_path('perf_with_tracepoint_event.data')) 73 event_names = set() 74 while self.report_lib.GetNextSample(): 75 event_names.add(self.report_lib.GetEventOfCurrentSample().name) 76 self.assertTrue('sched:sched_switch' in event_names) 77 self.assertTrue('cpu-cycles' in event_names) 78 79 def test_record_cmd(self): 80 self.report_lib.SetRecordFile(TestHelper.testdata_path('perf_with_trace_offcpu.data')) 81 self.assertEqual(self.report_lib.GetRecordCmd(), 82 "/data/local/tmp/simpleperf record --trace-offcpu --duration 2 -g " + 83 "./simpleperf_runtest_run_and_sleep64") 84 85 def test_offcpu(self): 86 self.report_lib.SetRecordFile(TestHelper.testdata_path('perf_with_trace_offcpu.data')) 87 total_period = 0 88 sleep_function_period = 0 89 sleep_function_name = "SleepFunction(unsigned long long)" 90 while self.report_lib.GetNextSample(): 91 sample = self.report_lib.GetCurrentSample() 92 total_period += sample.period 93 if self.report_lib.GetSymbolOfCurrentSample().symbol_name == sleep_function_name: 94 sleep_function_period += sample.period 95 continue 96 callchain = self.report_lib.GetCallChainOfCurrentSample() 97 for i in range(callchain.nr): 98 if callchain.entries[i].symbol.symbol_name == sleep_function_name: 99 sleep_function_period += sample.period 100 break 101 self.assertEqual(self.report_lib.GetEventOfCurrentSample().name, 'cpu-cycles') 102 sleep_percentage = float(sleep_function_period) / total_period 103 self.assertGreater(sleep_percentage, 0.30) 104 105 def test_show_art_frames(self): 106 def has_art_frame(report_lib): 107 report_lib.SetRecordFile(TestHelper.testdata_path('perf_with_interpreter_frames.data')) 108 result = False 109 while report_lib.GetNextSample(): 110 callchain = report_lib.GetCallChainOfCurrentSample() 111 for i in range(callchain.nr): 112 if callchain.entries[i].symbol.symbol_name == 'artMterpAsmInstructionStart': 113 result = True 114 break 115 report_lib.Close() 116 return result 117 118 report_lib = ReportLib() 119 self.assertFalse(has_art_frame(report_lib)) 120 report_lib = ReportLib() 121 report_lib.ShowArtFrames(False) 122 self.assertFalse(has_art_frame(report_lib)) 123 report_lib = ReportLib() 124 report_lib.ShowArtFrames(True) 125 self.assertTrue(has_art_frame(report_lib)) 126 127 def test_merge_java_methods(self): 128 def parse_dso_names(report_lib): 129 dso_names = set() 130 report_lib.SetRecordFile(TestHelper.testdata_path('perf_with_interpreter_frames.data')) 131 while report_lib.GetNextSample(): 132 dso_names.add(report_lib.GetSymbolOfCurrentSample().dso_name) 133 callchain = report_lib.GetCallChainOfCurrentSample() 134 for i in range(callchain.nr): 135 dso_names.add(callchain.entries[i].symbol.dso_name) 136 report_lib.Close() 137 has_jit_symfiles = any('TemporaryFile-' in name for name in dso_names) 138 has_jit_cache = '[JIT cache]' in dso_names 139 return has_jit_symfiles, has_jit_cache 140 141 report_lib = ReportLib() 142 self.assertEqual(parse_dso_names(report_lib), (False, True)) 143 144 report_lib = ReportLib() 145 report_lib.MergeJavaMethods(True) 146 self.assertEqual(parse_dso_names(report_lib), (False, True)) 147 148 report_lib = ReportLib() 149 report_lib.MergeJavaMethods(False) 150 self.assertEqual(parse_dso_names(report_lib), (True, False)) 151 152 def test_jited_java_methods(self): 153 report_lib = ReportLib() 154 report_lib.SetRecordFile(TestHelper.testdata_path('perf_with_jit_symbol.data')) 155 has_jit_cache = False 156 while report_lib.GetNextSample(): 157 if report_lib.GetSymbolOfCurrentSample().dso_name == '[JIT app cache]': 158 has_jit_cache = True 159 callchain = report_lib.GetCallChainOfCurrentSample() 160 for i in range(callchain.nr): 161 if callchain.entries[i].symbol.dso_name == '[JIT app cache]': 162 has_jit_cache = True 163 report_lib.Close() 164 self.assertTrue(has_jit_cache) 165 166 def test_tracing_data(self): 167 self.report_lib.SetRecordFile(TestHelper.testdata_path('perf_with_tracepoint_event.data')) 168 has_tracing_data = False 169 while self.report_lib.GetNextSample(): 170 event = self.report_lib.GetEventOfCurrentSample() 171 tracing_data = self.report_lib.GetTracingDataOfCurrentSample() 172 if event.name == 'sched:sched_switch': 173 self.assertIsNotNone(tracing_data) 174 self.assertIn('prev_pid', tracing_data) 175 self.assertIn('next_comm', tracing_data) 176 if tracing_data['prev_pid'] == 9896 and tracing_data['next_comm'] == 'swapper/4': 177 has_tracing_data = True 178 else: 179 self.assertIsNone(tracing_data) 180 self.assertTrue(has_tracing_data) 181 182 def test_dynamic_field_in_tracing_data(self): 183 self.report_lib.SetRecordFile(TestHelper.testdata_path( 184 'perf_with_tracepoint_event_dynamic_field.data')) 185 has_dynamic_field = False 186 while self.report_lib.GetNextSample(): 187 event = self.report_lib.GetEventOfCurrentSample() 188 tracing_data = self.report_lib.GetTracingDataOfCurrentSample() 189 if event.name == 'kprobes:myopen': 190 self.assertIsNotNone(tracing_data) 191 self.assertIn('name', tracing_data) 192 if tracing_data['name'] == '/sys/kernel/debug/tracing/events/kprobes/myopen/format': 193 has_dynamic_field = True 194 else: 195 self.assertIsNone(tracing_data) 196 self.assertTrue(has_dynamic_field) 197 198 def test_add_proguard_mapping_file(self): 199 with self.assertRaises(ValueError): 200 self.report_lib.AddProguardMappingFile('non_exist_file') 201 proguard_mapping_file = TestHelper.testdata_path('proguard_mapping.txt') 202 self.report_lib.AddProguardMappingFile(proguard_mapping_file) 203