diff options
author | Trevor Gamblin <tgamblin@baylibre.com> | 2023-10-26 10:07:46 -0400 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2023-10-26 21:11:28 +0100 |
commit | 207a5a21d38f4ed1b71aed0158ce067b57502cc7 (patch) | |
tree | 2f612a8d475ed4d4dc0f994b3ca320e5e073c10e /meta/lib/patchtest/tests/test_mbox.py | |
parent | cdee2b22e1f3b35eb77fed0d431acdf3c358ee6c (diff) | |
download | poky-207a5a21d38f4ed1b71aed0158ce067b57502cc7.tar.gz |
patchtest: simplify test directory structure
Consolidate the various mbox tests into a new TestMbox class, metadata
tests into TestMetadata, and patch tests into TestPatch. Also update the
selftest filenames to match the changes. The test contents are not
significantly changed (other than to reference the new class names).
While this doesn't improve overall readability, it does result in more
obvious categorization, and more importantly reduces the number of calls
to setup tinfoil in the tests, resulting in a roughly 25% reduction in
runtime.
Before:
[tgamblin@megalith poky]$ time ./meta/lib/patchtest/selftest/selftest
XPASS: PatchSignedOffBy.test_signed_off_by_presence (file: PatchSignedOffBy.test_signed_off_by_presence.pass)
XFAIL: Shortlog.test_shortlog_format (file: Shortlog.test_shortlog_format.fail)
XFAIL: MboxFormat.test_mbox_format (file: MboxFormat.test_mbox_format.1.fail)
XPASS: Shortlog.test_shortlog_length (file: Shortlog.test_shortlog_length.pass)
XFAIL: CommitMessage.test_commit_message_presence (file: CommitMessage.test_commit_message_presence.fail)
XFAIL: SrcUri.test_src_uri_left_files (file: SrcUri.test_src_uri_left_files.fail)
XPASS: Author.test_author_valid (file: Author.test_author_valid.1.pass)
XFAIL: LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned (file: LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.fail)
XPASS: CVE.test_cve_tag_format (file: CVE.test_cve_tag_format.pass)
XPASS: CVE.test_cve_presence_in_commit_message (file: CVE.test_cve_presence_in_commit_message.pass)
XFAIL: CVE.test_cve_tag_format (file: CVE.test_cve_tag_format.fail)
XFAIL: Author.test_author_valid (file: Author.test_author_valid.1.fail)
XFAIL: LicFilesChkSum.test_lic_files_chksum_presence (file: LicFilesChkSum.test_lic_files_chksum_presence.fail)
XSKIP: Merge.test_series_merge_on_head (file: Merge.test_series_merge_on_head.2.skip)
XPASS: MboxFormat.test_mbox_format (file: MboxFormat.test_mbox_format.pass)
XFAIL: SignedOffBy.test_signed_off_by_presence (file: SignedOffBy.test_signed_off_by_presence.1.fail)
XPASS: Shortlog.test_shortlog_format (file: Shortlog.test_shortlog_format.pass)
XFAIL: SignedOffBy.test_signed_off_by_presence (file: SignedOffBy.test_signed_off_by_presence.2.fail)
XFAIL: MboxFormat.test_mbox_format (file: MboxFormat.test_mbox_format.2.fail)
XFAIL: Summary.test_summary_presence (file: Summary.test_summary_presence.fail)
XPASS: Author.test_author_valid (file: Author.test_author_valid.2.pass)
XSKIP: Merge.test_series_merge_on_head (file: Merge.test_series_merge_on_head.1.skip)
XPASS: Bugzilla.test_bugzilla_entry_format (file: Bugzilla.test_bugzilla_entry_format.pass)
XFAIL: CVE.test_cve_presence_in_commit_message (file: CVE.test_cve_presence_in_commit_message.fail)
XPASS: SignedOffBy.test_signed_off_by_presence (file: SignedOffBy.test_signed_off_by_presence.pass)
XPASS: LicFilesChkSum.test_lic_files_chksum_presence (file: LicFilesChkSum.test_lic_files_chksum_presence.pass)
XPASS: CommitMessage.test_commit_message_presence (file: CommitMessage.test_commit_message_presence.pass)
XPASS: Summary.test_summary_presence (file: Summary.test_summary_presence.pass)
XPASS: LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned (file: LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.pass)
XFAIL: Shortlog.test_shortlog_length (file: Shortlog.test_shortlog_length.fail)
XFAIL: PatchSignedOffBy.test_signed_off_by_presence (file: PatchSignedOffBy.test_signed_off_by_presence.fail)
XFAIL: Bugzilla.test_bugzilla_entry_format (file: Bugzilla.test_bugzilla_entry_format.fail)
XPASS: SrcUri.test_src_uri_left_files (file: SrcUri.test_src_uri_left_files.pass)
XFAIL: Author.test_author_valid (file: Author.test_author_valid.2.fail)
============================================================================
Testsuite summary for patchtest
============================================================================
============================================================================
real 24m14.386s
user 1m13.599s
sys 0m21.477s
After:
[tgamblin@megalith poky]$ time ./meta/lib/patchtest/selftest/selftest
XFAIL: TestMbox.test_bugzilla_entry_format (file: TestMbox.test_bugzilla_entry_format.fail)
XPASS: TestMetadata.test_summary_presence (file: TestMetadata.test_summary_presence.pass)
XFAIL: TestMbox.test_mbox_format (file: TestMbox.test_mbox_format.1.fail)
XFAIL: TestMetadata.test_src_uri_left_files (file: TestMetadata.test_src_uri_left_files.fail)
XSKIP: TestMbox.test_series_merge_on_head (file: TestMbox.test_series_merge_on_head.2.skip)
XPASS: TestMbox.test_commit_message_presence (file: TestMbox.test_commit_message_presence.pass)
XFAIL: TestMbox.test_commit_message_presence (file: TestMbox.test_commit_message_presence.fail)
XPASS: TestMbox.test_signed_off_by_presence (file: TestMbox.test_signed_off_by_presence.pass)
XFAIL: TestPatch.test_cve_tag_format (file: TestPatch.test_cve_tag_format.fail)
XFAIL: TestMbox.test_author_valid (file: TestMbox.test_author_valid.1.fail)
XFAIL: TestMbox.test_shortlog_length (file: TestMbox.test_shortlog_length.fail)
XPASS: TestMbox.test_mbox_format (file: TestMbox.test_mbox_format.pass)
XFAIL: TestPatch.test_signed_off_by_presence (file: TestPatch.test_signed_off_by_presence.fail)
XFAIL: TestMbox.test_shortlog_format (file: TestMbox.test_shortlog_format.fail)
XFAIL: TestMbox.test_mbox_format (file: TestMbox.test_mbox_format.2.fail)
XPASS: TestPatch.test_cve_tag_format (file: TestPatch.test_cve_tag_format.pass)
XSKIP: TestMbox.test_series_merge_on_head (file: TestMbox.test_series_merge_on_head.1.skip)
XPASS: TestMbox.test_author_valid (file: TestMbox.test_author_valid.2.pass)
XPASS: TestMetadata.test_lic_files_chksum_modified_not_mentioned (file: TestMetadata.test_lic_files_chksum_modified_not_mentioned.pass)
XPASS: TestMbox.test_bugzilla_entry_format (file: TestMbox.test_bugzilla_entry_format.pass)
XPASS: TestMetadata.test_src_uri_left_files (file: TestMetadata.test_src_uri_left_files.pass)
XPASS: TestMetadata.test_lic_files_chksum_presence (file: TestMetadata.test_lic_files_chksum_presence.pass)
XPASS: TestMbox.test_cve_presence_in_commit_message (file: TestMbox.test_cve_presence_in_commit_message.pass)
XFAIL: TestMbox.test_signed_off_by_presence (file: TestMbox.test_signed_off_by_presence.2.fail)
XFAIL: TestMbox.test_author_valid (file: TestMbox.test_author_valid.2.fail)
XFAIL: TestMetadata.test_lic_files_chksum_presence (file: TestMetadata.test_lic_files_chksum_presence.fail)
XPASS: TestMbox.test_shortlog_format (file: TestMbox.test_shortlog_format.pass)
XPASS: TestMbox.test_author_valid (file: TestMbox.test_author_valid.1.pass)
XPASS: TestPatch.test_signed_off_by_presence (file: TestPatch.test_signed_off_by_presence.pass)
XFAIL: TestMetadata.test_lic_files_chksum_modified_not_mentioned (file: TestMetadata.test_lic_files_chksum_modified_not_mentioned.fail)
XPASS: TestMbox.test_shortlog_length (file: TestMbox.test_shortlog_length.pass)
XFAIL: TestMbox.test_signed_off_by_presence (file: TestMbox.test_signed_off_by_presence.1.fail)
XFAIL: TestMbox.test_cve_presence_in_commit_message (file: TestMbox.test_cve_presence_in_commit_message.fail)
XFAIL: TestMetadata.test_summary_presence (file: TestMetadata.test_summary_presence.fail)
============================================================================
Testsuite summary for patchtest
============================================================================
============================================================================
real 18m39.749s
user 0m41.857s
sys 0m14.708s
(From OE-Core rev: f788592da2fd0e21638ce2c3326675a060ba51cf)
Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/patchtest/tests/test_mbox.py')
-rw-r--r-- | meta/lib/patchtest/tests/test_mbox.py | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/meta/lib/patchtest/tests/test_mbox.py b/meta/lib/patchtest/tests/test_mbox.py new file mode 100644 index 0000000000..95002c9e2a --- /dev/null +++ b/meta/lib/patchtest/tests/test_mbox.py | |||
@@ -0,0 +1,183 @@ | |||
1 | # Checks related to the patch's author | ||
2 | # | ||
3 | # Copyright (C) 2016 Intel Corporation | ||
4 | # | ||
5 | # SPDX-License-Identifier: GPL-2.0-only | ||
6 | |||
7 | import base | ||
8 | import collections | ||
9 | import parse_cve_tags | ||
10 | import parse_shortlog | ||
11 | import parse_signed_off_by | ||
12 | import pyparsing | ||
13 | import subprocess | ||
14 | from data import PatchTestInput | ||
15 | |||
16 | def headlog(): | ||
17 | output = subprocess.check_output( | ||
18 | "cd %s; git log --pretty='%%h#%%aN#%%cD:#%%s' -1" % PatchTestInput.repodir, | ||
19 | universal_newlines=True, | ||
20 | shell=True | ||
21 | ) | ||
22 | return output.split('#') | ||
23 | |||
24 | class TestMbox(base.Base): | ||
25 | |||
26 | auh_email = 'auh@auh.yoctoproject.org' | ||
27 | |||
28 | invalids = [pyparsing.Regex("^Upgrade Helper.+"), | ||
29 | pyparsing.Regex(auh_email), | ||
30 | pyparsing.Regex("uh@not\.set"), | ||
31 | pyparsing.Regex("\S+@example\.com")] | ||
32 | |||
33 | rexp_detect = pyparsing.Regex('\[\s?YOCTO.*\]') | ||
34 | rexp_validation = pyparsing.Regex('\[(\s?YOCTO\s?#\s?(\d+)\s?,?)+\]') | ||
35 | revert_shortlog_regex = pyparsing.Regex('Revert\s+".*"') | ||
36 | prog = parse_cve_tags.cve_tag | ||
37 | patch_prog = parse_cve_tags.patch_cve_tag | ||
38 | signoff_prog = parse_signed_off_by.signed_off_by | ||
39 | revert_shortlog_regex = pyparsing.Regex('Revert\s+".*"') | ||
40 | maxlength = 90 | ||
41 | |||
42 | # base paths of main yocto project sub-projects | ||
43 | paths = { | ||
44 | 'oe-core': ['meta-selftest', 'meta-skeleton', 'meta', 'scripts'], | ||
45 | 'bitbake': ['bitbake'], | ||
46 | 'documentation': ['documentation'], | ||
47 | 'poky': ['meta-poky','meta-yocto-bsp'], | ||
48 | 'oe': ['meta-gpe', 'meta-gnome', 'meta-efl', 'meta-networking', 'meta-multimedia','meta-initramfs', 'meta-ruby', 'contrib', 'meta-xfce', 'meta-filesystems', 'meta-perl', 'meta-webserver', 'meta-systemd', 'meta-oe', 'meta-python'] | ||
49 | } | ||
50 | |||
51 | # scripts folder is a mix of oe-core and poky, most is oe-core code except: | ||
52 | poky_scripts = ['scripts/yocto-bsp', 'scripts/yocto-kernel', 'scripts/yocto-layer', 'scripts/lib/bsp'] | ||
53 | |||
54 | Project = collections.namedtuple('Project', ['name', 'listemail', 'gitrepo', 'paths']) | ||
55 | |||
56 | bitbake = Project(name='Bitbake', listemail='bitbake-devel@lists.openembedded.org', gitrepo='http://git.openembedded.org/bitbake/', paths=paths['bitbake']) | ||
57 | doc = Project(name='Documentantion', listemail='yocto@yoctoproject.org', gitrepo='http://git.yoctoproject.org/cgit/cgit.cgi/yocto-docs/', paths=paths['documentation']) | ||
58 | poky = Project(name='Poky', listemail='poky@yoctoproject.org', gitrepo='http://git.yoctoproject.org/cgit/cgit.cgi/poky/', paths=paths['poky']) | ||
59 | oe = Project(name='oe', listemail='openembedded-devel@lists.openembedded.org', gitrepo='http://git.openembedded.org/meta-openembedded/', paths=paths['oe']) | ||
60 | |||
61 | |||
62 | def test_signed_off_by_presence(self): | ||
63 | for commit in TestMbox.commits: | ||
64 | # skip those patches that revert older commits, these do not required the tag presence | ||
65 | if self.revert_shortlog_regex.search_string(commit.shortlog): | ||
66 | continue | ||
67 | if not self.signoff_prog.search_string(commit.payload): | ||
68 | self.fail('Mbox is missing Signed-off-by. Add it manually or with "git commit --amend -s"', | ||
69 | commit=commit) | ||
70 | |||
71 | def test_shortlog_format(self): | ||
72 | for commit in TestMbox.commits: | ||
73 | shortlog = commit.shortlog | ||
74 | if not shortlog.strip(): | ||
75 | self.skip('Empty shortlog, no reason to execute shortlog format test') | ||
76 | else: | ||
77 | # no reason to re-check on revert shortlogs | ||
78 | if shortlog.startswith('Revert "'): | ||
79 | continue | ||
80 | try: | ||
81 | parse_shortlog.shortlog.parseString(shortlog) | ||
82 | except pyparsing.ParseException as pe: | ||
83 | self.fail('Commit shortlog (first line of commit message) should follow the format "<target>: <summary>"', | ||
84 | commit=commit) | ||
85 | |||
86 | def test_shortlog_length(self): | ||
87 | for commit in TestMbox.commits: | ||
88 | # no reason to re-check on revert shortlogs | ||
89 | shortlog = commit.shortlog | ||
90 | if shortlog.startswith('Revert "'): | ||
91 | continue | ||
92 | l = len(shortlog) | ||
93 | if l > self.maxlength: | ||
94 | self.fail('Edit shortlog so that it is %d characters or less (currently %d characters)' % (self.maxlength, l), | ||
95 | commit=commit) | ||
96 | |||
97 | def test_series_merge_on_head(self): | ||
98 | self.skip("Merge test is disabled for now") | ||
99 | if PatchTestInput.repo.branch != "master": | ||
100 | self.skip("Skipping merge test since patch is not intended for master branch. Target detected is %s" % PatchTestInput.repo.branch) | ||
101 | if not PatchTestInput.repo.ismerged: | ||
102 | commithash, author, date, shortlog = headlog() | ||
103 | self.fail('Series does not apply on top of target branch. Rebase your series and ensure the target is correct', | ||
104 | data=[('Targeted branch', '%s (currently at %s)' % (PatchTestInput.repo.branch, commithash))]) | ||
105 | |||
106 | def test_target_mailing_list(self): | ||
107 | """In case of merge failure, check for other targeted projects""" | ||
108 | if PatchTestInput.repo.ismerged: | ||
109 | self.skip('Series merged, no reason to check other mailing lists') | ||
110 | |||
111 | # a meta project may be indicted in the message subject, if this is the case, just fail | ||
112 | # TODO: there may be other project with no-meta prefix, we also need to detect these | ||
113 | project_regex = pyparsing.Regex("\[(?P<project>meta-.+)\]") | ||
114 | for commit in TestMbox.commits: | ||
115 | match = project_regex.search_string(commit.subject) | ||
116 | if match: | ||
117 | self.fail('Series sent to the wrong mailing list. Check the project\'s README (%s) and send the patch to the indicated list' % match.group('project'), | ||
118 | commit=commit) | ||
119 | |||
120 | for patch in self.patchset: | ||
121 | folders = patch.path.split('/') | ||
122 | base_path = folders[0] | ||
123 | for project in [self.bitbake, self.doc, self.oe, self.poky]: | ||
124 | if base_path in project.paths: | ||
125 | self.fail('Series sent to the wrong mailing list or some patches from the series correspond to different mailing lists. Send the series again to the correct mailing list (ML)', | ||
126 | data=[('Suggested ML', '%s [%s]' % (project.listemail, project.gitrepo)), | ||
127 | ('Patch\'s path:', patch.path)]) | ||
128 | |||
129 | # check for poky's scripts code | ||
130 | if base_path.startswith('scripts'): | ||
131 | for poky_file in self.poky_scripts: | ||
132 | if patch.path.startswith(poky_file): | ||
133 | self.fail('Series sent to the wrong mailing list or some patches from the series correspond to different mailing lists. Send the series again to the correct mailing list (ML)', | ||
134 | data=[('Suggested ML', '%s [%s]' % (self.poky.listemail, self.poky.gitrepo)),('Patch\'s path:', patch.path)]) | ||
135 | |||
136 | def test_mbox_format(self): | ||
137 | if self.unidiff_parse_error: | ||
138 | self.fail('Series cannot be parsed correctly due to malformed diff lines. Create the series again using git-format-patch and ensure it can be applied using git am', | ||
139 | data=[('Diff line',self.unidiff_parse_error)]) | ||
140 | |||
141 | def test_commit_message_presence(self): | ||
142 | for commit in TestMbox.commits: | ||
143 | if not commit.commit_message.strip(): | ||
144 | self.fail('Mbox is missing a descriptive commit message. Please include a commit message on your patch explaining the change', commit=commit) | ||
145 | |||
146 | def test_cve_presence_in_commit_message(self): | ||
147 | if self.unidiff_parse_error: | ||
148 | self.skip('Parse error %s' % self.unidiff_parse_error) | ||
149 | |||
150 | # we are just interested in series that introduce CVE patches, thus discard other | ||
151 | # possibilities: modification to current CVEs, patch directly introduced into the | ||
152 | # recipe, upgrades already including the CVE, etc. | ||
153 | new_patches = [p for p in self.patchset if p.path.endswith('.patch') and p.is_added_file] | ||
154 | if not new_patches: | ||
155 | self.skip('No new patches introduced') | ||
156 | |||
157 | for commit in TestMbox.commits: | ||
158 | # skip those patches that revert older commits, these do not required the tag presence | ||
159 | if self.revert_shortlog_regex.search_string(commit.shortlog): | ||
160 | continue | ||
161 | if not self.patch_prog.search_string(commit.payload): | ||
162 | self.skip("No CVE tag in added patch, so not needed in mbox") | ||
163 | elif not self.prog.search_string(commit.payload): | ||
164 | self.fail('Missing or incorrectly formatted CVE tag in mbox. Correct or include the CVE tag in the mbox with format: "CVE: CVE-YYYY-XXXX"', | ||
165 | commit=commit) | ||
166 | |||
167 | def test_bugzilla_entry_format(self): | ||
168 | for commit in TestMbox.commits: | ||
169 | if not self.rexp_detect.search_string(commit.commit_message): | ||
170 | self.skip("No bug ID found") | ||
171 | elif not self.rexp_validation.search_string(commit.commit_message): | ||
172 | self.fail('Bugzilla issue ID is not correctly formatted - specify it with format: "[YOCTO #<bugzilla ID>]"', commit=commit) | ||
173 | |||
174 | def test_author_valid(self): | ||
175 | for commit in self.commits: | ||
176 | for invalid in self.invalids: | ||
177 | if invalid.search_string(commit.author): | ||
178 | self.fail('Invalid author %s. Resend the series with a valid patch author' % commit.author, commit=commit) | ||
179 | |||
180 | def test_non_auh_upgrade(self): | ||
181 | for commit in self.commits: | ||
182 | if self.auh_email in commit.payload: | ||
183 | self.fail('Invalid author %s. Resend the series with a valid patch author' % self.auh_email, commit=commit) | ||