Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve diagnostics for WPT failures #24981

Merged
merged 5 commits into from Dec 3, 2019
Next

Include test output in filtered WPT logs

  • Loading branch information
SimonSapin committed Dec 3, 2019
commit 0ac021c1a5bd29fd516c702ee057daf5a58cb66e
@@ -748,12 +748,12 @@ def wpt_chunks(platform, make_chunk_task, build_task, total_chunks, processes,
| cat
time ./mach test-wpt --release --processes $PROCESSES --timeout-multiplier=4 \
--headless --log-raw test-wdspec.log \
--log-errorsummary wdspec-errorsummary.log \
--log-servojson wdspec-jsonsummary.log \
--always-succeed \
webdriver \
| cat
./mach filter-intermittents \
wdspec-errorsummary.log \
wdspec-jsonsummary.log \
--log-intermittents intermittents.log \
--log-filteredsummary filtered-wdspec-errorsummary.log \
--tracker-api default \
@@ -768,11 +768,11 @@ def wpt_chunks(platform, make_chunk_task, build_task, total_chunks, processes,
--total-chunks "$TOTAL_CHUNKS" \
--this-chunk "$THIS_CHUNK" \
--log-raw test-wpt.log \
--log-errorsummary wpt-errorsummary.log \
--log-servojson wpt-jsonsummary.log \
--always-succeed \
| cat
./mach filter-intermittents \
wpt-errorsummary.log \
wpt-jsonsummary.log \
--log-intermittents intermittents.log \
--log-filteredsummary filtered-wpt-errorsummary.log \
--tracker-api default \
@@ -68,6 +68,7 @@


def create_parser_wpt():
import mozlog.commandline
parser = wptcommandline.create_parser()
parser.add_argument('--release', default=False, action="store_true",
help="Run with a release build of servo")
@@ -77,6 +78,8 @@ def create_parser_wpt():
help="Pass preferences to servo")
parser.add_argument('--layout-2020', default=False, action="store_true",
help="Use expected results for the 2020 layout engine")
parser.add_argument('--log-servojson', action="append", type=mozlog.commandline.log_file,
help="Servo's JSON logger of unexpected results")
parser.add_argument('--always-succeed', default=False, action="store_true",
help="Always yield exit code of zero")
return parser
@@ -511,7 +514,7 @@ def update_wpt(self, **kwargs):
description='Given a WPT error summary file, filter out intermittents and other cruft.',
category='testing')
@CommandArgument('summary',
help="Error summary log to take un")
help="Error summary log to take in")
@CommandArgument('--log-filteredsummary', default=None,
help='Print filtered log to file')
@CommandArgument('--log-intermittents', default=None,
@@ -529,10 +532,7 @@ def filter_intermittents(self, summary, log_filteredsummary, log_intermittents,
encoded_auth = base64.encodestring(file.read().strip()).replace('\n', '')
failures = []
with open(summary, "r") as file:
for line in file:
line_json = json.loads(line)
if 'status' in line_json:
failures += [line_json]
failures = [json.loads(line) for line in file]
actual_failures = []
intermittents = []
for failure in failures:
@@ -546,10 +546,7 @@ def filter_intermittents(self, summary, log_filteredsummary, log_intermittents,
request = urllib.request.Request("%s/query.py?name=%s" % (tracker_api, query))
search = urllib.request.urlopen(request)
data = json.load(search)
if len(data) == 0:
actual_failures += [failure]
else:
intermittents += [failure]
is_intermittent = len(data) > 0
else:
qstr = "repo:servo/servo+label:I-intermittent+type:issue+state:open+%s" % failure['test']
# we want `/` to get quoted, but not `+` (github's API doesn't like that), so we set `safe` to `+`
@@ -559,28 +556,30 @@ def filter_intermittents(self, summary, log_filteredsummary, log_intermittents,
request.add_header("Authorization", "Basic %s" % encoded_auth)
search = urllib.request.urlopen(request)
data = json.load(search)
if data['total_count'] == 0:
actual_failures += [failure]
else:
intermittents += [failure]
is_intermittent = data['total_count'] > 0

if is_intermittent:
intermittents.append(failure["output"])
else:
actual_failures.append(failure["output"])

def format(outputs, description, file=sys.stdout):
print(len(outputs), description + ":\n", file=file)
file.write('\n'.join(outputs).encode("utf-8"))

if log_intermittents:
with open(log_intermittents, "w") as intermittents_file:
for intermittent in intermittents:
json.dump(intermittent, intermittents_file, indent=4)
print("\n", end='', file=intermittents_file)
with open(log_intermittents, "wb") as file:
format(intermittents, "known-intermittent unexpected results", file)

output = open(log_filteredsummary, "w") if log_filteredsummary else sys.stdout
for failure in actual_failures:
json.dump(failure, output, indent=4)
print("\n", end='', file=output)
description = "unexpected results that are NOT known-intermittents"
if log_filteredsummary:
with open(log_filteredsummary, "wb") as file:
format(actual_failures, description, file)

if output is not sys.stdout:
output.close()
if actual_failures:
format(actual_failures, description)

if len(actual_failures) == 0:
return 0
return 1
return bool(actual_failures)

@Command('test-android-startup',
description='Extremely minimal testing of Servo for Android',
@@ -4,6 +4,7 @@

from mozlog.formatters import base
import collections
import json
import os
import sys
import subprocess
@@ -14,7 +15,7 @@
DEFAULT_CLEAR_EOL_CODE = u"\x1b[K"


class GroupingFormatter(base.BaseFormatter):
class ServoFormatter(base.BaseFormatter):
"""Formatter designed to produce unexpected test results grouped
together in a readable format."""
def __init__(self):
@@ -77,7 +78,7 @@ def text_to_erase_display(self):
return ((self.move_up + self.clear_eol) *
self.current_display.count('\n'))

def generate_output(self, text=None, new_display=None):
def generate_output(self, text=None, new_display=None, unexpected_in_test=None):
if not self.interactive:
return text

@@ -230,7 +231,8 @@ def test_end(self, data):
subtest_failures)
self.test_failure_text += output

return self.generate_output(text=output, new_display=new_display)
return self.generate_output(text=output, new_display=new_display,
unexpected_in_test=test_name)

def test_status(self, data):
if "expected" in data:
@@ -289,3 +291,16 @@ def log(self, data):

if data['level'] in ('CRITICAL', 'ERROR'):
return self.generate_output(text=data['message'] + "\n")


class ServoJsonFormatter(ServoFormatter):
def suite_start(self, data):
ServoFormatter.suite_start(self, data)
# Don't forward the return value

def generate_output(self, text=None, new_display=None, unexpected_in_test=None):
if unexpected_in_test:
return "%s\n" % json.dumps({"test": unexpected_in_test, "output": text})

def log(self, _):
return
@@ -34,7 +34,9 @@ def run_tests(**kwargs):
set_defaults(kwargs)

mozlog.commandline.log_formatters["servo"] = \
(grouping_formatter.GroupingFormatter, "A grouping output formatter")
(grouping_formatter.ServoFormatter, "Servo’s grouping output formatter")
mozlog.commandline.log_formatters["servojson"] = \
(grouping_formatter.ServoJsonFormatter, "Servo's JSON logger of unexpected results")

use_mach_logging = False
if len(kwargs["test_list"]) == 1:
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.