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 17import os 18import unittest 19 20from simpleperf_utils import remove 21from . app_test import TestExampleBase 22from . test_utils import INFERNO_SCRIPT, TestHelper 23 24 25class TestExampleCpp(TestExampleBase): 26 @classmethod 27 def setUpClass(cls): 28 cls.prepare("SimpleperfExampleCpp", "simpleperf.example.cpp", ".MainActivity") 29 30 def test_app_profiler(self): 31 self.common_test_app_profiler() 32 33 def test_app_profiler_profile_from_launch(self): 34 self.run_app_profiler(start_activity=True, build_binary_cache=False) 35 self.run_cmd(["report.py", "-g", "-o", "report.txt"]) 36 self.check_strings_in_file("report.txt", ["BusyLoopThread", "__start_thread"]) 37 38 def test_report(self): 39 self.common_test_report() 40 self.run_cmd(["report.py", "-g", "-o", "report.txt"]) 41 self.check_strings_in_file("report.txt", ["BusyLoopThread", "__start_thread"]) 42 43 def test_annotate(self): 44 self.common_test_annotate() 45 self.check_file_under_dir("annotated_files", "native-lib.cpp") 46 summary_file = os.path.join("annotated_files", "summary") 47 self.check_annotation_summary(summary_file, [ 48 ("native-lib.cpp", 20, 0), 49 ("BusyLoopThread", 20, 0), 50 ("line 43", 20, 0)]) 51 52 def test_report_sample(self): 53 self.common_test_report_sample( 54 ["BusyLoopThread", 55 "__start_thread"]) 56 57 def test_pprof_proto_generator(self): 58 check_strings_with_lines = [ 59 "native-lib.cpp", 60 "BusyLoopThread", 61 # Check if dso name in perf.data is replaced by binary path in binary_cache. 62 'filename: binary_cache'] 63 self.common_test_pprof_proto_generator( 64 check_strings_with_lines, 65 check_strings_without_lines=["BusyLoopThread"]) 66 67 def test_inferno(self): 68 self.common_test_inferno() 69 self.run_app_profiler() 70 self.run_cmd([INFERNO_SCRIPT, "-sc"]) 71 self.check_inferno_report_html([('BusyLoopThread', 20)]) 72 73 def test_report_html(self): 74 self.common_test_report_html() 75 self.run_cmd(['report_html.py', '--add_source_code', '--source_dirs', 'testdata', 76 '--add_disassembly', '--binary_filter', "libnative-lib.so"]) 77 78 79class TestExampleCppProfileableApk(TestExampleCpp): 80 """ Test profiling a profileable released apk.""" 81 @classmethod 82 def setUpClass(cls): 83 if TestHelper.android_version >= 10: 84 cls.prepare("SimpleperfExampleCpp", 85 "simpleperf.example.cpp", 86 ".MainActivity", apk_name='app-release.apk') 87 88 def setUp(self): 89 if TestHelper().android_version < 10: 90 raise unittest.SkipTest("Profileable apk isn't supported on Android < Q.") 91 super().setUp() 92 93 94class TestExampleCppRoot(TestExampleBase): 95 @classmethod 96 def setUpClass(cls): 97 cls.prepare("SimpleperfExampleCpp", 98 "simpleperf.example.cpp", 99 ".MainActivity", 100 adb_root=True) 101 102 def test_app_profiler(self): 103 self.common_test_app_profiler() 104 105 106class TestExampleCppTraceOffCpu(TestExampleBase): 107 @classmethod 108 def setUpClass(cls): 109 cls.prepare("SimpleperfExampleCpp", "simpleperf.example.cpp", ".SleepActivity") 110 111 def test_smoke(self): 112 self.run_app_profiler(record_arg="-g -f 1000 --duration 10 -e cpu-clock:u --trace-offcpu") 113 self.run_cmd(["report.py", "-g", "--comms", "SleepThread", "-o", "report.txt"]) 114 self.check_strings_in_file("report.txt", [ 115 "SleepThread(void*)", 116 "RunFunction()", 117 "SleepFunction(unsigned long long)"]) 118 if (self.adb.get_device_arch() in ['x86', 'x86_64'] and 119 TestHelper.get_kernel_version() < (4, 19)): 120 # Skip on x86 and kernel < 4.19, which doesn't have patch 121 # "perf/x86: Store user space frame-pointer value on a sample" and may fail to unwind 122 # system call. 123 TestHelper.log('Skip annotation test on x86 for kernel < 4.19.') 124 return 125 remove("annotated_files") 126 self.run_cmd(["annotate.py", "-s", self.example_path, "--comm", 127 "SleepThread", '--summary-width', '1000']) 128 self.check_exist(dirname="annotated_files") 129 self.check_file_under_dir("annotated_files", "native-lib.cpp") 130 summary_file = os.path.join("annotated_files", "summary") 131 self.check_annotation_summary(summary_file, [ 132 ("native-lib.cpp", 80, 20), 133 ("SleepThread", 80, 0), 134 ("RunFunction", 20, 20), 135 ("SleepFunction", 20, 0), 136 ("line 70", 20, 0), 137 ("line 80", 20, 0)]) 138 self.run_cmd([INFERNO_SCRIPT, "-sc"]) 139 self.check_inferno_report_html([('SleepThread', 80), 140 ('RunFunction', 20), 141 ('SleepFunction', 20)]) 142 143 144class TestExampleCppJniCall(TestExampleBase): 145 @classmethod 146 def setUpClass(cls): 147 cls.prepare("SimpleperfExampleCpp", "simpleperf.example.cpp", ".MixActivity") 148 149 def test_smoke(self): 150 if self.adb.get_android_version() == 8: 151 TestHelper.log( 152 "Android O needs wrap.sh to use compiled java code. But cpp example doesn't use wrap.sh.") 153 return 154 self.run_app_profiler() 155 self.run_cmd(["report.py", "-g", "--comms", "BusyThread", "-o", "report.txt"]) 156 self.check_strings_in_file("report.txt", [ 157 "simpleperf.example.cpp.MixActivity$1.run", 158 "Java_simpleperf_example_cpp_MixActivity_callFunction"]) 159 remove("annotated_files") 160 self.run_cmd(["annotate.py", "-s", self.example_path, "--comm", 161 "BusyThread", '--summary-width', '1000']) 162 self.check_exist(dirname="annotated_files") 163 self.check_file_under_dir("annotated_files", "native-lib.cpp") 164 summary_file = os.path.join("annotated_files", "summary") 165 self.check_annotation_summary(summary_file, [("native-lib.cpp", 5, 0), ("line 37", 5, 0)]) 166 if self.use_compiled_java_code: 167 self.check_file_under_dir("annotated_files", "MixActivity.java") 168 self.check_annotation_summary(summary_file, [ 169 ("MixActivity.java", 80, 0), 170 ("run", 80, 0), 171 ("line 27", 20, 0), 172 ("native-lib.cpp", 5, 0), 173 ("line 37", 5, 0)]) 174 175 self.run_cmd([INFERNO_SCRIPT, "-sc"]) 176 177 178class TestExampleCppForce32Bit(TestExampleCpp): 179 @classmethod 180 def setUpClass(cls): 181 cls.prepare("SimpleperfExampleCpp", 182 "simpleperf.example.cpp", 183 ".MainActivity", 184 abi=TestHelper.get_32bit_abi()) 185 186 187class TestExampleCppRootForce32Bit(TestExampleCppRoot): 188 @classmethod 189 def setUpClass(cls): 190 cls.prepare("SimpleperfExampleCpp", 191 "simpleperf.example.cpp", 192 ".MainActivity", 193 abi=TestHelper.get_32bit_abi(), 194 adb_root=False) 195 196 197class TestExampleCppTraceOffCpuForce32Bit(TestExampleCppTraceOffCpu): 198 @classmethod 199 def setUpClass(cls): 200 cls.prepare("SimpleperfExampleCpp", 201 "simpleperf.example.cpp", 202 ".SleepActivity", 203 abi=TestHelper.get_32bit_abi()) 204 205 def test_smoke(self): 206 if (self.adb.get_device_arch() in ['x86', 'x86_64'] and 207 self.adb.get_android_version() in [10, 11]): 208 TestHelper.log("Skip test on x86. Because simpleperf can't unwind 32bit vdso.") 209 return 210 super().test_smoke() 211