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
18
19from simpleperf_utils import remove
20from . app_test import TestExampleBase
21from . test_utils import INFERNO_SCRIPT, TestHelper
22
23
24class TestExampleWithNative(TestExampleBase):
25    @classmethod
26    def setUpClass(cls):
27        cls.prepare("SimpleperfExampleWithNative",
28                    "com.example.simpleperf.simpleperfexamplewithnative",
29                    ".MainActivity")
30
31    def test_app_profiler(self):
32        self.common_test_app_profiler()
33
34    def test_app_profiler_profile_from_launch(self):
35        self.run_app_profiler(start_activity=True, build_binary_cache=False)
36        self.run_cmd(["report.py", "-g", "-o", "report.txt"])
37        self.check_strings_in_file("report.txt", ["BusyLoopThread", "__start_thread"])
38
39    def test_report(self):
40        self.common_test_report()
41        self.run_cmd(["report.py", "-g", "-o", "report.txt"])
42        self.check_strings_in_file("report.txt", ["BusyLoopThread", "__start_thread"])
43
44    def test_annotate(self):
45        self.common_test_annotate()
46        self.check_file_under_dir("annotated_files", "native-lib.cpp")
47        summary_file = os.path.join("annotated_files", "summary")
48        self.check_annotation_summary(summary_file, [
49            ("native-lib.cpp", 20, 0),
50            ("BusyLoopThread", 20, 0),
51            ("line 46", 20, 0)])
52
53    def test_report_sample(self):
54        self.common_test_report_sample(
55            ["BusyLoopThread",
56             "__start_thread"])
57
58    def test_pprof_proto_generator(self):
59        check_strings_with_lines = [
60            "native-lib.cpp",
61            "BusyLoopThread",
62            # Check if dso name in perf.data is replaced by binary path in binary_cache.
63            'filename: binary_cache']
64        self.common_test_pprof_proto_generator(
65            check_strings_with_lines,
66            check_strings_without_lines=["BusyLoopThread"])
67
68    def test_inferno(self):
69        self.common_test_inferno()
70        self.run_app_profiler()
71        self.run_cmd([INFERNO_SCRIPT, "-sc"])
72        self.check_inferno_report_html([('BusyLoopThread', 20)])
73
74    def test_report_html(self):
75        self.common_test_report_html()
76        self.run_cmd(['report_html.py', '--add_source_code', '--source_dirs', 'testdata',
77                      '--add_disassembly', '--binary_filter', "libnative-lib.so"])
78
79
80class TestExampleWithNativeRoot(TestExampleBase):
81    @classmethod
82    def setUpClass(cls):
83        cls.prepare("SimpleperfExampleWithNative",
84                    "com.example.simpleperf.simpleperfexamplewithnative",
85                    ".MainActivity",
86                    adb_root=True)
87
88    def test_app_profiler(self):
89        self.common_test_app_profiler()
90
91
92class TestExampleWithNativeTraceOffCpu(TestExampleBase):
93    @classmethod
94    def setUpClass(cls):
95        cls.prepare("SimpleperfExampleWithNative",
96                    "com.example.simpleperf.simpleperfexamplewithnative",
97                    ".SleepActivity")
98
99    def test_smoke(self):
100        self.run_app_profiler(record_arg="-g -f 1000 --duration 10 -e cpu-cycles:u --trace-offcpu")
101        self.run_cmd(["report.py", "-g", "--comms", "SleepThread", "-o", "report.txt"])
102        self.check_strings_in_file("report.txt", [
103            "SleepThread(void*)",
104            "RunFunction()",
105            "SleepFunction(unsigned long long)"])
106        remove("annotated_files")
107        self.run_cmd(["annotate.py", "-s", self.example_path, "--comm", "SleepThread"])
108        self.check_exist(dirname="annotated_files")
109        self.check_file_under_dir("annotated_files", "native-lib.cpp")
110        summary_file = os.path.join("annotated_files", "summary")
111        self.check_annotation_summary(summary_file, [
112            ("native-lib.cpp", 80, 20),
113            ("SleepThread", 80, 0),
114            ("RunFunction", 20, 20),
115            ("SleepFunction", 20, 0),
116            ("line 73", 20, 0),
117            ("line 83", 20, 0)])
118        self.run_cmd([INFERNO_SCRIPT, "-sc"])
119        self.check_inferno_report_html([('SleepThread', 80),
120                                        ('RunFunction', 20),
121                                        ('SleepFunction', 20)])
122
123
124class TestExampleWithNativeJniCall(TestExampleBase):
125    @classmethod
126    def setUpClass(cls):
127        cls.prepare("SimpleperfExampleWithNative",
128                    "com.example.simpleperf.simpleperfexamplewithnative",
129                    ".MixActivity")
130
131    def test_smoke(self):
132        self.run_app_profiler()
133        self.run_cmd(["report.py", "-g", "--comms", "BusyThread", "-o", "report.txt"])
134        self.check_strings_in_file("report.txt", [
135            "com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run",
136            "Java_com_example_simpleperf_simpleperfexamplewithnative_MixActivity_callFunction"])
137        remove("annotated_files")
138        self.run_cmd(["annotate.py", "-s", self.example_path, "--comm", "BusyThread"])
139        self.check_exist(dirname="annotated_files")
140        self.check_file_under_dir("annotated_files", "native-lib.cpp")
141        summary_file = os.path.join("annotated_files", "summary")
142        self.check_annotation_summary(summary_file, [("native-lib.cpp", 5, 0), ("line 40", 5, 0)])
143        if self.use_compiled_java_code:
144            self.check_file_under_dir("annotated_files", "MixActivity.java")
145            self.check_annotation_summary(summary_file, [
146                ("MixActivity.java", 80, 0),
147                ("run", 80, 0),
148                ("line 26", 20, 0),
149                ("native-lib.cpp", 5, 0),
150                ("line 40", 5, 0)])
151
152        self.run_cmd([INFERNO_SCRIPT, "-sc"])
153
154
155class TestExampleWithNativeForce32Bit(TestExampleWithNative):
156    @classmethod
157    def setUpClass(cls):
158        cls.prepare("SimpleperfExampleWithNative",
159                    "com.example.simpleperf.simpleperfexamplewithnative",
160                    ".MainActivity",
161                    abi=TestHelper.get_32bit_abi())
162
163
164class TestExampleWithNativeRootForce32Bit(TestExampleWithNativeRoot):
165    @classmethod
166    def setUpClass(cls):
167        cls.prepare("SimpleperfExampleWithNative",
168                    "com.example.simpleperf.simpleperfexamplewithnative",
169                    ".MainActivity",
170                    abi=TestHelper.get_32bit_abi(),
171                    adb_root=False)
172
173
174class TestExampleWithNativeTraceOffCpuForce32Bit(TestExampleWithNativeTraceOffCpu):
175    @classmethod
176    def setUpClass(cls):
177        cls.prepare("SimpleperfExampleWithNative",
178                    "com.example.simpleperf.simpleperfexamplewithnative",
179                    ".SleepActivity",
180                    abi=TestHelper.get_32bit_abi())
181