[Piglit] [PATCH] profile: Don't exhaust generator when concurrency == "some"

Arkadiusz Hiler arkadiusz.hiler at intel.com
Wed May 9 10:45:39 UTC 2018

TestProfile.itertests() is a generator that we happily exhaust. If
concurrency == "some" then run_profile() invokes run_threads() twice,
once for thread safe tests, and once for non-safe ones. The first
invocation exhaust the generator, so the second one sees nothing.

This patch changes the call chain so that we call .itertests() in the
place we actually consume the generator, not earlier.

Reported-by: Stanislav Lisovskiy <stanislav.lisovskiy at intel.com>
Signed-off-by: Arkadiusz Hiler <arkadiusz.hiler at intel.com>
 framework/profile.py | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/framework/profile.py b/framework/profile.py
index 1c75025b3..f214006bc 100644
--- a/framework/profile.py
+++ b/framework/profile.py
@@ -561,12 +561,7 @@ def run(profiles, logger, backend, concurrency):
     chunksize = 1
-    profiles = [(p, p.itertests()) for p in profiles]
-    log = LogManager(logger, sum(len(p) for p, _ in profiles))
-    # check that after the filters are run there are actually tests to run.
-    # if not any(l for _, l in profiles):
-        # raise exceptions.PiglitUserError('no matching tests')
+    log = LogManager(logger, sum(len(p) for p in profiles))
     def test(name, test, profile, this_pool=None):
         """Function to call test.execute from map"""
@@ -576,33 +571,36 @@ def run(profiles, logger, backend, concurrency):
         if profile.options['monitor'].abort_needed:
-    def run_threads(pool, profile, test_list, filterby=None):
+    def run_threads(pool, profile, filterby=None):
         """ Open a pool, close it, and join it """
         if filterby:
             # Although filterby could be attached to TestProfile as a filter,
             # it would have to be removed when run_threads exits, requiring
             # more code, and adding side-effects
-            test_list = (x for x in test_list if filterby(x))
+            test_list = (x for x in profile.itertests() if filterby(x))
+        else:
+            test_list = list(profile.itertests())
         pool.imap(lambda pair: test(pair[0], pair[1], profile, pool),
                   test_list, chunksize)
-    def run_profile(profile, test_list):
+    def run_profile(profile):
         """Run an individual profile."""
         if concurrency == "all":
-            run_threads(multi, profile, test_list)
+            run_threads(multi, profile)
         elif concurrency == "none":
-            run_threads(single, profile, test_list)
+            run_threads(single, profile)
             assert concurrency == "some"
             # Filter and return only thread safe tests to the threaded pool
-            run_threads(multi, profile, test_list,
+            run_threads(multi, profile,
                         lambda x: x[1].run_concurrent)
             # Filter and return the non thread safe tests to the single
             # pool
-            run_threads(single, profile, test_list,
+            run_threads(single, profile,
                         lambda x: not x[1].run_concurrent)
@@ -615,7 +613,7 @@ def run(profiles, logger, backend, concurrency):
         for p in profiles:
-            run_profile(*p)
+            run_profile(p)
         for pool in [single, multi]:
@@ -623,6 +621,6 @@ def run(profiles, logger, backend, concurrency):
-    for p, _ in profiles:
+    for p in profiles:
         if p.options['monitor'].abort_needed:
             raise exceptions.PiglitAbort(p.options['monitor'].error_message)

More information about the Piglit mailing list