summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorTrevor Gamblin <tgamblin@baylibre.com>2023-10-26 10:07:46 -0400
committerSteve Sakoman <steve@sakoman.com>2023-11-24 05:01:37 -1000
commitf575a3bdd5f68097292ea4c8a193b4cf8dbaf674 (patch)
tree8a04c7b534070f9e9bcf1f541a7373b5a16ac858 /meta
parent5f1c17d70cb6f4c16218827070e3d940d530c28c (diff)
downloadpoky-f575a3bdd5f68097292ea4c8a193b4cf8dbaf674.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: 497e128546b37d6cf5fb86188fff4c7a22526ec8) Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> (cherry picked from commit f788592da2fd0e21638ce2c3326675a060ba51cf) Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta')
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.1.fail (renamed from meta/lib/patchtest/selftest/files/Author.test_author_valid.1.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.1.pass (renamed from meta/lib/patchtest/selftest/files/Author.test_author_valid.1.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.2.fail (renamed from meta/lib/patchtest/selftest/files/Author.test_author_valid.2.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.2.pass (renamed from meta/lib/patchtest/selftest/files/Author.test_author_valid.2.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_bugzilla_entry_format.fail (renamed from meta/lib/patchtest/selftest/files/Bugzilla.test_bugzilla_entry_format.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_bugzilla_entry_format.pass (renamed from meta/lib/patchtest/selftest/files/Bugzilla.test_bugzilla_entry_format.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_commit_message_presence.fail (renamed from meta/lib/patchtest/selftest/files/CommitMessage.test_commit_message_presence.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_commit_message_presence.pass (renamed from meta/lib/patchtest/selftest/files/CommitMessage.test_commit_message_presence.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_cve_presence_in_commit_message.fail (renamed from meta/lib/patchtest/selftest/files/CVE.test_cve_presence_in_commit_message.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_cve_presence_in_commit_message.pass (renamed from meta/lib/patchtest/selftest/files/CVE.test_cve_presence_in_commit_message.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_mbox_format.1.fail (renamed from meta/lib/patchtest/selftest/files/MboxFormat.test_mbox_format.1.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_mbox_format.2.fail (renamed from meta/lib/patchtest/selftest/files/MboxFormat.test_mbox_format.2.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_mbox_format.pass (renamed from meta/lib/patchtest/selftest/files/MboxFormat.test_mbox_format.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_series_merge_on_head.1.skip (renamed from meta/lib/patchtest/selftest/files/Merge.test_series_merge_on_head.1.skip)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_series_merge_on_head.2.skip (renamed from meta/lib/patchtest/selftest/files/Merge.test_series_merge_on_head.2.skip)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_format.fail (renamed from meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_format.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_format.pass (renamed from meta/lib/patchtest/selftest/files/CVE.test_cve_tag_format.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_length.fail (renamed from meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_length.fail)2
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_length.pass (renamed from meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_format.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_signed_off_by_presence.1.fail (renamed from meta/lib/patchtest/selftest/files/SignedOffBy.test_signed_off_by_presence.1.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_signed_off_by_presence.2.fail (renamed from meta/lib/patchtest/selftest/files/SignedOffBy.test_signed_off_by_presence.2.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMbox.test_signed_off_by_presence.pass (renamed from meta/lib/patchtest/selftest/files/PatchSignedOffBy.test_signed_off_by_presence.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_modified_not_mentioned.fail (renamed from meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_modified_not_mentioned.pass (renamed from meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_presence.fail (renamed from meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_presence.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_presence.pass (renamed from meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_presence.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMetadata.test_src_uri_left_files.fail (renamed from meta/lib/patchtest/selftest/files/SrcUri.test_src_uri_left_files.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMetadata.test_src_uri_left_files.pass (renamed from meta/lib/patchtest/selftest/files/SrcUri.test_src_uri_left_files.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMetadata.test_summary_presence.fail (renamed from meta/lib/patchtest/selftest/files/Summary.test_summary_presence.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestMetadata.test_summary_presence.pass (renamed from meta/lib/patchtest/selftest/files/Summary.test_summary_presence.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestPatch.test_cve_tag_format.fail (renamed from meta/lib/patchtest/selftest/files/CVE.test_cve_tag_format.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestPatch.test_cve_tag_format.pass (renamed from meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_length.pass)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestPatch.test_signed_off_by_presence.fail (renamed from meta/lib/patchtest/selftest/files/PatchSignedOffBy.test_signed_off_by_presence.fail)0
-rw-r--r--meta/lib/patchtest/selftest/files/TestPatch.test_signed_off_by_presence.pass (renamed from meta/lib/patchtest/selftest/files/SignedOffBy.test_signed_off_by_presence.pass)0
-rw-r--r--meta/lib/patchtest/tests/test_mbox.py183
-rw-r--r--meta/lib/patchtest/tests/test_mbox_author.py29
-rw-r--r--meta/lib/patchtest/tests/test_mbox_bugzilla.py20
-rw-r--r--meta/lib/patchtest/tests/test_mbox_cve.py38
-rw-r--r--meta/lib/patchtest/tests/test_mbox_description.py15
-rw-r--r--meta/lib/patchtest/tests/test_mbox_format.py14
-rw-r--r--meta/lib/patchtest/tests/test_mbox_mailinglist.py62
-rw-r--r--meta/lib/patchtest/tests/test_mbox_merge.py27
-rw-r--r--meta/lib/patchtest/tests/test_mbox_shortlog.py39
-rw-r--r--meta/lib/patchtest/tests/test_mbox_signed_off_by.py27
-rw-r--r--meta/lib/patchtest/tests/test_metadata.py204
-rw-r--r--meta/lib/patchtest/tests/test_metadata_lic_files_chksum.py74
-rw-r--r--meta/lib/patchtest/tests/test_metadata_license.py50
-rw-r--r--meta/lib/patchtest/tests/test_metadata_max_length.py25
-rw-r--r--meta/lib/patchtest/tests/test_metadata_src_uri.py73
-rw-r--r--meta/lib/patchtest/tests/test_metadata_summary.py26
-rw-r--r--meta/lib/patchtest/tests/test_patch.py (renamed from meta/lib/patchtest/tests/test_patch_upstream_status.py)53
-rw-r--r--meta/lib/patchtest/tests/test_patch_cve.py37
-rw-r--r--meta/lib/patchtest/tests/test_patch_signed_off_by.py41
53 files changed, 436 insertions, 603 deletions
diff --git a/meta/lib/patchtest/selftest/files/Author.test_author_valid.1.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.1.fail
index 0c40cdc1b6..0c40cdc1b6 100644
--- a/meta/lib/patchtest/selftest/files/Author.test_author_valid.1.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.1.fail
diff --git a/meta/lib/patchtest/selftest/files/Author.test_author_valid.1.pass b/meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.1.pass
index cbb8ef2cef..cbb8ef2cef 100644
--- a/meta/lib/patchtest/selftest/files/Author.test_author_valid.1.pass
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.1.pass
diff --git a/meta/lib/patchtest/selftest/files/Author.test_author_valid.2.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.2.fail
index 3e2b81bca1..3e2b81bca1 100644
--- a/meta/lib/patchtest/selftest/files/Author.test_author_valid.2.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.2.fail
diff --git a/meta/lib/patchtest/selftest/files/Author.test_author_valid.2.pass b/meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.2.pass
index f84e1265a7..f84e1265a7 100644
--- a/meta/lib/patchtest/selftest/files/Author.test_author_valid.2.pass
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_author_valid.2.pass
diff --git a/meta/lib/patchtest/selftest/files/Bugzilla.test_bugzilla_entry_format.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_bugzilla_entry_format.fail
index 80f409e952..80f409e952 100644
--- a/meta/lib/patchtest/selftest/files/Bugzilla.test_bugzilla_entry_format.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_bugzilla_entry_format.fail
diff --git a/meta/lib/patchtest/selftest/files/Bugzilla.test_bugzilla_entry_format.pass b/meta/lib/patchtest/selftest/files/TestMbox.test_bugzilla_entry_format.pass
index 2648b03364..2648b03364 100644
--- a/meta/lib/patchtest/selftest/files/Bugzilla.test_bugzilla_entry_format.pass
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_bugzilla_entry_format.pass
diff --git a/meta/lib/patchtest/selftest/files/CommitMessage.test_commit_message_presence.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_commit_message_presence.fail
index 93ca0f9119..93ca0f9119 100644
--- a/meta/lib/patchtest/selftest/files/CommitMessage.test_commit_message_presence.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_commit_message_presence.fail
diff --git a/meta/lib/patchtest/selftest/files/CommitMessage.test_commit_message_presence.pass b/meta/lib/patchtest/selftest/files/TestMbox.test_commit_message_presence.pass
index 5e3dcbd58b..5e3dcbd58b 100644
--- a/meta/lib/patchtest/selftest/files/CommitMessage.test_commit_message_presence.pass
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_commit_message_presence.pass
diff --git a/meta/lib/patchtest/selftest/files/CVE.test_cve_presence_in_commit_message.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_cve_presence_in_commit_message.fail
index d40b8a936b..d40b8a936b 100644
--- a/meta/lib/patchtest/selftest/files/CVE.test_cve_presence_in_commit_message.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_cve_presence_in_commit_message.fail
diff --git a/meta/lib/patchtest/selftest/files/CVE.test_cve_presence_in_commit_message.pass b/meta/lib/patchtest/selftest/files/TestMbox.test_cve_presence_in_commit_message.pass
index 433c7a450a..433c7a450a 100644
--- a/meta/lib/patchtest/selftest/files/CVE.test_cve_presence_in_commit_message.pass
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_cve_presence_in_commit_message.pass
diff --git a/meta/lib/patchtest/selftest/files/MboxFormat.test_mbox_format.1.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_mbox_format.1.fail
index 9cc4aab38a..9cc4aab38a 100644
--- a/meta/lib/patchtest/selftest/files/MboxFormat.test_mbox_format.1.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_mbox_format.1.fail
diff --git a/meta/lib/patchtest/selftest/files/MboxFormat.test_mbox_format.2.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_mbox_format.2.fail
index eca1c60085..eca1c60085 100644
--- a/meta/lib/patchtest/selftest/files/MboxFormat.test_mbox_format.2.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_mbox_format.2.fail
diff --git a/meta/lib/patchtest/selftest/files/MboxFormat.test_mbox_format.pass b/meta/lib/patchtest/selftest/files/TestMbox.test_mbox_format.pass
index 33940adffc..33940adffc 100644
--- a/meta/lib/patchtest/selftest/files/MboxFormat.test_mbox_format.pass
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_mbox_format.pass
diff --git a/meta/lib/patchtest/selftest/files/Merge.test_series_merge_on_head.1.skip b/meta/lib/patchtest/selftest/files/TestMbox.test_series_merge_on_head.1.skip
index 2a72457878..2a72457878 100644
--- a/meta/lib/patchtest/selftest/files/Merge.test_series_merge_on_head.1.skip
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_series_merge_on_head.1.skip
diff --git a/meta/lib/patchtest/selftest/files/Merge.test_series_merge_on_head.2.skip b/meta/lib/patchtest/selftest/files/TestMbox.test_series_merge_on_head.2.skip
index 49bd1f8ede..49bd1f8ede 100644
--- a/meta/lib/patchtest/selftest/files/Merge.test_series_merge_on_head.2.skip
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_series_merge_on_head.2.skip
diff --git a/meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_format.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_format.fail
index cdbbc61b61..cdbbc61b61 100644
--- a/meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_format.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_format.fail
diff --git a/meta/lib/patchtest/selftest/files/CVE.test_cve_tag_format.pass b/meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_format.pass
index ef6017037c..ef6017037c 100644
--- a/meta/lib/patchtest/selftest/files/CVE.test_cve_tag_format.pass
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_format.pass
diff --git a/meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_length.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_length.fail
index 247b2a8a80..629e78540b 100644
--- a/meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_length.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_length.fail
@@ -56,7 +56,7 @@ index 547587bef4..76975a6729 100644
56 56
57-SRC_URI = "file://helloworld.c" 57-SRC_URI = "file://helloworld.c"
58+SRC_URI = "file://helloworld.c \ 58+SRC_URI = "file://helloworld.c \
59+ file://CVE-1234-56789.patch \ 59+ file://0001-Fix-CVE-1234-56789.patch \
60+ " 60+ "
61 61
62 S = "${WORKDIR}" 62 S = "${WORKDIR}"
diff --git a/meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_format.pass b/meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_length.pass
index ef6017037c..ef6017037c 100644
--- a/meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_format.pass
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_shortlog_length.pass
diff --git a/meta/lib/patchtest/selftest/files/SignedOffBy.test_signed_off_by_presence.1.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_signed_off_by_presence.1.fail
index 35d92aeed7..35d92aeed7 100644
--- a/meta/lib/patchtest/selftest/files/SignedOffBy.test_signed_off_by_presence.1.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_signed_off_by_presence.1.fail
diff --git a/meta/lib/patchtest/selftest/files/SignedOffBy.test_signed_off_by_presence.2.fail b/meta/lib/patchtest/selftest/files/TestMbox.test_signed_off_by_presence.2.fail
index 68f38dee06..68f38dee06 100644
--- a/meta/lib/patchtest/selftest/files/SignedOffBy.test_signed_off_by_presence.2.fail
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_signed_off_by_presence.2.fail
diff --git a/meta/lib/patchtest/selftest/files/PatchSignedOffBy.test_signed_off_by_presence.pass b/meta/lib/patchtest/selftest/files/TestMbox.test_signed_off_by_presence.pass
index ea34c76f0d..ea34c76f0d 100644
--- a/meta/lib/patchtest/selftest/files/PatchSignedOffBy.test_signed_off_by_presence.pass
+++ b/meta/lib/patchtest/selftest/files/TestMbox.test_signed_off_by_presence.pass
diff --git a/meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.fail b/meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_modified_not_mentioned.fail
index ab6c52c374..ab6c52c374 100644
--- a/meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.fail
+++ b/meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_modified_not_mentioned.fail
diff --git a/meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.pass b/meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_modified_not_mentioned.pass
index 99d9f144da..99d9f144da 100644
--- a/meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.pass
+++ b/meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_modified_not_mentioned.pass
diff --git a/meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_presence.fail b/meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_presence.fail
index e14d644bb2..e14d644bb2 100644
--- a/meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_presence.fail
+++ b/meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_presence.fail
diff --git a/meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_presence.pass b/meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_presence.pass
index b8da16dfe5..b8da16dfe5 100644
--- a/meta/lib/patchtest/selftest/files/LicFilesChkSum.test_lic_files_chksum_presence.pass
+++ b/meta/lib/patchtest/selftest/files/TestMetadata.test_lic_files_chksum_presence.pass
diff --git a/meta/lib/patchtest/selftest/files/SrcUri.test_src_uri_left_files.fail b/meta/lib/patchtest/selftest/files/TestMetadata.test_src_uri_left_files.fail
index 983b6e0c2b..983b6e0c2b 100644
--- a/meta/lib/patchtest/selftest/files/SrcUri.test_src_uri_left_files.fail
+++ b/meta/lib/patchtest/selftest/files/TestMetadata.test_src_uri_left_files.fail
diff --git a/meta/lib/patchtest/selftest/files/SrcUri.test_src_uri_left_files.pass b/meta/lib/patchtest/selftest/files/TestMetadata.test_src_uri_left_files.pass
index 1f1a77e581..1f1a77e581 100644
--- a/meta/lib/patchtest/selftest/files/SrcUri.test_src_uri_left_files.pass
+++ b/meta/lib/patchtest/selftest/files/TestMetadata.test_src_uri_left_files.pass
diff --git a/meta/lib/patchtest/selftest/files/Summary.test_summary_presence.fail b/meta/lib/patchtest/selftest/files/TestMetadata.test_summary_presence.fail
index 2d2b4e683d..2d2b4e683d 100644
--- a/meta/lib/patchtest/selftest/files/Summary.test_summary_presence.fail
+++ b/meta/lib/patchtest/selftest/files/TestMetadata.test_summary_presence.fail
diff --git a/meta/lib/patchtest/selftest/files/Summary.test_summary_presence.pass b/meta/lib/patchtest/selftest/files/TestMetadata.test_summary_presence.pass
index 55f0309b3f..55f0309b3f 100644
--- a/meta/lib/patchtest/selftest/files/Summary.test_summary_presence.pass
+++ b/meta/lib/patchtest/selftest/files/TestMetadata.test_summary_presence.pass
diff --git a/meta/lib/patchtest/selftest/files/CVE.test_cve_tag_format.fail b/meta/lib/patchtest/selftest/files/TestPatch.test_cve_tag_format.fail
index c763a7506e..c763a7506e 100644
--- a/meta/lib/patchtest/selftest/files/CVE.test_cve_tag_format.fail
+++ b/meta/lib/patchtest/selftest/files/TestPatch.test_cve_tag_format.fail
diff --git a/meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_length.pass b/meta/lib/patchtest/selftest/files/TestPatch.test_cve_tag_format.pass
index ef6017037c..ef6017037c 100644
--- a/meta/lib/patchtest/selftest/files/Shortlog.test_shortlog_length.pass
+++ b/meta/lib/patchtest/selftest/files/TestPatch.test_cve_tag_format.pass
diff --git a/meta/lib/patchtest/selftest/files/PatchSignedOffBy.test_signed_off_by_presence.fail b/meta/lib/patchtest/selftest/files/TestPatch.test_signed_off_by_presence.fail
index ce8bf7b7d1..ce8bf7b7d1 100644
--- a/meta/lib/patchtest/selftest/files/PatchSignedOffBy.test_signed_off_by_presence.fail
+++ b/meta/lib/patchtest/selftest/files/TestPatch.test_signed_off_by_presence.fail
diff --git a/meta/lib/patchtest/selftest/files/SignedOffBy.test_signed_off_by_presence.pass b/meta/lib/patchtest/selftest/files/TestPatch.test_signed_off_by_presence.pass
index ea34c76f0d..ea34c76f0d 100644
--- a/meta/lib/patchtest/selftest/files/SignedOffBy.test_signed_off_by_presence.pass
+++ b/meta/lib/patchtest/selftest/files/TestPatch.test_signed_off_by_presence.pass
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
7import base
8import collections
9import parse_cve_tags
10import parse_shortlog
11import parse_signed_off_by
12import pyparsing
13import subprocess
14from data import PatchTestInput
15
16def 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
24class 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)
diff --git a/meta/lib/patchtest/tests/test_mbox_author.py b/meta/lib/patchtest/tests/test_mbox_author.py
deleted file mode 100644
index 74bc441250..0000000000
--- a/meta/lib/patchtest/tests/test_mbox_author.py
+++ /dev/null
@@ -1,29 +0,0 @@
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
7import base
8import pyparsing
9
10class Author(base.Base):
11
12 auh_email = 'auh@auh.yoctoproject.org'
13
14 invalids = [pyparsing.Regex("^Upgrade Helper.+"),
15 pyparsing.Regex(auh_email),
16 pyparsing.Regex("uh@not\.set"),
17 pyparsing.Regex("\S+@example\.com")]
18
19
20 def test_author_valid(self):
21 for commit in self.commits:
22 for invalid in self.invalids:
23 if invalid.search_string(commit.author):
24 self.fail('Invalid author %s. Resend the series with a valid patch author' % commit.author, commit=commit)
25
26 def test_non_auh_upgrade(self):
27 for commit in self.commits:
28 if self.auh_email in commit.payload:
29 self.fail('Invalid author %s. Resend the series with a valid patch author' % self.auh_email, commit=commit)
diff --git a/meta/lib/patchtest/tests/test_mbox_bugzilla.py b/meta/lib/patchtest/tests/test_mbox_bugzilla.py
deleted file mode 100644
index 99b529b755..0000000000
--- a/meta/lib/patchtest/tests/test_mbox_bugzilla.py
+++ /dev/null
@@ -1,20 +0,0 @@
1# Checks related to the patch's bugzilla tag
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import pyparsing
8import base
9
10class Bugzilla(base.Base):
11 rexp_detect = pyparsing.Regex('\[\s?YOCTO.*\]')
12 rexp_validation = pyparsing.Regex('\[(\s?YOCTO\s?#\s?(\d+)\s?,?)+\]')
13
14 def test_bugzilla_entry_format(self):
15 for commit in Bugzilla.commits:
16 if not self.rexp_detect.search_string(commit.commit_message):
17 self.skip("No bug ID found")
18 elif not self.rexp_validation.search_string(commit.commit_message):
19 self.fail('Bugzilla issue ID is not correctly formatted - specify it with format: "[YOCTO #<bugzilla ID>]"', commit=commit)
20
diff --git a/meta/lib/patchtest/tests/test_mbox_cve.py b/meta/lib/patchtest/tests/test_mbox_cve.py
deleted file mode 100644
index 29ab12cbb5..0000000000
--- a/meta/lib/patchtest/tests/test_mbox_cve.py
+++ /dev/null
@@ -1,38 +0,0 @@
1# Checks related to the patch's CVE lines
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6#
7
8import base
9import parse_cve_tags
10import pyparsing
11
12class CVE(base.Base):
13
14 revert_shortlog_regex = pyparsing.Regex('Revert\s+".*"')
15 prog = parse_cve_tags.cve_tag
16 patch_prog = parse_cve_tags.patch_cve_tag
17
18 def setUp(self):
19 if self.unidiff_parse_error:
20 self.skip('Parse error %s' % self.unidiff_parse_error)
21
22 # we are just interested in series that introduce CVE patches, thus discard other
23 # possibilities: modification to current CVEs, patch directly introduced into the
24 # recipe, upgrades already including the CVE, etc.
25 new_patches = [p for p in self.patchset if p.path.endswith('.patch') and p.is_added_file]
26 if not new_patches:
27 self.skip('No new patches introduced')
28
29 def test_cve_presence_in_commit_message(self):
30 for commit in CVE.commits:
31 # skip those patches that revert older commits, these do not required the tag presence
32 if self.revert_shortlog_regex.search_string(commit.shortlog):
33 continue
34 if not self.patch_prog.search_string(commit.payload):
35 self.skip("No CVE tag in added patch, so not needed in mbox")
36 elif not self.prog.search_string(commit.payload):
37 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"',
38 commit=commit)
diff --git a/meta/lib/patchtest/tests/test_mbox_description.py b/meta/lib/patchtest/tests/test_mbox_description.py
deleted file mode 100644
index 7874f9d038..0000000000
--- a/meta/lib/patchtest/tests/test_mbox_description.py
+++ /dev/null
@@ -1,15 +0,0 @@
1# Checks related to the patch's commit_message
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8
9class CommitMessage(base.Base):
10
11 def test_commit_message_presence(self):
12 for commit in CommitMessage.commits:
13 if not commit.commit_message.strip():
14 self.fail('Mbox is missing a descriptive commit message. Please include a commit message on your patch explaining the change', commit=commit)
15
diff --git a/meta/lib/patchtest/tests/test_mbox_format.py b/meta/lib/patchtest/tests/test_mbox_format.py
deleted file mode 100644
index fea3793e2e..0000000000
--- a/meta/lib/patchtest/tests/test_mbox_format.py
+++ /dev/null
@@ -1,14 +0,0 @@
1# Checks correct parsing of mboxes
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8
9class MboxFormat(base.Base):
10
11 def test_mbox_format(self):
12 if self.unidiff_parse_error:
13 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',
14 data=[('Diff line',self.unidiff_parse_error)])
diff --git a/meta/lib/patchtest/tests/test_mbox_mailinglist.py b/meta/lib/patchtest/tests/test_mbox_mailinglist.py
deleted file mode 100644
index feff436089..0000000000
--- a/meta/lib/patchtest/tests/test_mbox_mailinglist.py
+++ /dev/null
@@ -1,62 +0,0 @@
1# Check if the series was intended for other project (not OE-Core)
2#
3# Copyright (C) 2017 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import collections
8import base
9import pyparsing
10from data import PatchTestInput
11
12class MailingList(base.Base):
13
14 # base paths of main yocto project sub-projects
15 paths = {
16 'oe-core': ['meta-selftest', 'meta-skeleton', 'meta', 'scripts'],
17 'bitbake': ['bitbake'],
18 'documentation': ['documentation'],
19 'poky': ['meta-poky','meta-yocto-bsp'],
20 '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']
21 }
22
23 # scripts folder is a mix of oe-core and poky, most is oe-core code except:
24 poky_scripts = ['scripts/yocto-bsp', 'scripts/yocto-kernel', 'scripts/yocto-layer', 'scripts/lib/bsp']
25
26 Project = collections.namedtuple('Project', ['name', 'listemail', 'gitrepo', 'paths'])
27
28 bitbake = Project(name='Bitbake', listemail='bitbake-devel@lists.openembedded.org', gitrepo='http://git.openembedded.org/bitbake/', paths=paths['bitbake'])
29 doc = Project(name='Documentantion', listemail='yocto@yoctoproject.org', gitrepo='http://git.yoctoproject.org/cgit/cgit.cgi/yocto-docs/', paths=paths['documentation'])
30 poky = Project(name='Poky', listemail='poky@yoctoproject.org', gitrepo='http://git.yoctoproject.org/cgit/cgit.cgi/poky/', paths=paths['poky'])
31 oe = Project(name='oe', listemail='openembedded-devel@lists.openembedded.org', gitrepo='http://git.openembedded.org/meta-openembedded/', paths=paths['oe'])
32
33
34 def test_target_mailing_list(self):
35 """In case of merge failure, check for other targeted projects"""
36 if PatchTestInput.repo.ismerged:
37 self.skip('Series merged, no reason to check other mailing lists')
38
39 # a meta project may be indicted in the message subject, if this is the case, just fail
40 # TODO: there may be other project with no-meta prefix, we also need to detect these
41 project_regex = pyparsing.Regex("\[(?P<project>meta-.+)\]")
42 for commit in MailingList.commits:
43 match = project_regex.search_string(commit.subject)
44 if match:
45 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'),
46 commit=commit)
47
48 for patch in self.patchset:
49 folders = patch.path.split('/')
50 base_path = folders[0]
51 for project in [self.bitbake, self.doc, self.oe, self.poky]:
52 if base_path in project.paths:
53 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)',
54 data=[('Suggested ML', '%s [%s]' % (project.listemail, project.gitrepo)),
55 ('Patch\'s path:', patch.path)])
56
57 # check for poky's scripts code
58 if base_path.startswith('scripts'):
59 for poky_file in self.poky_scripts:
60 if patch.path.startswith(poky_file):
61 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)',
62 data=[('Suggested ML', '%s [%s]' % (self.poky.listemail, self.poky.gitrepo)),('Patch\'s path:', patch.path)])
diff --git a/meta/lib/patchtest/tests/test_mbox_merge.py b/meta/lib/patchtest/tests/test_mbox_merge.py
deleted file mode 100644
index 535026209f..0000000000
--- a/meta/lib/patchtest/tests/test_mbox_merge.py
+++ /dev/null
@@ -1,27 +0,0 @@
1# Check if mbox was merged by patchtest
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import subprocess
8import base
9from data import PatchTestInput
10
11def headlog():
12 output = subprocess.check_output(
13 "cd %s; git log --pretty='%%h#%%aN#%%cD:#%%s' -1" % PatchTestInput.repodir,
14 universal_newlines=True,
15 shell=True
16 )
17 return output.split('#')
18
19class Merge(base.Base):
20 def test_series_merge_on_head(self):
21 self.skip("Merge test is disabled for now")
22 if PatchTestInput.repo.branch != "master":
23 self.skip("Skipping merge test since patch is not intended for master branch. Target detected is %s" % PatchTestInput.repo.branch)
24 if not PatchTestInput.repo.ismerged:
25 commithash, author, date, shortlog = headlog()
26 self.fail('Series does not apply on top of target branch. Rebase your series and ensure the target is correct',
27 data=[('Targeted branch', '%s (currently at %s)' % (PatchTestInput.repo.branch, commithash))])
diff --git a/meta/lib/patchtest/tests/test_mbox_shortlog.py b/meta/lib/patchtest/tests/test_mbox_shortlog.py
deleted file mode 100644
index f5dbbc7807..0000000000
--- a/meta/lib/patchtest/tests/test_mbox_shortlog.py
+++ /dev/null
@@ -1,39 +0,0 @@
1# Checks related to the patch's summary
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8import parse_shortlog
9import pyparsing
10
11maxlength = 90
12
13class Shortlog(base.Base):
14
15 def test_shortlog_format(self):
16 for commit in Shortlog.commits:
17 shortlog = commit.shortlog
18 if not shortlog.strip():
19 self.skip('Empty shortlog, no reason to execute shortlog format test')
20 else:
21 # no reason to re-check on revert shortlogs
22 if shortlog.startswith('Revert "'):
23 continue
24 try:
25 parse_shortlog.shortlog.parseString(shortlog)
26 except pyparsing.ParseException as pe:
27 self.fail('Commit shortlog (first line of commit message) should follow the format "<target>: <summary>"',
28 commit=commit)
29
30 def test_shortlog_length(self):
31 for commit in Shortlog.commits:
32 # no reason to re-check on revert shortlogs
33 shortlog = commit.shortlog
34 if shortlog.startswith('Revert "'):
35 continue
36 l = len(shortlog)
37 if l > maxlength:
38 self.fail('Edit shortlog so that it is %d characters or less (currently %d characters)' % (maxlength, l),
39 commit=commit)
diff --git a/meta/lib/patchtest/tests/test_mbox_signed_off_by.py b/meta/lib/patchtest/tests/test_mbox_signed_off_by.py
deleted file mode 100644
index f3c5770961..0000000000
--- a/meta/lib/patchtest/tests/test_mbox_signed_off_by.py
+++ /dev/null
@@ -1,27 +0,0 @@
1# Checks related to the patch's signed-off-by lines
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8import parse_signed_off_by
9import pyparsing
10
11class SignedOffBy(base.Base):
12
13 revert_shortlog_regex = pyparsing.Regex('Revert\s+".*"')
14
15 @classmethod
16 def setUpClassLocal(cls):
17 # match self.mark with no '+' preceding it
18 cls.prog = parse_signed_off_by.signed_off_by
19
20 def test_signed_off_by_presence(self):
21 for commit in SignedOffBy.commits:
22 # skip those patches that revert older commits, these do not required the tag presence
23 if self.revert_shortlog_regex.search_string(commit.shortlog):
24 continue
25 if not SignedOffBy.prog.search_string(commit.payload):
26 self.fail('Mbox is missing Signed-off-by. Add it manually or with "git commit --amend -s"',
27 commit=commit)
diff --git a/meta/lib/patchtest/tests/test_metadata.py b/meta/lib/patchtest/tests/test_metadata.py
new file mode 100644
index 0000000000..34e119174f
--- /dev/null
+++ b/meta/lib/patchtest/tests/test_metadata.py
@@ -0,0 +1,204 @@
1# Checks related to the patch's LIC_FILES_CHKSUM metadata variable
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8import os
9import pyparsing
10from data import PatchTestInput, PatchTestDataStore
11
12class TestMetadata(base.Metadata):
13 metadata_lic = 'LICENSE'
14 invalid_license = 'PATCHTESTINVALID'
15 metadata_chksum = 'LIC_FILES_CHKSUM'
16 license_var = 'LICENSE'
17 closed = 'CLOSED'
18 lictag_re = pyparsing.AtLineStart("License-Update:")
19 add_mark = pyparsing.Regex('\+ ')
20 max_length = 200
21 metadata_src_uri = 'SRC_URI'
22 md5sum = 'md5sum'
23 sha256sum = 'sha256sum'
24 git_regex = pyparsing.Regex('^git\:\/\/.*')
25 metadata_summary = 'SUMMARY'
26
27 def test_license_presence(self):
28 if not self.added:
29 self.skip('No added recipes, skipping test')
30
31 # TODO: this is a workaround so we can parse the recipe not
32 # containing the LICENSE var: add some default license instead
33 # of INVALID into auto.conf, then remove this line at the end
34 auto_conf = os.path.join(os.environ.get('BUILDDIR'), 'conf', 'auto.conf')
35 open_flag = 'w'
36 if os.path.exists(auto_conf):
37 open_flag = 'a'
38 with open(auto_conf, open_flag) as fd:
39 for pn in self.added:
40 fd.write('LICENSE ??= "%s"\n' % self.invalid_license)
41
42 no_license = False
43 for pn in self.added:
44 rd = self.tinfoil.parse_recipe(pn)
45 license = rd.getVar(self.metadata_lic)
46 if license == self.invalid_license:
47 no_license = True
48 break
49
50 # remove auto.conf line or the file itself
51 if open_flag == 'w':
52 os.remove(auto_conf)
53 else:
54 fd = open(auto_conf, 'r')
55 lines = fd.readlines()
56 fd.close()
57 with open(auto_conf, 'w') as fd:
58 fd.write(''.join(lines[:-1]))
59
60 if no_license:
61 self.fail('Recipe does not have the LICENSE field set.')
62
63 def test_lic_files_chksum_presence(self):
64 if not self.added:
65 self.skip('No added recipes, skipping test')
66
67 for pn in self.added:
68 rd = self.tinfoil.parse_recipe(pn)
69 pathname = rd.getVar('FILE')
70 # we are not interested in images
71 if '/images/' in pathname:
72 continue
73 lic_files_chksum = rd.getVar(self.metadata_chksum)
74 if rd.getVar(self.license_var) == self.closed:
75 continue
76 if not lic_files_chksum:
77 self.fail('%s is missing in newly added recipe' % self.metadata_chksum)
78
79 def pretest_lic_files_chksum_modified_not_mentioned(self):
80 if not self.modified:
81 self.skip('No modified recipes, skipping pretest')
82 # get the proper metadata values
83 for pn in self.modified:
84 rd = self.tinfoil.parse_recipe(pn)
85 pathname = rd.getVar('FILE')
86 # we are not interested in images
87 if '/images/' in pathname:
88 continue
89 PatchTestDataStore['%s-%s-%s' % (self.shortid(),self.metadata_chksum,pn)] = rd.getVar(self.metadata_chksum)
90
91 def test_lic_files_chksum_modified_not_mentioned(self):
92 if not self.modified:
93 self.skip('No modified recipes, skipping test')
94
95 # get the proper metadata values
96 for pn in self.modified:
97 rd = self.tinfoil.parse_recipe(pn)
98 pathname = rd.getVar('FILE')
99 # we are not interested in images
100 if '/images/' in pathname:
101 continue
102 PatchTestDataStore['%s-%s-%s' % (self.shortid(),self.metadata_chksum,pn)] = rd.getVar(self.metadata_chksum)
103 # compare if there were changes between pre-merge and merge
104 for pn in self.modified:
105 pretest = PatchTestDataStore['pre%s-%s-%s' % (self.shortid(),self.metadata_chksum, pn)]
106 test = PatchTestDataStore['%s-%s-%s' % (self.shortid(),self.metadata_chksum, pn)]
107
108 # TODO: this is workaround to avoid false-positives when pretest metadata is empty (not reason found yet)
109 # For more info, check bug 12284
110 if not pretest:
111 return
112
113 if pretest != test:
114 # if any patch on the series contain reference on the metadata, fail
115 for commit in self.commits:
116 if self.lictag_re.search_string(commit.commit_message):
117 break
118 else:
119 self.fail('LIC_FILES_CHKSUM changed on target %s but there is no "License-Update:" tag in commit message. Include it with a brief description' % pn,
120 data=[('Current checksum', pretest), ('New checksum', test)])
121
122 def test_max_line_length(self):
123 for patch in self.patchset:
124 # for the moment, we are just interested in metadata
125 if patch.path.endswith('.patch'):
126 continue
127 payload = str(patch)
128 for line in payload.splitlines():
129 if self.add_mark.search_string(line):
130 current_line_length = len(line[1:])
131 if current_line_length > self.max_length:
132 self.fail('Patch line too long (current length %s, maximum is %s)' % (current_line_length, self.max_length),
133 data=[('Patch', patch.path), ('Line', '%s ...' % line[0:80])])
134
135 def pretest_src_uri_left_files(self):
136 # these tests just make sense on patches that can be merged
137 if not PatchTestInput.repo.canbemerged:
138 self.skip('Patch cannot be merged')
139 if not self.modified:
140 self.skip('No modified recipes, skipping pretest')
141
142 # get the proper metadata values
143 for pn in self.modified:
144 # we are not interested in images
145 if 'core-image' in pn:
146 continue
147 rd = self.tinfoil.parse_recipe(pn)
148 PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)] = rd.getVar(self.metadata_src_uri)
149
150 def test_src_uri_left_files(self):
151 # these tests just make sense on patches that can be merged
152 if not PatchTestInput.repo.canbemerged:
153 self.skip('Patch cannot be merged')
154 if not self.modified:
155 self.skip('No modified recipes, skipping pretest')
156
157 # get the proper metadata values
158 for pn in self.modified:
159 # we are not interested in images
160 if 'core-image' in pn:
161 continue
162 rd = self.tinfoil.parse_recipe(pn)
163 PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)] = rd.getVar(self.metadata_src_uri)
164
165 for pn in self.modified:
166 pretest_src_uri = PatchTestDataStore['pre%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)].split()
167 test_src_uri = PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)].split()
168
169 pretest_files = set([os.path.basename(patch) for patch in pretest_src_uri if patch.startswith('file://')])
170 test_files = set([os.path.basename(patch) for patch in test_src_uri if patch.startswith('file://')])
171
172 # check if files were removed
173 if len(test_files) < len(pretest_files):
174
175 # get removals from patchset
176 filesremoved_from_patchset = set()
177 for patch in self.patchset:
178 if patch.is_removed_file:
179 filesremoved_from_patchset.add(os.path.basename(patch.path))
180
181 # get the deleted files from the SRC_URI
182 filesremoved_from_usr_uri = pretest_files - test_files
183
184 # finally, get those patches removed at SRC_URI and not removed from the patchset
185 # TODO: we are not taking into account renames, so test may raise false positives
186 not_removed = filesremoved_from_usr_uri - filesremoved_from_patchset
187 if not_removed:
188 self.fail('Patches not removed from tree. Remove them and amend the submitted mbox',
189 data=[('Patch', f) for f in not_removed])
190
191 def test_summary_presence(self):
192 if not self.added:
193 self.skip('No added recipes, skipping test')
194
195 for pn in self.added:
196 # we are not interested in images
197 if 'core-image' in pn:
198 continue
199 rd = self.tinfoil.parse_recipe(pn)
200 summary = rd.getVar(self.metadata_summary)
201
202 # "${PN} version ${PN}-${PR}" is the default, so fail if default
203 if summary.startswith('%s version' % pn):
204 self.fail('%s is missing in newly added recipe' % self.metadata_summary)
diff --git a/meta/lib/patchtest/tests/test_metadata_lic_files_chksum.py b/meta/lib/patchtest/tests/test_metadata_lic_files_chksum.py
deleted file mode 100644
index fa4a28c7b2..0000000000
--- a/meta/lib/patchtest/tests/test_metadata_lic_files_chksum.py
+++ /dev/null
@@ -1,74 +0,0 @@
1# Checks related to the patch's LIC_FILES_CHKSUM metadata variable
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8import pyparsing
9from data import PatchTestInput, PatchTestDataStore
10
11class LicFilesChkSum(base.Metadata):
12 metadata = 'LIC_FILES_CHKSUM'
13 license = 'LICENSE'
14 closed = 'CLOSED'
15 lictag_re = pyparsing.AtLineStart("License-Update:")
16
17 def test_lic_files_chksum_presence(self):
18 if not self.added:
19 self.skip('No added recipes, skipping test')
20
21 for pn in self.added:
22 rd = self.tinfoil.parse_recipe(pn)
23 pathname = rd.getVar('FILE')
24 # we are not interested in images
25 if '/images/' in pathname:
26 continue
27 lic_files_chksum = rd.getVar(self.metadata)
28 if rd.getVar(self.license) == self.closed:
29 continue
30 if not lic_files_chksum:
31 self.fail('%s is missing in newly added recipe' % self.metadata)
32
33 def pretest_lic_files_chksum_modified_not_mentioned(self):
34 if not self.modified:
35 self.skip('No modified recipes, skipping pretest')
36 # get the proper metadata values
37 for pn in self.modified:
38 rd = self.tinfoil.parse_recipe(pn)
39 pathname = rd.getVar('FILE')
40 # we are not interested in images
41 if '/images/' in pathname:
42 continue
43 PatchTestDataStore['%s-%s-%s' % (self.shortid(),self.metadata,pn)] = rd.getVar(self.metadata)
44
45 def test_lic_files_chksum_modified_not_mentioned(self):
46 if not self.modified:
47 self.skip('No modified recipes, skipping test')
48
49 # get the proper metadata values
50 for pn in self.modified:
51 rd = self.tinfoil.parse_recipe(pn)
52 pathname = rd.getVar('FILE')
53 # we are not interested in images
54 if '/images/' in pathname:
55 continue
56 PatchTestDataStore['%s-%s-%s' % (self.shortid(),self.metadata,pn)] = rd.getVar(self.metadata)
57 # compare if there were changes between pre-merge and merge
58 for pn in self.modified:
59 pretest = PatchTestDataStore['pre%s-%s-%s' % (self.shortid(),self.metadata, pn)]
60 test = PatchTestDataStore['%s-%s-%s' % (self.shortid(),self.metadata, pn)]
61
62 # TODO: this is workaround to avoid false-positives when pretest metadata is empty (not reason found yet)
63 # For more info, check bug 12284
64 if not pretest:
65 return
66
67 if pretest != test:
68 # if any patch on the series contain reference on the metadata, fail
69 for commit in self.commits:
70 if self.lictag_re.search_string(commit.commit_message):
71 break
72 else:
73 self.fail('LIC_FILES_CHKSUM changed on target %s but there is no "License-Update:" tag in commit message. Include it with a brief description' % pn,
74 data=[('Current checksum', pretest), ('New checksum', test)])
diff --git a/meta/lib/patchtest/tests/test_metadata_license.py b/meta/lib/patchtest/tests/test_metadata_license.py
deleted file mode 100644
index 1a7f09b747..0000000000
--- a/meta/lib/patchtest/tests/test_metadata_license.py
+++ /dev/null
@@ -1,50 +0,0 @@
1# Checks related to the patch's LIC_FILES_CHKSUM metadata variable
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8import os
9from data import PatchTestInput
10
11class License(base.Metadata):
12 metadata = 'LICENSE'
13 invalid_license = 'PATCHTESTINVALID'
14
15 def test_license_presence(self):
16 if not self.added:
17 self.skip('No added recipes, skipping test')
18
19 # TODO: this is a workaround so we can parse the recipe not
20 # containing the LICENSE var: add some default license instead
21 # of INVALID into auto.conf, then remove this line at the end
22 auto_conf = os.path.join(os.environ.get('BUILDDIR'), 'conf', 'auto.conf')
23 open_flag = 'w'
24 if os.path.exists(auto_conf):
25 open_flag = 'a'
26 with open(auto_conf, open_flag) as fd:
27 for pn in self.added:
28 fd.write('LICENSE ??= "%s"\n' % self.invalid_license)
29
30 no_license = False
31 for pn in self.added:
32 rd = self.tinfoil.parse_recipe(pn)
33 license = rd.getVar(self.metadata)
34 if license == self.invalid_license:
35 no_license = True
36 break
37
38 # remove auto.conf line or the file itself
39 if open_flag == 'w':
40 os.remove(auto_conf)
41 else:
42 fd = open(auto_conf, 'r')
43 lines = fd.readlines()
44 fd.close()
45 with open(auto_conf, 'w') as fd:
46 fd.write(''.join(lines[:-1]))
47
48 if no_license:
49 self.fail('Recipe does not have the LICENSE field set.')
50
diff --git a/meta/lib/patchtest/tests/test_metadata_max_length.py b/meta/lib/patchtest/tests/test_metadata_max_length.py
deleted file mode 100644
index 98c48ef787..0000000000
--- a/meta/lib/patchtest/tests/test_metadata_max_length.py
+++ /dev/null
@@ -1,25 +0,0 @@
1# Checks related to patch line lengths
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8import pyparsing
9
10class MaxLength(base.Base):
11 add_mark = pyparsing.Regex('\+ ')
12 max_length = 200
13
14 def test_max_line_length(self):
15 for patch in self.patchset:
16 # for the moment, we are just interested in metadata
17 if patch.path.endswith('.patch'):
18 continue
19 payload = str(patch)
20 for line in payload.splitlines():
21 if self.add_mark.search_string(line):
22 current_line_length = len(line[1:])
23 if current_line_length > self.max_length:
24 self.fail('Patch line too long (current length %s, maximum is %s)' % (current_line_length, self.max_length),
25 data=[('Patch', patch.path), ('Line', '%s ...' % line[0:80])])
diff --git a/meta/lib/patchtest/tests/test_metadata_src_uri.py b/meta/lib/patchtest/tests/test_metadata_src_uri.py
deleted file mode 100644
index 87a24ea937..0000000000
--- a/meta/lib/patchtest/tests/test_metadata_src_uri.py
+++ /dev/null
@@ -1,73 +0,0 @@
1# Checks related to the patch's SRC_URI metadata variable
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8import os
9import pyparsing
10from data import PatchTestInput, PatchTestDataStore
11
12class SrcUri(base.Metadata):
13
14 metadata = 'SRC_URI'
15 md5sum = 'md5sum'
16 sha256sum = 'sha256sum'
17 git_regex = pyparsing.Regex('^git\:\/\/.*')
18
19 def setUp(self):
20 # these tests just make sense on patches that can be merged
21 if not PatchTestInput.repo.canbemerged:
22 self.skip('Patch cannot be merged')
23
24 def pretest_src_uri_left_files(self):
25 if not self.modified:
26 self.skip('No modified recipes, skipping pretest')
27
28 # get the proper metadata values
29 for pn in self.modified:
30 # we are not interested in images
31 if 'core-image' in pn:
32 continue
33 rd = self.tinfoil.parse_recipe(pn)
34 PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata, pn)] = rd.getVar(self.metadata)
35
36 def test_src_uri_left_files(self):
37 if not self.modified:
38 self.skip('No modified recipes, skipping pretest')
39
40 # get the proper metadata values
41 for pn in self.modified:
42 # we are not interested in images
43 if 'core-image' in pn:
44 continue
45 rd = self.tinfoil.parse_recipe(pn)
46 PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata, pn)] = rd.getVar(self.metadata)
47
48 for pn in self.modified:
49 pretest_src_uri = PatchTestDataStore['pre%s-%s-%s' % (self.shortid(), self.metadata, pn)].split()
50 test_src_uri = PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata, pn)].split()
51
52 pretest_files = set([os.path.basename(patch) for patch in pretest_src_uri if patch.startswith('file://')])
53 test_files = set([os.path.basename(patch) for patch in test_src_uri if patch.startswith('file://')])
54
55 # check if files were removed
56 if len(test_files) < len(pretest_files):
57
58 # get removals from patchset
59 filesremoved_from_patchset = set()
60 for patch in self.patchset:
61 if patch.is_removed_file:
62 filesremoved_from_patchset.add(os.path.basename(patch.path))
63
64 # get the deleted files from the SRC_URI
65 filesremoved_from_usr_uri = pretest_files - test_files
66
67 # finally, get those patches removed at SRC_URI and not removed from the patchset
68 # TODO: we are not taking into account renames, so test may raise false positives
69 not_removed = filesremoved_from_usr_uri - filesremoved_from_patchset
70 if not_removed:
71 self.fail('Patches not removed from tree. Remove them and amend the submitted mbox',
72 data=[('Patch', f) for f in not_removed])
73
diff --git a/meta/lib/patchtest/tests/test_metadata_summary.py b/meta/lib/patchtest/tests/test_metadata_summary.py
deleted file mode 100644
index 170e79eb4b..0000000000
--- a/meta/lib/patchtest/tests/test_metadata_summary.py
+++ /dev/null
@@ -1,26 +0,0 @@
1# Checks related to the patch's summary metadata variable
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8from data import PatchTestInput
9
10class Summary(base.Metadata):
11 metadata = 'SUMMARY'
12
13 def test_summary_presence(self):
14 if not self.added:
15 self.skip('No added recipes, skipping test')
16
17 for pn in self.added:
18 # we are not interested in images
19 if 'core-image' in pn:
20 continue
21 rd = self.tinfoil.parse_recipe(pn)
22 summary = rd.getVar(self.metadata)
23
24 # "${PN} version ${PN}-${PR}" is the default, so fail if default
25 if summary.startswith('%s version' % pn):
26 self.fail('%s is missing in newly added recipe' % self.metadata)
diff --git a/meta/lib/patchtest/tests/test_patch_upstream_status.py b/meta/lib/patchtest/tests/test_patch.py
index a5b278304e..b6904b185f 100644
--- a/meta/lib/patchtest/tests/test_patch_upstream_status.py
+++ b/meta/lib/patchtest/tests/test_patch.py
@@ -1,15 +1,19 @@
1# Checks related to the patch's upstream-status lines 1# Checks related to the patch's CVE lines
2# 2#
3# Copyright (C) 2016 Intel Corporation 3# Copyright (C) 2016 Intel Corporation
4# 4#
5# SPDX-License-Identifier: GPL-2.0-only 5# SPDX-License-Identifier: GPL-2.0-only
6#
6 7
7import base 8import base
9import parse_signed_off_by
8import parse_upstream_status 10import parse_upstream_status
9import pyparsing 11import pyparsing
10 12
11class PatchUpstreamStatus(base.Base): 13class TestPatch(base.Base):
12 14
15 re_cve_pattern = pyparsing.Regex("CVE\-\d{4}\-\d+")
16 re_cve_payload_tag = pyparsing.Regex("\+CVE:(\s+CVE\-\d{4}\-\d+)+")
13 upstream_status_regex = pyparsing.AtLineStart("+" + "Upstream-Status") 17 upstream_status_regex = pyparsing.AtLineStart("+" + "Upstream-Status")
14 18
15 @classmethod 19 @classmethod
@@ -20,17 +24,30 @@ class PatchUpstreamStatus(base.Base):
20 if patch.path.endswith('.patch') and patch.is_added_file: 24 if patch.path.endswith('.patch') and patch.is_added_file:
21 cls.newpatches.append(patch) 25 cls.newpatches.append(patch)
22 26
27 cls.mark = str(parse_signed_off_by.signed_off_by_mark).strip('"')
28
29 # match PatchSignedOffBy.mark with '+' preceding it
30 cls.prog = parse_signed_off_by.patch_signed_off_by
31
23 def setUp(self): 32 def setUp(self):
24 if self.unidiff_parse_error: 33 if self.unidiff_parse_error:
25 self.skip('Python-unidiff parse error') 34 self.skip('Parse error %s' % self.unidiff_parse_error)
35
26 self.valid_status = ', '.join(parse_upstream_status.upstream_status_nonliteral_valid_status) 36 self.valid_status = ', '.join(parse_upstream_status.upstream_status_nonliteral_valid_status)
27 self.standard_format = 'Upstream-Status: <Valid status>' 37 self.standard_format = 'Upstream-Status: <Valid status>'
28 38
39 # we are just interested in series that introduce CVE patches, thus discard other
40 # possibilities: modification to current CVEs, patch directly introduced into the
41 # recipe, upgrades already including the CVE, etc.
42 new_cves = [p for p in self.patchset if p.path.endswith('.patch') and p.is_added_file]
43 if not new_cves:
44 self.skip('No new CVE patches introduced')
45
29 def test_upstream_status_presence_format(self): 46 def test_upstream_status_presence_format(self):
30 if not PatchUpstreamStatus.newpatches: 47 if not TestPatch.newpatches:
31 self.skip("There are no new software patches, no reason to test Upstream-Status presence/format") 48 self.skip("There are no new software patches, no reason to test Upstream-Status presence/format")
32 49
33 for newpatch in PatchUpstreamStatus.newpatches: 50 for newpatch in TestPatch.newpatches:
34 payload = newpatch.__str__() 51 payload = newpatch.__str__()
35 if not self.upstream_status_regex.search_string(payload): 52 if not self.upstream_status_regex.search_string(payload):
36 self.fail('Added patch file is missing Upstream-Status in the header. Add Upstream-Status: <Valid status> to the header', 53 self.fail('Added patch file is missing Upstream-Status in the header. Add Upstream-Status: <Valid status> to the header',
@@ -57,3 +74,29 @@ class PatchUpstreamStatus(base.Base):
57 except pyparsing.ParseException as pe: 74 except pyparsing.ParseException as pe:
58 self.fail('Upstream-Status is in incorrect format', 75 self.fail('Upstream-Status is in incorrect format',
59 data=[('Current', pe.pstr), ('Standard format', self.standard_format), ('Valid status', self.valid_status)]) 76 data=[('Current', pe.pstr), ('Standard format', self.standard_format), ('Valid status', self.valid_status)])
77
78 def test_signed_off_by_presence(self):
79 if not TestPatch.newpatches:
80 self.skip("There are no new software patches, no reason to test %s presence" % PatchSignedOffBy.mark)
81
82 for newpatch in TestPatch.newpatches:
83 payload = newpatch.__str__()
84 for line in payload.splitlines():
85 if self.patchmetadata_regex.match(line):
86 continue
87 if TestPatch.prog.search_string(payload):
88 break
89 else:
90 self.fail('A patch file has been added, but does not have a Signed-off-by tag. Sign off the added patch file (%s)' % newpatch.path)
91
92 def test_cve_tag_format(self):
93 for commit in TestPatch.commits:
94 if self.re_cve_pattern.search_string(commit.shortlog) or self.re_cve_pattern.search_string(commit.commit_message):
95 tag_found = False
96 for line in commit.payload.splitlines():
97 if self.re_cve_payload_tag.search_string(line):
98 tag_found = True
99 break
100 if not tag_found:
101 self.fail('Missing or incorrectly formatted CVE tag in patch file. Correct or include the CVE tag in the patch with format: "CVE: CVE-YYYY-XXXX"',
102 commit=commit)
diff --git a/meta/lib/patchtest/tests/test_patch_cve.py b/meta/lib/patchtest/tests/test_patch_cve.py
deleted file mode 100644
index c77848de45..0000000000
--- a/meta/lib/patchtest/tests/test_patch_cve.py
+++ /dev/null
@@ -1,37 +0,0 @@
1# Checks related to the patch's CVE lines
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6#
7
8import base
9import pyparsing
10
11class CVE(base.Base):
12
13 re_cve_pattern = pyparsing.Regex("CVE\-\d{4}\-\d+")
14 re_cve_payload_tag = pyparsing.Regex("\+CVE:(\s+CVE\-\d{4}\-\d+)+")
15
16 def setUp(self):
17 if self.unidiff_parse_error:
18 self.skip('Parse error %s' % self.unidiff_parse_error)
19
20 # we are just interested in series that introduce CVE patches, thus discard other
21 # possibilities: modification to current CVEs, patch directly introduced into the
22 # recipe, upgrades already including the CVE, etc.
23 new_cves = [p for p in self.patchset if p.path.endswith('.patch') and p.is_added_file]
24 if not new_cves:
25 self.skip('No new CVE patches introduced')
26
27 def test_cve_tag_format(self):
28 for commit in CVE.commits:
29 if self.re_cve_pattern.search_string(commit.shortlog) or self.re_cve_pattern.search_string(commit.commit_message):
30 tag_found = False
31 for line in commit.payload.splitlines():
32 if self.re_cve_payload_tag.search_string(line):
33 tag_found = True
34 break
35 if not tag_found:
36 self.fail('Missing or incorrectly formatted CVE tag in patch file. Correct or include the CVE tag in the patch with format: "CVE: CVE-YYYY-XXXX"',
37 commit=commit)
diff --git a/meta/lib/patchtest/tests/test_patch_signed_off_by.py b/meta/lib/patchtest/tests/test_patch_signed_off_by.py
deleted file mode 100644
index b091ff6f10..0000000000
--- a/meta/lib/patchtest/tests/test_patch_signed_off_by.py
+++ /dev/null
@@ -1,41 +0,0 @@
1# Checks related to the patch's signed-off-by lines
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8import parse_signed_off_by
9
10class PatchSignedOffBy(base.Base):
11
12 @classmethod
13 def setUpClassLocal(cls):
14 cls.newpatches = []
15 # get just those relevant patches: new software patches
16 for patch in cls.patchset:
17 if patch.path.endswith('.patch') and patch.is_added_file:
18 cls.newpatches.append(patch)
19
20 cls.mark = str(parse_signed_off_by.signed_off_by_mark).strip('"')
21
22 # match PatchSignedOffBy.mark with '+' preceding it
23 cls.prog = parse_signed_off_by.patch_signed_off_by
24
25 def setUp(self):
26 if self.unidiff_parse_error:
27 self.skip('Parse error %s' % self.unidiff_parse_error)
28
29 def test_signed_off_by_presence(self):
30 if not PatchSignedOffBy.newpatches:
31 self.skip("There are no new software patches, no reason to test %s presence" % PatchSignedOffBy.mark)
32
33 for newpatch in PatchSignedOffBy.newpatches:
34 payload = newpatch.__str__()
35 for line in payload.splitlines():
36 if self.patchmetadata_regex.match(line):
37 continue
38 if PatchSignedOffBy.prog.search_string(payload):
39 break
40 else:
41 self.fail('A patch file has been added, but does not have a Signed-off-by tag. Sign off the added patch file (%s)' % newpatch.path)