[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:20:35 PDT 2014


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')
-- 
2.0.0



More information about the Piglit mailing list