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