From 4c378fc89566a329d0974bbcfefc7405779bc919 Mon Sep 17 00:00:00 2001 From: Trevor Gamblin Date: Tue, 24 Sep 2024 07:55:01 -0400 Subject: patchtest: simplify, rename modules - simplify base.py, data.py - move some leftover regex patterns to patterns.py - remove pyparsing path logic, since this is no longer needed - rename PatchTestInput class to PatchtestParser - data.py: rename to patchtest_parser.py - patterns.py: rename to patchtest_patterns.py - move PatchTestDataStore to test_metadata.py since that's the only place it's used - remove unused logger code (From OE-Core rev: 1e971b05b036b0b1eb0bdbd9b26b54d06e74294c) Signed-off-by: Trevor Gamblin Signed-off-by: Richard Purdie --- meta/lib/patchtest/data.py | 86 ----------------------- meta/lib/patchtest/patchtest_parser.py | 78 +++++++++++++++++++++ meta/lib/patchtest/patchtest_patterns.py | 96 ++++++++++++++++++++++++++ meta/lib/patchtest/patterns.py | 89 ------------------------ meta/lib/patchtest/tests/base.py | 48 ++++++++----- meta/lib/patchtest/tests/test_mbox.py | 69 ++++++++++++------ meta/lib/patchtest/tests/test_metadata.py | 91 ++++++++++++++++-------- meta/lib/patchtest/tests/test_patch.py | 95 ++++++++++++++++--------- meta/lib/patchtest/tests/test_python_pylint.py | 3 +- 9 files changed, 377 insertions(+), 278 deletions(-) delete mode 100644 meta/lib/patchtest/data.py create mode 100644 meta/lib/patchtest/patchtest_parser.py create mode 100644 meta/lib/patchtest/patchtest_patterns.py delete mode 100644 meta/lib/patchtest/patterns.py (limited to 'meta/lib/patchtest') diff --git a/meta/lib/patchtest/data.py b/meta/lib/patchtest/data.py deleted file mode 100644 index 356259921d..0000000000 --- a/meta/lib/patchtest/data.py +++ /dev/null @@ -1,86 +0,0 @@ -# ex:ts=4:sw=4:sts=4:et -# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- -# -# patchtestdata: module used to share command line arguments between -# patchtest & test suite and a data store between test cases -# -# Copyright (C) 2016 Intel Corporation -# -# SPDX-License-Identifier: GPL-2.0-only -# -# NOTE: Strictly speaking, unit test should be isolated from outside, -# but patchtest test suites uses command line input data and -# pretest and test test cases may use the datastore defined -# on this module - -import os -import argparse -import collections -import logging - -logger=logging.getLogger('patchtest') -info=logger.info - -default_testdir = os.path.abspath(os.path.dirname(__file__) + "/tests") -default_repodir = os.path.abspath(os.path.dirname(__file__) + "/../../..") - -# Data store commonly used to share values between pre and post-merge tests -PatchTestDataStore = collections.defaultdict(str) - -class PatchTestInput(object): - """Abstract the patchtest argument parser""" - - @classmethod - def set_namespace(cls): - parser = cls.get_parser() - parser.parse_args(namespace=cls) - - @classmethod - def get_parser(cls): - parser = argparse.ArgumentParser() - - target_patch_group = parser.add_mutually_exclusive_group(required=True) - - target_patch_group.add_argument('--patch', metavar='PATCH', dest='patch_path', - help='The patch to be tested') - - target_patch_group.add_argument('--directory', metavar='DIRECTORY', dest='patch_path', - help='The directory containing patches to be tested') - - parser.add_argument('--repodir', metavar='REPO', - default=default_repodir, - help="Name of the repository where patch is merged") - - parser.add_argument('--testdir', metavar='TESTDIR', - default=default_testdir, - help="Directory where test cases are located") - - parser.add_argument('--top-level-directory', '-t', - dest='topdir', - default=None, - help="Top level directory of project (defaults to start directory)") - - parser.add_argument('--pattern', '-p', - dest='pattern', - default='test*.py', - help="Pattern to match test files") - - parser.add_argument('--base-branch', '-b', - dest='basebranch', - help="Branch name used by patchtest to branch from. By default, it uses the current one.") - - parser.add_argument('--base-commit', '-c', - dest='basecommit', - help="Commit ID used by patchtest to branch from. By default, it uses HEAD.") - - parser.add_argument('--debug', '-d', - action='store_true', - help='Enable debug output') - - parser.add_argument('--log-results', - action='store_true', - help='Enable logging to a file matching the target patch name with ".testresult" appended') - - - return parser - diff --git a/meta/lib/patchtest/patchtest_parser.py b/meta/lib/patchtest/patchtest_parser.py new file mode 100644 index 0000000000..2a11cb76c2 --- /dev/null +++ b/meta/lib/patchtest/patchtest_parser.py @@ -0,0 +1,78 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# patchtestdata: module used to share command line arguments between +# patchtest & test suite and a data store between test cases +# +# Copyright (C) 2016 Intel Corporation +# +# SPDX-License-Identifier: GPL-2.0-only +# +# NOTE: Strictly speaking, unit test should be isolated from outside, +# but patchtest test suites uses command line input data and +# pretest and test test cases may use the datastore defined +# on this module + +import os +import argparse + +default_testdir = os.path.abspath(os.path.dirname(__file__) + "/tests") +default_repodir = os.path.abspath(os.path.dirname(__file__) + "/../../..") + +class PatchtestParser(object): + """Abstract the patchtest argument parser""" + + @classmethod + def set_namespace(cls): + parser = cls.get_parser() + parser.parse_args(namespace=cls) + + @classmethod + def get_parser(cls): + parser = argparse.ArgumentParser() + + target_patch_group = parser.add_mutually_exclusive_group(required=True) + + target_patch_group.add_argument('--patch', metavar='PATCH', dest='patch_path', + help='The patch to be tested') + + target_patch_group.add_argument('--directory', metavar='DIRECTORY', dest='patch_path', + help='The directory containing patches to be tested') + + parser.add_argument('--repodir', metavar='REPO', + default=default_repodir, + help="Name of the repository where patch is merged") + + parser.add_argument('--testdir', metavar='TESTDIR', + default=default_testdir, + help="Directory where test cases are located") + + parser.add_argument('--top-level-directory', '-t', + dest='topdir', + default=None, + help="Top level directory of project (defaults to start directory)") + + parser.add_argument('--pattern', '-p', + dest='pattern', + default='test*.py', + help="Pattern to match test files") + + parser.add_argument('--base-branch', '-b', + dest='basebranch', + help="Branch name used by patchtest to branch from. By default, it uses the current one.") + + parser.add_argument('--base-commit', '-c', + dest='basecommit', + help="Commit ID used by patchtest to branch from. By default, it uses HEAD.") + + parser.add_argument('--debug', '-d', + action='store_true', + help='Enable debug output') + + parser.add_argument('--log-results', + action='store_true', + help='Enable logging to a file matching the target patch name with ".testresult" appended') + + + return parser + diff --git a/meta/lib/patchtest/patchtest_patterns.py b/meta/lib/patchtest/patchtest_patterns.py new file mode 100644 index 0000000000..8c2e192fc9 --- /dev/null +++ b/meta/lib/patchtest/patchtest_patterns.py @@ -0,0 +1,96 @@ +# common pyparsing variables +# +# Copyright (C) 2016 Intel Corporation +# +# SPDX-License-Identifier: GPL-2.0-only + +import pyparsing +import re + +# general +colon = pyparsing.Literal(":") +line_start = pyparsing.LineStart() +line_end = pyparsing.LineEnd() +lessthan = pyparsing.Literal("<") +greaterthan = pyparsing.Literal(">") +inappropriate = pyparsing.CaselessLiteral("Inappropriate") +submitted = pyparsing.CaselessLiteral("Submitted") + +# word related +nestexpr = pyparsing.nestedExpr(opener='[', closer=']') +inappropriateinfo = pyparsing.Literal("Inappropriate") + nestexpr +submittedinfo = pyparsing.Literal("Submitted") + nestexpr +word = pyparsing.Word(pyparsing.alphas) +worddot = pyparsing.Word(pyparsing.alphas+".") + +# metadata + +metadata_lic = 'LICENSE' +invalid_license = 'PATCHTESTINVALID' +metadata_chksum = 'LIC_FILES_CHKSUM' +license_var = 'LICENSE' +closed = 'CLOSED' +lictag_re = pyparsing.AtLineStart("License-Update:") +lic_chksum_added = pyparsing.AtLineStart("+" + metadata_chksum) +lic_chksum_removed = pyparsing.AtLineStart("-" + metadata_chksum) +add_mark = pyparsing.Regex('\\+ ') +patch_max_line_length = 200 +metadata_src_uri = "SRC_URI" +metadata_summary = "SUMMARY" +cve_check_ignore_var = "CVE_CHECK_IGNORE" +cve_status_var = "CVE_STATUS" +endcommit_messages_regex = re.compile( + r"\(From \w+-\w+ rev:|(?[A-Za-z0-9._%+-]+)@(?P[A-Za-z0-9.-]+)\.(?P[A-Za-z]{2,})") + +signed_off_by_prefix = pyparsing.Literal("Signed-off-by:") +signed_off_by_name = pyparsing.Regex('\S+.*(?= <)') +signed_off_by_email = lessthan + email_pattern + greaterthan +signed_off_by = pyparsing.AtLineStart(signed_off_by_prefix + signed_off_by_name + signed_off_by_email) +patch_signed_off_by = pyparsing.AtLineStart("+" + signed_off_by_prefix + signed_off_by_name + signed_off_by_email) + +# upstream-status + +upstream_status_literal_valid_status = ["Pending", "Backport", "Denied", "Inappropriate", "Submitted"] +upstream_status_nonliteral_valid_status = ["Pending", "Backport", "Denied", "Inappropriate [reason]", "Submitted [where]"] + +upstream_status_valid_status = pyparsing.Or( + [pyparsing.Literal(status) for status in upstream_status_literal_valid_status] +) + +upstream_status_prefix = pyparsing.Literal("Upstream-Status") +upstream_status = line_start + upstream_status_prefix + colon + upstream_status_valid_status +upstream_status_inappropriate_info = line_start + upstream_status_prefix + colon + inappropriateinfo +upstream_status_submitted_info = line_start + upstream_status_prefix + colon + submittedinfo diff --git a/meta/lib/patchtest/patterns.py b/meta/lib/patchtest/patterns.py deleted file mode 100644 index b703b0c8b9..0000000000 --- a/meta/lib/patchtest/patterns.py +++ /dev/null @@ -1,89 +0,0 @@ -# common pyparsing variables -# -# Copyright (C) 2016 Intel Corporation -# -# SPDX-License-Identifier: GPL-2.0-only - -import pyparsing - -# general -colon = pyparsing.Literal(":") -line_start = pyparsing.LineStart() -line_end = pyparsing.LineEnd() -lessthan = pyparsing.Literal("<") -greaterthan = pyparsing.Literal(">") -inappropriate = pyparsing.CaselessLiteral("Inappropriate") -submitted = pyparsing.CaselessLiteral("Submitted") - -# word related -nestexpr = pyparsing.nestedExpr(opener='[', closer=']') -inappropriateinfo = pyparsing.Literal("Inappropriate") + nestexpr -submittedinfo = pyparsing.Literal("Submitted") + nestexpr -word = pyparsing.Word(pyparsing.alphas) -worddot = pyparsing.Word(pyparsing.alphas+".") - -# metadata - -metadata_lic = 'LICENSE' -invalid_license = 'PATCHTESTINVALID' -metadata_chksum = 'LIC_FILES_CHKSUM' -license_var = 'LICENSE' -closed = 'CLOSED' -lictag_re = pyparsing.AtLineStart("License-Update:") -lic_chksum_added = pyparsing.AtLineStart("+" + metadata_chksum) -lic_chksum_removed = pyparsing.AtLineStart("-" + metadata_chksum) -add_mark = pyparsing.Regex('\\+ ') -patch_max_line_length = 200 -metadata_src_uri = 'SRC_URI' -metadata_summary = 'SUMMARY' -cve_check_ignore_var = 'CVE_CHECK_IGNORE' -cve_status_var = 'CVE_STATUS' - -# mbox -auh_email = 'auh@yoctoproject.org' - -invalid_submitters = [pyparsing.Regex("^Upgrade Helper.+"), - pyparsing.Regex(auh_email), - pyparsing.Regex("uh@not\.set"), - pyparsing.Regex("\S+@example\.com")] - -mbox_bugzilla = pyparsing.Regex('\[\s?YOCTO.*\]') -mbox_bugzilla_validation = pyparsing.Regex('\[(\s?YOCTO\s?#\s?(\d+)\s?,?)+\]') -mbox_revert_shortlog_regex = pyparsing.Regex('Revert\s+".*"') -mbox_shortlog_maxlength = 90 - -# patch - -cve = pyparsing.Regex("CVE\-\d{4}\-\d+") -cve_payload_tag = pyparsing.Regex("\+CVE:(\s+CVE\-\d{4}\-\d+)+") -upstream_status_regex = pyparsing.AtLineStart("+" + "Upstream-Status") - -# shortlog - -shortlog_target = pyparsing.OneOrMore(pyparsing.Word(pyparsing.printables.replace(':',''))) -shortlog_summary = pyparsing.OneOrMore(pyparsing.Word(pyparsing.printables)) -shortlog = line_start + shortlog_target + colon + shortlog_summary + line_end - -# signed-off-bys - -email_pattern = pyparsing.Regex(r"(?P[A-Za-z0-9._%+-]+)@(?P[A-Za-z0-9.-]+)\.(?P[A-Za-z]{2,})") - -signed_off_by_prefix = pyparsing.Literal("Signed-off-by:") -signed_off_by_name = pyparsing.Regex('\S+.*(?= <)') -signed_off_by_email = lessthan + email_pattern + greaterthan -signed_off_by = pyparsing.AtLineStart(signed_off_by_prefix + signed_off_by_name + signed_off_by_email) -patch_signed_off_by = pyparsing.AtLineStart("+" + signed_off_by_prefix + signed_off_by_name + signed_off_by_email) - -# upstream-status - -upstream_status_literal_valid_status = ["Pending", "Backport", "Denied", "Inappropriate", "Submitted"] -upstream_status_nonliteral_valid_status = ["Pending", "Backport", "Denied", "Inappropriate [reason]", "Submitted [where]"] - -upstream_status_valid_status = pyparsing.Or( - [pyparsing.Literal(status) for status in upstream_status_literal_valid_status] -) - -upstream_status_prefix = pyparsing.Literal("Upstream-Status") -upstream_status = line_start + upstream_status_prefix + colon + upstream_status_valid_status -upstream_status_inappropriate_info = line_start + upstream_status_prefix + colon + inappropriateinfo -upstream_status_submitted_info = line_start + upstream_status_prefix + colon + submittedinfo diff --git a/meta/lib/patchtest/tests/base.py b/meta/lib/patchtest/tests/base.py index 911addb199..919ca136bb 100644 --- a/meta/lib/patchtest/tests/base.py +++ b/meta/lib/patchtest/tests/base.py @@ -8,20 +8,23 @@ import unittest import logging import json import unidiff -from data import PatchTestInput +from patchtest_parser import PatchtestParser import mailbox +import patchtest_patterns import collections import sys import os import re -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'pyparsing')) +logger = logging.getLogger("patchtest") +debug = logger.debug +info = logger.info +warn = logger.warn +error = logger.error -logger = logging.getLogger('patchtest') -debug=logger.debug -info=logger.info -warn=logger.warn -error=logger.error +Commit = collections.namedtuple( + "Commit", ["author", "subject", "commit_message", "shortlog", "payload"] +) Commit = collections.namedtuple('Commit', ['author', 'subject', 'commit_message', 'shortlog', 'payload']) @@ -34,9 +37,6 @@ class PatchtestOEError(Exception): class Base(unittest.TestCase): # if unit test fails, fail message will throw at least the following JSON: {"id": } - endcommit_messages_regex = re.compile(r'\(From \w+-\w+ rev:|(?: "', commit=commit) @@ -73,22 +75,34 @@ class TestMbox(base.Base): if shortlog.startswith('Revert "'): continue l = len(shortlog) - if l > patterns.mbox_shortlog_maxlength: - self.fail('Edit shortlog so that it is %d characters or less (currently %d characters)' % (patterns.mbox_shortlog_maxlength, l), - commit=commit) + if l > patchtest_patterns.mbox_shortlog_maxlength: + self.fail( + "Edit shortlog so that it is %d characters or less (currently %d characters)" + % (patchtest_patterns.mbox_shortlog_maxlength, l), + commit=commit, + ) def test_series_merge_on_head(self): self.skip("Merge test is disabled for now") - if PatchTestInput.repo.patch.branch != "master": + if PatchtestParser.repo.patch.branch != "master": self.skip( "Skipping merge test since patch is not intended" " for master branch. Target detected is %s" - % PatchTestInput.repo.patch.branch + % PatchtestParser.repo.patch.branch ) - if not PatchTestInput.repo.canbemerged: + if not PatchtestParser.repo.canbemerged: commithash, author, date, shortlog = headlog() - self.fail('Series does not apply on top of target branch %s' % PatchTestInput.repo.branch, - data=[('Targeted branch', '%s (currently at %s)' % (PatchTestInput.repo.branch, commithash))]) + self.fail( + "Series does not apply on top of target branch %s" + % PatchtestParser.repo.patch.branch, + data=[ + ( + "Targeted branch", + "%s (currently at %s)" + % (PatchtestParser.repo.patch.branch, commithash), + ) + ], + ) def test_target_mailing_list(self): """Check for other targeted projects""" @@ -129,19 +143,28 @@ class TestMbox(base.Base): self.fail('Please include a commit message on your patch explaining the change', commit=commit) def test_bugzilla_entry_format(self): - for commit in TestMbox.commits: - if not patterns.mbox_bugzilla.search_string(commit.commit_message): + for commit in self.commits: + if not patchtest_patterns.mbox_bugzilla.search_string(commit.commit_message): self.skip("No bug ID found") - elif not patterns.mbox_bugzilla_validation.search_string(commit.commit_message): - self.fail('Bugzilla issue ID is not correctly formatted - specify it with format: "[YOCTO #]"', commit=commit) + elif not patchtest_patterns.mbox_bugzilla_validation.search_string( + commit.commit_message + ): + self.fail( + 'Bugzilla issue ID is not correctly formatted - specify it with format: "[YOCTO #]"', + commit=commit, + ) def test_author_valid(self): for commit in self.commits: - for invalid in patterns.invalid_submitters: + for invalid in patchtest_patterns.invalid_submitters: if invalid.search_string(commit.author): self.fail('Invalid author %s. Resend the series with a valid patch author' % commit.author, commit=commit) def test_non_auh_upgrade(self): for commit in self.commits: - if patterns.auh_email in commit.commit_message: - self.fail('Invalid author %s. Resend the series with a valid patch author' % patterns.auh_email, commit=commit) + if patchtest_patterns.auh_email in commit.commit_message: + self.fail( + "Invalid author %s. Resend the series with a valid patch author" + % patchtest_patterns.auh_email, + commit=commit, + ) diff --git a/meta/lib/patchtest/tests/test_metadata.py b/meta/lib/patchtest/tests/test_metadata.py index d7e5e187f6..2dee80b002 100644 --- a/meta/lib/patchtest/tests/test_metadata.py +++ b/meta/lib/patchtest/tests/test_metadata.py @@ -5,10 +5,14 @@ # SPDX-License-Identifier: GPL-2.0-only import base +import collections import os -import patterns +import patchtest_patterns import pyparsing -from data import PatchTestInput, PatchTestDataStore +from patchtest_parser import PatchtestParser + +# Data store commonly used to share values between pre and post-merge tests +PatchTestDataStore = collections.defaultdict(str) class TestMetadata(base.Metadata): @@ -25,13 +29,13 @@ class TestMetadata(base.Metadata): open_flag = 'a' with open(auto_conf, open_flag) as fd: for pn in self.added: - fd.write('LICENSE ??= "%s"\n' % patterns.invalid_license) + fd.write('LICENSE ??= "%s"\n' % patchtest_patterns.invalid_license) no_license = False for pn in self.added: rd = self.tinfoil.parse_recipe(pn) - license = rd.getVar(patterns.metadata_lic) - if license == patterns.invalid_license: + license = rd.getVar(patchtest_patterns.metadata_lic) + if license == patchtest_patterns.invalid_license: no_license = True break @@ -58,11 +62,13 @@ class TestMetadata(base.Metadata): # we are not interested in images if '/images/' in pathname: continue - lic_files_chksum = rd.getVar(patterns.metadata_chksum) - if rd.getVar(patterns.license_var) == patterns.closed: + lic_files_chksum = rd.getVar(patchtest_patterns.metadata_chksum) + if rd.getVar(patchtest_patterns.license_var) == patchtest_patterns.closed: continue if not lic_files_chksum: - self.fail('%s is missing in newly added recipe' % patterns.metadata_chksum) + self.fail( + "%s is missing in newly added recipe" % patchtest_patterns.metadata_chksum + ) def test_lic_files_chksum_modified_not_mentioned(self): if not self.modified: @@ -73,11 +79,13 @@ class TestMetadata(base.Metadata): if patch.path.endswith('.patch'): continue payload = str(patch) - if (patterns.lic_chksum_added.search_string(payload) or patterns.lic_chksum_removed.search_string(payload)): + if patchtest_patterns.lic_chksum_added.search_string( + payload + ) or patchtest_patterns.lic_chksum_removed.search_string(payload): # if any patch on the series contain reference on the metadata, fail for commit in self.commits: - if patterns.lictag_re.search_string(commit.commit_message): - break + if patchtest_patterns.lictag_re.search_string(commit.commit_message): + break else: self.fail('LIC_FILES_CHKSUM changed without "License-Update:" tag and description in commit message') @@ -88,16 +96,22 @@ class TestMetadata(base.Metadata): continue payload = str(patch) for line in payload.splitlines(): - if patterns.add_mark.search_string(line): + if patchtest_patterns.add_mark.search_string(line): current_line_length = len(line[1:]) - if current_line_length > patterns.patch_max_line_length: - self.fail('Patch line too long (current length %s, maximum is %s)' % (current_line_length, patterns.patch_max_line_length), - data=[('Patch', patch.path), ('Line', '%s ...' % line[0:80])]) + if current_line_length > patchtest_patterns.patch_max_line_length: + self.fail( + "Patch line too long (current length %s, maximum is %s)" + % (current_line_length, patchtest_patterns.patch_max_line_length), + data=[ + ("Patch", patch.path), + ("Line", "%s ..." % line[0:80]), + ], + ) def pretest_src_uri_left_files(self): # these tests just make sense on patches that can be merged - if not PatchTestInput.repo.canbemerged: - self.skip('Patch cannot be merged') + if not PatchtestParser.repo.canbemerged: + self.skip("Patch cannot be merged") if not self.modified: self.skip('No modified recipes, skipping pretest') @@ -107,12 +121,14 @@ class TestMetadata(base.Metadata): if 'core-image' in pn: continue rd = self.tinfoil.parse_recipe(pn) - PatchTestDataStore['%s-%s-%s' % (self.shortid(), patterns.metadata_src_uri, pn)] = rd.getVar(patterns.metadata_src_uri) + PatchTestDataStore[ + "%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn) + ] = rd.getVar(patchtest_patterns.metadata_src_uri) def test_src_uri_left_files(self): # these tests just make sense on patches that can be merged - if not PatchTestInput.repo.canbemerged: - self.skip('Patch cannot be merged') + if not PatchtestParser.repo.canbemerged: + self.skip("Patch cannot be merged") if not self.modified: self.skip('No modified recipes, skipping pretest') @@ -122,11 +138,17 @@ class TestMetadata(base.Metadata): if 'core-image' in pn: continue rd = self.tinfoil.parse_recipe(pn) - PatchTestDataStore['%s-%s-%s' % (self.shortid(), patterns.metadata_src_uri, pn)] = rd.getVar(patterns.metadata_src_uri) + PatchTestDataStore[ + "%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn) + ] = rd.getVar(patchtest_patterns.metadata_src_uri) for pn in self.modified: - pretest_src_uri = PatchTestDataStore['pre%s-%s-%s' % (self.shortid(), patterns.metadata_src_uri, pn)].split() - test_src_uri = PatchTestDataStore['%s-%s-%s' % (self.shortid(), patterns.metadata_src_uri, pn)].split() + pretest_src_uri = PatchTestDataStore[ + "pre%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn) + ].split() + test_src_uri = PatchTestDataStore[ + "%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn) + ].split() pretest_files = set([os.path.basename(patch) for patch in pretest_src_uri if patch.startswith('file://')]) test_files = set([os.path.basename(patch) for patch in test_src_uri if patch.startswith('file://')]) @@ -159,23 +181,32 @@ class TestMetadata(base.Metadata): if 'core-image' in pn: continue rd = self.tinfoil.parse_recipe(pn) - summary = rd.getVar(patterns.metadata_summary) + summary = rd.getVar(patchtest_patterns.metadata_summary) # "${PN} version ${PN}-${PR}" is the default, so fail if default - if summary.startswith('%s version' % pn): - self.fail('%s is missing in newly added recipe' % patterns.metadata_summary) + if summary.startswith("%s version" % pn): + self.fail( + "%s is missing in newly added recipe" % patchtest_patterns.metadata_summary + ) def test_cve_check_ignore(self): # Skip if we neither modified a recipe or target branches are not # Nanbield and newer. CVE_CHECK_IGNORE was first deprecated in Nanbield. - if not self.modified or PatchTestInput.repo.patch.branch == "kirkstone" or PatchTestInput.repo.patch.branch == "dunfell": - self.skip('No modified recipes or older target branch, skipping test') + if ( + not self.modified + or PatchtestParser.repo.patch.branch == "kirkstone" + or PatchtestParser.repo.patch.branch == "dunfell" + ): + self.skip("No modified recipes or older target branch, skipping test") for pn in self.modified: # we are not interested in images if 'core-image' in pn: continue rd = self.tinfoil.parse_recipe(pn) - cve_check_ignore = rd.getVar(patterns.cve_check_ignore_var) + cve_check_ignore = rd.getVar(patchtest_patterns.cve_check_ignore_var) if cve_check_ignore is not None: - self.fail('%s is deprecated and should be replaced by %s' % (patterns.cve_check_ignore_var, patterns.cve_status_var)) + self.fail( + "%s is deprecated and should be replaced by %s" + % (patchtest_patterns.cve_check_ignore_var, patchtest_patterns.cve_status_var) + ) diff --git a/meta/lib/patchtest/tests/test_patch.py b/meta/lib/patchtest/tests/test_patch.py index d856b216f0..d08b8a5019 100644 --- a/meta/lib/patchtest/tests/test_patch.py +++ b/meta/lib/patchtest/tests/test_patch.py @@ -7,7 +7,7 @@ import base import os -import patterns +import patchtest_patterns import pyparsing class TestPatch(base.Base): @@ -20,17 +20,17 @@ class TestPatch(base.Base): if patch.path.endswith('.patch') and patch.is_added_file: cls.newpatches.append(patch) - cls.mark = str(patterns.signed_off_by_prefix).strip('"') + cls.mark = str(patchtest_patterns.signed_off_by_prefix).strip('"') # match PatchSignedOffBy.mark with '+' preceding it - cls.prog = patterns.patch_signed_off_by + cls.prog = patchtest_patterns.patch_signed_off_by def setUp(self): if self.unidiff_parse_error: self.skip('Parse error %s' % self.unidiff_parse_error) - self.valid_status = ', '.join(patterns.upstream_status_nonliteral_valid_status) - self.standard_format = 'Upstream-Status: ' + self.valid_status = ", ".join(patchtest_patterns.upstream_status_nonliteral_valid_status) + self.standard_format = "Upstream-Status: " # we are just interested in series that introduce CVE patches, thus discard other # possibilities: modification to current CVEs, patch directly introduced into the @@ -45,31 +45,62 @@ class TestPatch(base.Base): for newpatch in TestPatch.newpatches: payload = newpatch.__str__() - if not patterns.upstream_status_regex.search_string(payload): - self.fail('Added patch file is missing Upstream-Status: in the commit message', - data=[('Standard format', self.standard_format), ('Valid status', self.valid_status)]) + if not patchtest_patterns.upstream_status_regex.search_string(payload): + self.fail( + "Added patch file is missing Upstream-Status: in the commit message", + data=[ + ("Standard format", self.standard_format), + ("Valid status", self.valid_status), + ], + ) for line in payload.splitlines(): - if self.patchmetadata_regex.match(line): + if patchtest_patterns.patchmetadata_regex.match(line): continue - if patterns.upstream_status_regex.search_string(line): - if patterns.inappropriate.searchString(line): - try: - patterns.upstream_status_inappropriate_info.parseString(line.lstrip('+')) - except pyparsing.ParseException as pe: - self.fail('Upstream-Status is Inappropriate, but no reason was provided', - data=[('Current', pe.pstr), ('Standard format', 'Upstream-Status: Inappropriate [reason]')]) - elif patterns.submitted.searchString(line): - try: - patterns.upstream_status_submitted_info.parseString(line.lstrip('+')) - except pyparsing.ParseException as pe: - self.fail('Upstream-Status is Submitted, but it is not mentioned where', - data=[('Current', pe.pstr), ('Standard format', 'Upstream-Status: Submitted [where]')]) - else: - try: - patterns.upstream_status.parseString(line.lstrip('+')) - except pyparsing.ParseException as pe: - self.fail('Upstream-Status is in incorrect format', - data=[('Current', pe.pstr), ('Standard format', self.standard_format), ('Valid status', self.valid_status)]) + if patchtest_patterns.upstream_status_regex.search_string(line): + if patchtest_patterns.inappropriate.searchString(line): + try: + patchtest_patterns.upstream_status_inappropriate_info.parseString( + line.lstrip("+") + ) + except pyparsing.ParseException as pe: + self.fail( + "Upstream-Status is Inappropriate, but no reason was provided", + data=[ + ("Current", pe.pstr), + ( + "Standard format", + "Upstream-Status: Inappropriate [reason]", + ), + ], + ) + elif patchtest_patterns.submitted.searchString(line): + try: + patchtest_patterns.upstream_status_submitted_info.parseString( + line.lstrip("+") + ) + except pyparsing.ParseException as pe: + self.fail( + "Upstream-Status is Submitted, but it is not mentioned where", + data=[ + ("Current", pe.pstr), + ( + "Standard format", + "Upstream-Status: Submitted [where]", + ), + ], + ) + else: + try: + patchtest_patterns.upstream_status.parseString(line.lstrip("+")) + except pyparsing.ParseException as pe: + self.fail( + "Upstream-Status is in incorrect format", + data=[ + ("Current", pe.pstr), + ("Standard format", self.standard_format), + ("Valid status", self.valid_status), + ], + ) def test_signed_off_by_presence(self): if not TestPatch.newpatches: @@ -78,7 +109,7 @@ class TestPatch(base.Base): for newpatch in TestPatch.newpatches: payload = newpatch.__str__() for line in payload.splitlines(): - if self.patchmetadata_regex.match(line): + if patchtest_patterns.patchmetadata_regex.match(line): continue if TestPatch.prog.search_string(payload): break @@ -87,10 +118,12 @@ class TestPatch(base.Base): def test_cve_tag_format(self): for commit in TestPatch.commits: - if patterns.cve.search_string(commit.shortlog) or patterns.cve.search_string(commit.commit_message): + if patchtest_patterns.cve.search_string( + commit.shortlog + ) or patchtest_patterns.cve.search_string(commit.commit_message): tag_found = False for line in commit.payload.splitlines(): - if patterns.cve_payload_tag.search_string(line): + if patchtest_patterns.cve_payload_tag.search_string(line): tag_found = True break if not tag_found: diff --git a/meta/lib/patchtest/tests/test_python_pylint.py b/meta/lib/patchtest/tests/test_python_pylint.py index b03fd6f4f6..ec9129bc79 100644 --- a/meta/lib/patchtest/tests/test_python_pylint.py +++ b/meta/lib/patchtest/tests/test_python_pylint.py @@ -5,9 +5,8 @@ # SPDX-License-Identifier: GPL-2.0-only import base -import patterns from io import StringIO -from data import PatchTestInput +from patchtest_parser import PatchtestParser from pylint.reporters.text import TextReporter import pylint.lint as lint -- cgit v1.2.3-54-g00ecf