1*8296aa0fSIan Rogers# SPDX-License-Identifier: GPL-2.0 2*8296aa0fSIan Rogers 3*8296aa0fSIan Rogersfrom __future__ import print_function 4*8296aa0fSIan Rogers 5*8296aa0fSIan Rogersimport os 6*8296aa0fSIan Rogersimport sys 7*8296aa0fSIan Rogersimport glob 8*8296aa0fSIan Rogersimport optparse 9*8296aa0fSIan Rogersimport platform 10*8296aa0fSIan Rogersimport tempfile 11*8296aa0fSIan Rogersimport logging 12*8296aa0fSIan Rogersimport re 13*8296aa0fSIan Rogersimport shutil 14*8296aa0fSIan Rogersimport subprocess 15*8296aa0fSIan Rogers 16*8296aa0fSIan Rogerstry: 17*8296aa0fSIan Rogers import configparser 18*8296aa0fSIan Rogersexcept ImportError: 19*8296aa0fSIan Rogers import ConfigParser as configparser 20*8296aa0fSIan Rogers 21*8296aa0fSIan Rogersdef data_equal(a, b): 22*8296aa0fSIan Rogers # Allow multiple values in assignment separated by '|' 23*8296aa0fSIan Rogers a_list = a.split('|') 24*8296aa0fSIan Rogers b_list = b.split('|') 25*8296aa0fSIan Rogers 26*8296aa0fSIan Rogers for a_item in a_list: 27*8296aa0fSIan Rogers for b_item in b_list: 28*8296aa0fSIan Rogers if (a_item == b_item): 29*8296aa0fSIan Rogers return True 30*8296aa0fSIan Rogers elif (a_item == '*') or (b_item == '*'): 31*8296aa0fSIan Rogers return True 32*8296aa0fSIan Rogers 33*8296aa0fSIan Rogers return False 34*8296aa0fSIan Rogers 35*8296aa0fSIan Rogersclass Fail(Exception): 36*8296aa0fSIan Rogers def __init__(self, test, msg): 37*8296aa0fSIan Rogers self.msg = msg 38*8296aa0fSIan Rogers self.test = test 39*8296aa0fSIan Rogers def getMsg(self): 40*8296aa0fSIan Rogers return '\'%s\' - %s' % (self.test.path, self.msg) 41*8296aa0fSIan Rogers 42*8296aa0fSIan Rogersclass Notest(Exception): 43*8296aa0fSIan Rogers def __init__(self, test, arch): 44*8296aa0fSIan Rogers self.arch = arch 45*8296aa0fSIan Rogers self.test = test 46*8296aa0fSIan Rogers def getMsg(self): 47*8296aa0fSIan Rogers return '[%s] \'%s\'' % (self.arch, self.test.path) 48*8296aa0fSIan Rogers 49*8296aa0fSIan Rogersclass Unsup(Exception): 50*8296aa0fSIan Rogers def __init__(self, test): 51*8296aa0fSIan Rogers self.test = test 52*8296aa0fSIan Rogers def getMsg(self): 53*8296aa0fSIan Rogers return '\'%s\'' % self.test.path 54*8296aa0fSIan Rogers 55*8296aa0fSIan Rogersclass Event(dict): 56*8296aa0fSIan Rogers terms = [ 57*8296aa0fSIan Rogers 'cpu', 58*8296aa0fSIan Rogers 'flags', 59*8296aa0fSIan Rogers 'type', 60*8296aa0fSIan Rogers 'size', 61*8296aa0fSIan Rogers 'config', 62*8296aa0fSIan Rogers 'sample_period', 63*8296aa0fSIan Rogers 'sample_type', 64*8296aa0fSIan Rogers 'read_format', 65*8296aa0fSIan Rogers 'disabled', 66*8296aa0fSIan Rogers 'inherit', 67*8296aa0fSIan Rogers 'pinned', 68*8296aa0fSIan Rogers 'exclusive', 69*8296aa0fSIan Rogers 'exclude_user', 70*8296aa0fSIan Rogers 'exclude_kernel', 71*8296aa0fSIan Rogers 'exclude_hv', 72*8296aa0fSIan Rogers 'exclude_idle', 73*8296aa0fSIan Rogers 'mmap', 74*8296aa0fSIan Rogers 'comm', 75*8296aa0fSIan Rogers 'freq', 76*8296aa0fSIan Rogers 'inherit_stat', 77*8296aa0fSIan Rogers 'enable_on_exec', 78*8296aa0fSIan Rogers 'task', 79*8296aa0fSIan Rogers 'watermark', 80*8296aa0fSIan Rogers 'precise_ip', 81*8296aa0fSIan Rogers 'mmap_data', 82*8296aa0fSIan Rogers 'sample_id_all', 83*8296aa0fSIan Rogers 'exclude_host', 84*8296aa0fSIan Rogers 'exclude_guest', 85*8296aa0fSIan Rogers 'exclude_callchain_kernel', 86*8296aa0fSIan Rogers 'exclude_callchain_user', 87*8296aa0fSIan Rogers 'wakeup_events', 88*8296aa0fSIan Rogers 'bp_type', 89*8296aa0fSIan Rogers 'config1', 90*8296aa0fSIan Rogers 'config2', 91*8296aa0fSIan Rogers 'branch_sample_type', 92*8296aa0fSIan Rogers 'sample_regs_user', 93*8296aa0fSIan Rogers 'sample_stack_user', 94*8296aa0fSIan Rogers ] 95*8296aa0fSIan Rogers 96*8296aa0fSIan Rogers def add(self, data): 97*8296aa0fSIan Rogers for key, val in data: 98*8296aa0fSIan Rogers log.debug(" %s = %s" % (key, val)) 99*8296aa0fSIan Rogers self[key] = val 100*8296aa0fSIan Rogers 101*8296aa0fSIan Rogers def __init__(self, name, data, base): 102*8296aa0fSIan Rogers log.debug(" Event %s" % name); 103*8296aa0fSIan Rogers self.name = name; 104*8296aa0fSIan Rogers self.group = '' 105*8296aa0fSIan Rogers self.add(base) 106*8296aa0fSIan Rogers self.add(data) 107*8296aa0fSIan Rogers 108*8296aa0fSIan Rogers def equal(self, other): 109*8296aa0fSIan Rogers for t in Event.terms: 110*8296aa0fSIan Rogers log.debug(" [%s] %s %s" % (t, self[t], other[t])); 111*8296aa0fSIan Rogers if t not in self or t not in other: 112*8296aa0fSIan Rogers return False 113*8296aa0fSIan Rogers if not data_equal(self[t], other[t]): 114*8296aa0fSIan Rogers return False 115*8296aa0fSIan Rogers return True 116*8296aa0fSIan Rogers 117*8296aa0fSIan Rogers def optional(self): 118*8296aa0fSIan Rogers if 'optional' in self and self['optional'] == '1': 119*8296aa0fSIan Rogers return True 120*8296aa0fSIan Rogers return False 121*8296aa0fSIan Rogers 122*8296aa0fSIan Rogers def diff(self, other): 123*8296aa0fSIan Rogers for t in Event.terms: 124*8296aa0fSIan Rogers if t not in self or t not in other: 125*8296aa0fSIan Rogers continue 126*8296aa0fSIan Rogers if not data_equal(self[t], other[t]): 127*8296aa0fSIan Rogers log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) 128*8296aa0fSIan Rogers 129*8296aa0fSIan Rogersdef parse_version(version): 130*8296aa0fSIan Rogers if not version: 131*8296aa0fSIan Rogers return None 132*8296aa0fSIan Rogers return [int(v) for v in version.split(".")[0:2]] 133*8296aa0fSIan Rogers 134*8296aa0fSIan Rogers# Test file description needs to have following sections: 135*8296aa0fSIan Rogers# [config] 136*8296aa0fSIan Rogers# - just single instance in file 137*8296aa0fSIan Rogers# - needs to specify: 138*8296aa0fSIan Rogers# 'command' - perf command name 139*8296aa0fSIan Rogers# 'args' - special command arguments 140*8296aa0fSIan Rogers# 'ret' - Skip test if Perf doesn't exit with this value (0 by default) 141*8296aa0fSIan Rogers# 'test_ret'- If set to 'true', fail test instead of skipping for 'ret' argument 142*8296aa0fSIan Rogers# 'arch' - architecture specific test (optional) 143*8296aa0fSIan Rogers# comma separated list, ! at the beginning 144*8296aa0fSIan Rogers# negates it. 145*8296aa0fSIan Rogers# 'auxv' - Truthy statement that is evaled in the scope of the auxv map. When false, 146*8296aa0fSIan Rogers# the test is skipped. For example 'auxv["AT_HWCAP"] == 10'. (optional) 147*8296aa0fSIan Rogers# 'kernel_since' - Inclusive kernel version from which the test will start running. Only the 148*8296aa0fSIan Rogers# first two values are supported, for example "6.1" (optional) 149*8296aa0fSIan Rogers# 'kernel_until' - Exclusive kernel version from which the test will stop running. (optional) 150*8296aa0fSIan Rogers# [eventX:base] 151*8296aa0fSIan Rogers# - one or multiple instances in file 152*8296aa0fSIan Rogers# - expected values assignments 153*8296aa0fSIan Rogersclass Test(object): 154*8296aa0fSIan Rogers def __init__(self, path, options): 155*8296aa0fSIan Rogers parser = configparser.ConfigParser() 156*8296aa0fSIan Rogers parser.read(path) 157*8296aa0fSIan Rogers 158*8296aa0fSIan Rogers log.warning("running '%s'" % path) 159*8296aa0fSIan Rogers 160*8296aa0fSIan Rogers self.path = path 161*8296aa0fSIan Rogers self.test_dir = options.test_dir 162*8296aa0fSIan Rogers self.perf = options.perf 163*8296aa0fSIan Rogers self.command = parser.get('config', 'command') 164*8296aa0fSIan Rogers self.args = parser.get('config', 'args') 165*8296aa0fSIan Rogers 166*8296aa0fSIan Rogers try: 167*8296aa0fSIan Rogers self.ret = parser.get('config', 'ret') 168*8296aa0fSIan Rogers except: 169*8296aa0fSIan Rogers self.ret = 0 170*8296aa0fSIan Rogers 171*8296aa0fSIan Rogers self.test_ret = parser.getboolean('config', 'test_ret', fallback=False) 172*8296aa0fSIan Rogers 173*8296aa0fSIan Rogers try: 174*8296aa0fSIan Rogers self.arch = parser.get('config', 'arch') 175*8296aa0fSIan Rogers log.warning("test limitation '%s'" % self.arch) 176*8296aa0fSIan Rogers except: 177*8296aa0fSIan Rogers self.arch = '' 178*8296aa0fSIan Rogers 179*8296aa0fSIan Rogers self.auxv = parser.get('config', 'auxv', fallback=None) 180*8296aa0fSIan Rogers self.kernel_since = parse_version(parser.get('config', 'kernel_since', fallback=None)) 181*8296aa0fSIan Rogers self.kernel_until = parse_version(parser.get('config', 'kernel_until', fallback=None)) 182*8296aa0fSIan Rogers self.expect = {} 183*8296aa0fSIan Rogers self.result = {} 184*8296aa0fSIan Rogers log.debug(" loading expected events"); 185*8296aa0fSIan Rogers self.load_events(path, self.expect) 186*8296aa0fSIan Rogers 187*8296aa0fSIan Rogers def is_event(self, name): 188*8296aa0fSIan Rogers if name.find("event") == -1: 189*8296aa0fSIan Rogers return False 190*8296aa0fSIan Rogers else: 191*8296aa0fSIan Rogers return True 192*8296aa0fSIan Rogers 193*8296aa0fSIan Rogers def skip_test_kernel_since(self): 194*8296aa0fSIan Rogers if not self.kernel_since: 195*8296aa0fSIan Rogers return False 196*8296aa0fSIan Rogers return not self.kernel_since <= parse_version(platform.release()) 197*8296aa0fSIan Rogers 198*8296aa0fSIan Rogers def skip_test_kernel_until(self): 199*8296aa0fSIan Rogers if not self.kernel_until: 200*8296aa0fSIan Rogers return False 201*8296aa0fSIan Rogers return not parse_version(platform.release()) < self.kernel_until 202*8296aa0fSIan Rogers 203*8296aa0fSIan Rogers def skip_test_auxv(self): 204*8296aa0fSIan Rogers def new_auxv(a, pattern): 205*8296aa0fSIan Rogers items = list(filter(None, pattern.split(a))) 206*8296aa0fSIan Rogers # AT_HWCAP is hex but doesn't have a prefix, so special case it 207*8296aa0fSIan Rogers if items[0] == "AT_HWCAP": 208*8296aa0fSIan Rogers value = int(items[-1], 16) 209*8296aa0fSIan Rogers else: 210*8296aa0fSIan Rogers try: 211*8296aa0fSIan Rogers value = int(items[-1], 0) 212*8296aa0fSIan Rogers except: 213*8296aa0fSIan Rogers value = items[-1] 214*8296aa0fSIan Rogers return (items[0], value) 215*8296aa0fSIan Rogers 216*8296aa0fSIan Rogers if not self.auxv: 217*8296aa0fSIan Rogers return False 218*8296aa0fSIan Rogers auxv = subprocess.check_output("LD_SHOW_AUXV=1 sleep 0", shell=True) \ 219*8296aa0fSIan Rogers .decode(sys.stdout.encoding) 220*8296aa0fSIan Rogers pattern = re.compile(r"[: ]+") 221*8296aa0fSIan Rogers auxv = dict([new_auxv(a, pattern) for a in auxv.splitlines()]) 222*8296aa0fSIan Rogers return not eval(self.auxv) 223*8296aa0fSIan Rogers 224*8296aa0fSIan Rogers def skip_test_arch(self, myarch): 225*8296aa0fSIan Rogers # If architecture not set always run test 226*8296aa0fSIan Rogers if self.arch == '': 227*8296aa0fSIan Rogers # log.warning("test for arch %s is ok" % myarch) 228*8296aa0fSIan Rogers return False 229*8296aa0fSIan Rogers 230*8296aa0fSIan Rogers # Allow multiple values in assignment separated by ',' 231*8296aa0fSIan Rogers arch_list = self.arch.split(',') 232*8296aa0fSIan Rogers 233*8296aa0fSIan Rogers # Handle negated list such as !s390x,ppc 234*8296aa0fSIan Rogers if arch_list[0][0] == '!': 235*8296aa0fSIan Rogers arch_list[0] = arch_list[0][1:] 236*8296aa0fSIan Rogers log.warning("excluded architecture list %s" % arch_list) 237*8296aa0fSIan Rogers for arch_item in arch_list: 238*8296aa0fSIan Rogers # log.warning("test for %s arch is %s" % (arch_item, myarch)) 239*8296aa0fSIan Rogers if arch_item == myarch: 240*8296aa0fSIan Rogers return True 241*8296aa0fSIan Rogers return False 242*8296aa0fSIan Rogers 243*8296aa0fSIan Rogers for arch_item in arch_list: 244*8296aa0fSIan Rogers # log.warning("test for architecture '%s' current '%s'" % (arch_item, myarch)) 245*8296aa0fSIan Rogers if arch_item == myarch: 246*8296aa0fSIan Rogers return False 247*8296aa0fSIan Rogers return True 248*8296aa0fSIan Rogers 249*8296aa0fSIan Rogers def restore_sample_rate(self, value=10000): 250*8296aa0fSIan Rogers try: 251*8296aa0fSIan Rogers # Check value of sample_rate 252*8296aa0fSIan Rogers with open("/proc/sys/kernel/perf_event_max_sample_rate", "r") as fIn: 253*8296aa0fSIan Rogers curr_value = fIn.readline() 254*8296aa0fSIan Rogers # If too low restore to reasonable value 255*8296aa0fSIan Rogers if not curr_value or int(curr_value) < int(value): 256*8296aa0fSIan Rogers with open("/proc/sys/kernel/perf_event_max_sample_rate", "w") as fOut: 257*8296aa0fSIan Rogers fOut.write(str(value)) 258*8296aa0fSIan Rogers 259*8296aa0fSIan Rogers except IOError as e: 260*8296aa0fSIan Rogers log.warning("couldn't restore sample_rate value: I/O error %s" % e) 261*8296aa0fSIan Rogers except ValueError as e: 262*8296aa0fSIan Rogers log.warning("couldn't restore sample_rate value: Value error %s" % e) 263*8296aa0fSIan Rogers except TypeError as e: 264*8296aa0fSIan Rogers log.warning("couldn't restore sample_rate value: Type error %s" % e) 265*8296aa0fSIan Rogers 266*8296aa0fSIan Rogers def load_events(self, path, events): 267*8296aa0fSIan Rogers parser_event = configparser.ConfigParser() 268*8296aa0fSIan Rogers parser_event.read(path) 269*8296aa0fSIan Rogers 270*8296aa0fSIan Rogers # The event record section header contains 'event' word, 271*8296aa0fSIan Rogers # optionaly followed by ':' allowing to load 'parent 272*8296aa0fSIan Rogers # event' first as a base 273*8296aa0fSIan Rogers for section in filter(self.is_event, parser_event.sections()): 274*8296aa0fSIan Rogers 275*8296aa0fSIan Rogers parser_items = parser_event.items(section); 276*8296aa0fSIan Rogers base_items = {} 277*8296aa0fSIan Rogers 278*8296aa0fSIan Rogers # Read parent event if there's any 279*8296aa0fSIan Rogers if (':' in section): 280*8296aa0fSIan Rogers base = section[section.index(':') + 1:] 281*8296aa0fSIan Rogers parser_base = configparser.ConfigParser() 282*8296aa0fSIan Rogers parser_base.read(self.test_dir + '/' + base) 283*8296aa0fSIan Rogers base_items = parser_base.items('event') 284*8296aa0fSIan Rogers 285*8296aa0fSIan Rogers e = Event(section, parser_items, base_items) 286*8296aa0fSIan Rogers events[section] = e 287*8296aa0fSIan Rogers 288*8296aa0fSIan Rogers def run_cmd(self, tempdir): 289*8296aa0fSIan Rogers junk1, junk2, junk3, junk4, myarch = (os.uname()) 290*8296aa0fSIan Rogers 291*8296aa0fSIan Rogers if self.skip_test_arch(myarch): 292*8296aa0fSIan Rogers raise Notest(self, myarch) 293*8296aa0fSIan Rogers 294*8296aa0fSIan Rogers if self.skip_test_auxv(): 295*8296aa0fSIan Rogers raise Notest(self, "auxv skip") 296*8296aa0fSIan Rogers 297*8296aa0fSIan Rogers if self.skip_test_kernel_since(): 298*8296aa0fSIan Rogers raise Notest(self, "old kernel skip") 299*8296aa0fSIan Rogers 300*8296aa0fSIan Rogers if self.skip_test_kernel_until(): 301*8296aa0fSIan Rogers raise Notest(self, "new kernel skip") 302*8296aa0fSIan Rogers 303*8296aa0fSIan Rogers self.restore_sample_rate() 304*8296aa0fSIan Rogers cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir, 305*8296aa0fSIan Rogers self.perf, self.command, tempdir, self.args) 306*8296aa0fSIan Rogers ret = os.WEXITSTATUS(os.system(cmd)) 307*8296aa0fSIan Rogers 308*8296aa0fSIan Rogers log.info(" '%s' ret '%s', expected '%s'" % (cmd, str(ret), str(self.ret))) 309*8296aa0fSIan Rogers 310*8296aa0fSIan Rogers if not data_equal(str(ret), str(self.ret)): 311*8296aa0fSIan Rogers if self.test_ret: 312*8296aa0fSIan Rogers raise Fail(self, "Perf exit code failure") 313*8296aa0fSIan Rogers else: 314*8296aa0fSIan Rogers raise Unsup(self) 315*8296aa0fSIan Rogers 316*8296aa0fSIan Rogers def compare(self, expect, result): 317*8296aa0fSIan Rogers match = {} 318*8296aa0fSIan Rogers 319*8296aa0fSIan Rogers log.debug(" compare"); 320*8296aa0fSIan Rogers 321*8296aa0fSIan Rogers # For each expected event find all matching 322*8296aa0fSIan Rogers # events in result. Fail if there's not any. 323*8296aa0fSIan Rogers for exp_name, exp_event in expect.items(): 324*8296aa0fSIan Rogers exp_list = [] 325*8296aa0fSIan Rogers res_event = {} 326*8296aa0fSIan Rogers log.debug(" matching [%s]" % exp_name) 327*8296aa0fSIan Rogers for res_name, res_event in result.items(): 328*8296aa0fSIan Rogers log.debug(" to [%s]" % res_name) 329*8296aa0fSIan Rogers if (exp_event.equal(res_event)): 330*8296aa0fSIan Rogers exp_list.append(res_name) 331*8296aa0fSIan Rogers log.debug(" ->OK") 332*8296aa0fSIan Rogers else: 333*8296aa0fSIan Rogers log.debug(" ->FAIL"); 334*8296aa0fSIan Rogers 335*8296aa0fSIan Rogers log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list))) 336*8296aa0fSIan Rogers 337*8296aa0fSIan Rogers # we did not any matching event - fail 338*8296aa0fSIan Rogers if not exp_list: 339*8296aa0fSIan Rogers if exp_event.optional(): 340*8296aa0fSIan Rogers log.debug(" %s does not match, but is optional" % exp_name) 341*8296aa0fSIan Rogers else: 342*8296aa0fSIan Rogers if not res_event: 343*8296aa0fSIan Rogers log.debug(" res_event is empty"); 344*8296aa0fSIan Rogers else: 345*8296aa0fSIan Rogers exp_event.diff(res_event) 346*8296aa0fSIan Rogers raise Fail(self, 'match failure'); 347*8296aa0fSIan Rogers 348*8296aa0fSIan Rogers match[exp_name] = exp_list 349*8296aa0fSIan Rogers 350*8296aa0fSIan Rogers # For each defined group in the expected events 351*8296aa0fSIan Rogers # check we match the same group in the result. 352*8296aa0fSIan Rogers for exp_name, exp_event in expect.items(): 353*8296aa0fSIan Rogers group = exp_event.group 354*8296aa0fSIan Rogers 355*8296aa0fSIan Rogers if (group == ''): 356*8296aa0fSIan Rogers continue 357*8296aa0fSIan Rogers 358*8296aa0fSIan Rogers for res_name in match[exp_name]: 359*8296aa0fSIan Rogers res_group = result[res_name].group 360*8296aa0fSIan Rogers if res_group not in match[group]: 361*8296aa0fSIan Rogers raise Fail(self, 'group failure') 362*8296aa0fSIan Rogers 363*8296aa0fSIan Rogers log.debug(" group: [%s] matches group leader %s" % 364*8296aa0fSIan Rogers (exp_name, str(match[group]))) 365*8296aa0fSIan Rogers 366*8296aa0fSIan Rogers log.debug(" matched") 367*8296aa0fSIan Rogers 368*8296aa0fSIan Rogers def resolve_groups(self, events): 369*8296aa0fSIan Rogers for name, event in events.items(): 370*8296aa0fSIan Rogers group_fd = event['group_fd']; 371*8296aa0fSIan Rogers if group_fd == '-1': 372*8296aa0fSIan Rogers continue; 373*8296aa0fSIan Rogers 374*8296aa0fSIan Rogers for iname, ievent in events.items(): 375*8296aa0fSIan Rogers if (ievent['fd'] == group_fd): 376*8296aa0fSIan Rogers event.group = iname 377*8296aa0fSIan Rogers log.debug('[%s] has group leader [%s]' % (name, iname)) 378*8296aa0fSIan Rogers break; 379*8296aa0fSIan Rogers 380*8296aa0fSIan Rogers def run(self): 381*8296aa0fSIan Rogers tempdir = tempfile.mkdtemp(); 382*8296aa0fSIan Rogers 383*8296aa0fSIan Rogers try: 384*8296aa0fSIan Rogers # run the test script 385*8296aa0fSIan Rogers self.run_cmd(tempdir); 386*8296aa0fSIan Rogers 387*8296aa0fSIan Rogers # load events expectation for the test 388*8296aa0fSIan Rogers log.debug(" loading result events"); 389*8296aa0fSIan Rogers for f in glob.glob(tempdir + '/event*'): 390*8296aa0fSIan Rogers self.load_events(f, self.result); 391*8296aa0fSIan Rogers 392*8296aa0fSIan Rogers # resolve group_fd to event names 393*8296aa0fSIan Rogers self.resolve_groups(self.expect); 394*8296aa0fSIan Rogers self.resolve_groups(self.result); 395*8296aa0fSIan Rogers 396*8296aa0fSIan Rogers # do the expectation - results matching - both ways 397*8296aa0fSIan Rogers self.compare(self.expect, self.result) 398*8296aa0fSIan Rogers self.compare(self.result, self.expect) 399*8296aa0fSIan Rogers 400*8296aa0fSIan Rogers finally: 401*8296aa0fSIan Rogers # cleanup 402*8296aa0fSIan Rogers shutil.rmtree(tempdir) 403*8296aa0fSIan Rogers 404*8296aa0fSIan Rogers 405*8296aa0fSIan Rogersdef run_tests(options): 406*8296aa0fSIan Rogers for f in glob.glob(options.test_dir + '/' + options.test): 407*8296aa0fSIan Rogers try: 408*8296aa0fSIan Rogers Test(f, options).run() 409*8296aa0fSIan Rogers except Unsup as obj: 410*8296aa0fSIan Rogers log.warning("unsupp %s" % obj.getMsg()) 411*8296aa0fSIan Rogers except Notest as obj: 412*8296aa0fSIan Rogers log.warning("skipped %s" % obj.getMsg()) 413*8296aa0fSIan Rogers 414*8296aa0fSIan Rogersdef setup_log(verbose): 415*8296aa0fSIan Rogers global log 416*8296aa0fSIan Rogers level = logging.CRITICAL 417*8296aa0fSIan Rogers 418*8296aa0fSIan Rogers if verbose == 1: 419*8296aa0fSIan Rogers level = logging.WARNING 420*8296aa0fSIan Rogers if verbose == 2: 421*8296aa0fSIan Rogers level = logging.INFO 422*8296aa0fSIan Rogers if verbose >= 3: 423*8296aa0fSIan Rogers level = logging.DEBUG 424*8296aa0fSIan Rogers 425*8296aa0fSIan Rogers log = logging.getLogger('test') 426*8296aa0fSIan Rogers log.setLevel(level) 427*8296aa0fSIan Rogers ch = logging.StreamHandler() 428*8296aa0fSIan Rogers ch.setLevel(level) 429*8296aa0fSIan Rogers formatter = logging.Formatter('%(message)s') 430*8296aa0fSIan Rogers ch.setFormatter(formatter) 431*8296aa0fSIan Rogers log.addHandler(ch) 432*8296aa0fSIan Rogers 433*8296aa0fSIan RogersUSAGE = '''%s [OPTIONS] 434*8296aa0fSIan Rogers -d dir # tests dir 435*8296aa0fSIan Rogers -p path # perf binary 436*8296aa0fSIan Rogers -t test # single test 437*8296aa0fSIan Rogers -v # verbose level 438*8296aa0fSIan Rogers''' % sys.argv[0] 439*8296aa0fSIan Rogers 440*8296aa0fSIan Rogersdef main(): 441*8296aa0fSIan Rogers parser = optparse.OptionParser(usage=USAGE) 442*8296aa0fSIan Rogers 443*8296aa0fSIan Rogers parser.add_option("-t", "--test", 444*8296aa0fSIan Rogers action="store", type="string", dest="test") 445*8296aa0fSIan Rogers parser.add_option("-d", "--test-dir", 446*8296aa0fSIan Rogers action="store", type="string", dest="test_dir") 447*8296aa0fSIan Rogers parser.add_option("-p", "--perf", 448*8296aa0fSIan Rogers action="store", type="string", dest="perf") 449*8296aa0fSIan Rogers parser.add_option("-v", "--verbose", 450*8296aa0fSIan Rogers default=0, action="count", dest="verbose") 451*8296aa0fSIan Rogers 452*8296aa0fSIan Rogers options, args = parser.parse_args() 453*8296aa0fSIan Rogers if args: 454*8296aa0fSIan Rogers parser.error('FAILED wrong arguments %s' % ' '.join(args)) 455*8296aa0fSIan Rogers return -1 456*8296aa0fSIan Rogers 457*8296aa0fSIan Rogers setup_log(options.verbose) 458*8296aa0fSIan Rogers 459*8296aa0fSIan Rogers if not options.test_dir: 460*8296aa0fSIan Rogers print('FAILED no -d option specified') 461*8296aa0fSIan Rogers sys.exit(-1) 462*8296aa0fSIan Rogers 463*8296aa0fSIan Rogers if not options.test: 464*8296aa0fSIan Rogers options.test = 'test*' 465*8296aa0fSIan Rogers 466*8296aa0fSIan Rogers try: 467*8296aa0fSIan Rogers run_tests(options) 468*8296aa0fSIan Rogers 469*8296aa0fSIan Rogers except Fail as obj: 470*8296aa0fSIan Rogers print("FAILED %s" % obj.getMsg()) 471*8296aa0fSIan Rogers sys.exit(-1) 472*8296aa0fSIan Rogers 473*8296aa0fSIan Rogers sys.exit(0) 474*8296aa0fSIan Rogers 475*8296aa0fSIan Rogersif __name__ == '__main__': 476*8296aa0fSIan Rogers main() 477