summaryrefslogtreecommitdiffstats
path: root/meta/lib/patchtest/tests/test_metadata.py
diff options
context:
space:
mode:
authorTrevor Gamblin <tgamblin@baylibre.com>2023-10-26 10:07:46 -0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2023-10-26 21:11:28 +0100
commit207a5a21d38f4ed1b71aed0158ce067b57502cc7 (patch)
tree2f612a8d475ed4d4dc0f994b3ca320e5e073c10e /meta/lib/patchtest/tests/test_metadata.py
parentcdee2b22e1f3b35eb77fed0d431acdf3c358ee6c (diff)
downloadpoky-207a5a21d38f4ed1b71aed0158ce067b57502cc7.tar.gz
patchtest: simplify test directory structure
Consolidate the various mbox tests into a new TestMbox class, metadata tests into TestMetadata, and patch tests into TestPatch. Also update the selftest filenames to match the changes. The test contents are not significantly changed (other than to reference the new class names). While this doesn't improve overall readability, it does result in more obvious categorization, and more importantly reduces the number of calls to setup tinfoil in the tests, resulting in a roughly 25% reduction in runtime. Before: [tgamblin@megalith poky]$ time ./meta/lib/patchtest/selftest/selftest XPASS: PatchSignedOffBy.test_signed_off_by_presence (file: PatchSignedOffBy.test_signed_off_by_presence.pass) XFAIL: Shortlog.test_shortlog_format (file: Shortlog.test_shortlog_format.fail) XFAIL: MboxFormat.test_mbox_format (file: MboxFormat.test_mbox_format.1.fail) XPASS: Shortlog.test_shortlog_length (file: Shortlog.test_shortlog_length.pass) XFAIL: CommitMessage.test_commit_message_presence (file: CommitMessage.test_commit_message_presence.fail) XFAIL: SrcUri.test_src_uri_left_files (file: SrcUri.test_src_uri_left_files.fail) XPASS: Author.test_author_valid (file: Author.test_author_valid.1.pass) XFAIL: LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned (file: LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.fail) XPASS: CVE.test_cve_tag_format (file: CVE.test_cve_tag_format.pass) XPASS: CVE.test_cve_presence_in_commit_message (file: CVE.test_cve_presence_in_commit_message.pass) XFAIL: CVE.test_cve_tag_format (file: CVE.test_cve_tag_format.fail) XFAIL: Author.test_author_valid (file: Author.test_author_valid.1.fail) XFAIL: LicFilesChkSum.test_lic_files_chksum_presence (file: LicFilesChkSum.test_lic_files_chksum_presence.fail) XSKIP: Merge.test_series_merge_on_head (file: Merge.test_series_merge_on_head.2.skip) XPASS: MboxFormat.test_mbox_format (file: MboxFormat.test_mbox_format.pass) XFAIL: SignedOffBy.test_signed_off_by_presence (file: SignedOffBy.test_signed_off_by_presence.1.fail) XPASS: Shortlog.test_shortlog_format (file: Shortlog.test_shortlog_format.pass) XFAIL: SignedOffBy.test_signed_off_by_presence (file: SignedOffBy.test_signed_off_by_presence.2.fail) XFAIL: MboxFormat.test_mbox_format (file: MboxFormat.test_mbox_format.2.fail) XFAIL: Summary.test_summary_presence (file: Summary.test_summary_presence.fail) XPASS: Author.test_author_valid (file: Author.test_author_valid.2.pass) XSKIP: Merge.test_series_merge_on_head (file: Merge.test_series_merge_on_head.1.skip) XPASS: Bugzilla.test_bugzilla_entry_format (file: Bugzilla.test_bugzilla_entry_format.pass) XFAIL: CVE.test_cve_presence_in_commit_message (file: CVE.test_cve_presence_in_commit_message.fail) XPASS: SignedOffBy.test_signed_off_by_presence (file: SignedOffBy.test_signed_off_by_presence.pass) XPASS: LicFilesChkSum.test_lic_files_chksum_presence (file: LicFilesChkSum.test_lic_files_chksum_presence.pass) XPASS: CommitMessage.test_commit_message_presence (file: CommitMessage.test_commit_message_presence.pass) XPASS: Summary.test_summary_presence (file: Summary.test_summary_presence.pass) XPASS: LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned (file: LicFilesChkSum.test_lic_files_chksum_modified_not_mentioned.pass) XFAIL: Shortlog.test_shortlog_length (file: Shortlog.test_shortlog_length.fail) XFAIL: PatchSignedOffBy.test_signed_off_by_presence (file: PatchSignedOffBy.test_signed_off_by_presence.fail) XFAIL: Bugzilla.test_bugzilla_entry_format (file: Bugzilla.test_bugzilla_entry_format.fail) XPASS: SrcUri.test_src_uri_left_files (file: SrcUri.test_src_uri_left_files.pass) XFAIL: Author.test_author_valid (file: Author.test_author_valid.2.fail) ============================================================================ Testsuite summary for patchtest ============================================================================ ============================================================================ real 24m14.386s user 1m13.599s sys 0m21.477s After: [tgamblin@megalith poky]$ time ./meta/lib/patchtest/selftest/selftest XFAIL: TestMbox.test_bugzilla_entry_format (file: TestMbox.test_bugzilla_entry_format.fail) XPASS: TestMetadata.test_summary_presence (file: TestMetadata.test_summary_presence.pass) XFAIL: TestMbox.test_mbox_format (file: TestMbox.test_mbox_format.1.fail) XFAIL: TestMetadata.test_src_uri_left_files (file: TestMetadata.test_src_uri_left_files.fail) XSKIP: TestMbox.test_series_merge_on_head (file: TestMbox.test_series_merge_on_head.2.skip) XPASS: TestMbox.test_commit_message_presence (file: TestMbox.test_commit_message_presence.pass) XFAIL: TestMbox.test_commit_message_presence (file: TestMbox.test_commit_message_presence.fail) XPASS: TestMbox.test_signed_off_by_presence (file: TestMbox.test_signed_off_by_presence.pass) XFAIL: TestPatch.test_cve_tag_format (file: TestPatch.test_cve_tag_format.fail) XFAIL: TestMbox.test_author_valid (file: TestMbox.test_author_valid.1.fail) XFAIL: TestMbox.test_shortlog_length (file: TestMbox.test_shortlog_length.fail) XPASS: TestMbox.test_mbox_format (file: TestMbox.test_mbox_format.pass) XFAIL: TestPatch.test_signed_off_by_presence (file: TestPatch.test_signed_off_by_presence.fail) XFAIL: TestMbox.test_shortlog_format (file: TestMbox.test_shortlog_format.fail) XFAIL: TestMbox.test_mbox_format (file: TestMbox.test_mbox_format.2.fail) XPASS: TestPatch.test_cve_tag_format (file: TestPatch.test_cve_tag_format.pass) XSKIP: TestMbox.test_series_merge_on_head (file: TestMbox.test_series_merge_on_head.1.skip) XPASS: TestMbox.test_author_valid (file: TestMbox.test_author_valid.2.pass) XPASS: TestMetadata.test_lic_files_chksum_modified_not_mentioned (file: TestMetadata.test_lic_files_chksum_modified_not_mentioned.pass) XPASS: TestMbox.test_bugzilla_entry_format (file: TestMbox.test_bugzilla_entry_format.pass) XPASS: TestMetadata.test_src_uri_left_files (file: TestMetadata.test_src_uri_left_files.pass) XPASS: TestMetadata.test_lic_files_chksum_presence (file: TestMetadata.test_lic_files_chksum_presence.pass) XPASS: TestMbox.test_cve_presence_in_commit_message (file: TestMbox.test_cve_presence_in_commit_message.pass) XFAIL: TestMbox.test_signed_off_by_presence (file: TestMbox.test_signed_off_by_presence.2.fail) XFAIL: TestMbox.test_author_valid (file: TestMbox.test_author_valid.2.fail) XFAIL: TestMetadata.test_lic_files_chksum_presence (file: TestMetadata.test_lic_files_chksum_presence.fail) XPASS: TestMbox.test_shortlog_format (file: TestMbox.test_shortlog_format.pass) XPASS: TestMbox.test_author_valid (file: TestMbox.test_author_valid.1.pass) XPASS: TestPatch.test_signed_off_by_presence (file: TestPatch.test_signed_off_by_presence.pass) XFAIL: TestMetadata.test_lic_files_chksum_modified_not_mentioned (file: TestMetadata.test_lic_files_chksum_modified_not_mentioned.fail) XPASS: TestMbox.test_shortlog_length (file: TestMbox.test_shortlog_length.pass) XFAIL: TestMbox.test_signed_off_by_presence (file: TestMbox.test_signed_off_by_presence.1.fail) XFAIL: TestMbox.test_cve_presence_in_commit_message (file: TestMbox.test_cve_presence_in_commit_message.fail) XFAIL: TestMetadata.test_summary_presence (file: TestMetadata.test_summary_presence.fail) ============================================================================ Testsuite summary for patchtest ============================================================================ ============================================================================ real 18m39.749s user 0m41.857s sys 0m14.708s (From OE-Core rev: f788592da2fd0e21638ce2c3326675a060ba51cf) Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/patchtest/tests/test_metadata.py')
-rw-r--r--meta/lib/patchtest/tests/test_metadata.py204
1 files changed, 204 insertions, 0 deletions
diff --git a/meta/lib/patchtest/tests/test_metadata.py b/meta/lib/patchtest/tests/test_metadata.py
new file mode 100644
index 0000000000..34e119174f
--- /dev/null
+++ b/meta/lib/patchtest/tests/test_metadata.py
@@ -0,0 +1,204 @@
1# Checks related to the patch's LIC_FILES_CHKSUM metadata variable
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# SPDX-License-Identifier: GPL-2.0-only
6
7import base
8import os
9import pyparsing
10from data import PatchTestInput, PatchTestDataStore
11
12class TestMetadata(base.Metadata):
13 metadata_lic = 'LICENSE'
14 invalid_license = 'PATCHTESTINVALID'
15 metadata_chksum = 'LIC_FILES_CHKSUM'
16 license_var = 'LICENSE'
17 closed = 'CLOSED'
18 lictag_re = pyparsing.AtLineStart("License-Update:")
19 add_mark = pyparsing.Regex('\+ ')
20 max_length = 200
21 metadata_src_uri = 'SRC_URI'
22 md5sum = 'md5sum'
23 sha256sum = 'sha256sum'
24 git_regex = pyparsing.Regex('^git\:\/\/.*')
25 metadata_summary = 'SUMMARY'
26
27 def test_license_presence(self):
28 if not self.added:
29 self.skip('No added recipes, skipping test')
30
31 # TODO: this is a workaround so we can parse the recipe not
32 # containing the LICENSE var: add some default license instead
33 # of INVALID into auto.conf, then remove this line at the end
34 auto_conf = os.path.join(os.environ.get('BUILDDIR'), 'conf', 'auto.conf')
35 open_flag = 'w'
36 if os.path.exists(auto_conf):
37 open_flag = 'a'
38 with open(auto_conf, open_flag) as fd:
39 for pn in self.added:
40 fd.write('LICENSE ??= "%s"\n' % self.invalid_license)
41
42 no_license = False
43 for pn in self.added:
44 rd = self.tinfoil.parse_recipe(pn)
45 license = rd.getVar(self.metadata_lic)
46 if license == self.invalid_license:
47 no_license = True
48 break
49
50 # remove auto.conf line or the file itself
51 if open_flag == 'w':
52 os.remove(auto_conf)
53 else:
54 fd = open(auto_conf, 'r')
55 lines = fd.readlines()
56 fd.close()
57 with open(auto_conf, 'w') as fd:
58 fd.write(''.join(lines[:-1]))
59
60 if no_license:
61 self.fail('Recipe does not have the LICENSE field set.')
62
63 def test_lic_files_chksum_presence(self):
64 if not self.added:
65 self.skip('No added recipes, skipping test')
66
67 for pn in self.added:
68 rd = self.tinfoil.parse_recipe(pn)
69 pathname = rd.getVar('FILE')
70 # we are not interested in images
71 if '/images/' in pathname:
72 continue
73 lic_files_chksum = rd.getVar(self.metadata_chksum)
74 if rd.getVar(self.license_var) == self.closed:
75 continue
76 if not lic_files_chksum:
77 self.fail('%s is missing in newly added recipe' % self.metadata_chksum)
78
79 def pretest_lic_files_chksum_modified_not_mentioned(self):
80 if not self.modified:
81 self.skip('No modified recipes, skipping pretest')
82 # get the proper metadata values
83 for pn in self.modified:
84 rd = self.tinfoil.parse_recipe(pn)
85 pathname = rd.getVar('FILE')
86 # we are not interested in images
87 if '/images/' in pathname:
88 continue
89 PatchTestDataStore['%s-%s-%s' % (self.shortid(),self.metadata_chksum,pn)] = rd.getVar(self.metadata_chksum)
90
91 def test_lic_files_chksum_modified_not_mentioned(self):
92 if not self.modified:
93 self.skip('No modified recipes, skipping test')
94
95 # get the proper metadata values
96 for pn in self.modified:
97 rd = self.tinfoil.parse_recipe(pn)
98 pathname = rd.getVar('FILE')
99 # we are not interested in images
100 if '/images/' in pathname:
101 continue
102 PatchTestDataStore['%s-%s-%s' % (self.shortid(),self.metadata_chksum,pn)] = rd.getVar(self.metadata_chksum)
103 # compare if there were changes between pre-merge and merge
104 for pn in self.modified:
105 pretest = PatchTestDataStore['pre%s-%s-%s' % (self.shortid(),self.metadata_chksum, pn)]
106 test = PatchTestDataStore['%s-%s-%s' % (self.shortid(),self.metadata_chksum, pn)]
107
108 # TODO: this is workaround to avoid false-positives when pretest metadata is empty (not reason found yet)
109 # For more info, check bug 12284
110 if not pretest:
111 return
112
113 if pretest != test:
114 # if any patch on the series contain reference on the metadata, fail
115 for commit in self.commits:
116 if self.lictag_re.search_string(commit.commit_message):
117 break
118 else:
119 self.fail('LIC_FILES_CHKSUM changed on target %s but there is no "License-Update:" tag in commit message. Include it with a brief description' % pn,
120 data=[('Current checksum', pretest), ('New checksum', test)])
121
122 def test_max_line_length(self):
123 for patch in self.patchset:
124 # for the moment, we are just interested in metadata
125 if patch.path.endswith('.patch'):
126 continue
127 payload = str(patch)
128 for line in payload.splitlines():
129 if self.add_mark.search_string(line):
130 current_line_length = len(line[1:])
131 if current_line_length > self.max_length:
132 self.fail('Patch line too long (current length %s, maximum is %s)' % (current_line_length, self.max_length),
133 data=[('Patch', patch.path), ('Line', '%s ...' % line[0:80])])
134
135 def pretest_src_uri_left_files(self):
136 # these tests just make sense on patches that can be merged
137 if not PatchTestInput.repo.canbemerged:
138 self.skip('Patch cannot be merged')
139 if not self.modified:
140 self.skip('No modified recipes, skipping pretest')
141
142 # get the proper metadata values
143 for pn in self.modified:
144 # we are not interested in images
145 if 'core-image' in pn:
146 continue
147 rd = self.tinfoil.parse_recipe(pn)
148 PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)] = rd.getVar(self.metadata_src_uri)
149
150 def test_src_uri_left_files(self):
151 # these tests just make sense on patches that can be merged
152 if not PatchTestInput.repo.canbemerged:
153 self.skip('Patch cannot be merged')
154 if not self.modified:
155 self.skip('No modified recipes, skipping pretest')
156
157 # get the proper metadata values
158 for pn in self.modified:
159 # we are not interested in images
160 if 'core-image' in pn:
161 continue
162 rd = self.tinfoil.parse_recipe(pn)
163 PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)] = rd.getVar(self.metadata_src_uri)
164
165 for pn in self.modified:
166 pretest_src_uri = PatchTestDataStore['pre%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)].split()
167 test_src_uri = PatchTestDataStore['%s-%s-%s' % (self.shortid(), self.metadata_src_uri, pn)].split()
168
169 pretest_files = set([os.path.basename(patch) for patch in pretest_src_uri if patch.startswith('file://')])
170 test_files = set([os.path.basename(patch) for patch in test_src_uri if patch.startswith('file://')])
171
172 # check if files were removed
173 if len(test_files) < len(pretest_files):
174
175 # get removals from patchset
176 filesremoved_from_patchset = set()
177 for patch in self.patchset:
178 if patch.is_removed_file:
179 filesremoved_from_patchset.add(os.path.basename(patch.path))
180
181 # get the deleted files from the SRC_URI
182 filesremoved_from_usr_uri = pretest_files - test_files
183
184 # finally, get those patches removed at SRC_URI and not removed from the patchset
185 # TODO: we are not taking into account renames, so test may raise false positives
186 not_removed = filesremoved_from_usr_uri - filesremoved_from_patchset
187 if not_removed:
188 self.fail('Patches not removed from tree. Remove them and amend the submitted mbox',
189 data=[('Patch', f) for f in not_removed])
190
191 def test_summary_presence(self):
192 if not self.added:
193 self.skip('No added recipes, skipping test')
194
195 for pn in self.added:
196 # we are not interested in images
197 if 'core-image' in pn:
198 continue
199 rd = self.tinfoil.parse_recipe(pn)
200 summary = rd.getVar(self.metadata_summary)
201
202 # "${PN} version ${PN}-${PR}" is the default, so fail if default
203 if summary.startswith('%s version' % pn):
204 self.fail('%s is missing in newly added recipe' % self.metadata_summary)