Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Unified Diff: third_party/typ/typ/json_results.py

Issue 627763002: Add new 'typ' python testing framework to third_party/. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: upload to typ v0.8.1, update README.chromium Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/typ/typ/json_results.py
diff --git a/third_party/typ/typ/json_results.py b/third_party/typ/typ/json_results.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e03f6febbdc485bc9ccf2785e5369a21280b3c7
--- /dev/null
+++ b/third_party/typ/typ/json_results.py
@@ -0,0 +1,186 @@
+# Copyright 2014 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from collections import OrderedDict
+
+import json
+
+
+class ResultType(object):
+ Pass = 'Pass'
+ Failure = 'Failure'
+ ImageOnlyFailure = 'ImageOnlyFailure'
+ Timeout = 'Timeout'
+ Crash = 'Crash'
+ Skip = 'Skip'
+
+ values = (Pass, Failure, ImageOnlyFailure, Timeout, Crash, Skip)
+
+
+class Result(object):
+ # too many instance attributes pylint: disable=R0902
+ # too many arguments pylint: disable=R0913
+
+ def __init__(self, name, actual, started, took, worker,
+ expected=None, unexpected=False,
+ flaky=False, code=0, out='', err='', pid=0):
+ self.name = name
+ self.actual = actual
+ self.started = started
+ self.took = took
+ self.worker = worker
+ self.expected = expected or [ResultType.Pass]
+ self.unexpected = unexpected
+ self.flaky = flaky
+ self.code = code
+ self.out = out
+ self.err = err
+ self.pid = pid
+
+
+class ResultSet(object):
+
+ def __init__(self):
+ self.results = []
+
+ def add(self, result):
+ self.results.append(result)
+
+
+TEST_SEPARATOR = '.'
+
+
+def make_full_results(metadata, seconds_since_epoch, all_test_names, results):
+ """Convert the typ results to the Chromium JSON test result format.
+
+ See http://www.chromium.org/developers/the-json-test-results-format
+ """
+
+ # We use OrderedDicts here so that the output is stable.
+ full_results = OrderedDict()
+ full_results['version'] = 3
+ full_results['interrupted'] = False
+ full_results['path_delimiter'] = TEST_SEPARATOR
+ full_results['seconds_since_epoch'] = seconds_since_epoch
+
+ for md in metadata:
+ key, val = md.split('=', 1)
+ full_results[key] = val
+
+ passing_tests = _passing_test_names(results)
+ failed_tests = failed_test_names(results)
+ skipped_tests = set(all_test_names) - passing_tests - failed_tests
+
+ full_results['num_failures_by_type'] = OrderedDict()
+ full_results['num_failures_by_type']['FAIL'] = len(failed_tests)
+ full_results['num_failures_by_type']['PASS'] = len(passing_tests)
+ full_results['num_failures_by_type']['SKIP'] = len(skipped_tests)
+
+ full_results['tests'] = OrderedDict()
+
+ for test_name in all_test_names:
+ value = OrderedDict()
+ if test_name in skipped_tests:
+ value['expected'] = 'SKIP'
+ value['actual'] = 'SKIP'
+ else:
+ value['expected'] = 'PASS'
+ value['actual'] = _actual_results_for_test(test_name, results)
+ if value['actual'].endswith('FAIL'):
+ value['is_unexpected'] = True
+ _add_path_to_trie(full_results['tests'], test_name, value)
+
+ return full_results
+
+
+def make_upload_request(test_results_server, builder, master, testtype,
+ full_results):
+ url = 'http://%s/testfile/upload' % test_results_server
+ attrs = [('builder', builder),
+ ('master', master),
+ ('testtype', testtype)]
+ content_type, data = _encode_multipart_form_data(attrs, full_results)
+ return url, content_type, data
+
+
+def exit_code_from_full_results(full_results):
+ return 1 if num_failures(full_results) else 0
+
+
+def num_failures(full_results):
+ return full_results['num_failures_by_type']['FAIL']
+
+
+def failed_test_names(results):
+ names = set()
+ for r in results.results:
+ if r.actual == ResultType.Failure:
+ names.add(r.name)
+ elif (r.actual == ResultType.Pass and
+ r.name in names): # pragma: untested
+ names.remove(r.name)
+ return names
+
+
+def _passing_test_names(results):
+ return set(r.name for r in results.results if r.actual == ResultType.Pass)
+
+
+def _actual_results_for_test(test_name, results):
+ actuals = []
+ for r in results.results:
+ if r.name == test_name:
+ if r.actual == ResultType.Failure:
+ actuals.append('FAIL')
+ elif r.actual == ResultType.Pass:
+ actuals.append('PASS')
+
+ assert actuals, 'We did not find any result data for %s.' % test_name
+ return ' '.join(actuals)
+
+
+def _add_path_to_trie(trie, path, value):
+ if TEST_SEPARATOR not in path:
+ trie[path] = value
+ return
+ directory, rest = path.split(TEST_SEPARATOR, 1)
+ if directory not in trie:
+ trie[directory] = {}
+ _add_path_to_trie(trie[directory], rest, value)
+
+
+def _encode_multipart_form_data(attrs, test_results):
+ # Cloned from webkitpy/common/net/file_uploader.py
+ BOUNDARY = '-J-S-O-N-R-E-S-U-L-T-S---B-O-U-N-D-A-R-Y-'
+ CRLF = '\r\n'
+ lines = []
+
+ for key, value in attrs:
+ lines.append('--' + BOUNDARY)
+ lines.append('Content-Disposition: form-data; name="%s"' % key)
+ lines.append('')
+ lines.append(value)
+
+ lines.append('--' + BOUNDARY)
+ lines.append('Content-Disposition: form-data; name="file"; '
+ 'filename="full_results.json"')
+ lines.append('Content-Type: application/json')
+ lines.append('')
+ lines.append(json.dumps(test_results))
+
+ lines.append('--' + BOUNDARY + '--')
+ lines.append('')
+ body = CRLF.join(lines)
+ content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
+ return content_type, body

Powered by Google App Engine
This is Rietveld 408576698