[Piglit] [Patch v2 1/4] framework: allow loading a piglit.conf from more locations
Dylan Baker
baker.dylan.c at gmail.com
Mon Jul 7 16:33:09 PDT 2014
On Monday, July 07, 2014 04:20:35 PM Dylan Baker 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)
> 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')
This breaks a couple of framework tests, I have a fix, which is pretty simple,
it just needs to catch an additional exception.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20140707/3ea7b010/attachment-0001.sig>
More information about the Piglit
mailing list