[Piglit] [PATCH 15/15] framework: add boilerplate to turn off process isolation

Dylan Baker dylan at pnwbakers.com
Fri Sep 9 19:18:53 UTC 2016


This adds a switch to to turn off process isolation (it is normally on),
for now this only affects shader_runner, but in the future could affect
more tests, like glslparsertest or dEQP.

Signed-off-by: Dylan Baker <dylanx.c.baker at intel.com>
---
 framework/options.py      |  1 +
 framework/programs/run.py | 22 ++++++++++++++++++++++
 piglit.conf.example       |  7 +++++++
 tests/all.py              | 34 +++++++++++++++++++++++++++++-----
 tests/shader.py           |  4 ++--
 5 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/framework/options.py b/framework/options.py
index 94a8084..5cb88aa 100644
--- a/framework/options.py
+++ b/framework/options.py
@@ -197,6 +197,7 @@ class _Options(object):  # pylint: disable=too-many-instance-attributes
         self.monitored = False
         self.sync = False
         self.deqp_mustpass = False
+        self.process_isolation = True
 
         # env is used to set some base environment variables that are not going
         # to change across runs, without sending them to os.environ which is
diff --git a/framework/programs/run.py b/framework/programs/run.py
index f531b37..2f0e9dc 100644
--- a/framework/programs/run.py
+++ b/framework/programs/run.py
@@ -41,6 +41,16 @@ __all__ = ['run',
            'resume']
 
 
+def booltype(val):
+    if val.lower() in ['false', 'no', '0']:
+        return False
+    elif val.lower() in ['true', 'yes', '1']:
+        return True
+    raise argparse.ArgumentTypeError(
+        'Case insensitve values of "yes", "no", "false", "true", and "0" or '
+        '"1" are accepted.')
+
+
 def _default_platform():
     """ Logic to determine the default platform to use
 
@@ -183,6 +193,16 @@ def _run_parser(input_):
                         help='Run only the tests in the deqp mustpass list '
                              'when running a deqp gles{2,3,31} profile, '
                              'otherwise run all tests.')
+    parser.add_argument('--process-isolation',
+                        dest='process_isolation',
+                        action='store',
+                        type=booltype,
+                        default=core.PIGLIT_CONFIG.safe_get(
+                            'core', 'process isolation', 'true'),
+                        help='Set this to allow tests to run without process '
+                             'isolation. This allows, but does not require, '
+                             'tests to run multiple tests per process.
+                             'This value can also be set in piglit.conf.')
     parser.add_argument("test_profile",
                         metavar="<Profile path(s)>",
                         nargs='+',
@@ -264,6 +284,7 @@ def run(input_):
     options.OPTIONS.monitored = args.monitored
     options.OPTIONS.sync = args.sync
     options.OPTIONS.deqp_mustpass = args.deqp_mustpass
+    options.OPTIONS.process_isolation = args.process_isolation
 
     # Set the platform to pass to waffle
     options.OPTIONS.env['PIGLIT_PLATFORM'] = args.platform
@@ -352,6 +373,7 @@ def resume(input_):
     options.OPTIONS.monitored = results.options['monitored']
     options.OPTIONS.sync = results.options['sync']
     options.OPTIONS.deqp_mustpass = results.options['deqp_mustpass']
+    options.OPTIONS.proces_isolation = results.options['process_isolation']
 
     core.get_config(args.config_file)
 
diff --git a/piglit.conf.example b/piglit.conf.example
index 56eb83d..17f2329 100644
--- a/piglit.conf.example
+++ b/piglit.conf.example
@@ -170,6 +170,13 @@ run_test=./%(test_name)s
 ; Default: 'bz2'
 ;compression=bz2
 
+; Set this value to change whether piglit defaults to using process isolation
+; or not. Care should be taken when using this option since it provides a
+; performance improvement, but with a cost in stability and reproducibility.
+; 
+; Default: True
+;process isolation=True
+
 [expected-failures]
 ; Provide a list of test names that are expected to fail.  These tests
 ; will be listed as passing in JUnit output when they fail.  Any
diff --git a/tests/all.py b/tests/all.py
index 3961656..2399d5e 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -4,20 +4,26 @@
 from __future__ import (
     absolute_import, division, print_function, unicode_literals
 )
+import collections
 import itertools
 import os
 import platform
 
+import six
 from six.moves import range
 
 from framework import grouptools
+from framework import options
 from framework.profile import TestProfile
-from framework.test import (PiglitGLTest, GleanTest, ShaderTest,
+from framework.test import (PiglitGLTest, GleanTest,
                             GLSLParserTest, GLSLParserNoConfigError)
+from framework.test.shader_test import ShaderTest, MultiShaderTest
 from .py_modules.constants import TESTS_DIR, GENERATED_TESTS_DIR
 
 __all__ = ['profile']
 
+PROCESS_ISOLATION = options.OPTIONS.process_isolation
+
 # Disable bad hanging indent errors in pylint
 # There is a bug in pyling which causes the profile.group_manager to be tagged
 # as bad hanging indent, even though it seems to be correct (and similar syntax
@@ -213,13 +219,20 @@ def power_set(s):
 # Collecting all tests
 profile = TestProfile()  # pylint: disable=invalid-name
 
+shader_tests = collections.defaultdict(list)
+
 # Find and add all shader tests.
 for basedir in [TESTS_DIR, GENERATED_TESTS_DIR]:
     for dirpath, _, filenames in os.walk(basedir):
         for filename in filenames:
             testname, ext = os.path.splitext(filename)
+            groupname = grouptools.from_path(os.path.relpath(dirpath, basedir))
             if ext == '.shader_test':
-                test = ShaderTest(os.path.join(dirpath, filename))
+                if PROCESS_ISOLATION:
+                    test = ShaderTest(os.path.join(dirpath, filename))
+                else:
+                    shader_tests[groupname].append(os.path.join(dirpath, filename))
+                    continue
             elif ext in ['.vert', '.tesc', '.tese', '.geom', '.frag', '.comp']:
                 try:
                     test = GLSLParserTest(os.path.join(dirpath, filename))
@@ -234,13 +247,24 @@ for basedir in [TESTS_DIR, GENERATED_TESTS_DIR]:
             else:
                 continue
 
-            group = grouptools.join(
-                grouptools.from_path(os.path.relpath(dirpath, basedir)),
-                testname)
+            group = grouptools.join(groupname, testname)
             assert group not in profile.test_list, group
 
             profile.test_list[group] = test
 
+# Because we need to handle duplicate group names in TESTS and GENERATED_TESTS
+# this dictionary is constructed, then added to the actual test dictionary.
+for group, files in six.iteritems(shader_tests):
+    assert group not in profile.test_list, 'duplicate group: {}'.format(group)
+    # If there is only one file in the directory use a normal shader_test.
+    # Otherwise use a MultiShaderTest
+    if len(files) == 1:
+        group = grouptools.join(
+            group, os.path.basename(os.path.splitext(files[0])[0]))
+        profile.test_list[group] = ShaderTest(files[0])
+    else:
+        profile.test_list[group] = MultiShaderTest(files)
+
 # Collect and add all asmparsertests
 for basedir in [TESTS_DIR, GENERATED_TESTS_DIR]:
     _basedir = os.path.join(basedir, 'asmparsertest', 'shaders')
diff --git a/tests/shader.py b/tests/shader.py
index 452f36a..3d67679 100644
--- a/tests/shader.py
+++ b/tests/shader.py
@@ -4,9 +4,9 @@ from __future__ import (
     absolute_import, division, print_function, unicode_literals
 )
 
-from framework.test import ShaderTest
+from framework.test.shader_test import ShaderTest, MultiShaderTest
 from tests.all import profile
 
 __all__ = ['profile']
 
-profile.filter_tests(lambda _, t: isinstance(t, ShaderTest))
+profile.filter_tests(lambda _, t: isinstance(t, (ShaderTest, MultiShaderTest)))
-- 
git-series 0.8.10


More information about the Piglit mailing list