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

CI Build&Test: Show segfaults using GitHub annotations #37738

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
86 changes: 69 additions & 17 deletions src/sage/doctest/reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
# https://www.gnu.org/licenses/
# ****************************************************************************

import re
from sys import stdout
from signal import (SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL,
SIGINT, SIGKILL, SIGPIPE, SIGQUIT, SIGSEGV, SIGTERM)
Expand Down Expand Up @@ -222,6 +223,69 @@
cmd += f" [failed in baseline: {failed}]"
return cmd

def _log_failure(self, source, fail_msg, event, output=None):
r"""
Report on the result of a failed doctest run.

INPUT:

- ``source`` -- a source from :mod:`sage.doctest.sources`

- ``fail_msg`` -- a string

- ``event`` -- a string

- ``output`` -- optional string

EXAMPLES::

sage: from sage.doctest.reporting import DocTestReporter
sage: from sage.doctest.control import DocTestController, DocTestDefaults
sage: from sage.doctest.sources import FileDocTestSource
sage: from sage.env import SAGE_SRC
sage: import os
sage: filename = os.path.join(SAGE_SRC, 'sage', 'doctest', 'reporting.py')
sage: DD = DocTestDefaults()
sage: FDS = FileDocTestSource(filename, DD)
sage: DC = DocTestController(DD,[filename])
sage: DTR = DocTestReporter(DC)
sage: DTR._log_failure(FDS, "Timed out", "process (pid=1234) timed out", "Output so far...")
Timed out
**********************************************************************
Tests run before process (pid=1234) timed out:
Output so far...
**********************************************************************
"""
log = self.controller.log
format = self.controller.options.format
if format == 'sage':
stars = "*" * 70
log(f" {fail_msg}\n{stars}\n")
if output:
log(f"Tests run before {event}:")
log(output)
log(stars)
elif format == 'github':

Check warning on line 268 in src/sage/doctest/reporting.py

View check run for this annotation

Codecov / codecov/patch

src/sage/doctest/reporting.py#L268

Added line #L268 was not covered by tests
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#using-workflow-commands-to-access-toolkit-functions
command = f'::error title={fail_msg}'
command += f',file={source.printpath}'
if output:
if m := re.search("## line ([0-9]+) ##\n-{40,100}\n(.*)", output, re.MULTILINE | re.DOTALL):
lineno = m.group(1)
message = m.group(2)
command += f',line={lineno}'

Check warning on line 276 in src/sage/doctest/reporting.py

View check run for this annotation

Codecov / codecov/patch

src/sage/doctest/reporting.py#L270-L276

Added lines #L270 - L276 were not covered by tests
else:
message = output

Check warning on line 278 in src/sage/doctest/reporting.py

View check run for this annotation

Codecov / codecov/patch

src/sage/doctest/reporting.py#L278

Added line #L278 was not covered by tests
# Urlencoding trick for multi-line annotations
# https://github.com/actions/starter-workflows/issues/68#issuecomment-581479448
message = message.replace('\n', '%0A')

Check warning on line 281 in src/sage/doctest/reporting.py

View check run for this annotation

Codecov / codecov/patch

src/sage/doctest/reporting.py#L281

Added line #L281 was not covered by tests
else:
message = ""
command += f'::{message}'
log(command)

Check warning on line 285 in src/sage/doctest/reporting.py

View check run for this annotation

Codecov / codecov/patch

src/sage/doctest/reporting.py#L283-L285

Added lines #L283 - L285 were not covered by tests
else:
raise ValueError(f'unknown format option: {format}')

Check warning on line 287 in src/sage/doctest/reporting.py

View check run for this annotation

Codecov / codecov/patch

src/sage/doctest/reporting.py#L287

Added line #L287 was not covered by tests

def report(self, source, timeout, return_code, results, output, pid=None):
"""
Report on the result of running doctests on a given source.
Expand Down Expand Up @@ -434,9 +498,7 @@
fail_msg += " (and interrupt failed)"
else:
fail_msg += " (with %s after interrupt)" % signal_name(sig)
log(" %s\n%s\nTests run before %s timed out:" % (fail_msg, "*"*70, process_name))
log(output)
log("*"*70)
self._log_failure(source, fail_msg, f"{process_name} timed out", output)
postscript['lines'].append(self.report_head(source, fail_msg))
stats[basename] = {"failed": True, "walltime": 1e6, "ntests": ntests}
if not baseline.get('failed', False):
Expand All @@ -448,9 +510,7 @@
fail_msg = "Killed due to %s" % signal_name(-return_code)
if ntests > 0:
fail_msg += " after testing finished"
log(" %s\n%s\nTests run before %s failed:" % (fail_msg,"*"*70, process_name))
log(output)
log("*"*70)
self._log_failure(source, fail_msg, f"{process_name} failed", output)
postscript['lines'].append(self.report_head(source, fail_msg))
stats[basename] = {"failed": True, "walltime": 1e6, "ntests": ntests}
if not baseline.get('failed', False):
Expand All @@ -465,15 +525,11 @@
else:
cpu = 1e6
if result_dict.err == 'badresult':
log(" Error in doctesting framework (bad result returned)\n%s\nTests run before error:" % ("*"*70))
log(output)
log("*"*70)
self._log_failure(source, "Error in doctesting framework (bad result returned)", "error", output)
postscript['lines'].append(self.report_head(source, "Testing error: bad result"))
self.error_status |= 64
elif result_dict.err == 'noresult':
log(" Error in doctesting framework (no result returned)\n%s\nTests run before error:" % ("*"*70))
log(output)
log("*"*70)
self._log_failure(source, "Error in doctesting framework (no result returned)", "error", output)

Check warning on line 532 in src/sage/doctest/reporting.py

View check run for this annotation

Codecov / codecov/patch

src/sage/doctest/reporting.py#L532

Added line #L532 was not covered by tests
postscript['lines'].append(self.report_head(source, "Testing error: no result"))
self.error_status |= 64
elif result_dict.err == 'tab':
Expand All @@ -499,11 +555,7 @@
else:
err = repr(result_dict.err)
fail_msg = "%s in doctesting framework" % err

log(" %s\n%s" % (fail_msg, "*"*70))
if output:
log("Tests run before doctest exception:\n" + output)
log("*"*70)
self._log_failure(source, fail_msg, "exception", output)

Check warning on line 558 in src/sage/doctest/reporting.py

View check run for this annotation

Codecov / codecov/patch

src/sage/doctest/reporting.py#L558

Added line #L558 was not covered by tests
postscript['lines'].append(self.report_head(source, fail_msg))
if hasattr(result_dict, 'tb'):
log(result_dict.tb)
Expand Down