mirror of
git://git.yoctoproject.org/poky.git
synced 2025-07-19 12:39:02 +02:00

- simplify base.py, data.py - move some leftover regex patterns to patterns.py - remove pyparsing path logic, since this is no longer needed - rename PatchTestInput class to PatchtestParser - data.py: rename to patchtest_parser.py - patterns.py: rename to patchtest_patterns.py - move PatchTestDataStore to test_metadata.py since that's the only place it's used - remove unused logger code (From OE-Core rev: 1e971b05b036b0b1eb0bdbd9b26b54d06e74294c) Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
213 lines
8.8 KiB
Python
213 lines
8.8 KiB
Python
# Checks related to the patch's LIC_FILES_CHKSUM metadata variable
|
|
#
|
|
# Copyright (C) 2016 Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
import base
|
|
import collections
|
|
import os
|
|
import patchtest_patterns
|
|
import pyparsing
|
|
from patchtest_parser import PatchtestParser
|
|
|
|
# Data store commonly used to share values between pre and post-merge tests
|
|
PatchTestDataStore = collections.defaultdict(str)
|
|
|
|
class TestMetadata(base.Metadata):
|
|
|
|
def test_license_presence(self):
|
|
if not self.added:
|
|
self.skip('No added recipes, skipping test')
|
|
|
|
# TODO: this is a workaround so we can parse the recipe not
|
|
# containing the LICENSE var: add some default license instead
|
|
# of INVALID into auto.conf, then remove this line at the end
|
|
auto_conf = os.path.join(os.environ.get('BUILDDIR'), 'conf', 'auto.conf')
|
|
open_flag = 'w'
|
|
if os.path.exists(auto_conf):
|
|
open_flag = 'a'
|
|
with open(auto_conf, open_flag) as fd:
|
|
for pn in self.added:
|
|
fd.write('LICENSE ??= "%s"\n' % patchtest_patterns.invalid_license)
|
|
|
|
no_license = False
|
|
for pn in self.added:
|
|
rd = self.tinfoil.parse_recipe(pn)
|
|
license = rd.getVar(patchtest_patterns.metadata_lic)
|
|
if license == patchtest_patterns.invalid_license:
|
|
no_license = True
|
|
break
|
|
|
|
# remove auto.conf line or the file itself
|
|
if open_flag == 'w':
|
|
os.remove(auto_conf)
|
|
else:
|
|
fd = open(auto_conf, 'r')
|
|
lines = fd.readlines()
|
|
fd.close()
|
|
with open(auto_conf, 'w') as fd:
|
|
fd.write(''.join(lines[:-1]))
|
|
|
|
if no_license:
|
|
self.fail('Recipe does not have the LICENSE field set.')
|
|
|
|
def test_lic_files_chksum_presence(self):
|
|
if not self.added:
|
|
self.skip('No added recipes, skipping test')
|
|
|
|
for pn in self.added:
|
|
rd = self.tinfoil.parse_recipe(pn)
|
|
pathname = rd.getVar('FILE')
|
|
# we are not interested in images
|
|
if '/images/' in pathname:
|
|
continue
|
|
lic_files_chksum = rd.getVar(patchtest_patterns.metadata_chksum)
|
|
if rd.getVar(patchtest_patterns.license_var) == patchtest_patterns.closed:
|
|
continue
|
|
if not lic_files_chksum:
|
|
self.fail(
|
|
"%s is missing in newly added recipe" % patchtest_patterns.metadata_chksum
|
|
)
|
|
|
|
def test_lic_files_chksum_modified_not_mentioned(self):
|
|
if not self.modified:
|
|
self.skip('No modified recipes, skipping test')
|
|
|
|
for patch in self.patchset:
|
|
# for the moment, we are just interested in metadata
|
|
if patch.path.endswith('.patch'):
|
|
continue
|
|
payload = str(patch)
|
|
if patchtest_patterns.lic_chksum_added.search_string(
|
|
payload
|
|
) or patchtest_patterns.lic_chksum_removed.search_string(payload):
|
|
# if any patch on the series contain reference on the metadata, fail
|
|
for commit in self.commits:
|
|
if patchtest_patterns.lictag_re.search_string(commit.commit_message):
|
|
break
|
|
else:
|
|
self.fail('LIC_FILES_CHKSUM changed without "License-Update:" tag and description in commit message')
|
|
|
|
def test_max_line_length(self):
|
|
for patch in self.patchset:
|
|
# for the moment, we are just interested in metadata
|
|
if patch.path.endswith('.patch'):
|
|
continue
|
|
payload = str(patch)
|
|
for line in payload.splitlines():
|
|
if patchtest_patterns.add_mark.search_string(line):
|
|
current_line_length = len(line[1:])
|
|
if current_line_length > patchtest_patterns.patch_max_line_length:
|
|
self.fail(
|
|
"Patch line too long (current length %s, maximum is %s)"
|
|
% (current_line_length, patchtest_patterns.patch_max_line_length),
|
|
data=[
|
|
("Patch", patch.path),
|
|
("Line", "%s ..." % line[0:80]),
|
|
],
|
|
)
|
|
|
|
def pretest_src_uri_left_files(self):
|
|
# these tests just make sense on patches that can be merged
|
|
if not PatchtestParser.repo.canbemerged:
|
|
self.skip("Patch cannot be merged")
|
|
if not self.modified:
|
|
self.skip('No modified recipes, skipping pretest')
|
|
|
|
# get the proper metadata values
|
|
for pn in self.modified:
|
|
# we are not interested in images
|
|
if 'core-image' in pn:
|
|
continue
|
|
rd = self.tinfoil.parse_recipe(pn)
|
|
PatchTestDataStore[
|
|
"%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn)
|
|
] = rd.getVar(patchtest_patterns.metadata_src_uri)
|
|
|
|
def test_src_uri_left_files(self):
|
|
# these tests just make sense on patches that can be merged
|
|
if not PatchtestParser.repo.canbemerged:
|
|
self.skip("Patch cannot be merged")
|
|
if not self.modified:
|
|
self.skip('No modified recipes, skipping pretest')
|
|
|
|
# get the proper metadata values
|
|
for pn in self.modified:
|
|
# we are not interested in images
|
|
if 'core-image' in pn:
|
|
continue
|
|
rd = self.tinfoil.parse_recipe(pn)
|
|
PatchTestDataStore[
|
|
"%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn)
|
|
] = rd.getVar(patchtest_patterns.metadata_src_uri)
|
|
|
|
for pn in self.modified:
|
|
pretest_src_uri = PatchTestDataStore[
|
|
"pre%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn)
|
|
].split()
|
|
test_src_uri = PatchTestDataStore[
|
|
"%s-%s-%s" % (self.shortid(), patchtest_patterns.metadata_src_uri, pn)
|
|
].split()
|
|
|
|
pretest_files = set([os.path.basename(patch) for patch in pretest_src_uri if patch.startswith('file://')])
|
|
test_files = set([os.path.basename(patch) for patch in test_src_uri if patch.startswith('file://')])
|
|
|
|
# check if files were removed
|
|
if len(test_files) < len(pretest_files):
|
|
|
|
# get removals from patchset
|
|
filesremoved_from_patchset = set()
|
|
for patch in self.patchset:
|
|
if patch.is_removed_file:
|
|
filesremoved_from_patchset.add(os.path.basename(patch.path))
|
|
|
|
# get the deleted files from the SRC_URI
|
|
filesremoved_from_usr_uri = pretest_files - test_files
|
|
|
|
# finally, get those patches removed at SRC_URI and not removed from the patchset
|
|
# TODO: we are not taking into account renames, so test may raise false positives
|
|
not_removed = filesremoved_from_usr_uri - filesremoved_from_patchset
|
|
if not_removed:
|
|
self.fail('Patches not removed from tree. Remove them and amend the submitted mbox',
|
|
data=[('Patch', f) for f in not_removed])
|
|
|
|
def test_summary_presence(self):
|
|
if not self.added:
|
|
self.skip('No added recipes, skipping test')
|
|
|
|
for pn in self.added:
|
|
# we are not interested in images
|
|
if 'core-image' in pn:
|
|
continue
|
|
rd = self.tinfoil.parse_recipe(pn)
|
|
summary = rd.getVar(patchtest_patterns.metadata_summary)
|
|
|
|
# "${PN} version ${PN}-${PR}" is the default, so fail if default
|
|
if summary.startswith("%s version" % pn):
|
|
self.fail(
|
|
"%s is missing in newly added recipe" % patchtest_patterns.metadata_summary
|
|
)
|
|
|
|
def test_cve_check_ignore(self):
|
|
# Skip if we neither modified a recipe or target branches are not
|
|
# Nanbield and newer. CVE_CHECK_IGNORE was first deprecated in Nanbield.
|
|
if (
|
|
not self.modified
|
|
or PatchtestParser.repo.patch.branch == "kirkstone"
|
|
or PatchtestParser.repo.patch.branch == "dunfell"
|
|
):
|
|
self.skip("No modified recipes or older target branch, skipping test")
|
|
for pn in self.modified:
|
|
# we are not interested in images
|
|
if 'core-image' in pn:
|
|
continue
|
|
rd = self.tinfoil.parse_recipe(pn)
|
|
cve_check_ignore = rd.getVar(patchtest_patterns.cve_check_ignore_var)
|
|
|
|
if cve_check_ignore is not None:
|
|
self.fail(
|
|
"%s is deprecated and should be replaced by %s"
|
|
% (patchtest_patterns.cve_check_ignore_var, patchtest_patterns.cve_status_var)
|
|
)
|