diff options
Diffstat (limited to 'meta/lib/patchtest/tests/test_metadata.py')
-rw-r--r-- | meta/lib/patchtest/tests/test_metadata.py | 107 |
1 files changed, 61 insertions, 46 deletions
diff --git a/meta/lib/patchtest/tests/test_metadata.py b/meta/lib/patchtest/tests/test_metadata.py index f5dbcf01ed..2dee80b002 100644 --- a/meta/lib/patchtest/tests/test_metadata.py +++ b/meta/lib/patchtest/tests/test_metadata.py | |||
@@ -5,28 +5,16 @@ | |||
5 | # SPDX-License-Identifier: GPL-2.0-only | 5 | # SPDX-License-Identifier: GPL-2.0-only |
6 | 6 | ||
7 | import base | 7 | import base |
8 | import collections | ||
8 | import os | 9 | import os |
10 | import patchtest_patterns | ||
9 | import pyparsing | 11 | import pyparsing |
10 | from data import PatchTestInput, PatchTestDataStore | 12 | from patchtest_parser import PatchtestParser |
13 | |||
14 | # Data store commonly used to share values between pre and post-merge tests | ||
15 | PatchTestDataStore = collections.defaultdict(str) | ||
11 | 16 | ||
12 | class TestMetadata(base.Metadata): | 17 | 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 | lic_chksum_added = pyparsing.AtLineStart("+" + metadata_chksum) | ||
20 | lic_chksum_removed = pyparsing.AtLineStart("-" + metadata_chksum) | ||
21 | add_mark = pyparsing.Regex('\\+ ') | ||
22 | max_length = 200 | ||
23 | metadata_src_uri = 'SRC_URI' | ||
24 | md5sum = 'md5sum' | ||
25 | sha256sum = 'sha256sum' | ||
26 | git_regex = pyparsing.Regex('^git\\:\\/\\/.*') | ||
27 | metadata_summary = 'SUMMARY' | ||
28 | cve_check_ignore_var = 'CVE_CHECK_IGNORE' | ||
29 | cve_status_var = 'CVE_STATUS' | ||
30 | 18 | ||
31 | def test_license_presence(self): | 19 | def test_license_presence(self): |
32 | if not self.added: | 20 | if not self.added: |
@@ -41,13 +29,13 @@ class TestMetadata(base.Metadata): | |||
41 | open_flag = 'a' | 29 | open_flag = 'a' |
42 | with open(auto_conf, open_flag) as fd: | 30 | with open(auto_conf, open_flag) as fd: |
43 | for pn in self.added: | 31 | for pn in self.added: |
44 | fd.write('LICENSE ??= "%s"\n' % self.invalid_license) | 32 | fd.write('LICENSE ??= "%s"\n' % patchtest_patterns.invalid_license) |
45 | 33 | ||
46 | no_license = False | 34 | no_license = False |
47 | for pn in self.added: | 35 | for pn in self.added: |
48 | rd = self.tinfoil.parse_recipe(pn) | 36 | rd = self.tinfoil.parse_recipe(pn) |
49 | license = rd.getVar(self.metadata_lic) | 37 | license = rd.getVar(patchtest_patterns.metadata_lic) |
50 | if license == self.invalid_license: | 38 | if license == patchtest_patterns.invalid_license: |
51 | no_license = True | 39 | no_license = True |
52 | break | 40 | break |
53 | 41 | ||
@@ -74,11 +62,13 @@ class TestMetadata(base.Metadata): | |||
74 | # we are not interested in images | 62 | # we are not interested in images |
75 | if '/images/' in pathname: | 63 | if '/images/' in pathname: |
76 | continue | 64 | continue |
77 | lic_files_chksum = rd.getVar(self.metadata_chksum) | 65 | lic_files_chksum = rd.getVar(patchtest_patterns.metadata_chksum) |
78 | if rd.getVar(self.license_var) == self.closed: | 66 | if rd.getVar(patchtest_patterns.license_var) == patchtest_patterns.closed: |
79 | continue | 67 | continue |
80 | if not lic_files_chksum: | 68 | if not lic_files_chksum: |
81 | self.fail('%s is missing in newly added recipe' % self.metadata_chksum) | 69 | self.fail( |
70 | "%s is missing in newly added recipe" % patchtest_patterns.metadata_chksum | ||
71 | ) | ||
82 | 72 | ||
83 | def test_lic_files_chksum_modified_not_mentioned(self): | 73 | def test_lic_files_chksum_modified_not_mentioned(self): |
84 | if not self.modified: | 74 | if not self.modified: |
@@ -89,11 +79,13 @@ class TestMetadata(base.Metadata): | |||
89 | if patch.path.endswith('.patch'): | 79 | if patch.path.endswith('.patch'): |
90 | continue | 80 | continue |
91 | payload = str(patch) | 81 | payload = str(patch) |
92 | if (self.lic_chksum_added.search_string(payload) or self.lic_chksum_removed.search_string(payload)): | 82 | if patchtest_patterns.lic_chksum_added.search_string( |
83 | payload | ||
84 | ) or patchtest_patterns.lic_chksum_removed.search_string(payload): | ||
93 | # if any patch on the series contain reference on the metadata, fail | 85 | # if any patch on the series contain reference on the metadata, fail |
94 | for commit in self.commits: | 86 | for commit in self.commits: |
95 | if self.lictag_re.search_string(commit.commit_message): | 87 | if patchtest_patterns.lictag_re.search_string(commit.commit_message): |
96 | break | 88 | break |
97 | else: | 89 | else: |
98 | self.fail('LIC_FILES_CHKSUM changed without "License-Update:" tag and description in commit message') | 90 | self.fail('LIC_FILES_CHKSUM changed without "License-Update:" tag and description in commit message') |
99 | 91 | ||
@@ -104,16 +96,22 @@ class TestMetadata(base.Metadata): | |||
104 | continue | 96 | continue |
105 | payload = str(patch) | 97 | payload = str(patch) |
106 | for line in payload.splitlines(): | 98 | for line in payload.splitlines(): |
107 | if self.add_mark.search_string(line): | 99 | if patchtest_patterns.add_mark.search_string(line): |
108 | current_line_length = len(line[1:]) | 100 | current_line_length = len(line[1:]) |
109 | if current_line_length > self.max_length: | 101 | if current_line_length > patchtest_patterns.patch_max_line_length: |
110 | self.fail('Patch line too long (current length %s, maximum is %s)' % (current_line_length, self.max_length), | 102 | self.fail( |
111 | data=[('Patch', patch.path), ('Line', '%s ...' % line[0:80])]) | 103 | "Patch line too long (current length %s, maximum is %s)" |
104 | % (current_line_length, patchtest_patterns.patch_max_line_length), | ||
105 | data=[ | ||
106 | ("Patch", patch.path), | ||
107 | ("Line", "%s ..." % line[0:80]), | ||
108 | ], | ||
109 | ) | ||
112 | 110 | ||
113 | def pretest_src_uri_left_files(self): | 111 | def pretest_src_uri_left_files(self): |
114 | # these tests just make sense on patches that can be merged | 112 | # these tests just make sense on patches that can be merged |
115 | if not PatchTestInput.repo.canbemerged: | 113 | if not PatchtestParser.repo.canbemerged: |
116 | self.skip('Patch cannot be merged') | 114 | self.skip("Patch cannot be merged") |
117 | if not self.modified: | 115 | if not self.modified: |
118 | self.skip('No modified recipes, skipping pretest') | 116 | self.skip('No modified recipes, skipping pretest') |
119 | 117 | ||
@@ -123,12 +121,14 @@ class TestMetadata(base.Metadata): | |||
123 | if 'core-image' in pn: | 121 | if 'core-image' in pn: |
124 | continue | 122 | continue |
125 | rd = self.tinfoil.parse_recipe(pn) | 123 | rd = self.tinfoil.parse_recipe(pn) |
126 | PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)] = rd.getVar(self.metadata_src_uri) | 124 | PatchTestDataStore[ |
125 | "%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn) | ||
126 | ] = rd.getVar(patchtest_patterns.metadata_src_uri) | ||
127 | 127 | ||
128 | def test_src_uri_left_files(self): | 128 | def test_src_uri_left_files(self): |
129 | # these tests just make sense on patches that can be merged | 129 | # these tests just make sense on patches that can be merged |
130 | if not PatchTestInput.repo.canbemerged: | 130 | if not PatchtestParser.repo.canbemerged: |
131 | self.skip('Patch cannot be merged') | 131 | self.skip("Patch cannot be merged") |
132 | if not self.modified: | 132 | if not self.modified: |
133 | self.skip('No modified recipes, skipping pretest') | 133 | self.skip('No modified recipes, skipping pretest') |
134 | 134 | ||
@@ -138,11 +138,17 @@ class TestMetadata(base.Metadata): | |||
138 | if 'core-image' in pn: | 138 | if 'core-image' in pn: |
139 | continue | 139 | continue |
140 | rd = self.tinfoil.parse_recipe(pn) | 140 | rd = self.tinfoil.parse_recipe(pn) |
141 | PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)] = rd.getVar(self.metadata_src_uri) | 141 | PatchTestDataStore[ |
142 | "%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn) | ||
143 | ] = rd.getVar(patchtest_patterns.metadata_src_uri) | ||
142 | 144 | ||
143 | for pn in self.modified: | 145 | for pn in self.modified: |
144 | pretest_src_uri = PatchTestDataStore['pre%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)].split() | 146 | pretest_src_uri = PatchTestDataStore[ |
145 | test_src_uri = PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)].split() | 147 | "pre%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn) |
148 | ].split() | ||
149 | test_src_uri = PatchTestDataStore[ | ||
150 | "%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn) | ||
151 | ].split() | ||
146 | 152 | ||
147 | pretest_files = set([os.path.basename(patch) for patch in pretest_src_uri if patch.startswith('file://')]) | 153 | pretest_files = set([os.path.basename(patch) for patch in pretest_src_uri if patch.startswith('file://')]) |
148 | test_files = set([os.path.basename(patch) for patch in test_src_uri if patch.startswith('file://')]) | 154 | test_files = set([os.path.basename(patch) for patch in test_src_uri if patch.startswith('file://')]) |
@@ -175,23 +181,32 @@ class TestMetadata(base.Metadata): | |||
175 | if 'core-image' in pn: | 181 | if 'core-image' in pn: |
176 | continue | 182 | continue |
177 | rd = self.tinfoil.parse_recipe(pn) | 183 | rd = self.tinfoil.parse_recipe(pn) |
178 | summary = rd.getVar(self.metadata_summary) | 184 | summary = rd.getVar(patchtest_patterns.metadata_summary) |
179 | 185 | ||
180 | # "${PN} version ${PN}-${PR}" is the default, so fail if default | 186 | # "${PN} version ${PN}-${PR}" is the default, so fail if default |
181 | if summary.startswith('%s version' % pn): | 187 | if summary.startswith("%s version" % pn): |
182 | self.fail('%s is missing in newly added recipe' % self.metadata_summary) | 188 | self.fail( |
189 | "%s is missing in newly added recipe" % patchtest_patterns.metadata_summary | ||
190 | ) | ||
183 | 191 | ||
184 | def test_cve_check_ignore(self): | 192 | def test_cve_check_ignore(self): |
185 | # Skip if we neither modified a recipe or target branches are not | 193 | # Skip if we neither modified a recipe or target branches are not |
186 | # Nanbield and newer. CVE_CHECK_IGNORE was first deprecated in Nanbield. | 194 | # Nanbield and newer. CVE_CHECK_IGNORE was first deprecated in Nanbield. |
187 | if not self.modified or PatchTestInput.repo.branch == "kirkstone" or PatchTestInput.repo.branch == "dunfell": | 195 | if ( |
188 | self.skip('No modified recipes or older target branch, skipping test') | 196 | not self.modified |
197 | or PatchtestParser.repo.patch.branch == "kirkstone" | ||
198 | or PatchtestParser.repo.patch.branch == "dunfell" | ||
199 | ): | ||
200 | self.skip("No modified recipes or older target branch, skipping test") | ||
189 | for pn in self.modified: | 201 | for pn in self.modified: |
190 | # we are not interested in images | 202 | # we are not interested in images |
191 | if 'core-image' in pn: | 203 | if 'core-image' in pn: |
192 | continue | 204 | continue |
193 | rd = self.tinfoil.parse_recipe(pn) | 205 | rd = self.tinfoil.parse_recipe(pn) |
194 | cve_check_ignore = rd.getVar(self.cve_check_ignore_var) | 206 | cve_check_ignore = rd.getVar(patchtest_patterns.cve_check_ignore_var) |
195 | 207 | ||
196 | if cve_check_ignore is not None: | 208 | if cve_check_ignore is not None: |
197 | self.fail('%s is deprecated and should be replaced by %s' % (self.cve_check_ignore_var, self.cve_status_var)) | 209 | self.fail( |
210 | "%s is deprecated and should be replaced by %s" | ||
211 | % (patchtest_patterns.cve_check_ignore_var, patchtest_patterns.cve_status_var) | ||
212 | ) | ||