This allows us to encapsulate a lot of the error handling logic into a single place with easy to use methods. This should reduce the amount of code in consumers of PIGLIT_CONFIG.
It adds two new methods, safe_get and required_get, which operate on NoOptionError or NoSectionError. With safe_get, if either of these is raised None will be return, for required_get a PiglitFatalError will be raised. Signed-off-by: Dylan Baker <[email protected]> --- framework/core.py | 56 +++++++++++++++++++++++++++++-- framework/tests/core_tests.py | 76 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 122 insertions(+), 10 deletions(-) diff --git a/framework/core.py b/framework/core.py index 3ee2870..f9cdbfe 100644 --- a/framework/core.py +++ b/framework/core.py @@ -30,17 +30,69 @@ import subprocess import sys import ConfigParser +from framework import exceptions + __all__ = [ 'PIGLIT_CONFIG', 'PLATFORMS', + 'PiglitConfig', 'Options', 'collect_system_info', 'parse_listfile', ] - PLATFORMS = ["glx", "x11_egl", "wayland", "gbm", "mixed_glx_egl"] -PIGLIT_CONFIG = ConfigParser.SafeConfigParser(allow_no_value=True) + + +class PiglitConfig(ConfigParser.SafeConfigParser): + """Custom Config parser that provides a few extra helpers.""" + def __init__(self, *args, **kwargs): + # In Python2 the ConfigParser classes are old style, you can't use + # super() on them. sigh + ConfigParser.SafeConfigParser.__init__(self, *args, **kwargs) + self.filename = None + + def readfp(self, fp, filename=None): + # In Python2 the ConfigParser classes are old style, you can't use + # super() on them. sigh + ConfigParser.SafeConfigParser.readfp(self, fp, filename) + self.filename = os.path.abspath(filename or fp.name) + + def safe_get(self, *args, **kwargs): + """A version of self.get that doesn't raise NoSectionError or + NoOptionError. + + This is equivalent to passing if the option isn't found. It will return + None if an error is caught + + """ + try: + return self.get(*args, **kwargs) + except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): + return None + + def required_get(self, section, option, **kwargs): + """A version fo self.get that raises PiglitFatalError. + + If self.get returns NoSectionError or NoOptionError then this will + raise a PiglitFatalException, aborting the program. + + """ + try: + return self.get(section, option, **kwargs) + except ConfigParser.NoSectionError: + raise exceptions.PiglitFatalError( + 'No Section "{}" in file "{}".\n' + 'This section is required.'.format( + section, self.filename)) + except ConfigParser.NoOptionError: + raise exceptions.PiglitFatalError( + 'No option "{}" from section "{}" in file "{}".\n' + 'This option is required.'.format( + option, section, self.filename)) + + +PIGLIT_CONFIG = PiglitConfig(allow_no_value=True) def get_config(arg=None): diff --git a/framework/tests/core_tests.py b/framework/tests/core_tests.py index d3ca563..9a49515 100644 --- a/framework/tests/core_tests.py +++ b/framework/tests/core_tests.py @@ -24,14 +24,16 @@ from __future__ import print_function, absolute_import import os import collections import shutil -import ConfigParser import textwrap import functools +import ConfigParser import nose.tools as nt +from framework import core, exceptions import framework.tests.utils as utils -import framework.core as core + +# pylint: disable=line-too-long,invalid-name _CONF_FILE = textwrap.dedent("""\ [nose-test] @@ -80,7 +82,7 @@ def _save_core_config(func): if restore_piglitconf: shutil.move('piglit.conf.restore', 'piglit.conf') - core.PIGLIT_CONFIG = ConfigParser.SafeConfigParser( + core.PIGLIT_CONFIG = core.PiglitConfig( allow_no_value=True) except Exception as e: raise utils.UtilsError(e) @@ -90,13 +92,31 @@ def _save_core_config(func): def _reset_piglit_config(): """ Set core.PIGLIT_CONFIG back to pristine """ - core.PIGLIT_CONFIG = ConfigParser.SafeConfigParser() + core.PIGLIT_CONFIG = core.PiglitConfig(allow_no_value=True) [email protected]_error -def test_options_init(): - """core.Options(): Class initializes""" - core.Options() [email protected]_generator +def test_generate_initialize(): + """ Generator that creates tests to initialize all of the classes in core + + In a compiled language the compiler provides this kind of checking, but in + an interpreted language like python you don't have a compiler test. The + unit tests generated by this function serve as a similar test, does this + even work? + + """ + def check_initialize(target): + """ Check that a class initializes without error """ + func = target() + # Asserting that func exists will fail for Group and TestrunResult which + # are dict subclasses + assert isinstance(func, target) + + + for target in [core.Options, core.PiglitConfig]: + check_initialize.description = "Test that {} initializes".format( + target.__name__) + yield check_initialize, target def test_parse_listfile_return(): @@ -213,3 +233,43 @@ def test_piglit_root(): nt.ok_(core.PIGLIT_CONFIG.has_section('nose-test'), msg='$PIGLIT_ROOT not found') + + +class TestPiglitConfig(object): + """Tests for PiglitConfig methods.""" + @classmethod + def setup_class(cls): + cls.conf = core.PiglitConfig() + cls.conf.add_section('set') + cls.conf.set('set', 'options', 'bool') + + def test_safe_get_valid(self): + """core.PiglitConfig: safe_get returns a value if its in the Config""" + nt.assert_equal(self.conf.safe_get('set', 'options'), 'bool') + + def test_PiglitConfig_required_get_valid(self): + """core.PiglitConfig: required_get returns a value if its in the Config + """ + nt.assert_equal(self.conf.required_get('set', 'options'), 'bool') + + def test_safe_get_missing_option(self): + """core.PiglitConfig: safe_get returns None if the option is missing + """ + nt.assert_equal(self.conf.safe_get('set', 'invalid'), None) + + def test_safe_get_missing_section(self): + """core.PiglitConfig: safe_get returns None if the section is missing + """ + nt.assert_equal(self.conf.safe_get('invalid', 'invalid'), None) + + @nt.raises(exceptions.PiglitFatalError) + def test_required_get_missing_option(self): + """core.PiglitConfig: required_get raises PiglitFatalError if the option is missing + """ + self.conf.required_get('set', 'invalid') + + @nt.raises(exceptions.PiglitFatalError) + def test_required_get_missing_section(self): + """core.PiglitConfig: required_get raises PiglitFatalError if the section is missing + """ + self.conf.required_get('invalid', 'invalid') -- 2.4.0 _______________________________________________ Piglit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/piglit
