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.dyla...@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.
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/piglit