1*4882a593Smuzhiyun# Copyright (C) 2017 Intel Corporation 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# SPDX-License-Identifier: MIT 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun 6*4882a593Smuzhiyunimport glob 7*4882a593Smuzhiyunimport os 8*4882a593Smuzhiyunimport unittest 9*4882a593Smuzhiyunimport re 10*4882a593Smuzhiyunfrom checklayer import get_signatures, LayerType, check_command, get_depgraph, compare_signatures 11*4882a593Smuzhiyunfrom checklayer.case import OECheckLayerTestCase 12*4882a593Smuzhiyun 13*4882a593Smuzhiyunclass CommonCheckLayer(OECheckLayerTestCase): 14*4882a593Smuzhiyun def test_readme(self): 15*4882a593Smuzhiyun if self.tc.layer['type'] == LayerType.CORE: 16*4882a593Smuzhiyun raise unittest.SkipTest("Core layer's README is top level") 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun # The top-level README file may have a suffix (like README.rst or README.txt). 19*4882a593Smuzhiyun readme_files = glob.glob(os.path.join(self.tc.layer['path'], '[Rr][Ee][Aa][Dd][Mm][Ee]*')) 20*4882a593Smuzhiyun self.assertTrue(len(readme_files) > 0, 21*4882a593Smuzhiyun msg="Layer doesn't contain a README file.") 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun # There might be more than one file matching the file pattern above 24*4882a593Smuzhiyun # (for example, README.rst and README-COPYING.rst). The one with the shortest 25*4882a593Smuzhiyun # name is considered the "main" one. 26*4882a593Smuzhiyun readme_file = sorted(readme_files)[0] 27*4882a593Smuzhiyun data = '' 28*4882a593Smuzhiyun with open(readme_file, 'r') as f: 29*4882a593Smuzhiyun data = f.read() 30*4882a593Smuzhiyun self.assertTrue(data, 31*4882a593Smuzhiyun msg="Layer contains a README file but it is empty.") 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun # If a layer's README references another README, then the checks below are not valid 34*4882a593Smuzhiyun if re.search('README', data, re.IGNORECASE): 35*4882a593Smuzhiyun return 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun self.assertIn('maintainer', data.lower()) 38*4882a593Smuzhiyun self.assertIn('patch', data.lower()) 39*4882a593Smuzhiyun # Check that there is an email address in the README 40*4882a593Smuzhiyun email_regex = re.compile(r"[^@]+@[^@]+") 41*4882a593Smuzhiyun self.assertTrue(email_regex.match(data)) 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun def test_parse(self): 44*4882a593Smuzhiyun check_command('Layer %s failed to parse.' % self.tc.layer['name'], 45*4882a593Smuzhiyun 'bitbake -p') 46*4882a593Smuzhiyun 47*4882a593Smuzhiyun def test_show_environment(self): 48*4882a593Smuzhiyun check_command('Layer %s failed to show environment.' % self.tc.layer['name'], 49*4882a593Smuzhiyun 'bitbake -e') 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun def test_world(self): 52*4882a593Smuzhiyun ''' 53*4882a593Smuzhiyun "bitbake world" is expected to work. test_signatures does not cover that 54*4882a593Smuzhiyun because it is more lenient and ignores recipes in a world build that 55*4882a593Smuzhiyun are not actually buildable, so here we fail when "bitbake -S none world" 56*4882a593Smuzhiyun fails. 57*4882a593Smuzhiyun ''' 58*4882a593Smuzhiyun get_signatures(self.td['builddir'], failsafe=False) 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun def test_world_inherit_class(self): 61*4882a593Smuzhiyun ''' 62*4882a593Smuzhiyun This also does "bitbake -S none world" along with inheriting "yocto-check-layer" 63*4882a593Smuzhiyun class, which can do additional per-recipe test cases. 64*4882a593Smuzhiyun ''' 65*4882a593Smuzhiyun msg = [] 66*4882a593Smuzhiyun try: 67*4882a593Smuzhiyun get_signatures(self.td['builddir'], failsafe=False, machine=None, extravars='BB_ENV_PASSTHROUGH_ADDITIONS="$BB_ENV_PASSTHROUGH_ADDITIONS INHERIT" INHERIT="yocto-check-layer"') 68*4882a593Smuzhiyun except RuntimeError as ex: 69*4882a593Smuzhiyun msg.append(str(ex)) 70*4882a593Smuzhiyun if msg: 71*4882a593Smuzhiyun msg.insert(0, 'Layer %s failed additional checks from yocto-check-layer.bbclass\nSee below log for specific recipe parsing errors:\n' % \ 72*4882a593Smuzhiyun self.tc.layer['name']) 73*4882a593Smuzhiyun self.fail('\n'.join(msg)) 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun def test_signatures(self): 76*4882a593Smuzhiyun if self.tc.layer['type'] == LayerType.SOFTWARE and \ 77*4882a593Smuzhiyun not self.tc.test_software_layer_signatures: 78*4882a593Smuzhiyun raise unittest.SkipTest("Not testing for signature changes in a software layer %s." \ 79*4882a593Smuzhiyun % self.tc.layer['name']) 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun curr_sigs, _ = get_signatures(self.td['builddir'], failsafe=True) 82*4882a593Smuzhiyun msg = compare_signatures(self.td['sigs'], curr_sigs) 83*4882a593Smuzhiyun if msg is not None: 84*4882a593Smuzhiyun self.fail('Adding layer %s changed signatures.\n%s' % (self.tc.layer['name'], msg)) 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun def test_layerseries_compat(self): 87*4882a593Smuzhiyun for collection_name, collection_data in self.tc.layer['collections'].items(): 88*4882a593Smuzhiyun self.assertTrue(collection_data['compat'], "Collection %s from layer %s does not set compatible oe-core versions via LAYERSERIES_COMPAT_collection." \ 89*4882a593Smuzhiyun % (collection_name, self.tc.layer['name'])) 90