[Piglit] [PATCH 02/12] framework/shader_test.py: Replace ShaderTest class with function
Dylan Baker
baker.dylan.c at gmail.com
Tue Feb 11 18:11:07 PST 2014
This replaces the ShaderTest class with a shader_test function that
returns a PlainExecTest instance. The reason to make this transition is
simple, ShaderTest never actually modified any of the methods in
PlainExecTest, it never needed to be a class, making it a function
reduces the amount of code required, vastly reduces the complexity of
the code, and makes testing much simpler.
This also removes the dmesg_test for ShaderTest, since shader_test just
returns a PlainExecTest, there isn't any reason for dmesg to test it
specially.
Signed-off-by: Dylan Baker <baker.dylan.c at gmail.com>
---
framework/shader_test.py | 233 +++++++++++------------------------------
framework/tests/dmesg_tests.py | 4 -
2 files changed, 59 insertions(+), 178 deletions(-)
diff --git a/framework/shader_test.py b/framework/shader_test.py
index 81fef09..ee0dd05 100644
--- a/framework/shader_test.py
+++ b/framework/shader_test.py
@@ -27,12 +27,69 @@ import os
import os.path as path
import re
-from .core import testBinDir, Group, Test, TestResult
+from .core import testBinDir, Group
from .exectest import PlainExecTest
+__all__ = ['add_shader_test', 'add_shader_test_dir']
+
+
+def shader_test(arguments):
+ """ Parse a shader test file and return a PlainExecTest instance
+
+ This function parses a shader test to determine if it's a GL, GLES2 or
+ GLES3 test, and then returns a PlainExecTest setup properly.
+
+ """
+
+ # Compile a bunch of regexes that are used to find the configuration block
+ # in a shader_test
+ re_require_header = re.compile(r'\s*\[require\]')
+ re_end_require_block = re.compile(r'\s*\[')
+ re_gl = re.compile(r'\s*GL\s*(<|<=|=|>=|>)\s*(\d.\d)')
+ re_gles2 = re.compile(r'\s*GL ES\s*(<|<=|=|>=|>)\s*(2.\d)')
+ re_gles3 = re.compile(r'\s*GL ES\s*(<|<=|=|>=|>)\s*(3.\d)')
+
+ # Iterate over each line of the shader_test file, looking for the
+ # configuration block. When it's found, look for a GL version setting and
+ # apply that
+ with open(arguments, 'r') as shader_file:
+ config_block_found = False
+ gl_api = None
+
+ for line in shader_file:
+ # We need to find the first line of the configuration file, as soon
+ # as we do then we can move on to geting the configuration. The
+ # first line needs to be parsed by the next block.
+ if not config_block_found:
+ if re_require_header.match(line):
+ config_block_found = True
+ continue
+
+ # Find the OpenGL API to use
+ if re_gles2.match(line):
+ gl_api = "GLES2"
+ break
+ elif re_gles3.match(line):
+ gl_api = "GLES3"
+ break
+ elif (re_gl.match(line) or re_end_require_block.match(line)):
+ # In the event that we reach the end of the config black and
+ # an API hasn't been found, it's an old test and uses "GL"
+ gl_api = "GL"
+ break
+
+ # Create the PlainExecTest instance, if no API was selected then gl_api
+ # will be none, which will except here.
+ get_gl = {"GL": path.join(testBinDir, 'shader_runner'),
+ "GLES2": path.join(testBinDir, 'shader_runner_gles2'),
+ "GLES3": path.join(testBinDir, 'shader_runner_gles3')}
+
+ return PlainExecTest([get_gl[gl_api], arguments, '-auto'])
+
+
def add_shader_test(group, testname, filepath):
- group[testname] = ShaderTest([filepath, '-auto'])
+ group[testname] = shader_test(filepath)
def add_shader_test_dir(group, dirpath, recursive=False):
@@ -51,175 +108,3 @@ def add_shader_test_dir(group, dirpath, recursive=False):
continue
testname = filename[0:-(len(ext) + 1)] # +1 for '.'
add_shader_test(group, testname, filepath)
-
-
-class ShaderTest(PlainExecTest):
- API_ERROR = 0
- API_GL = 1
- API_GLES2 = 2
- API_GLES3 = 3
-
- __has_compiled_regexes = False
- __re_require_header = None
- __re_gl = None
- __re_gles2 = None
- __re_gles3 = None
- __re_gl_unknown = None
-
- @classmethod
- def __compile_regexes(cls):
- """Compile the regular expressions needed to parse shader tests.
-
- Hundreds, maybe thousands, of ShaderTests may be instantiated. This
- function compiles the regular expressions only once, at class scope,
- and uses them for all instances.
-
- This function is idempotent."""
-
- if cls.__has_compiled_regexes:
- return
-
- common = {
- 'cmp': r'(<|<=|=|>=|>)',
- 'gl_version': r'(\d.\d)',
- 'gles2_version': r'(2.\d\s)',
- 'gles3_version': r'(3.\d\s)',
- 'comment': r'(#.*)'
- }
-
- cls.__re_require_header = re.compile(r'^\s*\[require\]'
- '\s*{comment}?$'.format(**common))
- cls.__re_end_require_block = re.compile(r'^\s*\['.format(*common))
- cls.__re_gl = re.compile(r'^\s*GL\s*{cmp}\s*{gl_version}\s*{comment}'
- '?$'.format(**common))
- cls.__re_gles2 = re.compile(r'^\s*GL ES\s*{cmp}\s*{gles2_version}'
- '\s*{comment}?$'.format(**common))
- cls.__re_gles3 = re.compile(r'^\s*GL ES\s*{cmp}\s*{gles3_version}'
- '\s*{comment}?$'.format(**common))
- cls.__re_gl_unknown = re.compile(r'^\s*GL\s*{cmp}'.format(**common))
-
- def __init__(self, shader_runner_args):
- Test.__init__(self, runConcurrent=True)
-
- assert(isinstance(shader_runner_args, list))
- assert(isinstance(shader_runner_args[0], str) or
- isinstance(shader_runner_args[0], unicode))
-
- self.__shader_runner_args = shader_runner_args
- self.__test_filepath = shader_runner_args[0]
- self.__result = None
- self.__command = None
- self.__gl_api = None
-
- self.env = {}
-
- def __report_failure(self, message):
- assert(self.__result is None)
- self.__result = TestResult()
- self.__result["result"] = "fail"
- self.__result["errors"] = [message]
-
- def __parse_test_file(self):
- self.__set_gl_api()
-
- def __set_gl_api(self):
- """Set self.__gl_api by parsing the test's requirement block.
-
- This function is idempotent."""
-
- if self.__gl_api is not None:
- return
-
- cls = self.__class__
- cls.__compile_regexes()
-
- PARSE_FIND_REQUIRE_HEADER = 0
- PARSE_FIND_GL_REQUIREMENT = 1
-
- parse_state = PARSE_FIND_REQUIRE_HEADER
-
- try:
- with open(self.__test_filepath) as f:
- for line in f:
- if parse_state == PARSE_FIND_REQUIRE_HEADER:
- if cls.__re_require_header.match(line) is not None:
- parse_state = PARSE_FIND_GL_REQUIREMENT
- else:
- continue
- elif parse_state == PARSE_FIND_GL_REQUIREMENT:
- if cls.__re_gl.match(line) is not None:
- self.__gl_api = ShaderTest.API_GL
- return
- elif cls.__re_gles2.match(line) is not None:
- self.__gl_api = ShaderTest.API_GLES2
- return
- elif cls.__re_gles3.match(line) is not None:
- self.__gl_api = ShaderTest.API_GLES3
- return
- elif cls.__re_gl_unknown.match(line) is not None:
- self.__report_failure("Failed to parse GL "
- "requirement: " + line)
- self.__gl_api = ShaderTest.API_ERROR
- return
- elif cls.__re_end_require_block.match(line):
- # Default to GL if no API is given.
- self.__gl_api = ShaderTest.API_GL
- return
- else:
- continue
- else:
- assert(False)
-
- if parse_state == PARSE_FIND_REQUIRE_HEADER or \
- parse_state == PARSE_FIND_GL_REQUIREMENT:
- # If no requirements are found, then assume the required
- # API is GL. This matches the behavior of the
- # shader_runner executable, whose default requirements are
- # GL >= 1.0 and GLSL >= 1.10.
- self.__gl_api = ShaderTest.API_GL
- else:
- assert(False)
-
- except IOError:
- self.__report_failure("Failed to read test file "
- "{0!r}".format(self.__test_filepath))
- return
-
- @property
- def command(self):
- if self.__command is not None:
- return self.__command
-
- self.__set_gl_api()
-
- if self.__result is not None:
- assert(self.__result["result"] == "fail")
- return ["/bin/false"]
-
- if self.__gl_api == ShaderTest.API_GL:
- runner = "shader_runner"
- elif self.__gl_api == ShaderTest.API_GLES2:
- runner = "shader_runner_gles2"
- elif self.__gl_api == ShaderTest.API_GLES3:
- runner = "shader_runner_gles3"
- else:
- assert(False)
-
- runner = os.path.join(testBinDir, runner)
- self.__command = [runner] + self.__shader_runner_args
- return self.__command
-
- def run(self, env):
- """ Parse the test file's [require] block to determine which
- executable is needed to run the test. Then run the executable on the
- test file."""
-
- # Parse the test file to discover any errors.
- self.__parse_test_file()
-
- if self.__result is not None:
- # We've already decided the test result, most likely because
- # parsing the test file discovered an error.
- return self.__result
-
- return PlainExecTest.run(self, env)
diff --git a/framework/tests/dmesg_tests.py b/framework/tests/dmesg_tests.py
index 287cf74..b96c067 100644
--- a/framework/tests/dmesg_tests.py
+++ b/framework/tests/dmesg_tests.py
@@ -29,7 +29,6 @@ from framework.dmesg import DummyDmesg, LinuxDmesg, get_dmesg, DmesgError
from framework.core import TestResult, PiglitJSONEncoder, Environment
from framework.exectest import PlainExecTest
from framework.gleantest import GleanTest
-from framework.shader_test import ShaderTest
from framework.glsl_parser_test import GLSLParserTest
@@ -221,9 +220,6 @@ def test_testclasses_dmesg():
lists = [(PlainExecTest, ['attribs', '-auto', '-fbo'], 'PlainExecTest'),
(GleanTest, 'basic', "GleanTest"),
- (ShaderTest,
- ['tests/shaders/loopfunc.shader_test', '-auto', '-fbo'],
- 'ShaderTest'),
(GLSLParserTest, 'tests/glslparsertest/shaders/main1.vert',
'GLSLParserTest')]
--
1.8.5.4
More information about the Piglit
mailing list