1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# SPDX-License-Identifier: MIT 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun 5*4882a593Smuzhiyunimport os 6*4882a593Smuzhiyunimport re 7*4882a593Smuzhiyunimport glob as g 8*4882a593Smuzhiyunimport shutil 9*4882a593Smuzhiyunimport tempfile 10*4882a593Smuzhiyunfrom oeqa.selftest.case import OESelftestTestCase 11*4882a593Smuzhiyunfrom oeqa.selftest.cases.buildhistory import BuildhistoryBase 12*4882a593Smuzhiyunfrom oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars 13*4882a593Smuzhiyunimport oeqa.utils.ftools as ftools 14*4882a593Smuzhiyun 15*4882a593Smuzhiyunclass ImageOptionsTests(OESelftestTestCase): 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun def test_incremental_image_generation(self): 18*4882a593Smuzhiyun image_pkgtype = get_bb_var("IMAGE_PKGTYPE") 19*4882a593Smuzhiyun if image_pkgtype != 'rpm': 20*4882a593Smuzhiyun self.skipTest('Not using RPM as main package format') 21*4882a593Smuzhiyun bitbake("-c clean core-image-minimal") 22*4882a593Smuzhiyun self.write_config('INC_RPM_IMAGE_GEN = "1"') 23*4882a593Smuzhiyun self.append_config('IMAGE_FEATURES += "ssh-server-openssh"') 24*4882a593Smuzhiyun bitbake("core-image-minimal") 25*4882a593Smuzhiyun log_data_file = os.path.join(get_bb_var("WORKDIR", "core-image-minimal"), "temp/log.do_rootfs") 26*4882a593Smuzhiyun log_data_created = ftools.read_file(log_data_file) 27*4882a593Smuzhiyun incremental_created = re.search(r"Installing\s*:\s*packagegroup-core-ssh-openssh", log_data_created) 28*4882a593Smuzhiyun self.remove_config('IMAGE_FEATURES += "ssh-server-openssh"') 29*4882a593Smuzhiyun self.assertTrue(incremental_created, msg = "Match failed in:\n%s" % log_data_created) 30*4882a593Smuzhiyun bitbake("core-image-minimal") 31*4882a593Smuzhiyun log_data_removed = ftools.read_file(log_data_file) 32*4882a593Smuzhiyun incremental_removed = re.search(r"Erasing\s*:\s*packagegroup-core-ssh-openssh", log_data_removed) 33*4882a593Smuzhiyun self.assertTrue(incremental_removed, msg = "Match failed in:\n%s" % log_data_removed) 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun def test_ccache_tool(self): 36*4882a593Smuzhiyun bitbake("ccache-native") 37*4882a593Smuzhiyun bb_vars = get_bb_vars(['SYSROOT_DESTDIR', 'bindir'], 'ccache-native') 38*4882a593Smuzhiyun p = bb_vars['SYSROOT_DESTDIR'] + bb_vars['bindir'] + "/" + "ccache" 39*4882a593Smuzhiyun self.assertTrue(os.path.isfile(p), msg = "No ccache found (%s)" % p) 40*4882a593Smuzhiyun self.write_config('INHERIT += "ccache"') 41*4882a593Smuzhiyun recipe = "libgcc-initial" 42*4882a593Smuzhiyun self.add_command_to_tearDown('bitbake -c clean %s' % recipe) 43*4882a593Smuzhiyun bitbake("%s -c clean" % recipe) 44*4882a593Smuzhiyun bitbake("%s -f -c compile" % recipe) 45*4882a593Smuzhiyun log_compile = os.path.join(get_bb_var("WORKDIR", recipe), "temp/log.do_compile") 46*4882a593Smuzhiyun with open(log_compile, "r") as f: 47*4882a593Smuzhiyun loglines = "".join(f.readlines()) 48*4882a593Smuzhiyun self.assertIn("ccache", loglines, msg="No match for ccache in %s log.do_compile. For further details: %s" % (recipe , log_compile)) 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun def test_read_only_image(self): 51*4882a593Smuzhiyun distro_features = get_bb_var('DISTRO_FEATURES') 52*4882a593Smuzhiyun if not ('x11' in distro_features and 'opengl' in distro_features): 53*4882a593Smuzhiyun self.skipTest('core-image-sato/weston requires x11 and opengl in distro features') 54*4882a593Smuzhiyun self.write_config('IMAGE_FEATURES += "read-only-rootfs"') 55*4882a593Smuzhiyun bitbake("core-image-sato core-image-weston") 56*4882a593Smuzhiyun # do_image will fail if there are any pending postinsts 57*4882a593Smuzhiyun 58*4882a593Smuzhiyunclass DiskMonTest(OESelftestTestCase): 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun def test_stoptask_behavior(self): 61*4882a593Smuzhiyun self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"') 62*4882a593Smuzhiyun res = bitbake("delay -c delay", ignore_status = True) 63*4882a593Smuzhiyun self.assertTrue('ERROR: No new tasks can be executed since the disk space monitor action is "STOPTASKS"!' in res.output, msg = "Tasks should have stopped. Disk monitor is set to STOPTASK: %s" % res.output) 64*4882a593Smuzhiyun self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) 65*4882a593Smuzhiyun self.write_config('BB_DISKMON_DIRS = "HALT,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"') 66*4882a593Smuzhiyun res = bitbake("delay -c delay", ignore_status = True) 67*4882a593Smuzhiyun self.assertTrue('ERROR: Immediately halt since the disk space monitor action is "HALT"!' in res.output, "Tasks should have been halted immediately. Disk monitor is set to HALT: %s" % res.output) 68*4882a593Smuzhiyun self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) 69*4882a593Smuzhiyun self.write_config('BB_DISKMON_DIRS = "WARN,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"') 70*4882a593Smuzhiyun res = bitbake("delay -c delay") 71*4882a593Smuzhiyun self.assertTrue('WARNING: The free space' in res.output, msg = "A warning should have been displayed for disk monitor is set to WARN: %s" %res.output) 72*4882a593Smuzhiyun 73*4882a593Smuzhiyunclass SanityOptionsTest(OESelftestTestCase): 74*4882a593Smuzhiyun def getline(self, res, line): 75*4882a593Smuzhiyun for l in res.output.split('\n'): 76*4882a593Smuzhiyun if line in l: 77*4882a593Smuzhiyun return l 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun def test_options_warnqa_errorqa_switch(self): 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun self.write_config("INHERIT:remove = \"report-error\"") 82*4882a593Smuzhiyun if "packages-list" not in get_bb_var("ERROR_QA"): 83*4882a593Smuzhiyun self.append_config("ERROR_QA:append = \" packages-list\"") 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"') 86*4882a593Smuzhiyun self.add_command_to_tearDown('bitbake -c clean xcursor-transparent-theme') 87*4882a593Smuzhiyun res = bitbake("xcursor-transparent-theme -f -c package", ignore_status=True) 88*4882a593Smuzhiyun self.delete_recipeinc('xcursor-transparent-theme') 89*4882a593Smuzhiyun line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.") 90*4882a593Smuzhiyun self.assertTrue(line and line.startswith("ERROR:"), msg=res.output) 91*4882a593Smuzhiyun self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) 92*4882a593Smuzhiyun self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"') 93*4882a593Smuzhiyun self.append_config('ERROR_QA:remove = "packages-list"') 94*4882a593Smuzhiyun self.append_config('WARN_QA:append = " packages-list"') 95*4882a593Smuzhiyun res = bitbake("xcursor-transparent-theme -f -c package") 96*4882a593Smuzhiyun self.delete_recipeinc('xcursor-transparent-theme') 97*4882a593Smuzhiyun line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.") 98*4882a593Smuzhiyun self.assertTrue(line and line.startswith("WARNING:"), msg=res.output) 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun def test_layer_without_git_dir(self): 101*4882a593Smuzhiyun """ 102*4882a593Smuzhiyun Summary: Test that layer git revisions are displayed and do not fail without git repository 103*4882a593Smuzhiyun Expected: The build to be successful and without "fatal" errors 104*4882a593Smuzhiyun Product: oe-core 105*4882a593Smuzhiyun Author: Daniel Istrate <daniel.alexandrux.istrate@intel.com> 106*4882a593Smuzhiyun AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com> 107*4882a593Smuzhiyun """ 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun dirpath = tempfile.mkdtemp() 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun dummy_layer_name = 'meta-dummy' 112*4882a593Smuzhiyun dummy_layer_path = os.path.join(dirpath, dummy_layer_name) 113*4882a593Smuzhiyun dummy_layer_conf_dir = os.path.join(dummy_layer_path, 'conf') 114*4882a593Smuzhiyun os.makedirs(dummy_layer_conf_dir) 115*4882a593Smuzhiyun dummy_layer_conf_path = os.path.join(dummy_layer_conf_dir, 'layer.conf') 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun dummy_layer_content = 'BBPATH .= ":${LAYERDIR}"\n' \ 118*4882a593Smuzhiyun 'BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"\n' \ 119*4882a593Smuzhiyun 'BBFILE_COLLECTIONS += "%s"\n' \ 120*4882a593Smuzhiyun 'BBFILE_PATTERN_%s = "^${LAYERDIR}/"\n' \ 121*4882a593Smuzhiyun 'BBFILE_PRIORITY_%s = "6"\n' % (dummy_layer_name, dummy_layer_name, dummy_layer_name) 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun ftools.write_file(dummy_layer_conf_path, dummy_layer_content) 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun bblayers_conf = 'BBLAYERS += "%s"\n' % dummy_layer_path 126*4882a593Smuzhiyun self.write_bblayers_config(bblayers_conf) 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun test_recipe = 'ed' 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun ret = bitbake('-n %s' % test_recipe) 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun err = 'fatal: Not a git repository' 133*4882a593Smuzhiyun 134*4882a593Smuzhiyun shutil.rmtree(dirpath) 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun self.assertNotIn(err, ret.output) 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun 139*4882a593Smuzhiyunclass BuildhistoryTests(BuildhistoryBase): 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun def test_buildhistory_basic(self): 142*4882a593Smuzhiyun self.run_buildhistory_operation('xcursor-transparent-theme') 143*4882a593Smuzhiyun self.assertTrue(os.path.isdir(get_bb_var('BUILDHISTORY_DIR')), "buildhistory dir was not created.") 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun def test_buildhistory_buildtime_pr_backwards(self): 146*4882a593Smuzhiyun target = 'xcursor-transparent-theme' 147*4882a593Smuzhiyun error = "ERROR:.*QA Issue: Package version for package %s went backwards which would break package feeds \(from .*-r1.* to .*-r0.*\)" % target 148*4882a593Smuzhiyun self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True) 149*4882a593Smuzhiyun self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True, error_regex=error) 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun def test_fileinfo(self): 152*4882a593Smuzhiyun self.config_buildhistory() 153*4882a593Smuzhiyun bitbake('hicolor-icon-theme') 154*4882a593Smuzhiyun history_dir = get_bb_var('BUILDHISTORY_DIR_PACKAGE', 'hicolor-icon-theme') 155*4882a593Smuzhiyun self.assertTrue(os.path.isdir(history_dir), 'buildhistory dir was not created.') 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun def load_bh(f): 158*4882a593Smuzhiyun d = {} 159*4882a593Smuzhiyun for line in open(f): 160*4882a593Smuzhiyun split = [s.strip() for s in line.split('=', 1)] 161*4882a593Smuzhiyun if len(split) > 1: 162*4882a593Smuzhiyun d[split[0]] = split[1] 163*4882a593Smuzhiyun return d 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme', 'latest')) 166*4882a593Smuzhiyun self.assertIn('FILELIST', data) 167*4882a593Smuzhiyun self.assertEqual(data['FILELIST'], '/usr/share/icons/hicolor/index.theme') 168*4882a593Smuzhiyun self.assertGreater(int(data['PKGSIZE']), 0) 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme-dev', 'latest')) 171*4882a593Smuzhiyun if 'FILELIST' in data: 172*4882a593Smuzhiyun self.assertEqual(data['FILELIST'], '') 173*4882a593Smuzhiyun self.assertEqual(int(data['PKGSIZE']), 0) 174*4882a593Smuzhiyun 175*4882a593Smuzhiyunclass ArchiverTest(OESelftestTestCase): 176*4882a593Smuzhiyun def test_arch_work_dir_and_export_source(self): 177*4882a593Smuzhiyun """ 178*4882a593Smuzhiyun Test for archiving the work directory and exporting the source files. 179*4882a593Smuzhiyun """ 180*4882a593Smuzhiyun self.write_config(""" 181*4882a593SmuzhiyunINHERIT += "archiver" 182*4882a593SmuzhiyunPACKAGE_CLASSES = "package_rpm" 183*4882a593SmuzhiyunARCHIVER_MODE[src] = "original" 184*4882a593SmuzhiyunARCHIVER_MODE[srpm] = "1" 185*4882a593Smuzhiyun""") 186*4882a593Smuzhiyun res = bitbake("xcursor-transparent-theme", ignore_status=True) 187*4882a593Smuzhiyun self.assertEqual(res.status, 0, "\nCouldn't build xcursortransparenttheme.\nbitbake output %s" % res.output) 188*4882a593Smuzhiyun deploy_dir_src = get_bb_var('DEPLOY_DIR_SRC') 189*4882a593Smuzhiyun pkgs_path = g.glob(str(deploy_dir_src) + "/allarch*/xcurs*") 190*4882a593Smuzhiyun src_file_glob = str(pkgs_path[0]) + "/xcursor*.src.rpm" 191*4882a593Smuzhiyun tar_file_glob = str(pkgs_path[0]) + "/xcursor*.tar.xz" 192*4882a593Smuzhiyun self.assertTrue((g.glob(src_file_glob) and g.glob(tar_file_glob)), "Couldn't find .src.rpm and .tar.xz files under %s/allarch*/xcursor*" % deploy_dir_src) 193*4882a593Smuzhiyun 194*4882a593Smuzhiyunclass ToolchainOptions(OESelftestTestCase): 195*4882a593Smuzhiyun def test_toolchain_fortran(self): 196*4882a593Smuzhiyun """ 197*4882a593Smuzhiyun Test that Fortran works by building a Hello, World binary. 198*4882a593Smuzhiyun """ 199*4882a593Smuzhiyun 200*4882a593Smuzhiyun features = 'FORTRAN:forcevariable = ",fortran"\n' 201*4882a593Smuzhiyun self.write_config(features) 202*4882a593Smuzhiyun bitbake('fortran-helloworld') 203*4882a593Smuzhiyun 204*4882a593Smuzhiyunclass SourceMirroring(OESelftestTestCase): 205*4882a593Smuzhiyun # Can we download everything from the Yocto Sources Mirror over http only 206*4882a593Smuzhiyun def test_yocto_source_mirror(self): 207*4882a593Smuzhiyun self.write_config(""" 208*4882a593SmuzhiyunBB_ALLOWED_NETWORKS = "downloads.yoctoproject.org" 209*4882a593SmuzhiyunMIRRORS = "" 210*4882a593SmuzhiyunDL_DIR = "${TMPDIR}/test_downloads" 211*4882a593SmuzhiyunSTAMPS_DIR = "${TMPDIR}/test_stamps" 212*4882a593SmuzhiyunSSTATE_DIR = "${TMPDIR}/test_sstate-cache" 213*4882a593SmuzhiyunPREMIRRORS = "\\ 214*4882a593Smuzhiyun bzr://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 215*4882a593Smuzhiyun cvs://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 216*4882a593Smuzhiyun git://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 217*4882a593Smuzhiyun gitsm://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 218*4882a593Smuzhiyun hg://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 219*4882a593Smuzhiyun osc://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 220*4882a593Smuzhiyun p4://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 221*4882a593Smuzhiyun svn://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 222*4882a593Smuzhiyun ftp://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 223*4882a593Smuzhiyun http://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n \\ 224*4882a593Smuzhiyun https://.*/.* http://downloads.yoctoproject.org/mirror/sources/ \\n" 225*4882a593Smuzhiyun""") 226*4882a593Smuzhiyun 227*4882a593Smuzhiyun bitbake("world --runall fetch") 228*4882a593Smuzhiyun 229*4882a593Smuzhiyun 230*4882a593Smuzhiyunclass Poisoning(OESelftestTestCase): 231*4882a593Smuzhiyun def test_poisoning(self): 232*4882a593Smuzhiyun res = bitbake("poison", ignore_status=True) 233*4882a593Smuzhiyun self.assertNotEqual(res.status, 0) 234*4882a593Smuzhiyun self.assertTrue("is unsafe for cross-compilation" in res.output) 235