12 class Fail(Exception):
13 def __init__(self, test, msg):
17 return '\'%s\' - %s' % (self.test.path, self.msg)
19 class Notest(Exception):
20 def __init__(self, test, arch):
24 return '[%s] \'%s\'' % (self.arch, self.test.path)
26 class Unsup(Exception):
27 def __init__(self, test):
30 return '\'%s\'' % self.test.path
62 'exclude_callchain_kernel',
63 'exclude_callchain_user',
75 log.debug(" %s = %s" % (key, val))
78 def __init__(self, name, data, base):
79 log.debug(" Event %s" % name);
85 def compare_data(self, a, b):
86 # Allow multiple values in assignment separated by '|'
92 if (a_item == b_item):
94 elif (a_item == '*') or (b_item == '*'):
99 def equal(self, other):
100 for t in Event.terms:
101 log.debug(" [%s] %s %s" % (t, self[t], other[t]));
102 if not self.has_key(t) or not other.has_key(t):
104 if not self.compare_data(self[t], other[t]):
108 def diff(self, other):
109 for t in Event.terms:
110 if not self.has_key(t) or not other.has_key(t):
112 if not self.compare_data(self[t], other[t]):
113 log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
115 # Test file description needs to have following sections:
117 # - just single instance in file
118 # - needs to specify:
119 # 'command' - perf command name
120 # 'args' - special command arguments
121 # 'ret' - expected command return value (0 by default)
122 # 'arch' - architecture specific test (optional)
123 # comma separated list, ! at the beginning
127 # - one or multiple instances in file
128 # - expected values assignments
130 def __init__(self, path, options):
131 parser = ConfigParser.SafeConfigParser()
134 log.warning("running '%s'" % path)
137 self.test_dir = options.test_dir
138 self.perf = options.perf
139 self.command = parser.get('config', 'command')
140 self.args = parser.get('config', 'args')
143 self.ret = parser.get('config', 'ret')
148 self.arch = parser.get('config', 'arch')
149 log.warning("test limitation '%s'" % self.arch)
155 log.debug(" loading expected events");
156 self.load_events(path, self.expect)
158 def is_event(self, name):
159 if name.find("event") == -1:
164 def skip_test(self, myarch):
165 # If architecture not set always run test
167 # log.warning("test for arch %s is ok" % myarch)
170 # Allow multiple values in assignment separated by ','
171 arch_list = self.arch.split(',')
173 # Handle negated list such as !s390x,ppc
174 if arch_list[0][0] == '!':
175 arch_list[0] = arch_list[0][1:]
176 log.warning("excluded architecture list %s" % arch_list)
177 for arch_item in arch_list:
178 # log.warning("test for %s arch is %s" % (arch_item, myarch))
179 if arch_item == myarch:
183 for arch_item in arch_list:
184 # log.warning("test for architecture '%s' current '%s'" % (arch_item, myarch))
185 if arch_item == myarch:
189 def load_events(self, path, events):
190 parser_event = ConfigParser.SafeConfigParser()
191 parser_event.read(path)
193 # The event record section header contains 'event' word,
194 # optionaly followed by ':' allowing to load 'parent
195 # event' first as a base
196 for section in filter(self.is_event, parser_event.sections()):
198 parser_items = parser_event.items(section);
201 # Read parent event if there's any
203 base = section[section.index(':') + 1:]
204 parser_base = ConfigParser.SafeConfigParser()
205 parser_base.read(self.test_dir + '/' + base)
206 base_items = parser_base.items('event')
208 e = Event(section, parser_items, base_items)
211 def run_cmd(self, tempdir):
212 junk1, junk2, junk3, junk4, myarch = (os.uname())
214 if self.skip_test(myarch):
215 raise Notest(self, myarch)
217 cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir,
218 self.perf, self.command, tempdir, self.args)
219 ret = os.WEXITSTATUS(os.system(cmd))
221 log.info(" '%s' ret %d " % (cmd, ret))
223 if ret != int(self.ret):
226 def compare(self, expect, result):
229 log.debug(" compare");
231 # For each expected event find all matching
232 # events in result. Fail if there's not any.
233 for exp_name, exp_event in expect.items():
235 log.debug(" matching [%s]" % exp_name)
236 for res_name, res_event in result.items():
237 log.debug(" to [%s]" % res_name)
238 if (exp_event.equal(res_event)):
239 exp_list.append(res_name)
242 log.debug(" ->FAIL");
244 log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list)))
246 # we did not any matching event - fail
248 exp_event.diff(res_event)
249 raise Fail(self, 'match failure');
251 match[exp_name] = exp_list
253 # For each defined group in the expected events
254 # check we match the same group in the result.
255 for exp_name, exp_event in expect.items():
256 group = exp_event.group
261 for res_name in match[exp_name]:
262 res_group = result[res_name].group
263 if res_group not in match[group]:
264 raise Fail(self, 'group failure')
266 log.debug(" group: [%s] matches group leader %s" %
267 (exp_name, str(match[group])))
269 log.debug(" matched")
271 def resolve_groups(self, events):
272 for name, event in events.items():
273 group_fd = event['group_fd'];
277 for iname, ievent in events.items():
278 if (ievent['fd'] == group_fd):
280 log.debug('[%s] has group leader [%s]' % (name, iname))
284 tempdir = tempfile.mkdtemp();
287 # run the test script
288 self.run_cmd(tempdir);
290 # load events expectation for the test
291 log.debug(" loading result events");
292 for f in glob.glob(tempdir + '/event*'):
293 self.load_events(f, self.result);
295 # resolve group_fd to event names
296 self.resolve_groups(self.expect);
297 self.resolve_groups(self.result);
299 # do the expectation - results matching - both ways
300 self.compare(self.expect, self.result)
301 self.compare(self.result, self.expect)
305 shutil.rmtree(tempdir)
308 def run_tests(options):
309 for f in glob.glob(options.test_dir + '/' + options.test):
311 Test(f, options).run()
313 log.warning("unsupp %s" % obj.getMsg())
315 log.warning("skipped %s" % obj.getMsg())
317 def setup_log(verbose):
319 level = logging.CRITICAL
322 level = logging.WARNING
326 level = logging.DEBUG
328 log = logging.getLogger('test')
330 ch = logging.StreamHandler()
332 formatter = logging.Formatter('%(message)s')
333 ch.setFormatter(formatter)
336 USAGE = '''%s [OPTIONS]
338 -p path # perf binary
339 -t test # single test
344 parser = optparse.OptionParser(usage=USAGE)
346 parser.add_option("-t", "--test",
347 action="store", type="string", dest="test")
348 parser.add_option("-d", "--test-dir",
349 action="store", type="string", dest="test_dir")
350 parser.add_option("-p", "--perf",
351 action="store", type="string", dest="perf")
352 parser.add_option("-v", "--verbose",
353 action="count", dest="verbose")
355 options, args = parser.parse_args()
357 parser.error('FAILED wrong arguments %s' % ' '.join(args))
360 setup_log(options.verbose)
362 if not options.test_dir:
363 print 'FAILED no -d option specified'
367 options.test = 'test*'
373 print "FAILED %s" % obj.getMsg();
378 if __name__ == '__main__':