]> git.cworth.org Git - apitrace-tests/commitdiff
Merge branch 'trim-auto'
authorJosé Fonseca <jfonseca@vmware.com>
Mon, 28 Jan 2013 19:48:41 +0000 (19:48 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Mon, 28 Jan 2013 19:48:41 +0000 (19:48 +0000)
31 files changed:
CMakeLists.txt
apps/README.markdown [new file with mode: 0644]
cli/.gitignore [new file with mode: 0644]
cli/CMakeLists.txt [new file with mode: 0644]
cli/README.markdown [new file with mode: 0644]
cli/cli-diff-images-mismatch.script [new file with mode: 0644]
cli/cli-diff-images.script [new file with mode: 0644]
cli/cli-trim-single-swapbuffers.script [new file with mode: 0644]
cli/cli-trim-unused-shaders.script [new file with mode: 0644]
cli/cli-trim-unused-textures.script [new file with mode: 0644]
cli/glxsimple.trace [new file with mode: 0644]
cli/images/black-1x1/0.png [new file with mode: 0644]
cli/images/white-1x1/0.png [new file with mode: 0644]
cli/src/.gitignore [new file with mode: 0644]
cli/src/Makefile [new file with mode: 0644]
cli/src/glxsimple.c [new file with mode: 0644]
cli/tri-ref-mismatch/tri0000000000.png [new file with mode: 0644]
cli/tri-ref/tri0000000000.png [new file with mode: 0644]
cli/tri.trace [new file with mode: 0644]
cli_driver.py [new file with mode: 0644]
traces/.gitignore
traces/README.markdown
traces/glxsimple.trace [new file with mode: 0644]
traces/trim-frame-set.script [new file with mode: 0644]
traces/trim-head-by-frame.script [new file with mode: 0644]
traces/trim-head.script [new file with mode: 0644]
trim_stress/.gitignore [new file with mode: 0644]
trim_stress/CMakeLists.txt [new file with mode: 0644]
trim_stress/README.markdown [new file with mode: 0644]
trim_stress/glxsimple.trace [new file with mode: 0644]
trim_stress_driver.py [new file with mode: 0644]

index 47c38cb06b3bfb488b699269d309c93c2edc1a57..2dff8574de0d8db7b37d5c3cc18e6d6b8c59d2e1 100644 (file)
@@ -47,6 +47,19 @@ elseif (PKG_CONFIG_FOUND)
        pkg_check_modules (GLESV2 glesv2)
 endif ()
 
+# Check for the presence of several python packages, which are needed to build
+# generated tests.
+execute_process(
+    COMMAND ${python} -c "import PIL"
+    OUTPUT_QUIET
+    ERROR_QUIET
+    RESULT_VARIABLE IMPORT_PIL_RESULT)
+if (IMPORT_PIL_RESULT EQUAL 0)
+    set (PIL_FOUND 1)
+else ()
+    message (STATUS "python PIL module not found")
+endif ()
+
 if (UNIX)
        link_libraries(m)
 endif (UNIX)
@@ -90,3 +103,18 @@ enable_testing()
 add_subdirectory (apps)
 add_subdirectory (traces)
 
+# FIXME: The tests in the cli directory are intended to be high-level
+# tests of the apitrace command-line interface which would ideally be
+# portable across all platforms. However, these tests all rely on
+# doing image comparisons and the current implementation of the
+# "apitrace dump-images" command relies on direct invocation of the
+# glretrace command.
+#
+# Someday, we should have more unified commands for replaying traces,
+# dumping images, etc. At that point these cli tests should be usable
+# with all targets so that we can drop the "if (OPENGL_FOUND)"
+# condition here.
+if (OPENGL_FOUND AND PIL_FOUND)
+    add_subdirectory (cli)
+    add_subdirectory (trim_stress)
+endif ()
diff --git a/apps/README.markdown b/apps/README.markdown
new file mode 100644 (file)
index 0000000..3820630
--- /dev/null
@@ -0,0 +1,34 @@
+These directories contain many drawing-api-specific test applications.
+
+Within each directory's CMakeLists.txt file are you will see
+definitions of tests such as the following:
+
+    add_app_test (
+        NAME "gl_default_sb"
+        TARGET gl_tri
+        ARGS -sb
+        REF default_sb.ref.txt
+    )
+
+This block specifies a test with NAME "gl_default_sb" that involves
+executing the TARGET program "gl_tri" with ARGS of "-sb". The REF
+script contains a reference trance that should result from tracing the
+given program, along with specifications for additional checks to be
+peformed.
+
+The actual execution of the test (and parsing of the REF script) is
+performed by the python program in ../app_driver.py. This driver
+program runs the application with the given arguments, performs a
+trace of the application, checks the trace against the reference
+script, and then run a "retrace" of the application (replaying the
+commands in the trace).
+
+In addition to a dump of the expected trace content, the reference
+file can contain directives to cause the driver program to perform
+additional checking. Some of the available directives are:
+
+  #image: Dump the current framebuffer image and compare against the
+          given file.
+
+  #state: Dump the current state in JSON format and compare against
+          the given file.
diff --git a/cli/.gitignore b/cli/.gitignore
new file mode 100644 (file)
index 0000000..cc6da65
--- /dev/null
@@ -0,0 +1,7 @@
+!*.trace
+tri-trim.trace
+tri-out
+glxsimple-ref
+glxsimple-out
+glxsimple-trim.trace
+glxsimple-trim-unused-textures.trace
diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9d7ce55
--- /dev/null
@@ -0,0 +1,29 @@
+function (ADD_CLI_TEST)
+    cmake_parse_arguments(
+        TEST
+        # Options
+        ""
+        # One value args
+        "NAME"
+        # Multi value args
+        ""
+        ${ARGN}
+    )
+
+    if (APITRACE_EXECUTABLE)
+        add_test(
+            NAME ${TEST_NAME}
+            COMMAND
+            python ${CMAKE_SOURCE_DIR}/cli_driver.py
+                --apitrace ${APITRACE_EXECUTABLE}
+                --apitrace-source ${APITRACE_SOURCE_DIR}
+                ${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}
+        )
+    endif ()
+endfunction ()
+
+add_cli_test(NAME "cli-diff-images.script")
+add_cli_test(NAME "cli-diff-images-mismatch.script")
+add_cli_test(NAME "cli-trim-single-swapbuffers.script")
+add_cli_test(NAME "cli-trim-unused-textures.script")
+add_cli_test(NAME "cli-trim-unused-shaders.script")
diff --git a/cli/README.markdown b/cli/README.markdown
new file mode 100644 (file)
index 0000000..4f49822
--- /dev/null
@@ -0,0 +1,39 @@
+This directory tests high-level functionality of apitrace command-line
+interface (cli). See also the neighboring "traces" directory which
+also tests the cli, but in ways that can only be verified by doing
+comparisons of resulting dump files.
+
+For writing new tests, if the functionality can be exercised by a
+sequence of apitrace command invocations, and then a final comparison
+of "apitrace dump" output, then it's likely simplest to write a new
+test in the traces directory. Otherwise, a new test program can be
+written in this directory.
+
+The tests in this directory are found in files with names matching
+*.script by convention. The scripts must be listed explicitly in the
+CMakeLists.txt file. Each script consists of simple line-based
+commands with the following meanings (based on the first word of each
+line):
+
+  apitrace:     Execute the current apitrace executable being tested
+               with the given arguments. If apitrace returns a
+               non-zero status, the test will fail.
+
+  expect:       Compare the results of the previously-executed command
+                with the given (json-quoted) string. If the strings
+                are not identical, the test will fail.
+
+  rm_and_mkdir: Remove any existing directory of the given name and
+                then create it. The directory name is always
+                interpreted locally. If this fails for any reason
+                other than "file does not exist" the test will fail.
+
+Note: Blank lines and lines beginning with '#' are ignored.
+
+Commands can be prefixed with "EXPECT_FAILURE:" to indicate that a
+command is expected to return a non-zero value. In this case, a return
+value of zero from the command will cause the test to fail.
+
+If none of the commands in the script cause the test to fail (as
+described above), then the test will pass.
+
diff --git a/cli/cli-diff-images-mismatch.script b/cli/cli-diff-images-mismatch.script
new file mode 100644 (file)
index 0000000..15446ad
--- /dev/null
@@ -0,0 +1,7 @@
+EXPECT_FAILURE: apitrace diff-images --verbose images/white-1x1/ images/black-1x1/
+
+# In addition to getting the return value indicating an error, let's
+# also require that "apitrace diff-images" gave us the output we
+# expect.
+
+expect "Comparing images/white-1x1/0.png and images/black-1x1/0.png ... MISMATCH\n"
diff --git a/cli/cli-diff-images.script b/cli/cli-diff-images.script
new file mode 100644 (file)
index 0000000..27327d4
--- /dev/null
@@ -0,0 +1,8 @@
+apitrace diff-images --verbose images/white-1x1/ images/white-1x1/
+
+# Ensure that the "apitrace diff-images" actually did something.  This
+# is important since if it couldn't find images in one directory or
+# the other then it would just silently return 0 and this test would
+# incorrectly pass.
+
+expect "Comparing images/white-1x1/0.png and images/white-1x1/0.png ... MATCH\n"
diff --git a/cli/cli-trim-single-swapbuffers.script b/cli/cli-trim-single-swapbuffers.script
new file mode 100644 (file)
index 0000000..e653d49
--- /dev/null
@@ -0,0 +1,15 @@
+# First, trim the trace to the final glxSwapBuffers call
+
+apitrace trim --auto --calls=27 tri.trace
+
+# Then dump the image and compare to our reference
+
+rm_and_mkdir ./tri-out
+apitrace dump-images --call-nos=no -o ./tri-out/tri tri-trim.trace
+apitrace diff-images -v ./tri-ref ./tri-out
+
+# In addition to getting the return value indicating no error, let's
+# also require that "apitrace diff-images" gave us the output we
+# expect.
+
+expect "Comparing ./tri-ref/tri0000000000.png and ./tri-out/tri0000000000.png ... MATCH\n"
diff --git a/cli/cli-trim-unused-shaders.script b/cli/cli-trim-unused-shaders.script
new file mode 100644 (file)
index 0000000..8d461b0
--- /dev/null
@@ -0,0 +1,120 @@
+# Generate reference images from unmodified trace.
+
+# We carefully generate images only for desired frames (dropping the
+# first frame that draws using shaders).
+
+rm_and_mkdir glxsimple-ref
+apitrace dump-images --calls=10,47,50,71,87,88 --call-nos=no -o ./glxsimple-ref/ glxsimple.trace
+
+# Trim to the same callset used to generate reference images
+
+apitrace trim --auto --calls=10,47,50,71,87,88 glxsimple.trace
+
+# Verify that we actually trimmed what we wanted to
+
+apitrace diff --diff=python glxsimple.trace glxsimple-trim.trace
+expect r"""  glXChooseVisual(37134976, 0, (GLX_RGBA, GLX_RED_SIZE, GLX_RED_SIZE, GLX_GREEN_SIZE, GLX_RED_SIZE, GLX_BLUE_SIZE, GLX_RED_SIZE, GLX_ALPHA_SIZE, GLX_RED_SIZE, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, GLX_RED_SIZE, GLX_X_VISUAL_TYPE, GLX_DIRECT_COLOR, 0)) = ([37179128, 34, 0, 24, 5, 16711680, 65280, 255, 256, 8])
+  glXCreateContext(37134976, ([37179128, 34, 0, 24, 5, 16711680, 65280, 255, 256, 8]), 0, True) = 37241648
+  glXMakeCurrent(37134976, 41943041, 37241648) = True
+  glViewport(0, 0, 64, 64)
+  glMatrixMode(GL_PROJECTION)
+  glLoadIdentity()
+  glOrtho(0.0, 64.0, 64.0, 0.0, 0.0, 1.0)
+  glMatrixMode(GL_MODELVIEW)
+  glClearColor(0.0, 0.0, 1.0, 1.0)
+  glClear((GL_COLOR_BUFFER_BIT))
+  glXSwapBuffers(37134976, 41943041)
+- glCreateShader(GL_VERTEX_SHADER) = 7
+- glShaderSource(7, 1, ('void main()\n{\n        gl_Position = ftransform();\n}\n'), 0)
+- glCompileShader(7)
+- glCreateShader(GL_FRAGMENT_SHADER) = 8
+- glShaderSource(8, 1, ('#version 120\nuniform vec4 color;\nvoid main()\n{\n        gl_FragColor = color;\n}\n'), 0)
+- glCompileShader(8)
+- glCreateProgram() = 9
+- glAttachShader(9, 7)
+- glAttachShader(9, 8)
+- glLinkProgram(9)
+- glUseProgram(9)
+- glGetUniformLocation(9, color) = 0
+- glUniform4f(0, 0.0, 1.0, 0.0, 1.0)
+- glBegin(GL_QUADS)
+- glVertex2f(0.0, 0.0)
+- glVertex2f(64.0, 0.0)
+- glVertex2f(64.0, 64.0)
+- glVertex2f(0.0, 64.0)
+- glEnd()
+  glUseProgram(0)
+- glXSwapBuffers(37134976, 41943041)
+  glGenTextures(1, (1))
+  glBindTexture(GL_TEXTURE_2D, 1)
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, blob(3))
+  glEnable(GL_TEXTURE_2D)
+  glBegin(GL_QUADS)
+  glTexCoord2f(0.0, 0.0)
+  glVertex2f(0.0, 0.0)
+  glTexCoord2f(1.0, 0.0)
+  glVertex2f(64.0, 0.0)
+  glTexCoord2f(1.0, 1.0)
+  glVertex2f(64.0, 64.0)
+  glTexCoord2f(0.0, 1.0)
+  glVertex2f(0.0, 64.0)
+  glEnd()
+  glDisable(GL_TEXTURE_2D)
+  glXSwapBuffers(37134976, 41943041)
+  glClearColor(1.0, 0.0, 0.0, 1.0)
+  glClear((GL_COLOR_BUFFER_BIT))
+  glXSwapBuffers(37134976, 41943041)
+  glCreateShader(GL_VERTEX_SHADER) = 10
+  glShaderSource(10, 1, ('void main()\n{\n        gl_Position = ftransform();\n}\n'), 0)
+  glCompileShader(10)
+  glCreateShader(GL_FRAGMENT_SHADER) = 11
+  glShaderSource(11, 1, ('#version 120\nuniform vec4 color;\nvoid main()\n{\n        gl_FragColor = color;\n}\n'), 0)
+  glCompileShader(11)
+  glCreateProgram() = 12
+  glAttachShader(12, 10)
+  glAttachShader(12, 11)
+  glLinkProgram(12)
+  glUseProgram(12)
+  glGetUniformLocation(12, color) = 0
+  glUniform4f(0, 1.0, 0.0, 1.0, 1.0)
+  glBegin(GL_QUADS)
+  glVertex2f(0.0, 0.0)
+  glVertex2f(64.0, 0.0)
+  glVertex2f(64.0, 64.0)
+  glVertex2f(0.0, 64.0)
+  glEnd()
+  glUseProgram(0)
+  glXSwapBuffers(37134976, 41943041)
+  glGenTextures(1, (2))
+  glBindTexture(GL_TEXTURE_2D, 2)
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, blob(3))
+  glEnable(GL_TEXTURE_2D)
+  glBegin(GL_QUADS)
+  glTexCoord2f(0.0, 0.0)
+  glVertex2f(0.0, 0.0)
+  glTexCoord2f(1.0, 0.0)
+  glVertex2f(64.0, 0.0)
+  glTexCoord2f(1.0, 1.0)
+  glVertex2f(64.0, 64.0)
+  glTexCoord2f(0.0, 1.0)
+  glVertex2f(0.0, 64.0)
+  glEnd()
+  glDisable(GL_TEXTURE_2D)
+  glXSwapBuffers(37134976, 41943041)
+  glXDestroyContext(37134976, 37241648)
+"""
+
+# Generate output images for all frames in the trimmed trace
+
+rm_and_mkdir glxsimple-out
+apitrace dump-images --call-nos=no -o ./glxsimple-out/ glxsimple-trim.trace
+
+# Compare output to reference images
+
+apitrace diff-images -v ./glxsimple-ref ./glxsimple-out
+expect r"""Comparing ./glxsimple-ref/0000000000.png and ./glxsimple-out/0000000000.png ... MATCH
+Comparing ./glxsimple-ref/0000000001.png and ./glxsimple-out/0000000001.png ... MATCH
+Comparing ./glxsimple-ref/0000000002.png and ./glxsimple-out/0000000002.png ... MATCH
+Comparing ./glxsimple-ref/0000000003.png and ./glxsimple-out/0000000003.png ... MATCH
+Comparing ./glxsimple-ref/0000000004.png and ./glxsimple-out/0000000004.png ... MATCH
+"""
diff --git a/cli/cli-trim-unused-textures.script b/cli/cli-trim-unused-textures.script
new file mode 100644 (file)
index 0000000..96ab853
--- /dev/null
@@ -0,0 +1,120 @@
+# Generate reference images from unmodified trace.
+
+# We carefully generate images only for desired frames (dropping the
+# first frame that draws using textures).
+
+rm_and_mkdir glxsimple-ref
+apitrace dump-images --calls=10,31,50,71,87,88 --call-nos=no -o ./glxsimple-ref/ glxsimple.trace
+
+# Trim to the same callset used to generate reference images
+
+apitrace trim --auto -o glxsimple-trim-unused-textures.trace --calls=10,31,50,71,87,88 glxsimple.trace
+
+# Verify that we actually trimmed what we wanted to
+
+apitrace diff --diff=python glxsimple.trace glxsimple-trim-unused-textures.trace
+expect r"""  glXChooseVisual(37134976, 0, (GLX_RGBA, GLX_RED_SIZE, GLX_RED_SIZE, GLX_GREEN_SIZE, GLX_RED_SIZE, GLX_BLUE_SIZE, GLX_RED_SIZE, GLX_ALPHA_SIZE, GLX_RED_SIZE, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, GLX_RED_SIZE, GLX_X_VISUAL_TYPE, GLX_DIRECT_COLOR, 0)) = ([37179128, 34, 0, 24, 5, 16711680, 65280, 255, 256, 8])
+  glXCreateContext(37134976, ([37179128, 34, 0, 24, 5, 16711680, 65280, 255, 256, 8]), 0, True) = 37241648
+  glXMakeCurrent(37134976, 41943041, 37241648) = True
+  glViewport(0, 0, 64, 64)
+  glMatrixMode(GL_PROJECTION)
+  glLoadIdentity()
+  glOrtho(0.0, 64.0, 64.0, 0.0, 0.0, 1.0)
+  glMatrixMode(GL_MODELVIEW)
+  glClearColor(0.0, 0.0, 1.0, 1.0)
+  glClear((GL_COLOR_BUFFER_BIT))
+  glXSwapBuffers(37134976, 41943041)
+  glCreateShader(GL_VERTEX_SHADER) = 7
+  glShaderSource(7, 1, ('void main()\n{\n        gl_Position = ftransform();\n}\n'), 0)
+  glCompileShader(7)
+  glCreateShader(GL_FRAGMENT_SHADER) = 8
+  glShaderSource(8, 1, ('#version 120\nuniform vec4 color;\nvoid main()\n{\n        gl_FragColor = color;\n}\n'), 0)
+  glCompileShader(8)
+  glCreateProgram() = 9
+  glAttachShader(9, 7)
+  glAttachShader(9, 8)
+  glLinkProgram(9)
+  glUseProgram(9)
+  glGetUniformLocation(9, color) = 0
+  glUniform4f(0, 0.0, 1.0, 0.0, 1.0)
+  glBegin(GL_QUADS)
+  glVertex2f(0.0, 0.0)
+  glVertex2f(64.0, 0.0)
+  glVertex2f(64.0, 64.0)
+  glVertex2f(0.0, 64.0)
+  glEnd()
+  glUseProgram(0)
+  glXSwapBuffers(37134976, 41943041)
+- glGenTextures(1, (1))
+  glBindTexture(GL_TEXTURE_2D, 1)
+- glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, blob(3))
+  glEnable(GL_TEXTURE_2D)
+- glBegin(GL_QUADS)
+- glTexCoord2f(0.0, 0.0)
+- glVertex2f(0.0, 0.0)
+- glTexCoord2f(1.0, 0.0)
+- glVertex2f(64.0, 0.0)
+- glTexCoord2f(1.0, 1.0)
+- glVertex2f(64.0, 64.0)
+- glTexCoord2f(0.0, 1.0)
+- glVertex2f(0.0, 64.0)
+- glEnd()
+  glDisable(GL_TEXTURE_2D)
+- glXSwapBuffers(37134976, 41943041)
+  glClearColor(1.0, 0.0, 0.0, 1.0)
+  glClear((GL_COLOR_BUFFER_BIT))
+  glXSwapBuffers(37134976, 41943041)
+  glCreateShader(GL_VERTEX_SHADER) = 10
+  glShaderSource(10, 1, ('void main()\n{\n        gl_Position = ftransform();\n}\n'), 0)
+  glCompileShader(10)
+  glCreateShader(GL_FRAGMENT_SHADER) = 11
+  glShaderSource(11, 1, ('#version 120\nuniform vec4 color;\nvoid main()\n{\n        gl_FragColor = color;\n}\n'), 0)
+  glCompileShader(11)
+  glCreateProgram() = 12
+  glAttachShader(12, 10)
+  glAttachShader(12, 11)
+  glLinkProgram(12)
+  glUseProgram(12)
+  glGetUniformLocation(12, color) = 0
+  glUniform4f(0, 1.0, 0.0, 1.0, 1.0)
+  glBegin(GL_QUADS)
+  glVertex2f(0.0, 0.0)
+  glVertex2f(64.0, 0.0)
+  glVertex2f(64.0, 64.0)
+  glVertex2f(0.0, 64.0)
+  glEnd()
+  glUseProgram(0)
+  glXSwapBuffers(37134976, 41943041)
+  glGenTextures(1, (2))
+  glBindTexture(GL_TEXTURE_2D, 2)
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, blob(3))
+  glEnable(GL_TEXTURE_2D)
+  glBegin(GL_QUADS)
+  glTexCoord2f(0.0, 0.0)
+  glVertex2f(0.0, 0.0)
+  glTexCoord2f(1.0, 0.0)
+  glVertex2f(64.0, 0.0)
+  glTexCoord2f(1.0, 1.0)
+  glVertex2f(64.0, 64.0)
+  glTexCoord2f(0.0, 1.0)
+  glVertex2f(0.0, 64.0)
+  glEnd()
+  glDisable(GL_TEXTURE_2D)
+  glXSwapBuffers(37134976, 41943041)
+  glXDestroyContext(37134976, 37241648)
+"""
+
+# Generate output images for all frames in the trimmed trace
+
+rm_and_mkdir glxsimple-out
+apitrace dump-images --call-nos=no -o ./glxsimple-out/ glxsimple-trim-unused-textures.trace
+
+# Compare output to reference images
+
+apitrace diff-images -v ./glxsimple-ref ./glxsimple-out
+expect r"""Comparing ./glxsimple-ref/0000000000.png and ./glxsimple-out/0000000000.png ... MATCH
+Comparing ./glxsimple-ref/0000000001.png and ./glxsimple-out/0000000001.png ... MATCH
+Comparing ./glxsimple-ref/0000000002.png and ./glxsimple-out/0000000002.png ... MATCH
+Comparing ./glxsimple-ref/0000000003.png and ./glxsimple-out/0000000003.png ... MATCH
+Comparing ./glxsimple-ref/0000000004.png and ./glxsimple-out/0000000004.png ... MATCH
+"""
diff --git a/cli/glxsimple.trace b/cli/glxsimple.trace
new file mode 100644 (file)
index 0000000..9c22592
Binary files /dev/null and b/cli/glxsimple.trace differ
diff --git a/cli/images/black-1x1/0.png b/cli/images/black-1x1/0.png
new file mode 100644 (file)
index 0000000..12b0fd3
Binary files /dev/null and b/cli/images/black-1x1/0.png differ
diff --git a/cli/images/white-1x1/0.png b/cli/images/white-1x1/0.png
new file mode 100644 (file)
index 0000000..9c2dfc7
Binary files /dev/null and b/cli/images/white-1x1/0.png differ
diff --git a/cli/src/.gitignore b/cli/src/.gitignore
new file mode 100644 (file)
index 0000000..db85a30
--- /dev/null
@@ -0,0 +1,2 @@
+*~
+glxsimple
diff --git a/cli/src/Makefile b/cli/src/Makefile
new file mode 100644 (file)
index 0000000..87102fc
--- /dev/null
@@ -0,0 +1,9 @@
+PROGS=glxsimple
+
+all: $(PROGS)
+
+%:%.c
+       $(CC) -Wall -Wextra -g -o $@ $^ -lGL -lX11 -lGLEW
+
+clean:
+       rm -f *.o $(PROGS)
diff --git a/cli/src/glxsimple.c b/cli/src/glxsimple.c
new file mode 100644 (file)
index 0000000..a4c9560
--- /dev/null
@@ -0,0 +1,285 @@
+/**************************************************************************
+ * Copyright 2012 Intel corporation
+ * 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.
+ *
+ **************************************************************************/
+
+#include <stdio.h>
+
+#include <X11/Xlib.h>
+#include <GL/glew.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+int width = 64;
+int height = 64;
+
+static void
+set_2d_projection (void)
+{
+       glMatrixMode (GL_PROJECTION);
+       glLoadIdentity ();
+       glOrtho (0, width, height, 0, 0, 1);
+       glMatrixMode (GL_MODELVIEW);
+}
+
+static void
+draw_fullscreen_quad (void)
+{
+       glBegin (GL_QUADS);
+       glVertex2f (0, 0);
+       glVertex2f (width, 0);
+       glVertex2f (width, height);
+       glVertex2f (0, height);
+       glEnd ();
+}
+
+static void
+draw_fullscreen_textured_quad (void)
+{
+       glBegin (GL_QUADS);
+       glTexCoord2f(0, 0); glVertex2f (0, 0);
+       glTexCoord2f(1, 0); glVertex2f (width, 0);
+       glTexCoord2f(1, 1); glVertex2f (width, height);
+       glTexCoord2f(0, 1); glVertex2f (0, height);
+       glEnd ();
+}
+
+static void
+paint_rgb_using_clear (double r, double g, double b)
+{
+        glClearColor(r, g, b, 1.0);
+        glClear(GL_COLOR_BUFFER_BIT);
+}
+
+static void
+paint_rgb_using_glsl (double r, double g, double b)
+{
+       const char * vs_source =
+               "void main()\n"
+               "{\n"
+               "        gl_Position = ftransform();\n"
+               "}\n";
+       const char * fs_source =
+               "#version 120\n"
+               "uniform vec4 color;\n"
+               "void main()\n"
+               "{\n"
+               "        gl_FragColor = color;\n"
+               "}\n";
+
+       GLuint vs, fs, program;
+       GLint color;
+
+       vs = glCreateShader (GL_VERTEX_SHADER);
+       glShaderSource (vs, 1, &vs_source, NULL);
+       glCompileShader (vs);
+
+       fs = glCreateShader (GL_FRAGMENT_SHADER);
+       glShaderSource (fs, 1, &fs_source, NULL);
+       glCompileShader (fs);
+
+       program = glCreateProgram ();
+       glAttachShader (program, vs);
+       glAttachShader (program, fs);
+
+       glLinkProgram (program);
+       glUseProgram (program);
+
+       color = glGetUniformLocation (program, "color");
+
+       glUniform4f (color, r, g, b, 1.0);
+
+       draw_fullscreen_quad ();
+
+       glUseProgram (0);
+}
+
+static GLuint
+create_rgb_texture (double r, double g, double b)
+{
+       uint8_t data[3];
+       GLuint texture = 0;
+
+       data[0] = (uint8_t) (255.0 * r);
+       data[1] = (uint8_t) (255.0 * g);
+       data[2] = (uint8_t) (255.0 * b);
+
+       glGenTextures (1, &texture);
+
+       glBindTexture (GL_TEXTURE_2D, texture);
+
+       glTexImage2D (GL_TEXTURE_2D,
+                     0, GL_COMPRESSED_RGBA,
+                     1, 1, 0,
+                     GL_RGB, GL_UNSIGNED_BYTE, data);
+
+       return texture;
+}
+
+static void
+paint_using_texture (GLuint texture)
+{
+       glBindTexture (GL_TEXTURE_2D, texture);
+
+       glEnable (GL_TEXTURE_2D);
+
+       draw_fullscreen_textured_quad ();
+
+       glDisable (GL_TEXTURE_2D);
+}
+
+static void
+draw (Display *dpy, Window window, int width, int height)
+{
+#define PASSES 2
+       int i;
+       GLenum glew_err;
+       GLuint texture[PASSES];
+
+        int visual_attr[] = {
+                GLX_RGBA,
+                GLX_RED_SIZE,          8,
+                GLX_GREEN_SIZE,        8,
+                GLX_BLUE_SIZE,         8,
+                GLX_ALPHA_SIZE,        8,
+                GLX_DOUBLEBUFFER,
+                GLX_DEPTH_SIZE,                24,
+                GLX_STENCIL_SIZE,      8,
+                GLX_X_VISUAL_TYPE,     GLX_DIRECT_COLOR,
+                None
+        };
+
+       /* Window and context setup. */
+        XVisualInfo *visual_info = glXChooseVisual(dpy, 0, visual_attr);
+        GLXContext ctx = glXCreateContext(dpy, visual_info, NULL, True);
+        glXMakeCurrent(dpy, window, ctx);
+
+       glew_err = glewInit();
+       if (glew_err != GLEW_OK)
+       {
+               fprintf (stderr, "glewInit failed: %s\n",
+                        glewGetErrorString(glew_err));
+               exit (1);
+       }
+
+        glViewport(0, 0, width, height);
+
+       set_2d_projection ();
+
+/* Simply count through some colors, frame by frame. */
+#define RGB(frame) (((frame+1)/4) % 2), (((frame+1)/2) % 2), ((frame+1) % 2)
+
+       int frame = 0;
+       for (i = 0; i < PASSES; i++) {
+
+               /* Frame: Draw a solid frame using glClear. */
+               paint_rgb_using_clear (RGB(frame));
+               glXSwapBuffers (dpy, window);
+               frame++;
+
+               /* Frame: Draw a solid frame using GLSL. */
+               paint_rgb_using_glsl (RGB(frame));
+               glXSwapBuffers (dpy, window);
+               frame++;
+
+               /* Frame: Draw a solid frame using a texture. */
+               texture[i] = create_rgb_texture (RGB(frame));
+               paint_using_texture (texture[i]);
+               glXSwapBuffers (dpy, window);
+               frame++;
+       }
+
+       /* Draw another frame with a re-used texture. */
+       paint_using_texture (texture[0]);
+       glXSwapBuffers (dpy, window);
+       frame++;
+
+       /* Cleanup */
+        glXDestroyContext (dpy, ctx);
+}
+
+static void
+handle_events(Display *dpy, Window window, int width, int height)
+{
+        XEvent xev;
+        KeyCode quit_code = XKeysymToKeycode (dpy, XStringToKeysym("Q"));
+
+        XNextEvent (dpy, &xev);
+
+        while (1) {
+                XNextEvent (dpy, &xev);
+                switch (xev.type) {
+                case KeyPress:
+                        if (xev.xkey.keycode == quit_code) {
+                                return;
+                        }
+                        break;
+                case ConfigureNotify:
+                        width = xev.xconfigure.width;
+                        height = xev.xconfigure.height;
+                        break;
+                case Expose:
+                        if (xev.xexpose.count == 0) {
+                                draw (dpy, window, width, height);
+                                return;
+                        }
+                        break;
+                }
+        }
+}
+
+int
+main (void)
+{
+        Display *dpy;
+        Window window;
+
+        dpy = XOpenDisplay (NULL);
+
+        if (dpy == NULL) {
+                fprintf(stderr, "Failed to open display %s\n",
+                        XDisplayName(NULL));
+                return 1;
+        }
+
+        window = XCreateSimpleWindow(dpy, DefaultRootWindow (dpy),
+                                     0, 0, width, height, 0,
+                                     BlackPixel (dpy, DefaultScreen (dpy)),
+                                     BlackPixel (dpy, DefaultScreen (dpy)));
+
+        XSelectInput(dpy, window,
+                     KeyPressMask | StructureNotifyMask | ExposureMask);
+
+        XMapWindow (dpy, window);
+
+        handle_events (dpy, window, width, height);
+
+        XDestroyWindow (dpy, window);
+        XCloseDisplay (dpy);
+
+        return 0;
+}
diff --git a/cli/tri-ref-mismatch/tri0000000000.png b/cli/tri-ref-mismatch/tri0000000000.png
new file mode 100644 (file)
index 0000000..e682610
Binary files /dev/null and b/cli/tri-ref-mismatch/tri0000000000.png differ
diff --git a/cli/tri-ref/tri0000000000.png b/cli/tri-ref/tri0000000000.png
new file mode 100644 (file)
index 0000000..b7840bd
Binary files /dev/null and b/cli/tri-ref/tri0000000000.png differ
diff --git a/cli/tri.trace b/cli/tri.trace
new file mode 100644 (file)
index 0000000..f900d52
Binary files /dev/null and b/cli/tri.trace differ
diff --git a/cli_driver.py b/cli_driver.py
new file mode 100644 (file)
index 0000000..6c1bfd0
--- /dev/null
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+
+# Copyright 2012 Intel Corporation
+#
+# 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.
+
+'''Test driver for scripts in the cli directory.'''
+
+import json
+import errno
+import shutil
+import subprocess
+import difflib
+
+from base_driver import *
+
+class CliDriver(Driver):
+
+    def do_apitrace(self, args):
+        cmd = [self.options.apitrace] + args.split()
+        print " ".join(cmd)
+        proc = subprocess.Popen(cmd, stdout = subprocess.PIPE)
+        self.output = proc.communicate()[0]
+
+        proc.wait()
+
+        if (self.expect_failure):
+            if (proc.returncode == 0):
+                fail("Command unexpectedly passed when expecting failure:\n    " + " ".join(cmd))
+        else:
+            if (proc.returncode != 0):
+                fail("Command failed (returned non-zero):\n    " + " ".join(cmd))
+
+    def do_expect(self, args):
+        expected = eval(args)
+        if (self.output != expected):
+            differ = difflib.Differ()
+            diff = differ.compare(expected.splitlines(1), self.output.splitlines(1))
+            diff = ''.join(diff)
+            fail("Unexpected output:\n%s\n" % diff)
+
+    def do_rm_and_mkdir(self, args):
+
+        args = args.split()
+
+        # Operate only on local directories
+        dir = './' + args[0]
+
+        # Failing to delete a directory that doesn't exist is no failure
+        def rmtree_onerror(function, path, excinfo):
+            if excinfo[0] == OSError and excinfo[1].errno != errno.ENOENT:
+                raise
+
+        shutil.rmtree(dir, onerror = rmtree_onerror)
+        os.makedirs(dir)
+
+    def unknown_command(self, args):
+        fail('Broken test script: Unknown command: %s' % (args))
+
+    def run_script(self, cli_script):
+        "Execute the commands in the given cli script."
+
+        commands = {
+            'apitrace': self.do_apitrace,
+            'expect': self.do_expect,
+            'rm_and_mkdir': self.do_rm_and_mkdir
+        }
+
+        script = open(cli_script, 'rt')
+
+        while True:
+
+            self.expect_failure = False
+
+            line = script.readline()
+
+            # Exit loop on EOF
+            if (line == ''):
+                break
+
+            line = line.rstrip()
+
+            if " " in line:
+                (cmd, args) = line.split(None,1)
+                if args.startswith('r"""'):
+                    while not line.endswith('"""'):
+                        line = script.readline()
+                        line = line.rstrip()
+                        args += '\n' + line
+            else:
+                cmd = line
+                args = ''
+
+            # Ignore blank lines and comments
+            if (len(cmd) == 0 or cmd == '\n' or cmd[0] == '#'):
+                continue
+
+            if (cmd == 'EXPECT_FAILURE:'):
+                self.expect_failure = True
+                if " " in args:
+                    (cmd, args) = args.split(None, 1)
+                else:
+                    cmd = args
+                    args = ''
+
+            commands.get(cmd, self.unknown_command)(args)
+
+    def run(self):
+        self.parseOptions()
+
+       self.run_script(self.args[0])
+
+        pass_()
+
+if __name__ == '__main__':
+    CliDriver().run()
index a0f8a412a65e7885fd2ed233b15664720d5d7322..4f72b30f8a837373767cc6449ca2006993f80d86 100644 (file)
@@ -1,2 +1,3 @@
 !*.trace
 *.src.trace
+*-trim.trace
index 2fd26af7360e8497f0a670663a6e8bb3a629f4a5..805ab98c689401c9ec42d1e03c7486d096543033 100644 (file)
@@ -1,3 +1,21 @@
+This directory tests various operations of the apitrace command-line
+interface (cli) operating on existings.
+
+All files with a .script extension specify a simple script for
+testing. The test driver (in ../tool_driver.py) will parse the script
+file line-by-line, interpreting each line as arguments to the apitrace
+cli interface and invoking the cli with the given arguments. This
+continues until the first line of the script beginning with the "dump"
+command.
+
+After a "dump" command in the script, the remainder of the script file
+provides the expected output of the given dump command. The tool
+driver will report a test failure if the actual dump output differs
+from that given in the.
+
+Here are descriptions of some of the trace files contained here which
+are used by the test scripts:
+
 *   zlib-no-eof.trace:  is a short, zlib compressed trace, with an unexpected end of
     file because the application terminated abnormally (which is actual very
     normal).
@@ -6,3 +24,6 @@
     any data from it.
 
 *   incomplete-call.trace:  trace with an incomplete call, with missing arguments
+
+*   glxsimple.trace: trace from a simple program showing drawing with
+    glClear, with GLSL shader, and with texture. See ../cli/src
\ No newline at end of file
diff --git a/traces/glxsimple.trace b/traces/glxsimple.trace
new file mode 100644 (file)
index 0000000..8726260
Binary files /dev/null and b/traces/glxsimple.trace differ
diff --git a/traces/trim-frame-set.script b/traces/trim-frame-set.script
new file mode 100644 (file)
index 0000000..33293c3
--- /dev/null
@@ -0,0 +1,20 @@
+trim --frames=0-5/draw,0-5/frame glxsimple.trace
+dump --verbose glxsimple-trim.trace
+0 glClear(mask = GL_COLOR_BUFFER_BIT)
+1 glXSwapBuffers(dpy = 0x236a280, drawable = 41943041)
+
+2 glEnd()
+3 glXSwapBuffers(dpy = 0x236a280, drawable = 41943041)
+
+4 glEnd()
+5 glXSwapBuffers(dpy = 0x236a280, drawable = 41943041)
+
+6 glClear(mask = GL_COLOR_BUFFER_BIT)
+7 glXSwapBuffers(dpy = 0x236a280, drawable = 41943041)
+
+8 glEnd()
+9 glXSwapBuffers(dpy = 0x236a280, drawable = 41943041)
+
+10 glEnd()
+11 glXSwapBuffers(dpy = 0x236a280, drawable = 41943041)
+
diff --git a/traces/trim-head-by-frame.script b/traces/trim-head-by-frame.script
new file mode 100644 (file)
index 0000000..64b7eb3
--- /dev/null
@@ -0,0 +1,14 @@
+trim -o trim-head-by-frame.src.trace --auto --frames=0 glxsimple.trace
+dump --verbose trim-head-by-frame.src.trace
+0 glXChooseVisual(dpy = 0x236a280, screen = 0, attribList = {GLX_RGBA, GLX_RED_SIZE, GLX_RED_SIZE, GLX_GREEN_SIZE, GLX_RED_SIZE, GLX_BLUE_SIZE, GLX_RED_SIZE, GLX_ALPHA_SIZE, GLX_RED_SIZE, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, GLX_RED_SIZE, GLX_X_VISUAL_TYPE, GLX_DIRECT_COLOR, 0}) = &{visual = 0x2374ef8, visualid = 34, screen = 0, depth = 24, c_class = 5, red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_rgb = 8}
+1 glXCreateContext(dpy = 0x236a280, vis = &{visual = 0x2374ef8, visualid = 34, screen = 0, depth = 24, c_class = 5, red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_rgb = 8}, shareList = NULL, direct = True) = 0x2384330
+2 glXMakeCurrent(dpy = 0x236a280, drawable = 41943041, ctx = 0x2384330) = True
+3 glViewport(x = 0, y = 0, width = 64, height = 64)
+4 glMatrixMode(mode = GL_PROJECTION)
+5 glLoadIdentity()
+6 glOrtho(left = 0, right = 64, bottom = 64, top = 0, zNear = 0, zFar = 1)
+7 glMatrixMode(mode = GL_MODELVIEW)
+8 glClearColor(red = 0, green = 0, blue = 1, alpha = 1)
+9 glClear(mask = GL_COLOR_BUFFER_BIT)
+10 glXSwapBuffers(dpy = 0x236a280, drawable = 41943041)
+
diff --git a/traces/trim-head.script b/traces/trim-head.script
new file mode 100644 (file)
index 0000000..897e4e9
--- /dev/null
@@ -0,0 +1,14 @@
+trim -o trim-head.src.trace --auto --calls=0-843 glxsimple.trace
+dump --verbose trim-head.src.trace
+0 glXChooseVisual(dpy = 0x236a280, screen = 0, attribList = {GLX_RGBA, GLX_RED_SIZE, GLX_RED_SIZE, GLX_GREEN_SIZE, GLX_RED_SIZE, GLX_BLUE_SIZE, GLX_RED_SIZE, GLX_ALPHA_SIZE, GLX_RED_SIZE, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, GLX_RED_SIZE, GLX_X_VISUAL_TYPE, GLX_DIRECT_COLOR, 0}) = &{visual = 0x2374ef8, visualid = 34, screen = 0, depth = 24, c_class = 5, red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_rgb = 8}
+1 glXCreateContext(dpy = 0x236a280, vis = &{visual = 0x2374ef8, visualid = 34, screen = 0, depth = 24, c_class = 5, red_mask = 16711680, green_mask = 65280, blue_mask = 255, colormap_size = 256, bits_per_rgb = 8}, shareList = NULL, direct = True) = 0x2384330
+2 glXMakeCurrent(dpy = 0x236a280, drawable = 41943041, ctx = 0x2384330) = True
+3 glViewport(x = 0, y = 0, width = 64, height = 64)
+4 glMatrixMode(mode = GL_PROJECTION)
+5 glLoadIdentity()
+6 glOrtho(left = 0, right = 64, bottom = 64, top = 0, zNear = 0, zFar = 1)
+7 glMatrixMode(mode = GL_MODELVIEW)
+8 glClearColor(red = 0, green = 0, blue = 1, alpha = 1)
+9 glClear(mask = GL_COLOR_BUFFER_BIT)
+10 glXSwapBuffers(dpy = 0x236a280, drawable = 41943041)
+
diff --git a/trim_stress/.gitignore b/trim_stress/.gitignore
new file mode 100644 (file)
index 0000000..2c3a0d6
--- /dev/null
@@ -0,0 +1,5 @@
+!*.trace
+*-ref/
+*-out
+*-index.html
+*.trace.trim
diff --git a/trim_stress/CMakeLists.txt b/trim_stress/CMakeLists.txt
new file mode 100644 (file)
index 0000000..652590d
--- /dev/null
@@ -0,0 +1,16 @@
+file (GLOB traces RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.trace)
+
+list (SORT traces)
+
+foreach (trace ${traces})
+    if (APITRACE_EXECUTABLE AND APITRACE_SOURCE_DIR)
+        add_test(
+            NAME trim-stress-${trace}
+            COMMAND
+            python ${CMAKE_SOURCE_DIR}/trim_stress_driver.py
+                --apitrace ${APITRACE_EXECUTABLE}
+                --apitrace-source ${APITRACE_SOURCE_DIR}
+                ${CMAKE_CURRENT_SOURCE_DIR}/${trace}
+        )
+    endif ()
+endforeach (trace)
diff --git a/trim_stress/README.markdown b/trim_stress/README.markdown
new file mode 100644 (file)
index 0000000..adab8dc
--- /dev/null
@@ -0,0 +1,19 @@
+This directory performs stress testing of "apitrace trim".
+
+For each trace file in this directory the trim_stress.py test driver
+will perform the following operations:
+
+Given <program>.trace:
+
+    1. Generate snapshots of original trace in ./<program>-ref/
+
+    2. For each frame of the trace:
+
+        1. Use "apitrace trim" to trim <program>.trace to a
+           single-frame trace in <program>-trim.trace
+
+       2. Generate a snapshot of the trimmed trace to
+          ./<program>-out/<frame>.png
+
+    3. Use "apitrace diff-images" to compare all snapshots in
+       ./<program>-out with those in ./<program>-ref
diff --git a/trim_stress/glxsimple.trace b/trim_stress/glxsimple.trace
new file mode 100644 (file)
index 0000000..162de4d
Binary files /dev/null and b/trim_stress/glxsimple.trace differ
diff --git a/trim_stress_driver.py b/trim_stress_driver.py
new file mode 100644 (file)
index 0000000..64863f8
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+# Copyright 2012 Intel Corporation
+#
+# 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.
+
+'''Stress test driver for apitrace trim.'''
+
+import os, errno, shutil, subprocess
+
+from base_driver import *
+
+def rm_and_mkdir(dir):
+
+    # Operate only on local directories
+    dir = './' + dir
+
+    # Failing to delete a directory that doesn't exist is no failure
+    def rmtree_onerror(function, path, excinfo):
+        if excinfo[0] == OSError and excinfo[1].errno != errno.ENOENT:
+            raise
+
+    shutil.rmtree(dir, onerror = rmtree_onerror)
+    os.makedirs(dir)
+
+class TrimStressDriver(Driver):
+
+    def trim_stress(self, trace_file):
+        "Execute an apitrace-trim stress test for the given trace."
+
+        (dir, file_name) = os.path.split(trace_file)
+        (name, extension) = file_name.rsplit('.', 1)
+
+        ref_dir = name + '-ref/'
+        out_dir = name + '-out/'
+        trim_file = name + '.trace.trim'
+
+        rm_and_mkdir(ref_dir)
+        rm_and_mkdir(out_dir)
+
+        subprocess.check_call([self.options.apitrace, "dump-images", "--call-nos=no", "--output=" + ref_dir, trace_file]);
+
+        # Count the number of frame snapshots generated
+        frames = 0
+        for dirpath, dirs, files in os.walk(ref_dir):
+            # Don't descend into any sub-directories (not that there
+            # should be any)
+            del dirs[:]
+            frames = len(files)
+
+        for frame in range(frames):
+            try:
+                subprocess.check_call([self.options.apitrace, "trim", "--auto", "--frame=%d" % (frame), "--output=" + trim_file, trace_file])
+            except:
+                print "An error occurred while trimming frame %d from %s" % (frame, trace_file)
+                fail()
+            try:
+                subprocess.check_call([self.options.apitrace, "dump-images", "--call-nos=no", "--output=" + out_dir + "frame", trim_file])
+            except:
+                print "An error occurred replaying %s to generate a frame snapshot" % (trim_file)
+                fail()
+            os.rename("%s/frame0000000000.png" % (out_dir), "%s/%010d.png" % (out_dir, frame))
+
+        try:
+            subprocess.check_call([self.options.apitrace, "diff-images", "-v", ref_dir, out_dir])
+        except:
+            print "Trimmed frames did not match reference images. See " + name + "-index.html"
+            fail()
+        finally:
+            os.rename("index.html", name + "-index.html")
+
+    def run(self):
+        self.parseOptions()
+
+       self.trim_stress(self.args[0])
+
+        pass_()
+
+if __name__ == '__main__':
+    TrimStressDriver().run()