Merging the glsl_parser_test module into exectest has all the same advantages as merging the gleantest module did. Fewer imports across the board, fewer namespaces to deal with, and clearer class relationships.
Signed-off-by: Dylan Baker <[email protected]> --- framework/exectest.py | 140 +++++++++++++++++++++++++- framework/glsl_parser_test.py | 161 ------------------------------ framework/tests/dmesg_tests.py | 9 +- framework/tests/exectest_test.py | 140 ++++++++++++++++++++++++-- framework/tests/glsl_parser_test_tests.py | 146 --------------------------- tests/all.py | 4 +- tests/gpu.py | 2 +- 7 files changed, 278 insertions(+), 324 deletions(-) delete mode 100644 framework/glsl_parser_test.py delete mode 100644 framework/tests/glsl_parser_test_tests.py diff --git a/framework/exectest.py b/framework/exectest.py index 4606b25..5f3a9ac 100644 --- a/framework/exectest.py +++ b/framework/exectest.py @@ -22,18 +22,25 @@ import errno import os +import os.path as path import subprocess import shlex import time import sys import traceback - +import ConfigParser +import re +from cStringIO import StringIO from .core import TestResult, Environment __all__ = ['Test', 'PiglitTest', 'GleanTest', + 'GLSLParserTest', + 'GLSLParserException', + 'add_glsl_parser_test', + 'import_glsl_parser_tests', 'TEST_BIN_DIR'] # Platform global variables @@ -313,3 +320,134 @@ class GleanTest(Test): self.result['result'] = 'fail' else: self.result['result'] = 'pass' + + +class GLSLParserTest(PiglitTest): + """ Read the options in a glsl parser test and create a Test object + + Specifically it is necessary to parse a glsl_parser_test to get information + about it before actually creating a PiglitTest. Even though this could + be done with a funciton wrapper, making it a distinct class makes it easier + to sort in the profile. + + Arguments: + filepath -- the path to a glsl_parser_test which must end in .frag, .vert, + or .geom + + """ + def __init__(self, filepath): + # Text of config section. + text_io = StringIO() + text_io.write('[config]\n') + + os.stat(filepath) + + # Parse the config file and get the config section, then write this + # section to a StringIO and pass that to ConfigParser + with open(filepath, 'r') as testfile: + + # Create a generator that iterates over the lines in the test file. + # This allows us to run the loop until we find the header, stop and + # then run again looking for the config sections. This reduces if + # checking substantially. + lines = (l for l in testfile) + + is_header = re.compile(r'\s*(//|/\*|\*)\s*\[config\]') + for line in lines: + if is_header.match(line): + break + else: + raise GLSLParserException("No [config] section found!") + + is_header = re.compile(r'\s*(//|/\*|\*)\s*\[end config\]') + for line in lines: + # Remove all leading whitespace + line = line.strip() + + # If strip renendered '' that means we had a blank newline, + # just go on + if line == '': + continue + # If we get to the end of the config break + elif is_header.match(line): + break + # If the starting character is a two character comment + # remove that and any newly revealed whitespace, then write + # it into the StringIO + elif line[:2] in ['//', '/*', '*/']: + text_io.write(line[2:].lstrip() + '\n') + # If we have just * then we're in the middle of a C style + # comment, do like above + elif line[:1] == '*': + text_io.write(line[1:].lstrip() + '\n') + else: + raise GLSLParserException( + "The config section is malformed." + "Check file {0}".format(filepath)) + else: + raise GLSLParserException("No [end config] section found!") + + config = ConfigParser.SafeConfigParser( + defaults={'require_extensions': '', 'check_link': 'false'}) + + # Verify that the config was valid + text = text_io.getvalue() + text_io.close() + config.readfp(StringIO(text)) + + for opt in ['expect_result', 'glsl_version']: + if not config.has_option('config', opt): + raise GLSLParserException("Missing required section {} " + "from config".format(opt)) + + # Create the command and pass it into a PiglitTest() + command = [path.join(TEST_BIN_DIR, 'glslparsertest'), + filepath, + config.get('config', 'expect_result'), + config.get('config', 'glsl_version')] + if config.get('config', 'check_link').lower() == 'true': + command.append('--check-link') + command.extend(config.get('config', 'require_extensions').split()) + + super(GLSLParserTest, self).__init__(command, run_concurrent=True) + + +class GLSLParserException(Exception): + pass + + +def add_glsl_parser_test(group, filepath, test_name): + """Add an instance of GLSLParserTest to the given group.""" + group[test_name] = GLSLParserTest(filepath) + + +def import_glsl_parser_tests(group, basepath, subdirectories): + """ + Recursively register each shader source file in the given + ``subdirectories`` as a GLSLParserTest . + + :subdirectories: A list of subdirectories under the basepath. + + The name with which each test is registered into the given group is + the shader source file's path relative to ``basepath``. For example, + if:: + import_glsl_parser_tests(group, 'a', ['b1', 'b2']) + is called and the file 'a/b1/c/d.frag' exists, then the test is + registered into the group as ``group['b1/c/d.frag']``. + """ + for d in subdirectories: + walk_dir = path.join(basepath, d) + for (dirpath, dirnames, filenames) in os.walk(walk_dir): + # Ignore dirnames. + for f in filenames: + # Add f as a test if its file extension is good. + ext = f.rsplit('.')[-1] + if ext in ['vert', 'geom', 'frag', 'comp']: + filepath = path.join(dirpath, f) + # testname := filepath relative to + # basepath. + testname = os.path.relpath(filepath, basepath) + if os.path.sep != '/': + testname = testname.replace(os.path.sep, '/', -1) + assert isinstance(testname, basestring) + add_glsl_parser_test(group, filepath, testname) diff --git a/framework/glsl_parser_test.py b/framework/glsl_parser_test.py deleted file mode 100644 index 4c1da49..0000000 --- a/framework/glsl_parser_test.py +++ /dev/null @@ -1,161 +0,0 @@ -# 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: -# -# 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 AUTHOR(S) 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. - -""" This module enables the running of GLSL parser tests. """ - -import ConfigParser -import os -import os.path as path -import re -from cStringIO import StringIO - -from .exectest import PiglitTest, TEST_BIN_DIR - - -def add_glsl_parser_test(group, filepath, test_name): - """Add an instance of GLSLParserTest to the given group.""" - group[test_name] = GLSLParserTest(filepath) - - -def import_glsl_parser_tests(group, basepath, subdirectories): - """ - Recursively register each shader source file in the given - ``subdirectories`` as a GLSLParserTest . - - :subdirectories: A list of subdirectories under the basepath. - - The name with which each test is registered into the given group is - the shader source file's path relative to ``basepath``. For example, - if:: - import_glsl_parser_tests(group, 'a', ['b1', 'b2']) - is called and the file 'a/b1/c/d.frag' exists, then the test is - registered into the group as ``group['b1/c/d.frag']``. - """ - for d in subdirectories: - walk_dir = path.join(basepath, d) - for (dirpath, dirnames, filenames) in os.walk(walk_dir): - # Ignore dirnames. - for f in filenames: - # Add f as a test if its file extension is good. - ext = f.rsplit('.')[-1] - if ext in ['vert', 'geom', 'frag', 'comp']: - filepath = path.join(dirpath, f) - # testname := filepath relative to - # basepath. - testname = os.path.relpath(filepath, basepath) - if os.path.sep != '/': - testname = testname.replace(os.path.sep, '/', -1) - assert isinstance(testname, basestring) - add_glsl_parser_test(group, filepath, testname) - - -class GLSLParserTest(PiglitTest): - """ Read the options in a glsl parser test and create a Test object - - Specifically it is necessary to parse a glsl_parser_test to get information - about it before actually creating a PiglitTest. Even though this could - be done with a funciton wrapper, making it a distinct class makes it easier - to sort in the profile. - - Arguments: - filepath -- the path to a glsl_parser_test which must end in .frag, .vert, - or .geom - - """ - def __init__(self, filepath): - # Text of config section. - text_io = StringIO() - text_io.write('[config]\n') - - os.stat(filepath) - - # Parse the config file and get the config section, then write this - # section to a StringIO and pass that to ConfigParser - with open(filepath, 'r') as testfile: - - # Create a generator that iterates over the lines in the test file. - # This allows us to run the loop until we find the header, stop and - # then run again looking for the config sections. This reduces if - # checking substantially. - lines = (l for l in testfile) - - is_header = re.compile(r'\s*(//|/\*|\*)\s*\[config\]') - for line in lines: - if is_header.match(line): - break - else: - raise GLSLParserException("No [config] section found!") - - is_header = re.compile(r'\s*(//|/\*|\*)\s*\[end config\]') - for line in lines: - # Remove all leading whitespace - line = line.strip() - - # If strip renendered '' that means we had a blank newline, - # just go on - if line == '': - continue - # If we get to the end of the config break - elif is_header.match(line): - break - # If the starting character is a two character comment - # remove that and any newly revealed whitespace, then write - # it into the StringIO - elif line[:2] in ['//', '/*', '*/']: - text_io.write(line[2:].lstrip() + '\n') - # If we have just * then we're in the middle of a C style - # comment, do like above - elif line[:1] == '*': - text_io.write(line[1:].lstrip() + '\n') - else: - raise GLSLParserException( - "The config section is malformed." - "Check file {0}".format(filepath)) - else: - raise GLSLParserException("No [end config] section found!") - - config = ConfigParser.SafeConfigParser( - defaults={'require_extensions': '', 'check_link': 'false'}) - - # Verify that the config was valid - text = text_io.getvalue() - text_io.close() - config.readfp(StringIO(text)) - - for opt in ['expect_result', 'glsl_version']: - if not config.has_option('config', opt): - raise GLSLParserException("Missing required section {} " - "from config".format(opt)) - - # Create the command and pass it into a PiglitTest() - command = [path.join(TEST_BIN_DIR, 'glslparsertest'), - filepath, - config.get('config', 'expect_result'), - config.get('config', 'glsl_version')] - if config.get('config', 'check_link').lower() == 'true': - command.append('--check-link') - command.extend(config.get('config', 'require_extensions').split()) - - super(GLSLParserTest, self).__init__(command, run_concurrent=True) - - -class GLSLParserException(Exception): - pass diff --git a/framework/tests/dmesg_tests.py b/framework/tests/dmesg_tests.py index 7a35718..2456384 100644 --- a/framework/tests/dmesg_tests.py +++ b/framework/tests/dmesg_tests.py @@ -27,9 +27,8 @@ import nose.tools as nt from nose.plugins.skip import SkipTest from framework.dmesg import DummyDmesg, LinuxDmesg, get_dmesg, DmesgError from framework.core import TestResult, PiglitJSONEncoder -from framework.exectest import PiglitTest, GleanTest +import framework.exectest as exectest from framework.shader_test import ShaderTest -from framework.glsl_parser_test import GLSLParserTest def _get_dmesg(): @@ -228,11 +227,11 @@ def test_json_serialize_updated_result(): def test_testclasses_dmesg(): """ Generator that creates tests for """ - lists = [(PiglitTest, ['attribs', '-auto', '-fbo'], 'PiglitTest'), - (GleanTest, 'basic', "GleanTest"), + lists = [(exectest.PiglitTest, ['attribs', '-auto', '-fbo'], 'PiglitTest'), + (exectest.GleanTest, 'basic', "GleanTest"), (ShaderTest, 'tests/shaders/loopfunc.shader_test', 'ShaderTest'), - (GLSLParserTest, 'tests/glslparsertest/shaders/main1.vert', + (exectest.GLSLParserTest, 'tests/glslparsertest/shaders/main1.vert', 'GLSLParserTest')] yieldable = check_classes_dmesg diff --git a/framework/tests/exectest_test.py b/framework/tests/exectest_test.py index 7c725e5..b68eb21 100644 --- a/framework/tests/exectest_test.py +++ b/framework/tests/exectest_test.py @@ -22,23 +22,25 @@ from __future__ import print_function import os +import nose.tools as nt from nose.plugins.skip import SkipTest -from framework.exectest import PiglitTest, Test, GleanTest +import framework.tests.utils as utils +import framework.exectest as exectest def test_initialize_test(): """ Test initializes """ - Test('/bin/true') + exectest.Test('/bin/true') def test_initialize_piglittest(): """ Test that PiglitTest initializes correctly """ - PiglitTest('/bin/true') + exectest.PiglitTest('/bin/true') def test_initialize_gleantest(): """ Test that GleanTest initilizes """ - test = GleanTest('name') + test = exectest.GleanTest('name') assert test @@ -55,9 +57,9 @@ def test_global_params_assignment(): initialized before it is set. """ - test1 = GleanTest('basic') - GleanTest.GLOBAL_PARAMS = ['--quick'] - test2 = GleanTest('basic') + test1 = exectest.GleanTest('basic') + exectest.GleanTest.GLOBAL_PARAMS = ['--quick'] + test2 = exectest.GleanTest('basic') assert test1.command == test2.command @@ -76,6 +78,128 @@ def test_bad_returncode(): # LD_LIBRARY_PATH os.environ = {} - test = GleanTest('basic') + test = exectest.GleanTest('basic') test.run() assert test.result['result'] == 'fail', "Result should have been fail" + + +def _check_config(content): + """ This is the test that actually checks the glsl config section """ + with utils.with_tempfile(content) as tfile: + return exectest.GLSLParserTest(tfile), tfile + + +def test_no_config_start(): + """ GLSLParserTest requires [config] """ + content = ('// expect_result: pass\n' + '// glsl_version: 1.00\n' + '// [end config]\n') + with utils.with_tempfile(content) as tfile: + with nt.assert_raises(exectest.GLSLParserException) as exc: + exectest.GLSLParserTest(tfile) + nt.assert_equal( + exc.exception, 'No [config] section found!', + msg="No config section found, no exception raised") + + +def test_find_config_start(): + """ GLSLParserTest finds [config] """ + content = ('// [config]\n' + '// glsl_version: 1.00\n' + '//\n') + with utils.with_tempfile(content) as tfile: + with nt.assert_raises(exectest.GLSLParserException) as exc: + exectest.GLSLParserTest(tfile) + nt.assert_not_equal( + exc.exception, 'No [config] section found!', + msg="Config section not parsed") + + +def test_no_config_end(): + """ GLSLParserTest requires [end config] """ + with utils.with_tempfile('// [config]\n') as tfile: + with nt.assert_raises(exectest.GLSLParserException) as exc: + exectest.GLSLParserTest(tfile) + nt.assert_equal( + exc.exception, 'No [end config] section found!', + msg="config section not closed, no exception raised") + + +def test_no_expect_result(): + """ expect_result section is required """ + content = ('// [config]\n' + '// glsl_version: 1.00\n' + '//\n') + with utils.with_tempfile(content) as tfile: + with nt.assert_raises(exectest.GLSLParserException) as exc: + exectest.GLSLParserTest(tfile) + nt.assert_equal( + exc.exception, + 'Missing required section expect_result from config', + msg="config section not closed, no exception raised") + + +def test_no_glsl_version(): + """ glsl_version section is required """ + content = ('//\n' + '// expect_result: pass\n' + '// [end config]\n') + with utils.with_tempfile(content) as tfile: + with nt.assert_raises(exectest.GLSLParserException) as exc: + exectest.GLSLParserTest(tfile) + nt.assert_equal( + exc.exception, + 'Missing required section glsl_version from config', + msg="config section not closed, no exception raised") + + +def test_cpp_comments(): + """ Parses C++ style comments """ + content = ('// [config]\n' + '// expect_result: pass\n' + '// glsl_version: 1.00\n' + '// [end config]\n') + test, name = _check_config(content) + + nt.assert_equal(test.command, [os.path.join(exectest.TEST_BIN_DIR, + 'glslparsertest'), + name, 'pass', '1.00'], + msg="C++ style comments were not properly parsed") + + +def test_c_comments(): + """ Parses C style comments """ + content = ('/*\n' + ' * [config]\n' + ' * expect_result: pass\n' + ' * glsl_version: 1.00\n' + ' * [end config]\n' + ' */\n') + test, name = _check_config(content) + + nt.assert_equal(test.command, [os.path.join(exectest.TEST_BIN_DIR, + 'glslparsertest'), + name, 'pass', '1.00'], + msg="C style comments were not properly parsed") + + +def test_blank_in_config(): + """ C++ style comments can have uncommented newlines """ + content = ('// [config]\n' + '\n' + '// expect_result: pass\n' + '// glsl_version: 1.00\n' + '// [end config]\n') + + test, name = _check_config(content) + + nt.assert_equal(test.command, [os.path.join(exectest.TEST_BIN_DIR, + 'glslparsertest'), + name, 'pass', '1.00'], + msg="A newline in a C++ style comment was not properly " + "parsed.") + + +def test_glslparser_initializer(): + """ GLSLParserTest initializes """ + exectest.GLSLParserTest('tests/spec/glsl-es-1.00/compiler/version-macro.frag') diff --git a/framework/tests/glsl_parser_test_tests.py b/framework/tests/glsl_parser_test_tests.py deleted file mode 100644 index 5e083b8..0000000 --- a/framework/tests/glsl_parser_test_tests.py +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright (c) 2014 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. - -""" Provides tests for the shader_test module """ - -import os -import nose.tools as nt -import framework.glsl_parser_test as glsl -import framework.tests.utils as utils -from framework.exectest import TEST_BIN_DIR - - -def _check_config(content): - """ This is the test that actually checks the glsl config section """ - with utils.with_tempfile(content) as tfile: - return glsl.GLSLParserTest(tfile), tfile - - -def test_no_config_start(): - """ GLSLParserTest requires [config] """ - content = ('// expect_result: pass\n' - '// glsl_version: 1.00\n' - '// [end config]\n') - with utils.with_tempfile(content) as tfile: - with nt.assert_raises(glsl.GLSLParserException) as exc: - glsl.GLSLParserTest(tfile) - nt.assert_equal( - exc.exception, 'No [config] section found!', - msg="No config section found, no exception raised") - - -def test_find_config_start(): - """ GLSLParserTest finds [config] """ - content = ('// [config]\n' - '// glsl_version: 1.00\n' - '//\n') - with utils.with_tempfile(content) as tfile: - with nt.assert_raises(glsl.GLSLParserException) as exc: - glsl.GLSLParserTest(tfile) - nt.assert_not_equal( - exc.exception, 'No [config] section found!', - msg="Config section not parsed") - - -def test_no_config_end(): - """ GLSLParserTest requires [end config] """ - with utils.with_tempfile('// [config]\n') as tfile: - with nt.assert_raises(glsl.GLSLParserException) as exc: - glsl.GLSLParserTest(tfile) - nt.assert_equal( - exc.exception, 'No [end config] section found!', - msg="config section not closed, no exception raised") - - -def test_no_expect_result(): - """ expect_result section is required """ - content = ('// [config]\n' - '// glsl_version: 1.00\n' - '//\n') - with utils.with_tempfile(content) as tfile: - with nt.assert_raises(glsl.GLSLParserException) as exc: - glsl.GLSLParserTest(tfile) - nt.assert_equal( - exc.exception, - 'Missing required section expect_result from config', - msg="config section not closed, no exception raised") - - -def test_no_glsl_version(): - """ glsl_version section is required """ - content = ('//\n' - '// expect_result: pass\n' - '// [end config]\n') - with utils.with_tempfile(content) as tfile: - with nt.assert_raises(glsl.GLSLParserException) as exc: - glsl.GLSLParserTest(tfile) - nt.assert_equal( - exc.exception, - 'Missing required section glsl_version from config', - msg="config section not closed, no exception raised") - - -def test_cpp_comments(): - """ Parses C++ style comments """ - content = ('// [config]\n' - '// expect_result: pass\n' - '// glsl_version: 1.00\n' - '// [end config]\n') - test, name = _check_config(content) - - nt.assert_equal(test.command, [os.path.join(TEST_BIN_DIR, 'glslparsertest'), - name, 'pass', '1.00'], - msg="C++ style comments were not properly parsed") - - -def test_c_comments(): - """ Parses C style comments """ - content = ('/*\n' - ' * [config]\n' - ' * expect_result: pass\n' - ' * glsl_version: 1.00\n' - ' * [end config]\n' - ' */\n') - test, name = _check_config(content) - - nt.assert_equal(test.command, [os.path.join(TEST_BIN_DIR, 'glslparsertest'), - name, 'pass', '1.00'], - msg="C style comments were not properly parsed") - - -def test_blank_in_config(): - """ C++ style comments can have uncommented newlines """ - content = ('// [config]\n' - '\n' - '// expect_result: pass\n' - '// glsl_version: 1.00\n' - '// [end config]\n') - - test, name = _check_config(content) - - nt.assert_equal(test.command, [os.path.join(TEST_BIN_DIR, 'glslparsertest'), - name, 'pass', '1.00'], - msg="A newline in a C++ style comment was not properly " - "parsed.") - - -def test_glslparser_initializer(): - """ GLSLParserTest initializes """ - glsl.GLSLParserTest('tests/spec/glsl-es-1.00/compiler/version-macro.frag') diff --git a/tests/all.py b/tests/all.py index d492023..179ad0e 100644 --- a/tests/all.py +++ b/tests/all.py @@ -10,8 +10,8 @@ import platform import shlex from framework.profile import TestProfile -from framework.exectest import PiglitTest, GleanTest -from framework.glsl_parser_test import GLSLParserTest, add_glsl_parser_test, import_glsl_parser_tests +from framework.exectest import (PiglitTest, GleanTest, add_glsl_parser_test, + import_glsl_parser_tests) from framework.shader_test import add_shader_test_dir # Path to tests dir, correct even when not running from the top directory. diff --git a/tests/gpu.py b/tests/gpu.py index 55ead29..14eaf23 100644 --- a/tests/gpu.py +++ b/tests/gpu.py @@ -3,7 +3,7 @@ # quick.tests minus compiler tests. from tests.quick import profile -from framework.glsl_parser_test import GLSLParserTest +from framework.exectest import GLSLParserTest __all__ = ['profile'] -- 2.0.0.rc0 _______________________________________________ Piglit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/piglit
