10930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui#!/usr/bin/env python 20930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# 30930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# Copyright (C) 2015 The Android Open Source Project 40930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# 50930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# Licensed under the Apache License, Version 2.0 (the "License"); 60930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# you may not use this file except in compliance with the License. 70930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# You may obtain a copy of the License at 80930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# 90930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# http://www.apache.org/licenses/LICENSE-2.0 100930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# 110930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# Unless required by applicable law or agreed to in writing, software 120930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# distributed under the License is distributed on an "AS IS" BASIS, 130930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 140930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# See the License for the specific language governing permissions and 150930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# limitations under the License. 160930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui# 170930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui"""Simpleperf runtest runner: run simpleperf runtests on host or on device. 180930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 19d4360f8c681a10d9d58173995aca2166aec65386Yabin CuiFor a simpleperf runtest like one_function test, it contains following steps: 20d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui1. Run simpleperf record command to record simpleperf_runtest_one_function's 21d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui running samples, which is generated in perf.data. 22d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui2. Run simpleperf report command to parse perf.data, generate perf.report. 23d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui4. Parse perf.report and see if it matches expectation. 240930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 25d4360f8c681a10d9d58173995aca2166aec65386Yabin CuiThe information of all runtests is stored in runtest.conf. 260930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui""" 270930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 280930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiimport re 290930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiimport subprocess 304a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cuiimport sys 310930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiimport xml.etree.ElementTree as ET 320930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 330930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 34d4360f8c681a10d9d58173995aca2166aec65386Yabin Cuiclass CallTreeNode(object): 35d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 36d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def __init__(self, name): 37d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.name = name 38d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.children = [] 39d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 40d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def add_child(self, child): 41d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.children.append(child) 42d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 43d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def __str__(self): 44d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return 'CallTreeNode:\n' + '\n'.join(self._dump(1)) 45d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 46d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def _dump(self, indent): 47d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui indent_str = ' ' * indent 48d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs = [indent_str + self.name] 49d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for child in self.children: 50d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.extend(child._dump(indent + 1)) 51d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return strs 52d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 53d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 540930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiclass Symbol(object): 550930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 56d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def __init__(self, name, comm, overhead, children_overhead): 570930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.name = name 580930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.comm = comm 590930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.overhead = overhead 60d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui # children_overhead is the overhead sum of this symbol and functions 61d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui # called by this symbol. 62d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.children_overhead = children_overhead 63d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.call_tree = None 64d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 65d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def set_call_tree(self, call_tree): 66d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.call_tree = call_tree 670930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 680930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui def __str__(self): 69d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs = [] 70d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.append('Symbol name=%s comm=%s overhead=%f children_overhead=%f' % ( 71d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.name, self.comm, self.overhead, self.children_overhead)) 72d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if self.call_tree: 73d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.append('\t%s' % self.call_tree) 74d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return '\n'.join(strs) 750930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 760930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 770930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiclass SymbolOverheadRequirement(object): 780930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 794a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui def __init__(self, symbol_name=None, comm=None, min_overhead=None, 800930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui max_overhead=None): 810930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.symbol_name = symbol_name 820930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.comm = comm 830930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.min_overhead = min_overhead 840930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.max_overhead = max_overhead 850930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 860930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui def __str__(self): 870930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui strs = [] 884a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui strs.append('SymbolOverheadRequirement') 894a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if self.symbol_name is not None: 904a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui strs.append('symbol_name=%s' % self.symbol_name) 910930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if self.comm is not None: 920930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui strs.append('comm=%s' % self.comm) 930930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if self.min_overhead is not None: 940930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui strs.append('min_overhead=%f' % self.min_overhead) 950930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if self.max_overhead is not None: 960930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui strs.append('max_overhead=%f' % self.max_overhead) 970930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return ' '.join(strs) 980930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 990930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui def is_match(self, symbol): 1004a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if self.symbol_name is not None: 1014a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if self.symbol_name != symbol.name: 1024a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui return False 1030930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if self.comm is not None: 1040930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if self.comm != symbol.comm: 1050930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return False 1060930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return True 1070930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 108d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def check_overhead(self, overhead): 1090930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if self.min_overhead is not None: 110d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if self.min_overhead > overhead: 1110930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return False 1120930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if self.max_overhead is not None: 113d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if self.max_overhead < overhead: 114d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return False 115d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return True 116d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 117d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 118d4360f8c681a10d9d58173995aca2166aec65386Yabin Cuiclass SymbolRelationRequirement(object): 119d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 120d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def __init__(self, symbol_name, comm=None): 121d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.symbol_name = symbol_name 122d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.comm = comm 123d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.children = [] 124d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 125d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def add_child(self, child): 126d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.children.append(child) 127d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 128d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def __str__(self): 129d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return 'SymbolRelationRequirement:\n' + '\n'.join(self._dump(1)) 130d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 131d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def _dump(self, indent): 132d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui indent_str = ' ' * indent 133d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs = [indent_str + self.symbol_name + 134d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui (' ' + self.comm if self.comm else '')] 135d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for child in self.children: 136d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.extend(child._dump(indent + 1)) 137d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return strs 138d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 139d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def is_match(self, symbol): 140d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if symbol.name != self.symbol_name: 141d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return False 142d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if self.comm is not None: 143d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if symbol.comm != self.comm: 144d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return False 145d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return True 146d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 147d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def check_relation(self, call_tree): 148d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not call_tree: 149d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return False 150d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if self.symbol_name != call_tree.name: 151d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return False 152d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for child in self.children: 153d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui child_matched = False 154d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for node in call_tree.children: 155d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if child.check_relation(node): 156d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui child_matched = True 157d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui break 158d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not child_matched: 1590930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return False 1600930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return True 1610930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 1620930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 1630930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiclass Test(object): 1640930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 165d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def __init__( 166d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self, 167d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui test_name, 168d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui executable_name, 1694a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui report_options, 170d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_overhead_requirements, 171d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_children_overhead_requirements, 172d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_relation_requirements): 1730930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.test_name = test_name 1740930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.executable_name = executable_name 1754a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui self.report_options = report_options 1760930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.symbol_overhead_requirements = symbol_overhead_requirements 177d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.symbol_children_overhead_requirements = ( 178d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_children_overhead_requirements) 179d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui self.symbol_relation_requirements = symbol_relation_requirements 1800930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 1810930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui def __str__(self): 1820930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui strs = [] 1830930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui strs.append('Test test_name=%s' % self.test_name) 1840930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui strs.append('\texecutable_name=%s' % self.executable_name) 1854a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui strs.append('\treport_options=%s' % (' '.join(self.report_options))) 186d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.append('\tsymbol_overhead_requirements:') 187d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for req in self.symbol_overhead_requirements: 188d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.append('\t\t%s' % req) 189d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.append('\tsymbol_children_overhead_requirements:') 190d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for req in self.symbol_children_overhead_requirements: 191d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.append('\t\t%s' % req) 192d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.append('\tsymbol_relation_requirements:') 193d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for req in self.symbol_relation_requirements: 194d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui strs.append('\t\t%s' % req) 1950930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return '\n'.join(strs) 1960930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 1970930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 1980930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuidef load_config_file(config_file): 1990930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui tests = [] 2000930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui tree = ET.parse(config_file) 2010930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui root = tree.getroot() 2020930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui assert root.tag == 'runtests' 2030930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui for test in root: 2040930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui assert test.tag == 'test' 2050930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui test_name = test.attrib['name'] 2060930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui executable_name = None 2074a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui report_options = [] 2080930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui symbol_overhead_requirements = [] 209d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_children_overhead_requirements = [] 210d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_relation_requirements = [] 2110930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui for test_item in test: 2120930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if test_item.tag == 'executable': 2130930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui executable_name = test_item.attrib['name'] 2144a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui elif test_item.tag == 'report': 2154a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui report_options = test_item.attrib['option'].split() 216d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui elif (test_item.tag == 'symbol_overhead' or 217d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui test_item.tag == 'symbol_children_overhead'): 2180930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui for symbol_item in test_item: 2190930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui assert symbol_item.tag == 'symbol' 2204a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui symbol_name = None 2214a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if 'name' in symbol_item.attrib: 2224a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui symbol_name = symbol_item.attrib['name'] 2230930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui comm = None 2240930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if 'comm' in symbol_item.attrib: 2250930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui comm = symbol_item.attrib['comm'] 2260930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui overhead_min = None 2270930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if 'min' in symbol_item.attrib: 2280930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui overhead_min = float(symbol_item.attrib['min']) 2290930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui overhead_max = None 2300930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if 'max' in symbol_item.attrib: 2310930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui overhead_max = float(symbol_item.attrib['max']) 2320930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 233d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if test_item.tag == 'symbol_overhead': 234d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_overhead_requirements.append( 235d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui SymbolOverheadRequirement( 236d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_name, 237d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui comm, 238d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui overhead_min, 239d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui overhead_max) 240d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui ) 241d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui else: 242d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_children_overhead_requirements.append( 243d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui SymbolOverheadRequirement( 244d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_name, 245d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui comm, 246d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui overhead_min, 247d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui overhead_max)) 248d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui elif test_item.tag == 'symbol_callgraph_relation': 249d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for symbol_item in test_item: 250d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui req = load_symbol_relation_requirement(symbol_item) 251d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_relation_requirements.append(req) 2520930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 2530930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui tests.append( 254d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui Test( 255d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui test_name, 256d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui executable_name, 2574a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui report_options, 258d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_overhead_requirements, 259d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_children_overhead_requirements, 260d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_relation_requirements)) 2610930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return tests 2620930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 2630930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 264d4360f8c681a10d9d58173995aca2166aec65386Yabin Cuidef load_symbol_relation_requirement(symbol_item): 265d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_name = symbol_item.attrib['name'] 266d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui comm = None 267d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if 'comm' in symbol_item.attrib: 268d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui comm = symbol_item.attrib['comm'] 269d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui req = SymbolRelationRequirement(symbol_name, comm) 270d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for item in symbol_item: 271d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui child_req = load_symbol_relation_requirement(item) 272d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui req.add_child(child_req) 273d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return req 274d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 275d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 2760930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiclass Runner(object): 2770930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 2780930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui def __init__(self, perf_path): 2790930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self.perf_path = perf_path 2800930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 281d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def record(self, test_executable_name, record_file, additional_options=[]): 282d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui call_args = [self.perf_path, 283d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 'record'] + additional_options + ['-e', 284d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 'cpu-cycles:u', 285d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui '-o', 286d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui record_file, 287d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui test_executable_name] 2880930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self._call(call_args) 2890930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 290d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def report(self, record_file, report_file, additional_options=[]): 291d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui call_args = [self.perf_path, 292d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 'report'] + additional_options + ['-i', 293d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui record_file] 2940930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui self._call(call_args, report_file) 2950930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 2960930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui def _call(self, args, output_file=None): 2970930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui pass 2980930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 2990930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3000930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiclass HostRunner(Runner): 3010930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3020930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui """Run perf test on host.""" 3030930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3040930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui def _call(self, args, output_file=None): 3050930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui output_fh = None 3060930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if output_file is not None: 3070930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui output_fh = open(output_file, 'w') 3080930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui subprocess.check_call(args, stdout=output_fh) 3090930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if output_fh is not None: 3100930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui output_fh.close() 3110930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3120930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3130930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiclass DeviceRunner(Runner): 3140930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3150930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui """Run perf test on device.""" 3160930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3170930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui def _call(self, args, output_file=None): 3180930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui output_fh = None 3190930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if output_file is not None: 3200930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui output_fh = open(output_file, 'w') 3210930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui args_with_adb = ['adb', 'shell'] 3220930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui args_with_adb.extend(args) 3230930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui subprocess.check_call(args_with_adb, stdout=output_fh) 3240930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if output_fh is not None: 3250930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui output_fh.close() 3260930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3270930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3280930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiclass ReportAnalyzer(object): 3290930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 3300930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui """Check if perf.report matches expectation in Configuration.""" 3310930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 332d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def _read_report_file(self, report_file, has_callgraph): 333d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui fh = open(report_file, 'r') 334d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui lines = fh.readlines() 335d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui fh.close() 336d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 337d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui lines = [x.rstrip() for x in lines] 338d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui blank_line_index = -1 339d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for i in range(len(lines)): 340d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not lines[i]: 341d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui blank_line_index = i 342d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui assert blank_line_index != -1 343d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui assert blank_line_index + 1 < len(lines) 344d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui title_line = lines[blank_line_index + 1] 345d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui report_item_lines = lines[blank_line_index + 2:] 346d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 347d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if has_callgraph: 348d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui assert re.search(r'^Children\s+Self\s+Command.+Symbol$', title_line) 349d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui else: 350d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui assert re.search(r'^Overhead\s+Command.+Symbol$', title_line) 351d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 352d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return self._parse_report_items(report_item_lines, has_callgraph) 353d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 354d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def _parse_report_items(self, lines, has_callgraph): 3550930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui symbols = [] 356d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui cur_symbol = None 357d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui call_tree_stack = {} 358d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui vertical_columns = [] 359d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui last_node = None 360d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui last_depth = -1 361d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 362d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for line in lines: 363d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not line: 364d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui continue 365d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not line[0].isspace(): 366d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if has_callgraph: 367d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui m = re.search(r'^([\d\.]+)%\s+([\d\.]+)%\s+(\S+).*\s+(\S+)$', line) 368d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui children_overhead = float(m.group(1)) 369d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui overhead = float(m.group(2)) 370d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui comm = m.group(3) 371d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_name = m.group(4) 372d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui cur_symbol = Symbol(symbol_name, comm, overhead, children_overhead) 373d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbols.append(cur_symbol) 374d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui else: 375d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui m = re.search(r'^([\d\.]+)%\s+(\S+).*\s+(\S+)$', line) 376d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui overhead = float(m.group(1)) 377d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui comm = m.group(2) 378d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol_name = m.group(3) 379d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui cur_symbol = Symbol(symbol_name, comm, overhead, 0) 380d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbols.append(cur_symbol) 381d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui # Each report item can have different column depths. 382d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui vertical_columns = [] 3830930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui else: 384d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for i in range(len(line)): 385d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if line[i] == '|': 386d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not vertical_columns or vertical_columns[-1] < i: 387d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui vertical_columns.append(i) 388d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 389d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not line.strip('| \t'): 3900930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui continue 391d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if line.find('-') == -1: 392d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui function_name = line.strip('| \t') 393d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui node = CallTreeNode(function_name) 394d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui last_node.add_child(node) 395d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui last_node = node 396d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui call_tree_stack[last_depth] = node 397d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui else: 398d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui pos = line.find('-') 399d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui depth = -1 400d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for i in range(len(vertical_columns)): 401d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if pos >= vertical_columns[i]: 402d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui depth = i 403d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui assert depth != -1 404d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 405d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui line = line.strip('|- \t') 406d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui m = re.search(r'^[\d\.]+%[-\s]+(.+)$', line) 407d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if m: 408d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui function_name = m.group(1) 409d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui else: 410d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui function_name = line 411d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 412d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui node = CallTreeNode(function_name) 413d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if depth == 0: 414d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui cur_symbol.set_call_tree(node) 415d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 416d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui else: 417d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui call_tree_stack[depth - 1].add_child(node) 418d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui call_tree_stack[depth] = node 419d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui last_node = node 420d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui last_depth = depth 4210930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 4220930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return symbols 4230930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 424d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def check_report_file(self, test, report_file, has_callgraph): 425d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbols = self._read_report_file(report_file, has_callgraph) 426d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not self._check_symbol_overhead_requirements(test, symbols): 427d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return False 428d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if has_callgraph: 429d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not self._check_symbol_children_overhead_requirements(test, symbols): 430d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return False 431d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not self._check_symbol_relation_requirements(test, symbols): 432d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return False 433d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return True 4340930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 435d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def _check_symbol_overhead_requirements(self, test, symbols): 4360930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui result = True 4370930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui matched = [False] * len(test.symbol_overhead_requirements) 4384a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui matched_overhead = [0] * len(test.symbol_overhead_requirements) 4390930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui for symbol in symbols: 4400930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui for i in range(len(test.symbol_overhead_requirements)): 441d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui req = test.symbol_overhead_requirements[i] 442d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if req.is_match(symbol): 4430930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui matched[i] = True 4444a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui matched_overhead[i] += symbol.overhead 4450930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui for i in range(len(matched)): 4460930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui if not matched[i]: 4470930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui print 'requirement (%s) has no matched symbol in test %s' % ( 4480930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui test.symbol_overhead_requirements[i], test) 4490930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui result = False 4504a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui else: 4514a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui fulfilled = req.check_overhead(matched_overhead[i]) 4524a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if not fulfilled: 4534a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui print "Symbol (%s) doesn't match requirement (%s) in test %s" % ( 4544a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui symbol, req, test) 4554a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui result = False 4560930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui return result 4570930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 458d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def _check_symbol_children_overhead_requirements(self, test, symbols): 459d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui result = True 460d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui matched = [False] * len(test.symbol_children_overhead_requirements) 461d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for symbol in symbols: 462d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for i in range(len(test.symbol_children_overhead_requirements)): 463d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui req = test.symbol_children_overhead_requirements[i] 464d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if req.is_match(symbol): 465d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui matched[i] = True 466d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui fulfilled = req.check_overhead(symbol.children_overhead) 467d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not fulfilled: 468d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui print "Symbol (%s) doesn't match requirement (%s) in test %s" % ( 469d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol, req, test) 470d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui result = False 471d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for i in range(len(matched)): 472d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not matched[i]: 473d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui print 'requirement (%s) has no matched symbol in test %s' % ( 474d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui test.symbol_children_overhead_requirements[i], test) 475d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui result = False 476d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return result 477d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 478d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui def _check_symbol_relation_requirements(self, test, symbols): 479d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui result = True 480d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui matched = [False] * len(test.symbol_relation_requirements) 481d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for symbol in symbols: 482d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for i in range(len(test.symbol_relation_requirements)): 483d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui req = test.symbol_relation_requirements[i] 484d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if req.is_match(symbol): 485d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui matched[i] = True 486d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui fulfilled = req.check_relation(symbol.call_tree) 487d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not fulfilled: 488d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui print "Symbol (%s) doesn't match requirement (%s) in test %s" % ( 489d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui symbol, req, test) 490d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui result = False 491d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui for i in range(len(matched)): 492d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui if not matched[i]: 493d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui print 'requirement (%s) has no matched symbol in test %s' % ( 494d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui test.symbol_relation_requirements[i], test) 495d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui result = False 496d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui return result 497d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 4980930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 4994a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cuidef runtest(host, device, normal, callgraph, selected_tests): 5000930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui tests = load_config_file('runtest.conf') 5010930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui host_runner = HostRunner('simpleperf') 5020930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui device_runner = DeviceRunner('simpleperf') 5030930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui report_analyzer = ReportAnalyzer() 5040930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui for test in tests: 5054a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if selected_tests is not None: 5064a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if test.test_name not in selected_tests: 5074a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui continue 5084a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if host and normal: 5094a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui host_runner.record(test.executable_name, 'perf.data') 5104a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui host_runner.report('perf.data', 'perf.report', 5114a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui additional_options = test.report_options) 5124a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui result = report_analyzer.check_report_file( 5134a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui test, 'perf.report', False) 5144a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui print 'test %s on host %s' % ( 5154a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui test.test_name, 'Succeeded' if result else 'Failed') 5164a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if not result: 5174a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui exit(1) 5184a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui 5194a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if device and normal: 5204a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui device_runner.record(test.executable_name, '/data/perf.data') 5214a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui device_runner.report('/data/perf.data', 'perf.report', 5224a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui additional_options = test.report_options) 5234a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui result = report_analyzer.check_report_file(test, 'perf.report', False) 5244a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui print 'test %s on device %s' % ( 5254a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui test.test_name, 'Succeeded' if result else 'Failed') 5264a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if not result: 5274a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui exit(1) 5284a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui 5294a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if host and callgraph: 5304a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui host_runner.record( 5314a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui test.executable_name, 5324a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui 'perf_g.data', 5334a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui additional_options=['-g']) 5344a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui host_runner.report( 5354a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui 'perf_g.data', 5364a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui 'perf_g.report', 5374a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui additional_options=['-g'] + test.report_options) 5384a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui result = report_analyzer.check_report_file(test, 'perf_g.report', True) 5394a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui print 'call-graph test %s on host %s' % ( 5404a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui test.test_name, 'Succeeded' if result else 'Failed') 5414a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if not result: 5424a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui exit(1) 5434a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui 5444a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if device and callgraph: 5454a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui device_runner.record( 5464a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui test.executable_name, 5474a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui '/data/perf_g.data', 5484a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui additional_options=['-g']) 5494a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui device_runner.report( 5504a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui '/data/perf_g.data', 5514a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui 'perf_g.report', 5524a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui additional_options=['-g'] + test.report_options) 5534a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui result = report_analyzer.check_report_file(test, 'perf_g.report', True) 5544a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui print 'call-graph test %s on device %s' % ( 5554a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui test.test_name, 'Succeeded' if result else 'Failed') 5564a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if not result: 5574a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui exit(1) 558d4360f8c681a10d9d58173995aca2166aec65386Yabin Cui 5594a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cuidef main(): 5604a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui host = True 5614a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui device = True 5624a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui normal = True 5634a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui callgraph = True 5644a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui selected_tests = None 5654a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui i = 1 5664a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui while i < len(sys.argv): 5674a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if sys.argv[i] == '--host': 5684a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui host = True 5694a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui device = False 5704a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui elif sys.argv[i] == '--device': 5714a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui host = False 5724a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui device = True 5734a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui elif sys.argv[i] == '--normal': 5744a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui normal = True 5754a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui callgraph = False 5764a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui elif sys.argv[i] == '--callgraph': 5774a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui normal = False 5784a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui callgraph = True 5794a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui elif sys.argv[i] == '--test': 5804a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if i < len(sys.argv): 5814a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui i += 1 5824a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui for test in sys.argv[i].split(','): 5834a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui if selected_tests is None: 5844a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui selected_tests = {} 5854a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui selected_tests[test] = True 5864a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui i += 1 5874a6c58dba06a907c2d687ff0983469c6abe640a7Yabin Cui runtest(host, device, normal, callgraph, selected_tests) 5880930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui 5890930ea88ef02f784044106c67b11f9b82afbda5dYabin Cuiif __name__ == '__main__': 5900930ea88ef02f784044106c67b11f9b82afbda5dYabin Cui main() 591