[Piglit] [PATCH 2/3] framework: Properly load JSON into internal representation

Dylan Baker dylan at pnwbakers.com
Tue Oct 25 19:54:02 UTC 2016


Currently piglit doesn't consistently deserialize JSON into it's
internal representation, leaving some bits as dictionaries or lists,
which breaks the summary code in particular. This patch corrects that.

Signed-off-by: Dylan Baker <dylanx.c.baker at intel.com>
---
 framework/programs/run.py                 |  2 +-
 framework/results.py                      | 23 +++++++--
 unittests/framework/backends/shared.py    |  4 ++
 unittests/framework/backends/test_json.py |  3 +-
 unittests/framework/test_results.py       | 77 +++++++++++--------------------
 5 files changed, 51 insertions(+), 58 deletions(-)

diff --git a/framework/programs/run.py b/framework/programs/run.py
index ecfc36f..5a2fcd0 100644
--- a/framework/programs/run.py
+++ b/framework/programs/run.py
@@ -339,7 +339,7 @@ def run(input_):
     profile.run(args.log_level, backend)
 
     results.time_elapsed.end = time.time()
-    backend.finalize({'time_elapsed': results.time_elapsed})
+    backend.finalize({'time_elapsed': results.time_elapsed.to_json()})
 
     print('Thank you for running Piglit!\n'
           'Results have been written to ' + args.results_path)
diff --git a/framework/results.py b/framework/results.py
index 5634df1..3c2bb2a 100644
--- a/framework/results.py
+++ b/framework/results.py
@@ -262,7 +262,9 @@ class Totals(dict):
     def __init__(self, *args, **kwargs):
         super(Totals, self).__init__(*args, **kwargs)
         for each in status.ALL:
-            self[str(each)] = 0
+            each = six.text_type(each)
+            if each not in self:
+                self[each] = 0
 
     def __bool__(self):
         # Since totals are prepopulated, calling 'if not <Totals instance>'
@@ -282,7 +284,10 @@ class Totals(dict):
     @classmethod
     def from_dict(cls, dict_):
         """Convert a dictionary into a Totals object."""
-        return cls(dict_)
+        tots = cls(dict_)
+        if '__type__' in tots:
+            del tots['__type__']
+        return tots
 
 
 class TestrunResult(object):
@@ -362,16 +367,24 @@ class TestrunResult(object):
         """
         res = cls()
         for name in ['name', 'uname', 'options', 'glxinfo', 'wglinfo', 'lspci',
-                     'time_elapsed', 'totals', 'results_version',
-                     'clinfo']:
+                     'results_version', 'clinfo']:
             value = dict_.get(name)
             if value:
                 setattr(res, name, value)
 
+        # Since this is used to load partial metadata when writing final test
+        # results there is no guarantee that this will have a "time_elapsed"
+        # key
+        if 'time_elapsed' in dict_:
+            setattr(res, 'time_elapsed',
+                    TimeAttribute.from_dict(dict_['time_elapsed']))
         res.tests = {n: TestResult.from_dict(t)
                      for n, t in six.iteritems(dict_['tests'])}
 
-        if not res.totals and not _no_totals:
+        if not 'totals' in dict_ and not _no_totals:
             res.calculate_group_totals()
+        else:
+            res.totals = {n: Totals.from_dict(t) for n, t in
+                          six.iteritems(dict_['totals'])}
 
         return res
diff --git a/unittests/framework/backends/shared.py b/unittests/framework/backends/shared.py
index ca2b478..d9f5790 100644
--- a/unittests/framework/backends/shared.py
+++ b/unittests/framework/backends/shared.py
@@ -105,6 +105,7 @@ JSON = {
     "glxinfo": None,
     "totals": {
         "spec": {
+            '__type__': 'Totals',
             "warn": 0,
             "timeout": 0,
             "skip": 0,
@@ -117,6 +118,7 @@ JSON = {
             "dmesg-fail": 0
         },
         "": {
+            '__type__': 'Totals',
             "warn": 0,
             "timeout": 0,
             "skip": 0,
@@ -129,6 +131,7 @@ JSON = {
             "dmesg-fail": 0
         },
         "spec@!opengl 1.0": {
+            '__type__': 'Totals',
             "warn": 0,
             "timeout": 0,
             "skip": 0,
@@ -141,6 +144,7 @@ JSON = {
             "dmesg-fail": 0
         },
         "root": {
+            '__type__': 'Totals',
             "warn": 0,
             "timeout": 0,
             "skip": 0,
diff --git a/unittests/framework/backends/test_json.py b/unittests/framework/backends/test_json.py
index da1015c..e23bc29 100644
--- a/unittests/framework/backends/test_json.py
+++ b/unittests/framework/backends/test_json.py
@@ -113,7 +113,8 @@ class TestJSONBackend(object):
             with test.write_test(self.name) as t:
                 t(self.result)
             test.finalize(
-                {'time_elapsed': results.TimeAttribute(start=0.0, end=1.0)})
+                {'time_elapsed':
+                    results.TimeAttribute(start=0.0, end=1.0).to_json()})
 
         def test_metadata_removed(self, tmpdir):
             assert not tmpdir.join('metadata.json').check()
diff --git a/unittests/framework/test_results.py b/unittests/framework/test_results.py
index 9fce9d5..52257e0 100644
--- a/unittests/framework/test_results.py
+++ b/unittests/framework/test_results.py
@@ -33,6 +33,8 @@ from framework import grouptools
 from framework import results
 from framework import status
 
+from .backends import shared
+
 # pylint: disable=no-self-use
 
 
@@ -169,6 +171,7 @@ class TestTestResult(object):
             def test_pid(self):
                 """sets pid properly."""
                 assert self.test.pid == self.dict['pid']
+
         class TestResult(object):
             """Tests for TestResult.result getter and setter methods."""
 
@@ -519,71 +522,43 @@ class TestTestrunResult(object):
     class TestFromDict(object):
         """Tests for TestrunResult.from_dict."""
 
-        @classmethod
-        def setup_class(cls):
-            """Setup values used by all tests."""
-            subtest = results.TestResult('fail')
-            subtest.subtests['foo'] = 'pass'
-
-            test = results.TestrunResult()
-            test.name = 'name'
-            test.uname = 'this is uname'
-            test.options = {'some': 'option'}
-            test.glxinfo = 'glxinfo'
-            test.wglinfo = 'wglinfo'
-            test.clinfo = 'clinfo'
-            test.lspci = 'this is lspci'
-            test.time_elapsed.end = 1.23
-            test.tests = {
-                'a test': results.TestResult('pass'),
-                'subtest': subtest,
-            }
-            # This will (hopefully) never be less than current
-            test.results_version = 100000
-
-            cls.baseline = test
-            cls.test = results.TestrunResult.from_dict(test.to_json())
+        @pytest.fixture(scope="module")
+        def inst(self):
+            return results.TestrunResult.from_dict(shared.JSON)
 
         @pytest.mark.parametrize("attrib", [
             'name', 'uname', 'glxinfo', 'wglinfo', 'lspci', 'results_version',
-            'clinfo'
+            'clinfo', 'options',
         ])
-        def test_attribs_restored(self, attrib):
+        def test_attribs_restored(self, attrib, inst):
             """tests for basic attributes."""
-            assert getattr(self.baseline, attrib) == getattr(self.test, attrib)
+            assert shared.JSON[attrib] == getattr(inst, attrib)
 
-        def test_tests(self):
+        def test_tests(self, inst):
             """tests is restored correctly."""
-            assert self.test.tests['a test'].result == \
-                self.baseline.tests['a test'].result
+            assert inst.tests.keys() == shared.JSON['tests'].keys()
 
-        def test_test_type(self):
+        def test_test_type(self, inst):
             """tests is restored correctly."""
-            assert isinstance(self.test.tests['a test'].result, status.Status)
+            assert isinstance(
+                inst.tests['spec@!opengl 1.0 at gl-1.0-readpixsanity'],
+                results.TestResult)
 
-        def test_totals(self):
+        def test_totals(self, inst):
             """totals is restored correctly."""
-            assert dict(self.baseline.totals) == dict(self.test.totals)
+            baseline = shared.JSON['totals'].copy()
+            for s in six.itervalues(baseline):
+                del s['__type__']
+            assert baseline == dict(inst.totals)
 
-        def test_subtests(self):
-            """subtests are restored correctly."""
-            assert self.test.tests['subtest'].subtests['foo'] == \
-                self.baseline.tests['subtest'].subtests['foo']
-
-        def test_subtest_type(self):
-            """subtests are Status instances."""
-            assert isinstance(self.test.tests['subtest'].subtests['foo'],
-                              status.Status)
-
-        def test_time_elapsed(self):
+        def test_time_elapsed(self, inst):
             """time_elapsed is restored correctly."""
-            assert self.baseline.time_elapsed.end == self.test.time_elapsed.end
-
-        def test_time(self):
-            """time_elapsed is TimeAttribute instance."""
-            assert isinstance(self.test.time_elapsed, results.TimeAttribute)
+            assert inst.time_elapsed.start == \
+                shared.JSON['time_elapsed']['start']
+            assert inst.time_elapsed.end == \
+                shared.JSON['time_elapsed']['end']
 
-    class TestGetResul(object):
+    class TestGetResult(object):
         """Tests for TestrunResult.get_result."""
 
         @classmethod
-- 
2.10.1



More information about the Piglit mailing list