18c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_cifrom __future__ import print_function
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ciimport os
68c2ecf20Sopenharmony_ciimport sys
78c2ecf20Sopenharmony_ciimport glob
88c2ecf20Sopenharmony_ciimport optparse
98c2ecf20Sopenharmony_ciimport tempfile
108c2ecf20Sopenharmony_ciimport logging
118c2ecf20Sopenharmony_ciimport shutil
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_citry:
148c2ecf20Sopenharmony_ci    import configparser
158c2ecf20Sopenharmony_ciexcept ImportError:
168c2ecf20Sopenharmony_ci    import ConfigParser as configparser
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cidef data_equal(a, b):
198c2ecf20Sopenharmony_ci    # Allow multiple values in assignment separated by '|'
208c2ecf20Sopenharmony_ci    a_list = a.split('|')
218c2ecf20Sopenharmony_ci    b_list = b.split('|')
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci    for a_item in a_list:
248c2ecf20Sopenharmony_ci        for b_item in b_list:
258c2ecf20Sopenharmony_ci            if (a_item == b_item):
268c2ecf20Sopenharmony_ci                return True
278c2ecf20Sopenharmony_ci            elif (a_item == '*') or (b_item == '*'):
288c2ecf20Sopenharmony_ci                return True
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci    return False
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ciclass Fail(Exception):
338c2ecf20Sopenharmony_ci    def __init__(self, test, msg):
348c2ecf20Sopenharmony_ci        self.msg = msg
358c2ecf20Sopenharmony_ci        self.test = test
368c2ecf20Sopenharmony_ci    def getMsg(self):
378c2ecf20Sopenharmony_ci        return '\'%s\' - %s' % (self.test.path, self.msg)
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ciclass Notest(Exception):
408c2ecf20Sopenharmony_ci    def __init__(self, test, arch):
418c2ecf20Sopenharmony_ci        self.arch = arch
428c2ecf20Sopenharmony_ci        self.test = test
438c2ecf20Sopenharmony_ci    def getMsg(self):
448c2ecf20Sopenharmony_ci        return '[%s] \'%s\'' % (self.arch, self.test.path)
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ciclass Unsup(Exception):
478c2ecf20Sopenharmony_ci    def __init__(self, test):
488c2ecf20Sopenharmony_ci        self.test = test
498c2ecf20Sopenharmony_ci    def getMsg(self):
508c2ecf20Sopenharmony_ci        return '\'%s\'' % self.test.path
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ciclass Event(dict):
538c2ecf20Sopenharmony_ci    terms = [
548c2ecf20Sopenharmony_ci        'cpu',
558c2ecf20Sopenharmony_ci        'flags',
568c2ecf20Sopenharmony_ci        'type',
578c2ecf20Sopenharmony_ci        'size',
588c2ecf20Sopenharmony_ci        'config',
598c2ecf20Sopenharmony_ci        'sample_period',
608c2ecf20Sopenharmony_ci        'sample_type',
618c2ecf20Sopenharmony_ci        'read_format',
628c2ecf20Sopenharmony_ci        'disabled',
638c2ecf20Sopenharmony_ci        'inherit',
648c2ecf20Sopenharmony_ci        'pinned',
658c2ecf20Sopenharmony_ci        'exclusive',
668c2ecf20Sopenharmony_ci        'exclude_user',
678c2ecf20Sopenharmony_ci        'exclude_kernel',
688c2ecf20Sopenharmony_ci        'exclude_hv',
698c2ecf20Sopenharmony_ci        'exclude_idle',
708c2ecf20Sopenharmony_ci        'mmap',
718c2ecf20Sopenharmony_ci        'comm',
728c2ecf20Sopenharmony_ci        'freq',
738c2ecf20Sopenharmony_ci        'inherit_stat',
748c2ecf20Sopenharmony_ci        'enable_on_exec',
758c2ecf20Sopenharmony_ci        'task',
768c2ecf20Sopenharmony_ci        'watermark',
778c2ecf20Sopenharmony_ci        'precise_ip',
788c2ecf20Sopenharmony_ci        'mmap_data',
798c2ecf20Sopenharmony_ci        'sample_id_all',
808c2ecf20Sopenharmony_ci        'exclude_host',
818c2ecf20Sopenharmony_ci        'exclude_guest',
828c2ecf20Sopenharmony_ci        'exclude_callchain_kernel',
838c2ecf20Sopenharmony_ci        'exclude_callchain_user',
848c2ecf20Sopenharmony_ci        'wakeup_events',
858c2ecf20Sopenharmony_ci        'bp_type',
868c2ecf20Sopenharmony_ci        'config1',
878c2ecf20Sopenharmony_ci        'config2',
888c2ecf20Sopenharmony_ci        'branch_sample_type',
898c2ecf20Sopenharmony_ci        'sample_regs_user',
908c2ecf20Sopenharmony_ci        'sample_stack_user',
918c2ecf20Sopenharmony_ci    ]
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci    def add(self, data):
948c2ecf20Sopenharmony_ci        for key, val in data:
958c2ecf20Sopenharmony_ci            log.debug("      %s = %s" % (key, val))
968c2ecf20Sopenharmony_ci            self[key] = val
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci    def __init__(self, name, data, base):
998c2ecf20Sopenharmony_ci        log.debug("    Event %s" % name);
1008c2ecf20Sopenharmony_ci        self.name  = name;
1018c2ecf20Sopenharmony_ci        self.group = ''
1028c2ecf20Sopenharmony_ci        self.add(base)
1038c2ecf20Sopenharmony_ci        self.add(data)
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci    def equal(self, other):
1068c2ecf20Sopenharmony_ci        for t in Event.terms:
1078c2ecf20Sopenharmony_ci            log.debug("      [%s] %s %s" % (t, self[t], other[t]));
1088c2ecf20Sopenharmony_ci            if t not in self or t not in other:
1098c2ecf20Sopenharmony_ci                return False
1108c2ecf20Sopenharmony_ci            if not data_equal(self[t], other[t]):
1118c2ecf20Sopenharmony_ci                return False
1128c2ecf20Sopenharmony_ci        return True
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci    def optional(self):
1158c2ecf20Sopenharmony_ci        if 'optional' in self and self['optional'] == '1':
1168c2ecf20Sopenharmony_ci            return True
1178c2ecf20Sopenharmony_ci        return False
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci    def diff(self, other):
1208c2ecf20Sopenharmony_ci        for t in Event.terms:
1218c2ecf20Sopenharmony_ci            if t not in self or t not in other:
1228c2ecf20Sopenharmony_ci                continue
1238c2ecf20Sopenharmony_ci            if not data_equal(self[t], other[t]):
1248c2ecf20Sopenharmony_ci                log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci# Test file description needs to have following sections:
1278c2ecf20Sopenharmony_ci# [config]
1288c2ecf20Sopenharmony_ci#   - just single instance in file
1298c2ecf20Sopenharmony_ci#   - needs to specify:
1308c2ecf20Sopenharmony_ci#     'command' - perf command name
1318c2ecf20Sopenharmony_ci#     'args'    - special command arguments
1328c2ecf20Sopenharmony_ci#     'ret'     - expected command return value (0 by default)
1338c2ecf20Sopenharmony_ci#     'arch'    - architecture specific test (optional)
1348c2ecf20Sopenharmony_ci#                 comma separated list, ! at the beginning
1358c2ecf20Sopenharmony_ci#                 negates it.
1368c2ecf20Sopenharmony_ci#
1378c2ecf20Sopenharmony_ci# [eventX:base]
1388c2ecf20Sopenharmony_ci#   - one or multiple instances in file
1398c2ecf20Sopenharmony_ci#   - expected values assignments
1408c2ecf20Sopenharmony_ciclass Test(object):
1418c2ecf20Sopenharmony_ci    def __init__(self, path, options):
1428c2ecf20Sopenharmony_ci        parser = configparser.SafeConfigParser()
1438c2ecf20Sopenharmony_ci        parser.read(path)
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci        log.warning("running '%s'" % path)
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci        self.path     = path
1488c2ecf20Sopenharmony_ci        self.test_dir = options.test_dir
1498c2ecf20Sopenharmony_ci        self.perf     = options.perf
1508c2ecf20Sopenharmony_ci        self.command  = parser.get('config', 'command')
1518c2ecf20Sopenharmony_ci        self.args     = parser.get('config', 'args')
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci        try:
1548c2ecf20Sopenharmony_ci            self.ret  = parser.get('config', 'ret')
1558c2ecf20Sopenharmony_ci        except:
1568c2ecf20Sopenharmony_ci            self.ret  = 0
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci        try:
1598c2ecf20Sopenharmony_ci            self.arch  = parser.get('config', 'arch')
1608c2ecf20Sopenharmony_ci            log.warning("test limitation '%s'" % self.arch)
1618c2ecf20Sopenharmony_ci        except:
1628c2ecf20Sopenharmony_ci            self.arch  = ''
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci        self.expect   = {}
1658c2ecf20Sopenharmony_ci        self.result   = {}
1668c2ecf20Sopenharmony_ci        log.debug("  loading expected events");
1678c2ecf20Sopenharmony_ci        self.load_events(path, self.expect)
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci    def is_event(self, name):
1708c2ecf20Sopenharmony_ci        if name.find("event") == -1:
1718c2ecf20Sopenharmony_ci            return False
1728c2ecf20Sopenharmony_ci        else:
1738c2ecf20Sopenharmony_ci            return True
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci    def skip_test(self, myarch):
1768c2ecf20Sopenharmony_ci        # If architecture not set always run test
1778c2ecf20Sopenharmony_ci        if self.arch == '':
1788c2ecf20Sopenharmony_ci            # log.warning("test for arch %s is ok" % myarch)
1798c2ecf20Sopenharmony_ci            return False
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci        # Allow multiple values in assignment separated by ','
1828c2ecf20Sopenharmony_ci        arch_list = self.arch.split(',')
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci        # Handle negated list such as !s390x,ppc
1858c2ecf20Sopenharmony_ci        if arch_list[0][0] == '!':
1868c2ecf20Sopenharmony_ci            arch_list[0] = arch_list[0][1:]
1878c2ecf20Sopenharmony_ci            log.warning("excluded architecture list %s" % arch_list)
1888c2ecf20Sopenharmony_ci            for arch_item in arch_list:
1898c2ecf20Sopenharmony_ci                # log.warning("test for %s arch is %s" % (arch_item, myarch))
1908c2ecf20Sopenharmony_ci                if arch_item == myarch:
1918c2ecf20Sopenharmony_ci                    return True
1928c2ecf20Sopenharmony_ci            return False
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci        for arch_item in arch_list:
1958c2ecf20Sopenharmony_ci            # log.warning("test for architecture '%s' current '%s'" % (arch_item, myarch))
1968c2ecf20Sopenharmony_ci            if arch_item == myarch:
1978c2ecf20Sopenharmony_ci                return False
1988c2ecf20Sopenharmony_ci        return True
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci    def load_events(self, path, events):
2018c2ecf20Sopenharmony_ci        parser_event = configparser.SafeConfigParser()
2028c2ecf20Sopenharmony_ci        parser_event.read(path)
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci        # The event record section header contains 'event' word,
2058c2ecf20Sopenharmony_ci        # optionaly followed by ':' allowing to load 'parent
2068c2ecf20Sopenharmony_ci        # event' first as a base
2078c2ecf20Sopenharmony_ci        for section in filter(self.is_event, parser_event.sections()):
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci            parser_items = parser_event.items(section);
2108c2ecf20Sopenharmony_ci            base_items   = {}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci            # Read parent event if there's any
2138c2ecf20Sopenharmony_ci            if (':' in section):
2148c2ecf20Sopenharmony_ci                base = section[section.index(':') + 1:]
2158c2ecf20Sopenharmony_ci                parser_base = configparser.SafeConfigParser()
2168c2ecf20Sopenharmony_ci                parser_base.read(self.test_dir + '/' + base)
2178c2ecf20Sopenharmony_ci                base_items = parser_base.items('event')
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci            e = Event(section, parser_items, base_items)
2208c2ecf20Sopenharmony_ci            events[section] = e
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci    def run_cmd(self, tempdir):
2238c2ecf20Sopenharmony_ci        junk1, junk2, junk3, junk4, myarch = (os.uname())
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci        if self.skip_test(myarch):
2268c2ecf20Sopenharmony_ci            raise Notest(self, myarch)
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci        cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir,
2298c2ecf20Sopenharmony_ci              self.perf, self.command, tempdir, self.args)
2308c2ecf20Sopenharmony_ci        ret = os.WEXITSTATUS(os.system(cmd))
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci        log.info("  '%s' ret '%s', expected '%s'" % (cmd, str(ret), str(self.ret)))
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci        if not data_equal(str(ret), str(self.ret)):
2358c2ecf20Sopenharmony_ci            raise Unsup(self)
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci    def compare(self, expect, result):
2388c2ecf20Sopenharmony_ci        match = {}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci        log.debug("  compare");
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci        # For each expected event find all matching
2438c2ecf20Sopenharmony_ci        # events in result. Fail if there's not any.
2448c2ecf20Sopenharmony_ci        for exp_name, exp_event in expect.items():
2458c2ecf20Sopenharmony_ci            exp_list = []
2468c2ecf20Sopenharmony_ci            res_event = {}
2478c2ecf20Sopenharmony_ci            log.debug("    matching [%s]" % exp_name)
2488c2ecf20Sopenharmony_ci            for res_name, res_event in result.items():
2498c2ecf20Sopenharmony_ci                log.debug("      to [%s]" % res_name)
2508c2ecf20Sopenharmony_ci                if (exp_event.equal(res_event)):
2518c2ecf20Sopenharmony_ci                    exp_list.append(res_name)
2528c2ecf20Sopenharmony_ci                    log.debug("    ->OK")
2538c2ecf20Sopenharmony_ci                else:
2548c2ecf20Sopenharmony_ci                    log.debug("    ->FAIL");
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci            log.debug("    match: [%s] matches %s" % (exp_name, str(exp_list)))
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci            # we did not any matching event - fail
2598c2ecf20Sopenharmony_ci            if not exp_list:
2608c2ecf20Sopenharmony_ci                if exp_event.optional():
2618c2ecf20Sopenharmony_ci                    log.debug("    %s does not match, but is optional" % exp_name)
2628c2ecf20Sopenharmony_ci                else:
2638c2ecf20Sopenharmony_ci                    if not res_event:
2648c2ecf20Sopenharmony_ci                        log.debug("    res_event is empty");
2658c2ecf20Sopenharmony_ci                    else:
2668c2ecf20Sopenharmony_ci                        exp_event.diff(res_event)
2678c2ecf20Sopenharmony_ci                    raise Fail(self, 'match failure');
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci            match[exp_name] = exp_list
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci        # For each defined group in the expected events
2728c2ecf20Sopenharmony_ci        # check we match the same group in the result.
2738c2ecf20Sopenharmony_ci        for exp_name, exp_event in expect.items():
2748c2ecf20Sopenharmony_ci            group = exp_event.group
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci            if (group == ''):
2778c2ecf20Sopenharmony_ci                continue
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci            for res_name in match[exp_name]:
2808c2ecf20Sopenharmony_ci                res_group = result[res_name].group
2818c2ecf20Sopenharmony_ci                if res_group not in match[group]:
2828c2ecf20Sopenharmony_ci                    raise Fail(self, 'group failure')
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci                log.debug("    group: [%s] matches group leader %s" %
2858c2ecf20Sopenharmony_ci                         (exp_name, str(match[group])))
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci        log.debug("  matched")
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci    def resolve_groups(self, events):
2908c2ecf20Sopenharmony_ci        for name, event in events.items():
2918c2ecf20Sopenharmony_ci            group_fd = event['group_fd'];
2928c2ecf20Sopenharmony_ci            if group_fd == '-1':
2938c2ecf20Sopenharmony_ci                continue;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci            for iname, ievent in events.items():
2968c2ecf20Sopenharmony_ci                if (ievent['fd'] == group_fd):
2978c2ecf20Sopenharmony_ci                    event.group = iname
2988c2ecf20Sopenharmony_ci                    log.debug('[%s] has group leader [%s]' % (name, iname))
2998c2ecf20Sopenharmony_ci                    break;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci    def run(self):
3028c2ecf20Sopenharmony_ci        tempdir = tempfile.mkdtemp();
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci        try:
3058c2ecf20Sopenharmony_ci            # run the test script
3068c2ecf20Sopenharmony_ci            self.run_cmd(tempdir);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci            # load events expectation for the test
3098c2ecf20Sopenharmony_ci            log.debug("  loading result events");
3108c2ecf20Sopenharmony_ci            for f in glob.glob(tempdir + '/event*'):
3118c2ecf20Sopenharmony_ci                self.load_events(f, self.result);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci            # resolve group_fd to event names
3148c2ecf20Sopenharmony_ci            self.resolve_groups(self.expect);
3158c2ecf20Sopenharmony_ci            self.resolve_groups(self.result);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci            # do the expectation - results matching - both ways
3188c2ecf20Sopenharmony_ci            self.compare(self.expect, self.result)
3198c2ecf20Sopenharmony_ci            self.compare(self.result, self.expect)
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci        finally:
3228c2ecf20Sopenharmony_ci            # cleanup
3238c2ecf20Sopenharmony_ci            shutil.rmtree(tempdir)
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cidef run_tests(options):
3278c2ecf20Sopenharmony_ci    for f in glob.glob(options.test_dir + '/' + options.test):
3288c2ecf20Sopenharmony_ci        try:
3298c2ecf20Sopenharmony_ci            Test(f, options).run()
3308c2ecf20Sopenharmony_ci        except Unsup as obj:
3318c2ecf20Sopenharmony_ci            log.warning("unsupp  %s" % obj.getMsg())
3328c2ecf20Sopenharmony_ci        except Notest as obj:
3338c2ecf20Sopenharmony_ci            log.warning("skipped %s" % obj.getMsg())
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_cidef setup_log(verbose):
3368c2ecf20Sopenharmony_ci    global log
3378c2ecf20Sopenharmony_ci    level = logging.CRITICAL
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci    if verbose == 1:
3408c2ecf20Sopenharmony_ci        level = logging.WARNING
3418c2ecf20Sopenharmony_ci    if verbose == 2:
3428c2ecf20Sopenharmony_ci        level = logging.INFO
3438c2ecf20Sopenharmony_ci    if verbose >= 3:
3448c2ecf20Sopenharmony_ci        level = logging.DEBUG
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci    log = logging.getLogger('test')
3478c2ecf20Sopenharmony_ci    log.setLevel(level)
3488c2ecf20Sopenharmony_ci    ch  = logging.StreamHandler()
3498c2ecf20Sopenharmony_ci    ch.setLevel(level)
3508c2ecf20Sopenharmony_ci    formatter = logging.Formatter('%(message)s')
3518c2ecf20Sopenharmony_ci    ch.setFormatter(formatter)
3528c2ecf20Sopenharmony_ci    log.addHandler(ch)
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ciUSAGE = '''%s [OPTIONS]
3558c2ecf20Sopenharmony_ci  -d dir  # tests dir
3568c2ecf20Sopenharmony_ci  -p path # perf binary
3578c2ecf20Sopenharmony_ci  -t test # single test
3588c2ecf20Sopenharmony_ci  -v      # verbose level
3598c2ecf20Sopenharmony_ci''' % sys.argv[0]
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cidef main():
3628c2ecf20Sopenharmony_ci    parser = optparse.OptionParser(usage=USAGE)
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci    parser.add_option("-t", "--test",
3658c2ecf20Sopenharmony_ci                      action="store", type="string", dest="test")
3668c2ecf20Sopenharmony_ci    parser.add_option("-d", "--test-dir",
3678c2ecf20Sopenharmony_ci                      action="store", type="string", dest="test_dir")
3688c2ecf20Sopenharmony_ci    parser.add_option("-p", "--perf",
3698c2ecf20Sopenharmony_ci                      action="store", type="string", dest="perf")
3708c2ecf20Sopenharmony_ci    parser.add_option("-v", "--verbose",
3718c2ecf20Sopenharmony_ci                      default=0, action="count", dest="verbose")
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci    options, args = parser.parse_args()
3748c2ecf20Sopenharmony_ci    if args:
3758c2ecf20Sopenharmony_ci        parser.error('FAILED wrong arguments %s' %  ' '.join(args))
3768c2ecf20Sopenharmony_ci        return -1
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci    setup_log(options.verbose)
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci    if not options.test_dir:
3818c2ecf20Sopenharmony_ci        print('FAILED no -d option specified')
3828c2ecf20Sopenharmony_ci        sys.exit(-1)
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci    if not options.test:
3858c2ecf20Sopenharmony_ci        options.test = 'test*'
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci    try:
3888c2ecf20Sopenharmony_ci        run_tests(options)
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci    except Fail as obj:
3918c2ecf20Sopenharmony_ci        print("FAILED %s" % obj.getMsg())
3928c2ecf20Sopenharmony_ci        sys.exit(-1)
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci    sys.exit(0)
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ciif __name__ == '__main__':
3978c2ecf20Sopenharmony_ci    main()
398