[Piglit] [PATCH 01/11] framework: Begin converting TestProfile to a flat dictionary of tests.

Kenneth Graunke kenneth at whitecape.org
Wed Feb 1 16:06:28 PST 2012

In the past, Piglit has stored test profiles as a hierarchy of Test and
Group objects: TestProfile contained a top-level Group, and each Group
could contain either Tests or Groups.  To refer to a test, one could do:

A second way of referring to tests is via their "fully qualified name",
using slashes to delimit groups.  The above example would be:

This fully qualified name is used for regular expression matching
(piglit-run.py's -t and -x options).  Since the advent of JSON, it's
also what gets stored in the results file.

Using the Group hierarchy is both complicated and inconvenient:
1. When running tests, we have to construct the fully qualified
   name in order to write it to the JSON (rather than just having it).
2. Adding the ability to "resume" a test run by re-reading the JSON
   results file and skipping tests that have already completed would
   require the opposite conversion (qualified name -> hierarchy).
3. Every Group has to be manually instantiated and added to the parent
   group (rather than just being created as necessary).
4. The Group class is actually just a dumb wrapper around Python's dict
   class, but with extra inconvenience.

This patch is an incremental step toward dropping the Group hierarchy.
It converts TestProfile.run() to use a simple dictionary where the keys
are fully qualified test names and the values are the Test objects.  To
avoid having to convert all.tests right away, it converts the Group
hierarchy into this data structure before running.

Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
 framework/core.py |   52 +++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/framework/core.py b/framework/core.py
index 0bef48d..d45308b 100644
--- a/framework/core.py
+++ b/framework/core.py
@@ -515,41 +515,59 @@ class Test:
 class Group(dict):
-	def doRun(self, env, path, json_writer):
-		'''
-		Schedule all tests in group for execution.
-		See ``Test.doRun``.
-		'''
-		for sub in sorted(self):
-			spath = sub
-			if len(path) > 0:
-				spath = path + '/' + spath
-			self[sub].doRun(env, spath, json_writer)
+	pass
 class TestProfile:
 	def __init__(self):
 		self.tests = Group()
+		self.test_list = {}
 		self.sleep = 0
+	def flatten_group_hierarchy(self):
+		'''
+		Convert Piglit's old hierarchical Group() structure into a flat
+		dictionary mapping from fully qualified test names to "Test" objects.
+		For example,
+		tests['spec']['glsl-1.30']['preprocessor']['compiler']['keywords']['void.frag']
+		would become:
+		test_list['spec/glsl-1.30/preprocessor/compiler/keywords/void.frag']
+		'''
+		def f(prefix, group, test_dict):
+			for key in group:
+				fullkey = key if prefix == '' else prefix + '/' + key
+				if isinstance(group[key], dict):
+					f(fullkey, group[key], test_dict)
+				else:
+					test_dict[fullkey] = group[key]
+		f('', self.tests, self.test_list)
+		# Clear out the old Group()
+		self.tests = Group()
 	def run(self, env, json_writer):
+		self.flatten_group_hierarchy()
 		Schedule all tests in profile for execution.
-		See ``Test.doRun``.
+		See ``Test.schedule`` and ``Test.run``.
-		# queue up the concurrent tests up front, so the pool
-		# is filled from the start of the test.
+		# Queue up all the concurrent tests, so the pool is filled
+		# at the start of the test run.
 		if env.concurrent:
 			env.run_concurrent = True
-			self.tests.doRun(env, '', json_writer)
+			for (path, test) in self.test_list.items():
+				test.doRun(env, path, json_writer)
 		# Run any remaining non-concurrent tests serially from this
 		# thread, while the concurrent tests 
 		env.run_concurrent = False
-		self.tests.doRun(env, '', json_writer)
+		for (path, test) in self.test_list.items():
+			if not env.concurrent or not test.runConcurrent:
+				test.doRun(env, path, json_writer)

More information about the Piglit mailing list