• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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