#!/usr/bin/env python3 # # Copyright (C) 2021 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import signal import subprocess import sys import time from simpleperf_utils import is_windows, remove from . app_test import TestExampleBase from . test_utils import TestHelper, INFERNO_SCRIPT class TestExamplePureJava(TestExampleBase): @classmethod def setUpClass(cls): cls.prepare("SimpleperfExamplePureJava", "com.example.simpleperf.simpleperfexamplepurejava", ".MainActivity") def test_app_profiler(self): self.common_test_app_profiler() def test_app_profiler_profile_from_launch(self): self.run_app_profiler(start_activity=True, build_binary_cache=False) self.run_cmd(["report.py", "-g", "-o", "report.txt"]) self.check_strings_in_file("report.txt", [ "com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run", "__start_thread"]) def test_app_profiler_multiprocesses(self): self.adb.check_run(['shell', 'am', 'force-stop', self.package_name]) self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MultiProcessActivity']) # Wait until both MultiProcessActivity and MultiProcessService set up. time.sleep(3) self.run_app_profiler(start_activity=False) self.run_cmd(["report.py", "-o", "report.txt"]) self.check_strings_in_file("report.txt", ["BusyService", "BusyThread"]) def test_app_profiler_with_ctrl_c(self): if is_windows(): return self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MainActivity']) time.sleep(1) args = [sys.executable, TestHelper.script_path("app_profiler.py"), "--app", self.package_name, "-r", "--duration 10000", "--disable_adb_root"] subproc = subprocess.Popen(args) time.sleep(3) subproc.send_signal(signal.SIGINT) subproc.wait() self.assertEqual(subproc.returncode, 0) self.run_cmd(["report.py"]) def test_app_profiler_stop_after_app_exit(self): self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MainActivity']) time.sleep(1) subproc = subprocess.Popen( [sys.executable, TestHelper.script_path('app_profiler.py'), '--app', self.package_name, '-r', '--duration 10000', '--disable_adb_root']) time.sleep(3) self.adb.check_run(['shell', 'am', 'force-stop', self.package_name]) subproc.wait() self.assertEqual(subproc.returncode, 0) self.run_cmd(["report.py"]) def test_app_profiler_with_ndk_path(self): # Although we pass an invalid ndk path, it should be able to find tools in default ndk path. self.run_cmd(['app_profiler.py', '--app', self.package_name, '-a', self.activity_name, '--ndk_path', '.']) def test_report(self): self.common_test_report() self.run_cmd(["report.py", "-g", "-o", "report.txt"]) self.check_strings_in_file("report.txt", [ "com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run", "__start_thread"]) def test_profile_with_process_id(self): self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MainActivity']) time.sleep(1) pid = self.adb.check_run_and_return_output([ 'shell', 'pidof', 'com.example.simpleperf.simpleperfexamplepurejava']).strip() self.run_app_profiler(start_activity=False, record_arg='-g --duration 10 -p ' + pid) self.run_cmd(["report.py", "-g", "-o", "report.txt"]) self.check_strings_in_file("report.txt", [ "com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run", "__start_thread"]) def test_annotate(self): self.common_test_annotate() if not self.use_compiled_java_code: # Currently annotating Java code is only supported when the Java code is compiled. return self.check_file_under_dir("annotated_files", "MainActivity.java") summary_file = os.path.join("annotated_files", "summary") self.check_annotation_summary(summary_file, [ ("MainActivity.java", 80, 80), ("run", 80, 0), ("callFunction", 0, 0), ("line 23", 80, 0)]) def test_report_sample(self): self.common_test_report_sample( ["com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run", "__start_thread"]) def test_pprof_proto_generator(self): check_strings_with_lines = [] if self.use_compiled_java_code: check_strings_with_lines = [ "com/example/simpleperf/simpleperfexamplepurejava/MainActivity.java", "run"] self.common_test_pprof_proto_generator( check_strings_with_lines=check_strings_with_lines, check_strings_without_lines=[ "com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run"]) def test_inferno(self): self.common_test_inferno() self.run_app_profiler() self.run_cmd([INFERNO_SCRIPT, "-sc"]) self.check_inferno_report_html( [('com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run', 80)]) self.run_cmd([INFERNO_SCRIPT, "-sc", "-o", "report2.html"]) self.check_inferno_report_html( [('com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run', 80)], "report2.html") def test_inferno_in_another_dir(self): test_dir = 'inferno_testdir' os.mkdir(test_dir) os.chdir(test_dir) self.run_cmd(['app_profiler.py', '--app', self.package_name, '-r', '-e task-clock:u -g --duration 3']) self.check_exist(filename="perf.data") self.run_cmd([INFERNO_SCRIPT, "-sc"]) def test_report_html(self): self.common_test_report_html() def test_run_simpleperf_without_usb_connection(self): self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MainActivity']) self.run_cmd(['run_simpleperf_without_usb_connection.py', 'start', '-p', self.package_name, '--size_limit', '1M']) self.adb.check_run(['kill-server']) time.sleep(3) # Start adb process outside self.test_dir. Because it will be removed after testing. os.chdir(self.test_dir.parent) self.adb.check_run(['devices']) os.chdir(self.test_dir) self.run_cmd(['run_simpleperf_without_usb_connection.py', 'stop']) self.check_exist(filename="perf.data") self.run_cmd(["report.py", "-g", "-o", "report.txt"]) class TestExamplePureJavaRoot(TestExampleBase): @classmethod def setUpClass(cls): cls.prepare("SimpleperfExamplePureJava", "com.example.simpleperf.simpleperfexamplepurejava", ".MainActivity", adb_root=True) def test_app_profiler(self): self.common_test_app_profiler() class TestExamplePureJavaTraceOffCpu(TestExampleBase): @classmethod def setUpClass(cls): cls.prepare("SimpleperfExamplePureJava", "com.example.simpleperf.simpleperfexamplepurejava", ".SleepActivity") def test_smoke(self): self.run_app_profiler(record_arg="-g -f 1000 --duration 10 -e cpu-cycles:u --trace-offcpu") self.run_cmd(["report.py", "-g", "-o", "report.txt"]) self.check_strings_in_file("report.txt", [ "com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.run", "com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.RunFunction", "com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.SleepFunction" ]) remove("annotated_files") self.run_cmd(["annotate.py", "-s", self.example_path]) self.check_exist(dirname="annotated_files") if self.use_compiled_java_code: self.check_file_under_dir("annotated_files", "SleepActivity.java") summary_file = os.path.join("annotated_files", "summary") self.check_annotation_summary(summary_file, [ ("SleepActivity.java", 80, 20), ("run", 80, 0), ("RunFunction", 20, 20), ("SleepFunction", 20, 0), ("line 24", 1, 0), ("line 32", 20, 0)]) self.run_cmd([INFERNO_SCRIPT, "-sc"]) self.check_inferno_report_html( [('com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.run', 80), ('com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.RunFunction', 20), ('com.example.simpleperf.simpleperfexamplepurejava.SleepActivity$1.SleepFunction', 20)])