]> git.cworth.org Git - apitrace-tests/commitdiff
Basic automation with CTest.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Thu, 27 Oct 2011 11:13:03 +0000 (12:13 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Thu, 27 Oct 2011 11:13:03 +0000 (12:13 +0100)
.gitignore
CMakeLists.txt
apps/gl/CMakeLists.txt
apps/gl/tri.ref.txt [new file with mode: 0644]
driver.py [new file with mode: 0755]

index 7c2ddbecafe31fb5045772e0d923c91d6c7b73f1..0f342ec3f394cd471e2872f7ac71fd59c703c72c 100644 (file)
@@ -2,6 +2,8 @@
 *.pyc
 CMakeCache.txt
 CMakeFiles
+CTestTestfile.cmake
 Makefile
+Testing
 cmake_install.cmake
 results
index 32c3029ebd9252e0a0726668530bfa0fa6834727..f69714af88f1010536d51f36d3cd8a085411c74a 100644 (file)
@@ -51,5 +51,11 @@ if (MSVC)
        add_definitions (-wd4244) # conversion' conversion from 'type1' to 'type2', possible loss of data
 endif ()
 
+
+set (APITRACE_BINARY_DIR "${CMAKE_BINARY_DIR}/.." CACHE PATH "apitrace build directory")
+
+
+enable_testing()
+
 add_subdirectory (apps)
 
index a6be3d035b83c834a65201f22e347fbf3408a50b..925261c2036bf72edd1975e6a3ba0d0fc7eed66e 100644 (file)
@@ -20,5 +20,12 @@ set (targets
 foreach (target ${targets})
        add_executable (${subdir}_${target} ${target}.c)
        set_target_properties (${subdir}_${target} PROPERTIES OUTPUT_NAME ${target})
-       install (TARGETS ${subdir}_${target} DESTINATION ${subdir})
+
+    add_test(
+        NAME ${subdir}_${target}
+        COMMAND python ${CMAKE_SOURCE_DIR}/driver.py
+            --build ${APITRACE_BINARY_DIR}
+            --ref-dump ${CMAKE_CURRENT_SOURCE_DIR}/${target}.ref.txt
+            ${CMAKE_CURRENT_BINARY_DIR}/${target}
+    )
 endforeach (target)
diff --git a/apps/gl/tri.ref.txt b/apps/gl/tri.ref.txt
new file mode 100644 (file)
index 0000000..060dd44
--- /dev/null
@@ -0,0 +1,16 @@
+glClearColor(red = 0.3, green = 0.1, blue = 0.3, alpha = 0)
+glViewport(x = 0, y = 0, width = 250, height = 250)
+glMatrixMode(mode = GL_PROJECTION)
+glLoadIdentity()
+glOrtho(left = -1, right = 1, bottom = -1, top = 1, zNear = -0.5, zFar = 1000)
+glMatrixMode(mode = GL_MODELVIEW)
+glClear(mask = GL_COLOR_BUFFER_BIT)
+glBegin(mode = GL_TRIANGLES)
+glColor3f(red = 0.8, green = 0, blue = 0)
+glVertex3f(x = -0.9, y = -0.9, z = -30)
+glColor3f(red = 0, green = 0.9, blue = 0)
+glVertex3f(x = 0.9, y = -0.9, z = -30)
+glColor3f(red = 0, green = 0, blue = 0.7)
+glVertex3f(x = 0, y = 0.9, z = -30)
+glEnd()
+glFlush()
diff --git a/driver.py b/driver.py
new file mode 100755 (executable)
index 0000000..a78be5b
--- /dev/null
+++ b/driver.py
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2011 Jose Fonseca
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+##########################################################################/
+
+'''Common test suite code.'''
+
+
+import math
+import optparse
+import os.path
+import re
+import signal
+import subprocess
+import sys
+import time
+
+
+def popen(command, *args, **kwargs):
+    if kwargs.get('cwd', None) is not None:
+        sys.stdout.write('cd %s && ' % kwargs['cwd'])
+    if 'env' in kwargs:
+        for name, value in kwargs['env'].iteritems():
+            if value != os.environ.get(name, None):
+                sys.stdout.write('%s=%s ' % (name, value))
+    sys.stdout.write(' '.join(command) + '\n')
+    sys.stdout.flush()
+    return subprocess.Popen(command, *args, **kwargs)
+
+
+def _get_build_path(path):
+    if options.build is not None:
+        path = os.path.abspath(os.path.join(options.build, path))
+    if not os.path.exists(path):
+        sys.stderr.write('error: %s does not exist\n' % path)
+        sys.exit(1)
+    return path
+
+
+class TestCase:
+
+    max_frames = None
+
+    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
+
+        if not os.path.exists(results):
+            os.makedirs(results)
+
+    expected_dump = None
+
+    def standalone(self):
+        p = popen(self.args, cwd=self.cwd)
+        p.wait()
+        if p.returncode:
+            sys.stdout.write('SKIP (application faied)\n')
+            sys.exit(0)
+
+    def trace(self):
+        self.trace_file = os.path.abspath(os.path.join(self.results, self.name + '.trace'))
+        ld_preload = _get_build_path('glxtrace.so')
+
+        env = os.environ.copy()
+        env['LD_PRELOAD'] = ld_preload
+        env['TRACE_FILE'] = self.trace_file
+        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()
+
+        if not os.path.exists(self.trace_file):
+            sys.stdout.write('FAIL (trace file missing)\n')
+            sys.exit(1)
+    
+    call_re = re.compile(r'^([0-9]+) (\w+)\(')
+
+    def dump(self):
+
+        cmd = [_get_build_path('tracedump'), '--color=never', self.trace_file]
+        p = popen(cmd, stdout=subprocess.PIPE)
+
+        swapbuffers = 0
+        flushes = 0
+
+        ref_line = ''
+        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()
+            mo = self.call_re.match(line)
+            assert mo
+            if mo:
+                call_no = int(mo.group(1))
+                function_name = mo.group(2)
+                if function_name == 'glXSwapBuffers':
+                    swapbuffers += 1
+                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()
+        p.wait()
+        if p.returncode != 0:
+            sys.stdout.write('FAIL (tracedump)\n')
+            sys.exit(1)
+        if ref_line:
+            sys.stdout.write('FAIL expected %s\n' % ref_line)
+
+
+    def run(self):
+        self.standalone()
+        self.trace()
+        self.dump()
+
+        sys.stdout.write('PASS\n')
+        return
+
+        ref_prefix = os.path.abspath(os.path.join(self.results, self.name + '.ref.'))
+        src_prefix = os.path.join(self.results, self.name + '.src.')
+        diff_prefix = os.path.join(self.results, self.name + '.diff.')
+
+
+        if not os.path.isfile(trace):
+            sys.stdout.write('SKIP (no trace)\n')
+            return
+        args = [_get_build_path('glretrace')]
+        if swapbuffers:
+            args += ['-db']
+            frames = swapbuffers
+        else:
+            args += ['-sb']
+            frames = flushes
+        args += ['-s', src_prefix]
+        args += [trace]
+        p = popen(args, stdout=subprocess.PIPE)
+        image_re = re.compile(r'^Wrote (.*\.png)$')
+        images = []
+        for line in p.stdout:
+            line = line.rstrip()
+            mo = image_re.match(line)
+            if mo:
+                image = mo.group(1)
+                if image.startswith(src_prefix):
+                    image = image[len(src_prefix):]
+                    images.append(image)
+        p.wait()
+        if p.returncode != 0:
+            sys.stdout.write('FAIL (glretrace)\n')
+            return
+
+        for image in images:
+            ref_image = ref_prefix + image
+            src_image = src_prefix + image
+            diff_image = diff_prefix + image
+            
+            if not os.path.isfile(ref_image):
+                continue
+            assert os.path.isfile(src_image)
+
+            comparer = Comparer(ref_image, src_image)
+            match = comparer.ae()
+            sys.stdout.write('%s: %s bits\n' % (image, comparer.precision()))
+            if not match:
+                comparer.write_diff(diff_image)
+                #report.add_snapshot(ref_image, src_image, diff_image)
+                sys.stdout.write('FAIL (snapshot)\n')
+                return
+
+
+
+def main():
+    global options
+
+    # Parse command line options
+    optparser = optparse.OptionParser(
+        usage='\n\t%prog [options] -- program [args] ...',
+        version='%%prog')
+    optparser.add_option(
+        '-B', '--build', metavar='PATH',
+        type='string', dest='build', default='..',
+        help='path to apitrace build')
+    optparser.add_option(
+        '-C', '--directory', metavar='PATH',
+        type='string', dest='cwd', default=None,
+        help='change to directory')
+    optparser.add_option(
+        '-R', '--results', metavar='PATH',
+        type='string', dest='results', default='results',
+        help='results directory [default=%default]')
+    optparser.add_option(
+        '--ref-dump', metavar='PATH',
+        type='string', dest='ref_dump', default=None,
+        help='reference dump')
+
+    (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,
+    )
+    test.ref_dump = options.ref_dump
+
+    test.run()
+
+
+if __name__ == '__main__':
+    main()