Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions .github/scripts/verify_console_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env python3

import argparse
import difflib
import re
import sys
from pathlib import Path

ANSI_PATTERN = re.compile(r"\x1b\[[0-9;]*[A-Za-z]")
LOG_PREFIX_PATTERN = re.compile(r"^\d{4}-\d{2}-\d{2}T[0-9:.]+Z\s+")
SHA_PATTERN = re.compile(
r"(https://github\.com/[^/]+/[^/]+/blob/)[0-9a-f]{40}(/)"
)
REPORT_MARKER = "##[error] Issues found!"
RESULT_LABELS = (
"cppcheck results:",
"clang-tidy results:",
"PyLint results:",
)
CPP_ISSUE_PATTERN = re.compile(
r"^(?P<path>/.+?):(?P<line>\d+):(?:\d+:)?\s+"
r"(?P<level>error|warning|style|performance|portability|information|note):\s+"
r"(?P<message>.+)$"
)
PYTHON_ISSUE_PATTERN = re.compile(
r"^(?P<path>.+?\.py):(?P<line>\d+):?\s+(?P<message>[A-Z]\d{4}:.+)$"
)


def _split_inline_result_label(line: str) -> list[str]:
for label in RESULT_LABELS:
if line.startswith(label):
remainder = line[len(label):].strip()
return [label, remainder] if remainder else [label]
return [line]


def _canonical_issue_line(line: str) -> str | None:
match = CPP_ISSUE_PATTERN.match(line)
if match:
return (
f"{match.group('path')}:{match.group('line')}: "
f"{match.group('level')}: {match.group('message')}"
)

match = PYTHON_ISSUE_PATTERN.match(line)
if match:
return f"{match.group('path')}:{match.group('line')}: {match.group('message')}"

return None


def normalize_console_output(output: str) -> str:
normalized = ANSI_PATTERN.sub("", output)
marker_index = normalized.rfind(REPORT_MARKER)
if marker_index == -1:
raise RuntimeError(f"Console output does not contain '{REPORT_MARKER}'")

normalized = normalized[marker_index:]
normalized = SHA_PATTERN.sub(r"\1<SHA>\2", normalized)
normalized = normalized.replace("\r\n", "\n").replace("\r", "\n")

lines: list[str] = []
for original_line in normalized.split("\n"):
original_line = LOG_PREFIX_PATTERN.sub("", original_line)
for line in _split_inline_result_label(original_line.strip()):
if not line:
continue

if line == REPORT_MARKER or line in RESULT_LABELS:
lines.append(line)
continue

issue_line = _canonical_issue_line(line)
if issue_line is not None:
lines.append(issue_line)

return "\n".join(lines).strip() + "\n"


def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--log", required=True)
parser.add_argument("--fixture", required=True)
return parser.parse_args()


def main() -> int:
args = parse_args()
actual = normalize_console_output(Path(args.log).read_text(encoding="utf-8"))
expected = normalize_console_output(Path(args.fixture).read_text(encoding="utf-8"))

if actual == expected:
print(f"Console output matches fixture: {args.fixture}")
return 0

diff = difflib.unified_diff(
expected.splitlines(),
actual.splitlines(),
fromfile=args.fixture,
tofile=args.log,
lineterm="",
)
print("\n".join(diff))
return 1


if __name__ == "__main__":
sys.exit(main())
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
##[error] Issues found!
PyLint results:
source.py:42: E0001: Parsing failed: 'Missing parentheses in call to 'print'. Did you mean print(...)? (source, line 42)' (syntax-error)
local.py:31: C0301: Line too long (182/100) (line-too-long)
local.py:1: C0114: Missing module docstring (missing-module-docstring)
local.py:1: C0116: Missing function or method docstring (missing-function-docstring)
local.py:1: W0621: Redefining name 'patch' from outer scope (line 29) (redefined-outer-name)
local.py:29: C0103: Constant name "patch" doesn't conform to UPPER_CASE naming style (invalid-name)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
##[error] Issues found!
cppcheck results:
/github/workspace/source.cpp:9: warning: Class 'Example' does not have a copy constructor which is recommended since it has dynamic memory/resource allocation(s). [noCopyConstructor]
/github/workspace/source.cpp:9: warning: Class 'Example' does not have a operator= which is recommended since it has dynamic memory/resource allocation(s). [noOperatorEq]
/github/workspace/source.cpp:36: error: Null pointer dereference: ptr [nullPointer]
/github/workspace/source.cpp:35: note: Assignment 'ptr=nullptr', assigned value is 0
/github/workspace/source.cpp:36: note: Null pointer dereference
/github/workspace/source.cpp:35: style: Variable 'ptr' can be declared as pointer to const [constVariablePointer]
/github/workspace/source.cpp:39: error: Out of bounds access in expression 'vec[10]' because 'vec' is empty. [containerOutOfBounds]
/github/workspace/source.cpp:41: style: Unused variable: unusedvec [unusedVariable]
clang-tidy results:
/github/workspace/another_source.cpp:1: error: function 'do_nothing' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage,-warnings-as-errors]
/github/workspace/source.cpp:2: error: included header string is not used directly [misc-include-cleaner,-warnings-as-errors]
/github/workspace/source.cpp:5: error: class 'Example' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions,hicpp-special-member-functions,-warnings-as-errors]
/github/workspace/source.cpp:9: error: 42 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers,-warnings-as-errors]
/github/workspace/source.cpp:11: error: parameter name 'p' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:21: error: function 'divide' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage,-warnings-as-errors]
/github/workspace/source.cpp:21: error: parameter name 'a' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:21: error: parameter name 'b' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:23: error: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]
/github/workspace/source.cpp:30: error: variable 'ex' of type 'Example' can be declared 'const' [misc-const-correctness,-warnings-as-errors]
/github/workspace/source.cpp:30: error: variable name 'ex' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:31: error: variable 'x' of type 'int' can be declared 'const' [misc-const-correctness,-warnings-as-errors]
/github/workspace/source.cpp:31: error: variable name 'x' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:31: error: 10 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers,-warnings-as-errors]
/github/workspace/source.cpp:32: error: variable 'y' of type 'int' can be declared 'const' [misc-const-correctness,-warnings-as-errors]
/github/workspace/source.cpp:32: error: variable name 'y' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:33: error: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]
/github/workspace/source.cpp:36: error: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]
/github/workspace/source.cpp:39: error: 10 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers,-warnings-as-errors]
/github/workspace/source.cpp:39: error: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]
/github/workspace/source.cpp:41: error: variable 'unusedvec' of type 'std::vector<int>' can be declared 'const' [misc-const-correctness,-warnings-as-errors]
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
##[error] Issues found!
cppcheck results:
/github/workspace/source.cpp:9: warning: Class 'Example' does not have a copy constructor which is recommended since it has dynamic memory/resource allocation(s). [noCopyConstructor]
/github/workspace/source.cpp:9: warning: Class 'Example' does not have a operator= which is recommended since it has dynamic memory/resource allocation(s). [noOperatorEq]
/github/workspace/source.cpp:36: error: Null pointer dereference: ptr [nullPointer]
/github/workspace/source.cpp:35: note: Assignment 'ptr=nullptr', assigned value is 0
/github/workspace/source.cpp:36: note: Null pointer dereference
/github/workspace/source.cpp:35: style: Variable 'ptr' can be declared as pointer to const [constVariablePointer]
/github/workspace/source.cpp:39: error: Out of bounds access in expression 'vec[10]' because 'vec' is empty. [containerOutOfBounds]
/github/workspace/source.cpp:41: style: Unused variable: unusedvec [unusedVariable]
clang-tidy results:
/github/workspace/another_source.cpp:1: error: function 'do_nothing' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage,-warnings-as-errors]
/github/workspace/source.cpp:2: error: included header string is not used directly [misc-include-cleaner,-warnings-as-errors]
/github/workspace/source.cpp:5: error: class 'Example' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions,hicpp-special-member-functions,-warnings-as-errors]
/github/workspace/source.cpp:9: error: 42 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers,-warnings-as-errors]
/github/workspace/source.cpp:11: error: parameter name 'p' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:21: error: function 'divide' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage,-warnings-as-errors]
/github/workspace/source.cpp:21: error: parameter name 'a' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:21: error: parameter name 'b' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:23: error: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]
/github/workspace/source.cpp:30: error: variable 'ex' of type 'Example' can be declared 'const' [misc-const-correctness,-warnings-as-errors]
/github/workspace/source.cpp:30: error: variable name 'ex' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:31: error: variable 'x' of type 'int' can be declared 'const' [misc-const-correctness,-warnings-as-errors]
/github/workspace/source.cpp:31: error: variable name 'x' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:31: error: 10 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers,-warnings-as-errors]
/github/workspace/source.cpp:32: error: variable 'y' of type 'int' can be declared 'const' [misc-const-correctness,-warnings-as-errors]
/github/workspace/source.cpp:32: error: variable name 'y' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
/github/workspace/source.cpp:33: error: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]
/github/workspace/source.cpp:36: error: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]
/github/workspace/source.cpp:39: error: 10 is a magic number; consider replacing it with a named constant [cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers,-warnings-as-errors]
/github/workspace/source.cpp:39: error: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl,-warnings-as-errors]
/github/workspace/source.cpp:41: error: variable 'unusedvec' of type 'std::vector<int>' can be declared 'const' [misc-const-correctness,-warnings-as-errors]
Loading
Loading