summaryrefslogtreecommitdiffstats
path: root/meta/lib/patchtest/tests/test_patch.py
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/patchtest/tests/test_patch.py')
-rw-r--r--meta/lib/patchtest/tests/test_patch.py103
1 files changed, 103 insertions, 0 deletions
diff --git a/meta/lib/patchtest/tests/test_patch.py b/meta/lib/patchtest/tests/test_patch.py
new file mode 100644
index 0000000000..d7187a0cb1
--- /dev/null
+++ b/meta/lib/patchtest/tests/test_patch.py
@@ -0,0 +1,103 @@
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 os
10import parse_signed_off_by
11import parse_upstream_status
12import pyparsing
13
14class TestPatch(base.Base):
15
16 re_cve_pattern = pyparsing.Regex("CVE\-\d{4}\-\d+")
17 re_cve_payload_tag = pyparsing.Regex("\+CVE:(\s+CVE\-\d{4}\-\d+)+")
18 upstream_status_regex = pyparsing.AtLineStart("+" + "Upstream-Status")
19
20 @classmethod
21 def setUpClassLocal(cls):
22 cls.newpatches = []
23 # get just those relevant patches: new software patches
24 for patch in cls.patchset:
25 if patch.path.endswith('.patch') and patch.is_added_file:
26 cls.newpatches.append(patch)
27
28 cls.mark = str(parse_signed_off_by.signed_off_by_mark).strip('"')
29
30 # match PatchSignedOffBy.mark with '+' preceding it
31 cls.prog = parse_signed_off_by.patch_signed_off_by
32
33 def setUp(self):
34 if self.unidiff_parse_error:
35 self.skip('Parse error %s' % self.unidiff_parse_error)
36
37 self.valid_status = ', '.join(parse_upstream_status.upstream_status_nonliteral_valid_status)
38 self.standard_format = 'Upstream-Status: <Valid status>'
39
40 # we are just interested in series that introduce CVE patches, thus discard other
41 # possibilities: modification to current CVEs, patch directly introduced into the
42 # recipe, upgrades already including the CVE, etc.
43 new_cves = [p for p in self.patchset if p.path.endswith('.patch') and p.is_added_file]
44 if not new_cves:
45 self.skip('No new CVE patches introduced')
46
47 def test_upstream_status_presence_format(self):
48 if not TestPatch.newpatches:
49 self.skip("There are no new software patches, no reason to test Upstream-Status presence/format")
50
51 for newpatch in TestPatch.newpatches:
52 payload = newpatch.__str__()
53 if not self.upstream_status_regex.search_string(payload):
54 self.fail('Added patch file is missing Upstream-Status: <Valid status> in the commit message',
55 data=[('Standard format', self.standard_format), ('Valid status', self.valid_status)])
56 for line in payload.splitlines():
57 if self.patchmetadata_regex.match(line):
58 continue
59 if self.upstream_status_regex.search_string(line):
60 if parse_upstream_status.inappropriate_status_mark.searchString(line):
61 try:
62 parse_upstream_status.upstream_status_inappropriate_info.parseString(line.lstrip('+'))
63 except pyparsing.ParseException as pe:
64 self.fail('Upstream-Status is Inappropriate, but no reason was provided',
65 data=[('Current', pe.pstr), ('Standard format', 'Upstream-Status: Inappropriate [reason]')])
66 elif parse_upstream_status.submitted_status_mark.searchString(line):
67 try:
68 parse_upstream_status.upstream_status_submitted_info.parseString(line.lstrip('+'))
69 except pyparsing.ParseException as pe:
70 self.fail('Upstream-Status is Submitted, but it is not mentioned where',
71 data=[('Current', pe.pstr), ('Standard format', 'Upstream-Status: Submitted [where]')])
72 else:
73 try:
74 parse_upstream_status.upstream_status.parseString(line.lstrip('+'))
75 except pyparsing.ParseException as pe:
76 self.fail('Upstream-Status is in incorrect format',
77 data=[('Current', pe.pstr), ('Standard format', self.standard_format), ('Valid status', self.valid_status)])
78
79 def test_signed_off_by_presence(self):
80 if not TestPatch.newpatches:
81 self.skip("There are no new software patches, no reason to test %s presence" % PatchSignedOffBy.mark)
82
83 for newpatch in TestPatch.newpatches:
84 payload = newpatch.__str__()
85 for line in payload.splitlines():
86 if self.patchmetadata_regex.match(line):
87 continue
88 if TestPatch.prog.search_string(payload):
89 break
90 else:
91 self.fail('A patch file has been added without a Signed-off-by tag: \'%s\'' % os.path.basename(newpatch.path))
92
93 def test_cve_tag_format(self):
94 for commit in TestPatch.commits:
95 if self.re_cve_pattern.search_string(commit.shortlog) or self.re_cve_pattern.search_string(commit.commit_message):
96 tag_found = False
97 for line in commit.payload.splitlines():
98 if self.re_cve_payload_tag.search_string(line):
99 tag_found = True
100 break
101 if not tag_found:
102 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"',
103 commit=commit)