]> git.cworth.org Git - apitrace-tests/blob - driver.py
a78be5b9fcfe9bfc73f346ec168e837f413c5819
[apitrace-tests] / driver.py
1 #!/usr/bin/env python
2 ##########################################################################
3 #
4 # Copyright 2011 Jose Fonseca
5 # All Rights Reserved.
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 # THE SOFTWARE.
24 #
25 ##########################################################################/
26
27 '''Common test suite code.'''
28
29
30 import math
31 import optparse
32 import os.path
33 import re
34 import signal
35 import subprocess
36 import sys
37 import time
38
39
40 def popen(command, *args, **kwargs):
41     if kwargs.get('cwd', None) is not None:
42         sys.stdout.write('cd %s && ' % kwargs['cwd'])
43     if 'env' in kwargs:
44         for name, value in kwargs['env'].iteritems():
45             if value != os.environ.get(name, None):
46                 sys.stdout.write('%s=%s ' % (name, value))
47     sys.stdout.write(' '.join(command) + '\n')
48     sys.stdout.flush()
49     return subprocess.Popen(command, *args, **kwargs)
50
51
52 def _get_build_path(path):
53     if options.build is not None:
54         path = os.path.abspath(os.path.join(options.build, path))
55     if not os.path.exists(path):
56         sys.stderr.write('error: %s does not exist\n' % path)
57         sys.exit(1)
58     return path
59
60
61 class TestCase:
62
63     max_frames = None
64
65     def __init__(self, name, args, cwd=None, build=None, results = '.'):
66         self.name = name
67         self.args = args
68         self.cwd = cwd
69         self.build = build
70         self.results = results
71
72         if not os.path.exists(results):
73             os.makedirs(results)
74
75     expected_dump = None
76
77     def standalone(self):
78         p = popen(self.args, cwd=self.cwd)
79         p.wait()
80         if p.returncode:
81             sys.stdout.write('SKIP (application faied)\n')
82             sys.exit(0)
83
84     def trace(self):
85         self.trace_file = os.path.abspath(os.path.join(self.results, self.name + '.trace'))
86         ld_preload = _get_build_path('glxtrace.so')
87
88         env = os.environ.copy()
89         env['LD_PRELOAD'] = ld_preload
90         env['TRACE_FILE'] = self.trace_file
91         if self.max_frames is not None:
92             env['TRACE_FRAMES'] = str(self.max_frames)
93
94         p = popen(self.args, env=env, cwd=self.cwd)
95         p.wait()
96
97         if not os.path.exists(self.trace_file):
98             sys.stdout.write('FAIL (trace file missing)\n')
99             sys.exit(1)
100     
101     call_re = re.compile(r'^([0-9]+) (\w+)\(')
102
103     def dump(self):
104
105         cmd = [_get_build_path('tracedump'), '--color=never', self.trace_file]
106         p = popen(cmd, stdout=subprocess.PIPE)
107
108         swapbuffers = 0
109         flushes = 0
110
111         ref_line = ''
112         if self.ref_dump is not None:
113             ref = open(self.ref_dump, 'rt')
114             ref_line = ref.readline().rstrip()
115         for line in p.stdout:
116             line = line.rstrip()
117             mo = self.call_re.match(line)
118             assert mo
119             if mo:
120                 call_no = int(mo.group(1))
121                 function_name = mo.group(2)
122                 if function_name == 'glXSwapBuffers':
123                     swapbuffers += 1
124                 if function_name in ('glFlush', 'glFinish'):
125                     flushes += 1
126                 src_line = line[mo.start(2):]
127                 sys.stdout.write(src_line + '\n')
128                 if ref_line:
129                     if src_line == ref_line:
130                         ref_line = ref.readline().rstrip()
131         p.wait()
132         if p.returncode != 0:
133             sys.stdout.write('FAIL (tracedump)\n')
134             sys.exit(1)
135         if ref_line:
136             sys.stdout.write('FAIL expected %s\n' % ref_line)
137
138
139     def run(self):
140         self.standalone()
141         self.trace()
142         self.dump()
143
144         sys.stdout.write('PASS\n')
145         return
146
147         ref_prefix = os.path.abspath(os.path.join(self.results, self.name + '.ref.'))
148         src_prefix = os.path.join(self.results, self.name + '.src.')
149         diff_prefix = os.path.join(self.results, self.name + '.diff.')
150
151
152         if not os.path.isfile(trace):
153             sys.stdout.write('SKIP (no trace)\n')
154             return
155         args = [_get_build_path('glretrace')]
156         if swapbuffers:
157             args += ['-db']
158             frames = swapbuffers
159         else:
160             args += ['-sb']
161             frames = flushes
162         args += ['-s', src_prefix]
163         args += [trace]
164         p = popen(args, stdout=subprocess.PIPE)
165         image_re = re.compile(r'^Wrote (.*\.png)$')
166         images = []
167         for line in p.stdout:
168             line = line.rstrip()
169             mo = image_re.match(line)
170             if mo:
171                 image = mo.group(1)
172                 if image.startswith(src_prefix):
173                     image = image[len(src_prefix):]
174                     images.append(image)
175         p.wait()
176         if p.returncode != 0:
177             sys.stdout.write('FAIL (glretrace)\n')
178             return
179
180         for image in images:
181             ref_image = ref_prefix + image
182             src_image = src_prefix + image
183             diff_image = diff_prefix + image
184             
185             if not os.path.isfile(ref_image):
186                 continue
187             assert os.path.isfile(src_image)
188
189             comparer = Comparer(ref_image, src_image)
190             match = comparer.ae()
191             sys.stdout.write('%s: %s bits\n' % (image, comparer.precision()))
192             if not match:
193                 comparer.write_diff(diff_image)
194                 #report.add_snapshot(ref_image, src_image, diff_image)
195                 sys.stdout.write('FAIL (snapshot)\n')
196                 return
197
198
199
200 def main():
201     global options
202
203     # Parse command line options
204     optparser = optparse.OptionParser(
205         usage='\n\t%prog [options] -- program [args] ...',
206         version='%%prog')
207     optparser.add_option(
208         '-B', '--build', metavar='PATH',
209         type='string', dest='build', default='..',
210         help='path to apitrace build')
211     optparser.add_option(
212         '-C', '--directory', metavar='PATH',
213         type='string', dest='cwd', default=None,
214         help='change to directory')
215     optparser.add_option(
216         '-R', '--results', metavar='PATH',
217         type='string', dest='results', default='results',
218         help='results directory [default=%default]')
219     optparser.add_option(
220         '--ref-dump', metavar='PATH',
221         type='string', dest='ref_dump', default=None,
222         help='reference dump')
223
224     (options, args) = optparser.parse_args(sys.argv[1:])
225     if not args:
226         optparser.error('program must be specified')
227
228     test = TestCase(
229         name = os.path.basename(args[0]), 
230         args = args,
231         cwd = options.cwd,
232         build = options.build,
233         results = options.results,
234     )
235     test.ref_dump = options.ref_dump
236
237     test.run()
238
239
240 if __name__ == '__main__':
241     main()