#
##########################################################################/
-'''Common test suite code.'''
+'''Main test driver.'''
-import math
import optparse
import os.path
+import platform
import re
-import signal
+import shutil
import subprocess
import sys
import time
sys.exit(1)
return path
+def _get_build_program(program):
+ if platform.system() == 'Windows':
+ program += '.exe'
+ return _get_build_path(program)
-class TestCase:
- max_frames = None
+class TestCase:
- def __init__(self, name, args, cwd=None, build=None, results = '.'):
- self.name = name
- self.args = args
- self.cwd = cwd
- self.build = build
- self.results = results
+ cmd = None
+ cwd = None
- if not os.path.exists(results):
- os.makedirs(results)
+ api = 'gl'
+ max_frames = None
+ trace_file = None
expected_dump = None
def standalone(self):
- p = popen(self.args, cwd=self.cwd)
+ if not self.cmd:
+ return
+
+ p = popen(self.cmd, cwd=self.cwd)
p.wait()
if p.returncode:
- sys.stdout.write('SKIP (application faied)\n')
- sys.exit(0)
+ self.skip('application returned code %i' % p.returncode)
+
+ api_map = {
+ 'gl': 'gl',
+ 'egl_gl': 'egl',
+ 'egl_gles1': 'egl',
+ 'egl_gles2': 'egl',
+ }
def trace(self):
- self.trace_file = os.path.abspath(os.path.join(self.results, self.name + '.trace'))
- ld_preload = _get_build_path('glxtrace.so')
+ if not self.cmd:
+ return
+
+ if self.trace_file is None:
+ name = os.path.basename(self.cmd[0])
+ self.trace_file = os.path.abspath(os.path.join(self.results, name + '.trace'))
+ if os.path.exists(self.trace_file):
+ os.remove(self.trace_file)
+ else:
+ trace_dir = os.path.dirname(self.trace_file)
+ if not os.path.exists(trace_dir):
+ os.makedirs(trace_dir)
+ cmd = self.cmd
env = os.environ.copy()
- env['LD_PRELOAD'] = ld_preload
- env['TRACE_FILE'] = self.trace_file
+
+ system = platform.system()
+ local_wrapper = None
+ if system == 'Windows':
+ wrapper = _get_build_path('wrappers/opengl32.dll')
+ local_wrapper = os.path.join(os.path.dirname(self.cmd[0]), os.path.basename(wrapper))
+ shutil.copy(wrapper, local_wrapper)
+ env['TRACE_FILE'] = self.trace_file
+ else:
+ apitrace = _get_build_program('apitrace')
+ cmd = [
+ apitrace, 'trace',
+ '--api', self.api_map[self.api],
+ '--output', self.trace_file,
+ '--'
+ ] + cmd
if self.max_frames is not None:
env['TRACE_FRAMES'] = str(self.max_frames)
- p = popen(self.args, env=env, cwd=self.cwd)
- p.wait()
+ try:
+ p = popen(cmd, env=env, cwd=self.cwd)
+ p.wait()
+ finally:
+ if local_wrapper is not None:
+ os.remove(local_wrapper)
if not os.path.exists(self.trace_file):
- sys.stdout.write('FAIL (trace file missing)\n')
- sys.exit(1)
+ self.fail('no trace file generated\n')
call_re = re.compile(r'^([0-9]+) (\w+)\(')
def dump(self):
- cmd = [_get_build_path('tracedump'), '--color=never', self.trace_file]
+ cmd = [_get_build_program('apitrace'), 'dump', '--color=never', self.trace_file]
p = popen(cmd, stdout=subprocess.PIPE)
swapbuffers = 0
flushes = 0
ref_line = ''
+ src_lines = []
if self.ref_dump is not None:
ref = open(self.ref_dump, 'rt')
ref_line = ref.readline().rstrip()
for line in p.stdout:
line = line.rstrip()
+ sys.stdout.write(line + '\n')
mo = self.call_re.match(line)
- assert mo
if mo:
call_no = int(mo.group(1))
function_name = mo.group(2)
if function_name in ('glFlush', 'glFinish'):
flushes += 1
src_line = line[mo.start(2):]
- sys.stdout.write(src_line + '\n')
- if ref_line:
- if src_line == ref_line:
- ref_line = ref.readline().rstrip()
+ else:
+ src_line = line
+ if ref_line:
+ if src_line == ref_line:
+ sys.stdout.write(src_line + '\n')
+ ref_line = ref.readline().rstrip()
+ src_lines = []
+ else:
+ src_lines.append(src_line)
+
p.wait()
if p.returncode != 0:
- sys.stdout.write('FAIL (tracedump)\n')
- sys.exit(1)
+ self.fail('`apitrace dump` returned code %i' % p.returncode)
if ref_line:
- sys.stdout.write('FAIL expected %s\n' % ref_line)
-
+ if src_lines:
+ self.fail('missing call `%s` (found `%s`)' % (ref_line, src_lines[0]))
+ else:
+ self.fail('missing call %s' % ref_line)
+
+ def retrace(self):
+ retrace = self.api_map[self.api] + 'retrace'
+ args = [_get_build_path(retrace)]
+ args += [self.trace_file]
+ p = popen(args, stdout=subprocess.PIPE)
+ p.wait()
+ if p.returncode != 0:
+ self.fail('`%s` returned code %i' % (retrace, p.returncode))
def run(self):
self.standalone()
self.trace()
self.dump()
+ self.retrace()
- sys.stdout.write('PASS\n')
+ self.pass_()
return
ref_prefix = os.path.abspath(os.path.join(self.results, self.name + '.ref.'))
if not os.path.isfile(trace):
sys.stdout.write('SKIP (no trace)\n')
return
- args = [_get_build_path('glretrace')]
+
+ retrace = self.api_map[self.api] + 'retrace'
+ args = [_get_build_path(retrace)]
if swapbuffers:
args += ['-db']
frames = swapbuffers
sys.stdout.write('FAIL (snapshot)\n')
return
+ def fail(self, reason=None):
+ self._exit('FAIL', 1, reason)
+
+ def skip(self, reason=None):
+ self._exit('SKIP', 0, reason)
+
+ def pass_(self, reason=None):
+ self._exit('PASS', 0, reason)
+
+ def _exit(self, status, code, reason=None):
+ if reason is None:
+ reason = ''
+ else:
+ reason = ' (%s)' % reason
+ sys.stdout.write('%s%s\n' % (status, reason))
+ sys.exit(code)
+
def main():
# Parse command line options
optparser = optparse.OptionParser(
- usage='\n\t%prog [options] -- program [args] ...',
+ usage='\n\t%prog [options] -- [TRACE|PROGRAM] ...',
version='%%prog')
+ optparser.add_option(
+ '-a', '--api', metavar='API',
+ type='string', dest='api', default='gl',
+ help='api to trace')
optparser.add_option(
'-B', '--build', metavar='PATH',
type='string', dest='build', default='..',
help='change to directory')
optparser.add_option(
'-R', '--results', metavar='PATH',
- type='string', dest='results', default='results',
+ type='string', dest='results', default='.',
help='results directory [default=%default]')
optparser.add_option(
'--ref-dump', metavar='PATH',
(options, args) = optparser.parse_args(sys.argv[1:])
if not args:
- optparser.error('program must be specified')
-
- test = TestCase(
- name = os.path.basename(args[0]),
- args = args,
- cwd = options.cwd,
- build = options.build,
- results = options.results,
- )
+ optparser.error('an argument must be specified')
+
+ if not os.path.exists(options.results):
+ os.makedirs(options.results)
+
+ test = TestCase()
+
+ if args[0].endswith('.trace'):
+ test.trace_file = args[0]
+ else:
+ test.cmd = args
+ test.cwd = options.cwd
+ test.api = options.api
test.ref_dump = options.ref_dump
+ test.results = options.results
test.run()