1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# SPDX-License-Identifier: MIT 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun 5*4882a593Smuzhiyunfrom oeqa.selftest.case import OESelftestTestCase 6*4882a593Smuzhiyun 7*4882a593Smuzhiyunimport oe.recipeutils 8*4882a593Smuzhiyun 9*4882a593Smuzhiyunclass Distrodata(OESelftestTestCase): 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun def test_checkpkg(self): 12*4882a593Smuzhiyun """ 13*4882a593Smuzhiyun Summary: Test that upstream version checks do not regress 14*4882a593Smuzhiyun Expected: Upstream version checks should succeed except for the recipes listed in the exception list. 15*4882a593Smuzhiyun Product: oe-core 16*4882a593Smuzhiyun Author: Alexander Kanavin <alex.kanavin@gmail.com> 17*4882a593Smuzhiyun """ 18*4882a593Smuzhiyun feature = 'LICENSE_FLAGS_ACCEPTED += " commercial"\n' 19*4882a593Smuzhiyun self.write_config(feature) 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun pkgs = oe.recipeutils.get_recipe_upgrade_status() 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun regressed_failures = [pkg[0] for pkg in pkgs if pkg[1] == 'UNKNOWN_BROKEN'] 24*4882a593Smuzhiyun regressed_successes = [pkg[0] for pkg in pkgs if pkg[1] == 'KNOWN_BROKEN'] 25*4882a593Smuzhiyun msg = "" 26*4882a593Smuzhiyun if len(regressed_failures) > 0: 27*4882a593Smuzhiyun msg = msg + """ 28*4882a593SmuzhiyunThe following packages failed upstream version checks. Please fix them using UPSTREAM_CHECK_URI/UPSTREAM_CHECK_REGEX 29*4882a593Smuzhiyun(when using tarballs) or UPSTREAM_CHECK_GITTAGREGEX (when using git). If an upstream version check cannot be performed 30*4882a593Smuzhiyun(for example, if upstream does not use git tags), you can set UPSTREAM_VERSION_UNKNOWN to '1' in the recipe to acknowledge 31*4882a593Smuzhiyunthat the check cannot be performed. 32*4882a593Smuzhiyun""" + "\n".join(regressed_failures) 33*4882a593Smuzhiyun if len(regressed_successes) > 0: 34*4882a593Smuzhiyun msg = msg + """ 35*4882a593SmuzhiyunThe following packages have been checked successfully for upstream versions, 36*4882a593Smuzhiyunbut their recipes claim otherwise by setting UPSTREAM_VERSION_UNKNOWN. Please remove that line from the recipes. 37*4882a593Smuzhiyun""" + "\n".join(regressed_successes) 38*4882a593Smuzhiyun self.assertTrue(len(regressed_failures) == 0 and len(regressed_successes) == 0, msg) 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun def test_missing_homepg(self): 41*4882a593Smuzhiyun """ 42*4882a593Smuzhiyun Summary: Test for oe-core recipes that don't have a HOMEPAGE or DESCRIPTION 43*4882a593Smuzhiyun Expected: All oe-core recipes should have a DESCRIPTION entry 44*4882a593Smuzhiyun Expected: All oe-core recipes should have a HOMEPAGE entry except for recipes that are not fetched from external sources. 45*4882a593Smuzhiyun Product: oe-core 46*4882a593Smuzhiyun """ 47*4882a593Smuzhiyun with bb.tinfoil.Tinfoil() as tinfoil: 48*4882a593Smuzhiyun tinfoil.prepare(config_only=False) 49*4882a593Smuzhiyun no_description = [] 50*4882a593Smuzhiyun no_homepage = [] 51*4882a593Smuzhiyun for fn in tinfoil.all_recipe_files(variants=False): 52*4882a593Smuzhiyun if not '/meta/recipes-' in fn: 53*4882a593Smuzhiyun # We are only interested in OE-Core 54*4882a593Smuzhiyun continue 55*4882a593Smuzhiyun rd = tinfoil.parse_recipe_file(fn, appends=False) 56*4882a593Smuzhiyun pn = rd.getVar('BPN') 57*4882a593Smuzhiyun srcfile = rd.getVar('SRC_URI').split() 58*4882a593Smuzhiyun #Since DESCRIPTION defaults to SUMMARY if not set, we are only interested in recipes without DESCRIPTION or SUMMARY 59*4882a593Smuzhiyun if not (rd.getVar('SUMMARY') or rd.getVar('DESCRIPTION')): 60*4882a593Smuzhiyun no_description.append((pn, fn)) 61*4882a593Smuzhiyun if not rd.getVar('HOMEPAGE'): 62*4882a593Smuzhiyun if srcfile and srcfile[0].startswith('file') or not rd.getVar('SRC_URI'): 63*4882a593Smuzhiyun # We are only interested in recipes SRC_URI fetched from external sources 64*4882a593Smuzhiyun continue 65*4882a593Smuzhiyun no_homepage.append((pn, fn)) 66*4882a593Smuzhiyun if no_homepage: 67*4882a593Smuzhiyun self.fail(""" 68*4882a593SmuzhiyunThe following recipes do not have a HOMEPAGE. Please add an entry for HOMEPAGE in the recipe. 69*4882a593Smuzhiyun""" + "\n".join(['%s (%s)' % i for i in no_homepage])) 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun if no_description: 72*4882a593Smuzhiyun self.fail(""" 73*4882a593SmuzhiyunThe following recipes do not have a DESCRIPTION. Please add an entry for DESCRIPTION in the recipe. 74*4882a593Smuzhiyun""" + "\n".join(['%s (%s)' % i for i in no_description])) 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun def test_maintainers(self): 77*4882a593Smuzhiyun """ 78*4882a593Smuzhiyun Summary: Test that oe-core recipes have a maintainer and entries in maintainers list have a recipe 79*4882a593Smuzhiyun Expected: All oe-core recipes (except a few special static/testing ones) should have a maintainer listed in maintainers.inc file. 80*4882a593Smuzhiyun Expected: All entries in maintainers list should have a recipe file that matches them 81*4882a593Smuzhiyun Product: oe-core 82*4882a593Smuzhiyun Author: Alexander Kanavin <alex.kanavin@gmail.com> 83*4882a593Smuzhiyun """ 84*4882a593Smuzhiyun def is_exception(pkg): 85*4882a593Smuzhiyun exceptions = ["packagegroup-", "initramfs-", "systemd-machine-units", "target-sdk-provides-dummy"] 86*4882a593Smuzhiyun for i in exceptions: 87*4882a593Smuzhiyun if i in pkg: 88*4882a593Smuzhiyun return True 89*4882a593Smuzhiyun return False 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun def is_maintainer_exception(entry): 92*4882a593Smuzhiyun exceptions = ["musl", "newlib", "linux-yocto", "linux-dummy", "mesa-gl", "libgfortran", 93*4882a593Smuzhiyun "cve-update-db-native", "rust"] 94*4882a593Smuzhiyun for i in exceptions: 95*4882a593Smuzhiyun if i in entry: 96*4882a593Smuzhiyun return True 97*4882a593Smuzhiyun return False 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun feature = 'require conf/distro/include/maintainers.inc\nLICENSE_FLAGS_ACCEPTED += " commercial"\nPARSE_ALL_RECIPES = "1"\nPACKAGE_CLASSES = "package_ipk package_deb package_rpm"\n' 100*4882a593Smuzhiyun self.write_config(feature) 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun with bb.tinfoil.Tinfoil() as tinfoil: 103*4882a593Smuzhiyun tinfoil.prepare(config_only=False) 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun with_maintainer_list = [] 106*4882a593Smuzhiyun no_maintainer_list = [] 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun missing_recipes = [] 109*4882a593Smuzhiyun recipes = [] 110*4882a593Smuzhiyun prefix = "RECIPE_MAINTAINER:pn-" 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun # We could have used all_recipes() here, but this method will find 113*4882a593Smuzhiyun # every recipe if we ever move to setting RECIPE_MAINTAINER in recipe files 114*4882a593Smuzhiyun # instead of maintainers.inc 115*4882a593Smuzhiyun for fn in tinfoil.all_recipe_files(variants=False): 116*4882a593Smuzhiyun if not '/meta/recipes-' in fn: 117*4882a593Smuzhiyun # We are only interested in OE-Core 118*4882a593Smuzhiyun continue 119*4882a593Smuzhiyun rd = tinfoil.parse_recipe_file(fn, appends=False) 120*4882a593Smuzhiyun pn = rd.getVar('PN') 121*4882a593Smuzhiyun recipes.append(pn) 122*4882a593Smuzhiyun if is_exception(pn): 123*4882a593Smuzhiyun continue 124*4882a593Smuzhiyun if rd.getVar('RECIPE_MAINTAINER'): 125*4882a593Smuzhiyun with_maintainer_list.append((pn, fn)) 126*4882a593Smuzhiyun else: 127*4882a593Smuzhiyun no_maintainer_list.append((pn, fn)) 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun maintainers = tinfoil.config_data.keys() 130*4882a593Smuzhiyun for key in maintainers: 131*4882a593Smuzhiyun if key.startswith(prefix): 132*4882a593Smuzhiyun recipe = tinfoil.config_data.expand(key[len(prefix):]) 133*4882a593Smuzhiyun if is_maintainer_exception(recipe): 134*4882a593Smuzhiyun continue 135*4882a593Smuzhiyun if recipe not in recipes: 136*4882a593Smuzhiyun missing_recipes.append(recipe) 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun if no_maintainer_list: 139*4882a593Smuzhiyun self.fail(""" 140*4882a593SmuzhiyunThe following recipes do not have a maintainer assigned to them. Please add an entry to meta/conf/distro/include/maintainers.inc file. 141*4882a593Smuzhiyun""" + "\n".join(['%s (%s)' % i for i in no_maintainer_list])) 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun if not with_maintainer_list: 144*4882a593Smuzhiyun self.fail(""" 145*4882a593SmuzhiyunThe list of oe-core recipes with maintainers is empty. This may indicate that the test has regressed and needs fixing. 146*4882a593Smuzhiyun""") 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun if missing_recipes: 149*4882a593Smuzhiyun self.fail(""" 150*4882a593SmuzhiyunUnable to find recipes for the following entries in maintainers.inc: 151*4882a593Smuzhiyun""" + "\n".join(['%s' % i for i in missing_recipes])) 152