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 collections 18import json 19import os 20import re 21import tempfile 22from typing import Any, Dict, List, Set 23 24from . test_utils import INFERNO_SCRIPT, TestBase, TestHelper 25 26 27class TestInferno(TestBase): 28 def get_report(self, options: List[str]) -> str: 29 self.run_cmd([INFERNO_SCRIPT] + options) 30 with open('report.html', 'r') as fh: 31 return fh.read() 32 33 def test_proguard_mapping_file(self): 34 """ Test --proguard-mapping-file option. """ 35 testdata_file = TestHelper.testdata_path('perf_need_proguard_mapping.data') 36 proguard_mapping_file = TestHelper.testdata_path('proguard_mapping.txt') 37 original_methodname = 'androidx.fragment.app.FragmentActivity.startActivityForResult' 38 # Can't show original method name without proguard mapping file. 39 self.assertNotIn(original_methodname, self.get_report( 40 ['--record_file', testdata_file, '-sc'])) 41 # Show original method name with proguard mapping file. 42 self.assertIn(original_methodname, self.get_report( 43 ['--record_file', testdata_file, '-sc', '--proguard-mapping-file', proguard_mapping_file])) 44 45 def test_trace_offcpu(self): 46 """ Test --trace-offcpu option. """ 47 testdata_file = TestHelper.testdata_path('perf_with_trace_offcpu_v2.data') 48 report = self.get_report(['--record_file', testdata_file, 49 '-sc', '--trace-offcpu', 'off-cpu']) 50 self.assertIn('Thread 6525 (com.google.samples.apps.sunflower) (42 samples)', report) 51 52 def test_sample_filters(self): 53 def get_threads_for_filter(filter: str) -> Set[int]: 54 report = self.get_report( 55 ['--record_file', TestHelper.testdata_path('perf_display_bitmaps.data'), 56 '-sc'] + filter.split()) 57 threads = set() 58 pattern = re.compile(r'Thread\s+(\d+)\s+') 59 threads = set() 60 for m in re.finditer(pattern, report): 61 threads.add(int(m.group(1))) 62 return threads 63 64 self.assertNotIn(31850, get_threads_for_filter('--exclude-pid 31850')) 65 self.assertIn(31850, get_threads_for_filter('--include-pid 31850')) 66 self.assertNotIn(31881, get_threads_for_filter('--exclude-tid 31881')) 67 self.assertIn(31881, get_threads_for_filter('--include-tid 31881')) 68 self.assertNotIn(31881, get_threads_for_filter( 69 '--exclude-process-name com.example.android.displayingbitmaps')) 70 self.assertIn(31881, get_threads_for_filter( 71 '--include-process-name com.example.android.displayingbitmaps')) 72 self.assertNotIn(31850, get_threads_for_filter( 73 '--exclude-thread-name com.example.android.displayingbitmaps')) 74 self.assertIn(31850, get_threads_for_filter( 75 '--include-thread-name com.example.android.displayingbitmaps')) 76 77 with tempfile.NamedTemporaryFile('w', delete=False) as filter_file: 78 filter_file.write('GLOBAL_BEGIN 684943449406175\nGLOBAL_END 684943449406176') 79 filter_file.flush() 80 threads = get_threads_for_filter('--filter-file ' + filter_file.name) 81 self.assertIn(31881, threads) 82 self.assertNotIn(31850, threads) 83 os.unlink(filter_file.name) 84 85 def test_show_art_frames(self): 86 art_frame_str = 'art::interpreter::DoCall' 87 options = ['--record_file', 88 TestHelper.testdata_path('perf_with_interpreter_frames.data'), '-sc'] 89 report = self.get_report(options) 90 self.assertNotIn(art_frame_str, report) 91 report = self.get_report(options + ['--show-art-frames']) 92 self.assertIn(art_frame_str, report) 93