1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#! /usr/bin/python
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengimport os
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengimport sys
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengimport glob
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengimport optparse
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengimport tempfile
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengimport logging
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengimport shutil
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengimport ConfigParser
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengclass Fail(Exception):
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def __init__(self, test, msg):
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.msg = msg
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.test = test
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def getMsg(self):
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        return '\'%s\' - %s' % (self.test.path, self.msg)
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengclass Unsup(Exception):
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def __init__(self, test):
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.test = test
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def getMsg(self):
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        return '\'%s\'' % self.test.path
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengclass Event(dict):
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    terms = [
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'cpu',
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'flags',
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'type',
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'size',
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'config',
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'sample_period',
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'sample_type',
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'read_format',
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'disabled',
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'inherit',
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'pinned',
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'exclusive',
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'exclude_user',
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'exclude_kernel',
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'exclude_hv',
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'exclude_idle',
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'mmap',
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'comm',
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'freq',
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'inherit_stat',
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'enable_on_exec',
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'task',
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'watermark',
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'precise_ip',
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'mmap_data',
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'sample_id_all',
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'exclude_host',
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'exclude_guest',
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'exclude_callchain_kernel',
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'exclude_callchain_user',
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'wakeup_events',
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'bp_type',
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'config1',
60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'config2',
61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'branch_sample_type',
62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'sample_regs_user',
63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        'sample_stack_user',
64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    ]
65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def add(self, data):
67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        for key, val in data:
68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            log.debug("      %s = %s" % (key, val))
69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            self[key] = val
70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def __init__(self, name, data, base):
72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        log.debug("    Event %s" % name);
73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.name  = name;
74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.group = ''
75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.add(base)
76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.add(data)
77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def compare_data(self, a, b):
79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        # Allow multiple values in assignment separated by '|'
80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        a_list = a.split('|')
81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        b_list = b.split('|')
82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        for a_item in a_list:
84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            for b_item in b_list:
85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                if (a_item == b_item):
86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                    return True
87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                elif (a_item == '*') or (b_item == '*'):
88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                    return True
89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        return False
91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def equal(self, other):
93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        for t in Event.terms:
94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            log.debug("      [%s] %s %s" % (t, self[t], other[t]));
95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            if not self.has_key(t) or not other.has_key(t):
96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                return False
97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            if not self.compare_data(self[t], other[t]):
98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                return False
99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        return True
100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def diff(self, other):
102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        for t in Event.terms:
103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            if not self.has_key(t) or not other.has_key(t):
104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                continue
105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            if not self.compare_data(self[t], other[t]):
106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng# Test file description needs to have following sections:
110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng# [config]
111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#   - just single instance in file
112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#   - needs to specify:
113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#     'command' - perf command name
114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#     'args'    - special command arguments
115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#     'ret'     - expected command return value (0 by default)
116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#
117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng# [eventX:base]
118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#   - one or multiple instances in file
119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#   - expected values assignments
120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengclass Test(object):
121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def __init__(self, path, options):
122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        parser = ConfigParser.SafeConfigParser()
123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        parser.read(path)
124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        log.warning("running '%s'" % path)
126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.path     = path
128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.test_dir = options.test_dir
129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.perf     = options.perf
130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.command  = parser.get('config', 'command')
131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.args     = parser.get('config', 'args')
132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        try:
134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            self.ret  = parser.get('config', 'ret')
135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        except:
136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            self.ret  = 0
137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.expect   = {}
139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.result   = {}
140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        log.debug("  loading expected events");
141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        self.load_events(path, self.expect)
142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def is_event(self, name):
144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        if name.find("event") == -1:
145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            return False
146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        else:
147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            return True
148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def load_events(self, path, events):
150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        parser_event = ConfigParser.SafeConfigParser()
151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        parser_event.read(path)
152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        # The event record section header contains 'event' word,
154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        # optionaly followed by ':' allowing to load 'parent
155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        # event' first as a base
156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        for section in filter(self.is_event, parser_event.sections()):
157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            parser_items = parser_event.items(section);
159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            base_items   = {}
160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            # Read parent event if there's any
162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            if (':' in section):
163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                base = section[section.index(':') + 1:]
164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                parser_base = ConfigParser.SafeConfigParser()
165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                parser_base.read(self.test_dir + '/' + base)
166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                base_items = parser_base.items('event')
167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            e = Event(section, parser_items, base_items)
169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            events[section] = e
170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def run_cmd(self, tempdir):
172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir,
173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng              self.perf, self.command, tempdir, self.args)
174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        ret = os.WEXITSTATUS(os.system(cmd))
175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        log.info("  '%s' ret %d " % (cmd, ret))
177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        if ret != int(self.ret):
179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            raise Unsup(self)
180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def compare(self, expect, result):
182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        match = {}
183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        log.debug("  compare");
185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        # For each expected event find all matching
187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        # events in result. Fail if there's not any.
188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        for exp_name, exp_event in expect.items():
189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            exp_list = []
190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            log.debug("    matching [%s]" % exp_name)
191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            for res_name, res_event in result.items():
192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                log.debug("      to [%s]" % res_name)
193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                if (exp_event.equal(res_event)):
194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                    exp_list.append(res_name)
195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                    log.debug("    ->OK")
196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                else:
197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                    log.debug("    ->FAIL");
198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            log.debug("    match: [%s] matches %s" % (exp_name, str(exp_list)))
200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            # we did not any matching event - fail
202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            if (not exp_list):
203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		exp_event.diff(res_event)
204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                raise Fail(self, 'match failure');
205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            match[exp_name] = exp_list
207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        # For each defined group in the expected events
209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        # check we match the same group in the result.
210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        for exp_name, exp_event in expect.items():
211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            group = exp_event.group
212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            if (group == ''):
214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                continue
215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            for res_name in match[exp_name]:
217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                res_group = result[res_name].group
218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                if res_group not in match[group]:
219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                    raise Fail(self, 'group failure')
220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                log.debug("    group: [%s] matches group leader %s" %
222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                         (exp_name, str(match[group])))
223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        log.debug("  matched")
225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def resolve_groups(self, events):
227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        for name, event in events.items():
228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            group_fd = event['group_fd'];
229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            if group_fd == '-1':
230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                continue;
231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            for iname, ievent in events.items():
233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                if (ievent['fd'] == group_fd):
234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                    event.group = iname
235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                    log.debug('[%s] has group leader [%s]' % (name, iname))
236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                    break;
237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    def run(self):
239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        tempdir = tempfile.mkdtemp();
240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        try:
242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            # run the test script
243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            self.run_cmd(tempdir);
244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            # load events expectation for the test
246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            log.debug("  loading result events");
247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            for f in glob.glob(tempdir + '/event*'):
248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                self.load_events(f, self.result);
249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            # resolve group_fd to event names
251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            self.resolve_groups(self.expect);
252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            self.resolve_groups(self.result);
253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            # do the expectation - results matching - both ways
255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            self.compare(self.expect, self.result)
256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            self.compare(self.result, self.expect)
257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        finally:
259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            # cleanup
260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            shutil.rmtree(tempdir)
261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengdef run_tests(options):
264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    for f in glob.glob(options.test_dir + '/' + options.test):
265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        try:
266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            Test(f, options).run()
267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        except Unsup, obj:
268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng            log.warning("unsupp  %s" % obj.getMsg())
269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengdef setup_log(verbose):
271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    global log
272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    level = logging.CRITICAL
273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    if verbose == 1:
275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        level = logging.WARNING
276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    if verbose == 2:
277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        level = logging.INFO
278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    if verbose >= 3:
279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        level = logging.DEBUG
280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    log = logging.getLogger('test')
282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    log.setLevel(level)
283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    ch  = logging.StreamHandler()
284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    ch.setLevel(level)
285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    formatter = logging.Formatter('%(message)s')
286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    ch.setFormatter(formatter)
287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    log.addHandler(ch)
288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen ChengUSAGE = '''%s [OPTIONS]
290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng  -d dir  # tests dir
291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng  -p path # perf binary
292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng  -t test # single test
293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng  -v      # verbose level
294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng''' % sys.argv[0]
295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengdef main():
297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    parser = optparse.OptionParser(usage=USAGE)
298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    parser.add_option("-t", "--test",
300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                      action="store", type="string", dest="test")
301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    parser.add_option("-d", "--test-dir",
302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                      action="store", type="string", dest="test_dir")
303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    parser.add_option("-p", "--perf",
304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                      action="store", type="string", dest="perf")
305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    parser.add_option("-v", "--verbose",
306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng                      action="count", dest="verbose")
307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    options, args = parser.parse_args()
309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    if args:
310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        parser.error('FAILED wrong arguments %s' %  ' '.join(args))
311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        return -1
312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    setup_log(options.verbose)
314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    if not options.test_dir:
316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        print 'FAILED no -d option specified'
317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        sys.exit(-1)
318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    if not options.test:
320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        options.test = 'test*'
321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    try:
323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        run_tests(options)
324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    except Fail, obj:
326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        print "FAILED %s" % obj.getMsg();
327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng        sys.exit(-1)
328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    sys.exit(0)
330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengif __name__ == '__main__':
332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng    main()
333