xref: /linux/tools/perf/tests/shell/lib/attr.py (revision 25768de50b1f2dbb6ea44bd5148a87fe2c9c3688)
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