diff options
| -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.py | 183 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_mbox_author.py | 29 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_mbox_bugzilla.py | 20 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_mbox_cve.py | 38 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_mbox_description.py | 15 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_mbox_format.py | 14 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_mbox_mailinglist.py | 62 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_mbox_merge.py | 27 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_mbox_shortlog.py | 39 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_mbox_signed_off_by.py | 27 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_metadata.py | 204 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_metadata_lic_files_chksum.py | 74 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_metadata_license.py | 50 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_metadata_max_length.py | 25 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_metadata_src_uri.py | 73 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_metadata_summary.py | 26 | ||||
| -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.py | 37 | ||||
| -rw-r--r-- | meta/lib/patchtest/tests/test_patch_signed_off_by.py | 41 |
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 | |||
| 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) | ||
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 | |||
| 7 | import base | ||
| 8 | import pyparsing | ||
| 9 | |||
| 10 | class 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 | |||
| 7 | import pyparsing | ||
| 8 | import base | ||
| 9 | |||
| 10 | class 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 | |||
| 8 | import base | ||
| 9 | import parse_cve_tags | ||
| 10 | import pyparsing | ||
| 11 | |||
| 12 | class 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 | |||
| 7 | import base | ||
| 8 | |||
| 9 | class 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 | |||
| 7 | import base | ||
| 8 | |||
| 9 | class 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 | |||
| 7 | import collections | ||
| 8 | import base | ||
| 9 | import pyparsing | ||
| 10 | from data import PatchTestInput | ||
| 11 | |||
| 12 | class 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 | |||
| 7 | import subprocess | ||
| 8 | import base | ||
| 9 | from data import PatchTestInput | ||
| 10 | |||
| 11 | def 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 | |||
| 19 | class 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 | |||
| 7 | import base | ||
| 8 | import parse_shortlog | ||
| 9 | import pyparsing | ||
| 10 | |||
| 11 | maxlength = 90 | ||
| 12 | |||
| 13 | class 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 | |||
| 7 | import base | ||
| 8 | import parse_signed_off_by | ||
| 9 | import pyparsing | ||
| 10 | |||
| 11 | class 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 | |||
| 7 | import base | ||
| 8 | import os | ||
| 9 | import pyparsing | ||
| 10 | from data import PatchTestInput, PatchTestDataStore | ||
| 11 | |||
| 12 | class 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 | |||
| 7 | import base | ||
| 8 | import pyparsing | ||
| 9 | from data import PatchTestInput, PatchTestDataStore | ||
| 10 | |||
| 11 | class 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 | |||
| 7 | import base | ||
| 8 | import os | ||
| 9 | from data import PatchTestInput | ||
| 10 | |||
| 11 | class 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 | |||
| 7 | import base | ||
| 8 | import pyparsing | ||
| 9 | |||
| 10 | class 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 | |||
| 7 | import base | ||
| 8 | import os | ||
| 9 | import pyparsing | ||
| 10 | from data import PatchTestInput, PatchTestDataStore | ||
| 11 | |||
| 12 | class 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 | |||
| 7 | import base | ||
| 8 | from data import PatchTestInput | ||
| 9 | |||
| 10 | class 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 | ||
| 7 | import base | 8 | import base |
| 9 | import parse_signed_off_by | ||
| 8 | import parse_upstream_status | 10 | import parse_upstream_status |
| 9 | import pyparsing | 11 | import pyparsing |
| 10 | 12 | ||
| 11 | class PatchUpstreamStatus(base.Base): | 13 | class 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 | |||
| 8 | import base | ||
| 9 | import pyparsing | ||
| 10 | |||
| 11 | class 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 | |||
| 7 | import base | ||
| 8 | import parse_signed_off_by | ||
| 9 | |||
| 10 | class 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) | ||
