[Piglit] [Patch v2 1/4] framework: allow loading a piglit.conf from more locations

Jordan Justen jljusten at gmail.com
Tue Jul 15 01:09:42 PDT 2014


On Mon, Jul 7, 2014 at 4:20 PM, Dylan Baker <baker.dylan.c at gmail.com> wrote:
> With this patch piglit.conf can live in a number of different places. It
> can live in the current directory, then in XDG_CONFIG_HOME
> ($HOME/.config by default), and finally in the piglit source directory.
>
> v2: - fix types (chadv)
>     - change load order to make ./.piglit.conf load first (chadv)
>     - Add framework tests
>
> Signed-off-by: Dylan Baker <baker.dylan.c at gmail.com>
> ---
>  framework/programs/run.py         |  39 +++++++--
>  framework/tests/programs_tests.py | 180 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 212 insertions(+), 7 deletions(-)
>  create mode 100644 framework/tests/programs_tests.py
>
> diff --git a/framework/programs/run.py b/framework/programs/run.py
> index c1a2658..8b8aa5a 100644
> --- a/framework/programs/run.py
> +++ b/framework/programs/run.py
> @@ -123,13 +123,7 @@ def run(input_):
>          args.concurrency = "none"
>
>      # Read the config file
> -    if args.config_file:
> -        core.PIGLIT_CONFIG.readfp(args.config_file)
> -        args.config_file.close()
> -    else:
> -        core.PIGLIT_CONFIG.read(os.path.abspath(
> -            os.path.join(
> -                os.path.dirname(__file__), '..', '..', 'piglit.conf')))
> +    _get_config(args.config_file)
>
>      # Pass arguments into Options
>      opts = core.Options(concurrent=args.concurrency,
> @@ -203,6 +197,11 @@ def resume(input_):
>                          type=path.realpath,
>                          metavar="<Results Path>",
>                          help="Path to results folder")
> +    parser.add_argument("-f", "--config",
> +                        dest="config_file",
> +                        type=argparse.FileType("r"),
> +                        help="Optionally specify a piglit config file to use. "
> +                             "Default is piglit.conf")
>      args = parser.parse_args(input_)
>
>      results = framework.results.load_results(args.results_path)
> @@ -214,6 +213,8 @@ def resume(input_):
>                          dmesg=results.options['dmesg'],
>                          verbose=results.options['verbose'])
>
> +    _get_config(args.config_file)
> +
>      if results.options.get('platform'):
>          opts.env['PIGLIT_PLATFORM'] = results.options['platform']
>
> @@ -242,3 +243,27 @@ def resume(input_):
>
>      print("Thank you for running Piglit!\n"
>            "Results have ben wrriten to {0}".format(results_path))
> +
> +
> +def _get_config(arg):
> +    if arg:
> +        core.PIGLIT_CONFIG.readfp(arg)
> +    else:
> +        # Try XDG_CONFIG_DIR, then try the local directory, finally try the
> +        # root of the piglit dir relative to this file
> +        for d in ['.',
> +                  os.environ.get('XDG_CONFIG_HOME',
> +                                 os.path.expandvars('$HOME/.config')),
> +                  os.path.join(os.path.dirname(__file__), '..', '..')]:
> +            try:
> +                with open(os.path.join(d, 'piglit.conf'), 'r') as f:
> +                    core.PIGLIT_CONFIG.readfp(f)
> +                break
> +            except IOError:
> +                pass
> +        else:
> +            if __debug__:
> +                print('Warning: piglit.conf not found!\n'
> +                      '(searching current dir, $HOME/.config, '
> +                      '$XDG_CONFIG_HOME, and piglit source dir)',
> +                      file=sys.stderr)

Did you mean to strip this debug warning? I don't think a warning
message is needed if piglit.conf doesn't exist.

-Jordan

> diff --git a/framework/tests/programs_tests.py b/framework/tests/programs_tests.py
> new file mode 100644
> index 0000000..c563ef0
> --- /dev/null
> +++ b/framework/tests/programs_tests.py
> @@ -0,0 +1,180 @@
> +# 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.
> +
> +
> +""" Tests for the programs package
> +
> +Currently there aren't very many tests for the modules in this package, so just
> +having a single test module seems appropriate
> +
> +"""
> +
> +import os
> +import shutil
> +import ConfigParser
> +import framework.core as core
> +import framework.programs.run as run
> +import framework.tests.utils as utils
> +import nose.tools as nt
> +
> +CONF_FILE = """
> +[nose-test]
> +; a section for testing behavior
> +dir = foo
> +"""
> +
> +
> +# Helpers
> +class _TestWithEnvClean(object):
> +    """ Class that does cleanup with saved state
> +
> +    This could be done with test fixtures, but this should be cleaner in the
> +    specific case of cleaning up environment variables
> +
> +    Nose will run a method (bound or unbound) at the start of the test called
> +    setup() and one at the end called teardown(), we have added a teardown
> +    method.
> +
> +    Using this gives us the assurance that we're not relying on settings from
> +    other tests, making ours pass or fail, and that os.enviorn is the same
> +    going in as it is going out.
> +
> +    This is modeled after Go's defer keyword.
> +
> +    """
> +    def __init__(self):
> +        self._saved = set()
> +        self._teardown_calls = []
> +
> +    def add_teardown(self, var, restore=True):
> +        """ Add os.environ values to remove in teardown """
> +        if var in os.environ:
> +            self._saved.add((var, os.environ.get(var), restore))
> +            del os.environ[var]
> +
> +    def defer(self, func, *args):
> +        """ Add a function (with arguments) to be run durring cleanup """
> +        self._teardown_calls.append((func, args))
> +
> +    def teardown(self):
> +        """ Teardown the test
> +
> +        Restore any variables that were unset at the begining of the test, and
> +        run any differed methods.
> +
> +        """
> +        for key, value, restore in self._saved:
> +            # If value is None the value was unset previously, put it back
> +            if value is None:
> +                del os.environ[key]
> +            elif restore:
> +                os.environ[key] = value
> +
> +        # Teardown calls is a FIFO stack, the defered calls must be run in
> +        # reversed order to make any sense
> +        for call, args in reversed(self._teardown_calls):
> +            call(*args)
> +
> +
> +# Tests
> +class TestGetConfigEnv(_TestWithEnvClean):
> +    def test(self):
> +        """ _get_config() finds $XDG_CONFIG_HOME/piglit.conf """
> +        self.defer(lambda: core.PIGLIT_CONFIG == ConfigParser.SafeConfigParser)
> +        self.add_teardown('XDG_CONFIG_HOME')
> +        if os.path.exists('piglit.conf'):
> +            shutil.move('piglit.conf', 'piglit.conf.restore')
> +            self.defer(shutil.move, 'piglit.conf.restore', 'piglit.conf')
> +
> +        with utils.tempdir() as tdir:
> +            os.environ['XDG_CONFIG_HOME'] = tdir
> +            with open(os.path.join(tdir, 'piglit.conf'), 'w') as f:
> +                f.write(CONF_FILE)
> +            run._get_config(None)
> +
> +        nt.ok_(core.PIGLIT_CONFIG.has_section('nose-test'),
> +               msg='$XDG_CONFIG_HOME not found')
> +
> +
> +class TestGetConfigHomeFallback(_TestWithEnvClean):
> +    def test(self):
> +        """ _get_config() finds $HOME/.config/piglit.conf """
> +        self.defer(lambda: core.PIGLIT_CONFIG == ConfigParser.SafeConfigParser)
> +        self.add_teardown('HOME')
> +        self.add_teardown('XDG_CONFIG_HOME')
> +        if os.path.exists('piglit.conf'):
> +            shutil.move('piglit.conf', 'piglit.conf.restore')
> +            self.defer(shutil.move, 'piglit.conf.restore', 'piglit.conf')
> +
> +        with utils.tempdir() as tdir:
> +            os.environ['HOME'] = tdir
> +            os.mkdir(os.path.join(tdir, '.config'))
> +            with open(os.path.join(tdir, '.config/piglit.conf'), 'w') as f:
> +                f.write(CONF_FILE)
> +
> +        nt.ok_(core.PIGLIT_CONFIG.has_section('nose-test'),
> +               msg='$HOME/.config not found')
> +
> +
> +class TestGetConfigLocal(_TestWithEnvClean):
> +    # These need to be empty to force '.' to be used
> +    def test(self):
> +        """ _get_config() finds ./piglit.conf """
> +        self.defer(lambda: core.PIGLIT_CONFIG == ConfigParser.SafeConfigParser)
> +        self.add_teardown('HOME')
> +        self.add_teardown('XDG_CONFIG_HOME')
> +        if os.path.exists('piglit.conf'):
> +            shutil.move('piglit.conf', 'piglit.conf.restore')
> +            self.defer(shutil.move, 'piglit.conf.restore', 'piglit.conf')
> +
> +        with utils.tempdir() as tdir:
> +            self.defer(os.chdir, os.getcwd())
> +            os.chdir(tdir)
> +
> +            with open(os.path.join(tdir, 'piglit.conf'), 'w') as f:
> +                f.write(CONF_FILE)
> +
> +            run._get_config(None)
> +
> +        nt.ok_(core.PIGLIT_CONFIG.has_section('nose-test'),
> +               msg='./piglit.conf not found')
> +
> +
> +class TestGetConfigRoot(_TestWithEnvClean):
> +    def test(self):
> +        """ _get_config() finds "piglit root"/piglit.conf """
> +        self.defer(lambda: core.PIGLIT_CONFIG == ConfigParser.SafeConfigParser)
> +        self.add_teardown('HOME')
> +        self.add_teardown('XDG_CONFIG_HOME')
> +
> +        if os.path.exists('piglit.conf'):
> +            shutil.move('piglit.conf', 'piglit.conf.restore')
> +            self.defer(shutil.move, 'piglit.conf.restore', 'piglit.conf')
> +
> +        with open('piglit.conf', 'w') as f:
> +            f.write(CONF_FILE)
> +        self.defer(os.unlink, 'piglit.conf')
> +        self.defer(os.chdir, os.getcwd())
> +        os.chdir('..')
> +
> +        run._get_config(None)
> +
> +        nt.ok_(core.PIGLIT_CONFIG.has_section('nose-test'),
> +               msg='$PIGLIT_ROOT not found')
> --
> 2.0.0
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit


More information about the Piglit mailing list