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 signal 19import subprocess 20import sys 21import time 22 23from simpleperf_utils import is_windows, remove 24from . app_test import TestExampleBase 25from . test_utils import TestHelper, INFERNO_SCRIPT 26 27 28class TestExamplePureJava(TestExampleBase): 29 @classmethod 30 def setUpClass(cls): 31 cls.prepare("SimpleperfExamplePureJava", 32 "com.example.simpleperf.simpleperfexamplepurejava", 33 ".MainActivity") 34 35 def test_app_profiler(self): 36 self.common_test_app_profiler() 37 38 def test_app_profiler_profile_from_launch(self): 39 self.run_app_profiler(start_activity=True, build_binary_cache=False) 40 self.run_cmd(["report.py", "-g", "-o", "report.txt"]) 41 self.check_strings_in_file("report.txt", [ 42 "com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run", 43 "__start_thread"]) 44 45 def test_app_profiler_multiprocesses(self): 46 self.adb.check_run(['shell', 'am', 'force-stop', self.package_name]) 47 self.adb.check_run(['shell', 'am', 'start', '-n', 48 self.package_name + '/.MultiProcessActivity']) 49 # Wait until both MultiProcessActivity and MultiProcessService set up. 50 time.sleep(3) 51 self.run_app_profiler(start_activity=False) 52 self.run_cmd(["report.py", "-o", "report.txt"]) 53 self.check_strings_in_file("report.txt", ["BusyService", "BusyThread"]) 54 55 def test_app_profiler_with_ctrl_c(self): 56 if is_windows(): 57 return 58 self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MainActivity']) 59 time.sleep(1) 60 args = [sys.executable, TestHelper.script_path("app_profiler.py"), 61 "--app", self.package_name, "-r", "--duration 10000", "--disable_adb_root"] 62 subproc = subprocess.Popen(args) 63 time.sleep(3) 64 65 subproc.send_signal(signal.SIGINT) 66 subproc.wait() 67 self.assertEqual(subproc.returncode, 0) 68 self.run_cmd(["report.py"]) 69 70 def test_app_profiler_stop_after_app_exit(self): 71 self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MainActivity']) 72 time.sleep(1) 73 subproc = subprocess.Popen( 74 [sys.executable, TestHelper.script_path('app_profiler.py'), 75 '--app', self.package_name, '-r', '--duration 10000', '--disable_adb_root']) 76 time.sleep(3) 77 self.adb.check_run(['shell', 'am', 'force-stop', self.package_name]) 78 subproc.wait() 79 self.assertEqual(subproc.returncode, 0) 80 self.run_cmd(["report.py"]) 81 82 def test_app_profiler_with_ndk_path(self): 83 # Although we pass an invalid ndk path, it should be able to find tools in default ndk path. 84 self.run_cmd(['app_profiler.py', '--app', self.package_name, '-a', self.activity_name, 85 '--ndk_path', '.']) 86 87 def test_report(self): 88 self.common_test_report() 89 self.run_cmd(["report.py", "-g", "-o", "report.txt"]) 90 self.check_strings_in_file("report.txt", [ 91 "com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run", 92 "__start_thread"]) 93 94 def test_profile_with_process_id(self): 95 self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MainActivity']) 96 time.sleep(1) 97 pid = self.adb.check_run_and_return_output([ 98 'shell', 'pidof', 'com.example.simpleperf.simpleperfexamplepurejava']).strip() 99 self.run_app_profiler(start_activity=False, record_arg='-g --duration 10 -p ' + pid) 100 self.run_cmd(["report.py", "-g", "-o", "report.txt"]) 101 self.check_strings_in_file("report.txt", [ 102 "com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run", 103 "__start_thread"]) 104 105 def test_annotate(self): 106 self.common_test_annotate() 107 if not self.use_compiled_java_code: 108 # Currently annotating Java code is only supported when the Java code is compiled. 109 return 110 self.check_file_under_dir("annotated_files", "MainActivity.java") 111 summary_file = os.path.join("annotated_files", "summary") 112 self.check_annotation_summary(summary_file, [ 113 ("MainActivity.java", 80, 80), 114 ("run", 80, 0), 115 ("callFunction", 0, 0), 116 ("line 23", 80, 0)]) 117 118 def test_report_sample(self): 119 self.common_test_report_sample( 120 ["com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run", 121 "__start_thread"]) 122 123 def test_pprof_proto_generator(self): 124 check_strings_with_lines = [] 125 if self.use_compiled_java_code: 126 check_strings_with_lines = [ 127 "com/example/simpleperf/simpleperfexamplepurejava/MainActivity.java", 128 "run"] 129 self.common_test_pprof_proto_generator( 130 check_strings_with_lines=check_strings_with_lines, 131 check_strings_without_lines=[ 132 "com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run"]) 133 134 def test_inferno(self): 135 self.common_test_inferno() 136 self.run_app_profiler() 137 self.run_cmd([INFERNO_SCRIPT, "-sc"]) 138 self.check_inferno_report_html( 139 [('com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run', 80)]) 140 self.run_cmd([INFERNO_SCRIPT, "-sc", "-o", "report2.html"]) 141 self.check_inferno_report_html( 142 [('com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run', 80)], 143 "report2.html") 144 145 def test_inferno_in_another_dir(self): 146 test_dir = 'inferno_testdir' 147 os.mkdir(test_dir) 148 os.chdir(test_dir) 149 self.run_cmd(['app_profiler.py', '--app', self.package_name, 150 '-r', '-e task-clock:u -g --duration 3']) 151 self.check_exist(filename="perf.data") 152 self.run_cmd([INFERNO_SCRIPT, "-sc"]) 153 154 def test_report_html(self): 155 self.common_test_report_html() 156 157 def test_run_simpleperf_without_usb_connection(self): 158 self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MainActivity']) 159 self.run_cmd(['run_simpleperf_without_usb_connection.py', 'start', '-p', 160 self.package_name, '--size_limit', '1M']) 161 self.adb.check_run(['kill-server']) 162 time.sleep(3) 163 # Start adb process outside self.test_dir. Because it will be removed after testing. 164 os.chdir(self.test_dir.parent) 165 self.adb.check_run(['devices']) 166 os.chdir(self.test_dir) 167 self.run_cmd(['run_simpleperf_without_usb_connection.py', 'stop']) 168 self.check_exist(filename="perf.data") 169 self.run_cmd(["report.py", "-g", "-o", "report.txt"]) 170 171 172class TestExamplePureJavaRoot(TestExampleBase): 173 @classmethod 174 def setUpClass(cls): 175 cls.prepare("SimpleperfExamplePureJava", 176 "com.example.simpleperf.simpleperfexamplepurejava", 177 ".MainActivity", 178 adb_root=True) 179 180 def test_app_profiler(self): 181 self.common_test_app_profiler() 182 183 184class TestExamplePureJavaTraceOffCpu(TestExampleBase): 185 @classmethod 186 def setUpClass(cls): 187 cls.prepare("SimpleperfExamplePureJava", 188 "com.example.simpleperf.simpleperfexamplepurejava", 189 ".SleepActivity") 190 191 def test_smoke(self): 192 self.run_app_profiler(record_arg="-g -f 1000 --duration 10 -e cpu-cycles:u --trace-offcpu") 193 self.run_cmd(["report.py", "-g", "-o", "report.txt"]) 194 self.check_strings_in_file("report.txt", [ 195 "com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.run", 196 "com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.RunFunction", 197 "com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.SleepFunction" 198 ]) 199 remove("annotated_files") 200 self.run_cmd(["annotate.py", "-s", self.example_path]) 201 self.check_exist(dirname="annotated_files") 202 if self.use_compiled_java_code: 203 self.check_file_under_dir("annotated_files", "SleepActivity.java") 204 summary_file = os.path.join("annotated_files", "summary") 205 self.check_annotation_summary(summary_file, [ 206 ("SleepActivity.java", 80, 20), 207 ("run", 80, 0), 208 ("RunFunction", 20, 20), 209 ("SleepFunction", 20, 0), 210 ("line 24", 1, 0), 211 ("line 32", 20, 0)]) 212 self.run_cmd([INFERNO_SCRIPT, "-sc"]) 213 self.check_inferno_report_html( 214 [('com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.run', 80), 215 ('com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.RunFunction', 216 20), 217 ('com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.SleepFunction', 218 20)]) 219