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 <[email protected]> --- 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 _______________________________________________ Piglit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/piglit
