Commit b2ae931c authored by chadversary's avatar chadversary

framework: Replace custom serialization format with json

The results file produced by piglit-run.py contains a serialized
TestrunResult, and the serialization format was horridly homebrew. This
commit replaces that insanity with json.

Benefits:
    - Net loss of 113 lines of code (ignoring comments and empty lines).
    - By using the json module in the Python standard library, serializing
      and unserializing is nearly as simple as `json.dump(object, file)`
      and `json.load(object, file)`.
    - By using a format that is easy to manipulate, it is now simple to
      extend Piglit to allow users to embed custom data into the results
      file.

As a side effect, the summary file is no longer needed, so it is no longer
produced.
Reviewed-by: Paul Berry's avatarPaul Berry <stereotype441@gmail.com>
Signed-off-by: chadversary's avatarChad Versace <chad@chad-versace.us>
parent 0a9773ea
This diff is collapsed.
......@@ -94,7 +94,7 @@ class PlainExecTest(Test):
self.handleErr(results, err)
results['info'] = "@@@Returncode: %d\n\nErrors:\n%s\n\nOutput:\n%s" % (proc.returncode, err, out)
results['info'] = "Returncode: %d\n\nErrors:\n%s\n\nOutput:\n%s" % (proc.returncode, err, out)
results['returncode'] = proc.returncode
results['command'] = ' '.join(self.command)
else:
......
......@@ -156,7 +156,7 @@ results is an array of GroupResult instances, one per testrun
childresults
)
else:
childresults = [r.get(name, core.TestResult({}, { 'result': 'skip' }))
childresults = [r.get(name, core.TestResult({ 'result': 'skip' }))
for r in self.results]
self.children[name] = TestSummary(
......@@ -188,8 +188,12 @@ class Summary:
"""\
testruns is an array of TestrunResult instances
"""
groups = [
core.GroupResult.make_tree(testrun.tests)
for testrun in testruns
]
self.testruns = testruns
self.root = GroupSummary(self, '', 'All', [tr.results for tr in testruns])
self.root = GroupSummary(self, '', 'All', groups)
def allTests(self):
"""\
......
#!/usr/bin/env python
#
# 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:
#
# 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 AUTHOR(S) 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.
from getopt import getopt, GetoptError
import sys
import framework.core as core
#############################################################################
##### Main program
#############################################################################
def usage():
USAGE = """\
Usage: %(progName)s [options] [main results file]
Options:
-h, --help Show this message
Example:
%(progName)s results/main > results/summary
"""
print USAGE % {'progName': sys.argv[0]}
sys.exit(1)
def main():
env = core.Environment()
try:
options, args = getopt(sys.argv[1:], "h", [ "help" ])
except GetoptError:
usage()
OptionName = ''
for name, value in options:
if name in ('-h', '--help'):
usage()
if len(args) != 1:
usage()
resultsFilename = args[0]
results = core.loadTestResults(resultsFilename)
for testname, result in results.allTestResults().items():
if 'info' in result:
if len(result['info']) > 4096:
result['info'] = result['info'][0:4096]
results.write(sys.stdout)
if __name__ == "__main__":
main()
......@@ -68,8 +68,8 @@ def main():
for resultsDir in args:
results = core.loadTestResults(resultsDir)
for testname, result in results.allTestResults().items():
combined.results[testname] = result
for testname, result in results.tests.items():
combined.tests[testname] = result
combined.write(sys.stdout)
......
......@@ -23,8 +23,12 @@
from getopt import getopt, GetoptError
import json
import os.path as path
import re
import sys, os
import time
import traceback
import framework.core as core
from framework.threads import synchronized_self
......@@ -120,27 +124,43 @@ def main():
core.checkDir(resultsDir, False)
results = core.TestrunResult()
# Set results.name
if OptionName is '':
results.name = path.basename(resultsDir)
else:
results.name = OptionName
results.__dict__.update(env.collectData())
profile = core.loadTestProfile(profileFilename)
env.file = SyncFileWriter(resultsDir + '/main')
env.file.writeLine("name: %(name)s" % { 'name': core.encode(OptionName) })
env.collectData()
profile.run(env)
env.file.close()
print "Writing summary file..."
results = core.loadTestResults(resultsDir)
for testname, result in results.allTestResults().items():
if 'info' in result:
if len(result['info']) > 4096:
result['info'] = result['info'][0:4096]
file = open(resultsDir + '/summary', "w")
results.write(file)
file.close()
time_start = time.time()
try:
profile.run(env, results)
except Exception as e:
if isinstance(e, KeyboardInterrupt):
# When the user interrupts the test run, he may still
# want the partial test results. So ignore
# KeyboardInterruption and proceed to writing the
# result files.
pass
else:
traceback.print_exc()
sys.exit(1)
time_end = time.time()
results.time_elapsed = time_end - time_start
result_filepath = os.path.join(resultsDir, 'main')
print("Writing results file...")
with open(result_filepath, 'w') as f:
results.write(f)
print
print 'Thank you for running Piglit!'
print 'Summary for submission has been written to ' + resultsDir + '/summary'
print 'Results have been written to ' + result_filepath
if __name__ == "__main__":
main()
......@@ -88,8 +88,8 @@ def buildDetailValue(detail):
items = items + ResultListItem % { 'detail': buildDetailValue(d) }
return ResultList % { 'items': items }
elif type(detail) == str and detail[0:3] == '@@@':
return ResultMString % { 'detail': cgi.escape(detail[3:]) }
elif isinstance(detail, str) or isinstance(detail, unicode):
return ResultMString % { 'detail': cgi.escape(detail) }
return cgi.escape(str(detail))
......@@ -97,7 +97,9 @@ def buildDetailValue(detail):
def buildDetails(testResult):
details = []
for name in testResult:
if type(name) != str or name == 'result':
assert(isinstance(name, basestring))
if name == 'result':
continue
value = buildDetailValue(testResult[name])
......@@ -133,7 +135,13 @@ def writeResultHtml(test, testResult, filename):
writefile(filename, Result % locals())
def writeTestrunHtml(testrun, filename):
detaildict = dict(filter(lambda item: item[0] in testrun.globalkeys, testrun.__dict__.items()))
detail_keys = [
key
for key in testrun.__dict__.keys()
if key in testrun.serialized_keys
if key != 'tests'
]
detaildict = dict([(k, testrun.__dict__[k]) for k in detail_keys])
details = buildDetails(detaildict)
name = testrun.name
codename = testrun.codename
......@@ -281,7 +289,7 @@ def parse_listfile(filename):
return eval(code)
def loadresult(descr, OptionPreferSummary):
result = core.loadTestResults(descr[0], OptionPreferSummary)
result = core.loadTestResults(descr[0])
if len(descr) > 1:
result.__dict__.update(descr[1])
return result
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment