1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# SPDX-License-Identifier: MIT 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun 5*4882a593Smuzhiyunfrom oeqa.selftest.case import OESelftestTestCase 6*4882a593Smuzhiyunfrom oeqa.core.decorator import OETestTag 7*4882a593Smuzhiyunfrom oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu 8*4882a593Smuzhiyunfrom oeqa.utils.sshcontrol import SSHControl 9*4882a593Smuzhiyunimport glob 10*4882a593Smuzhiyunimport os 11*4882a593Smuzhiyunimport json 12*4882a593Smuzhiyun 13*4882a593Smuzhiyunclass ImageFeatures(OESelftestTestCase): 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun test_user = 'tester' 16*4882a593Smuzhiyun root_user = 'root' 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun @OETestTag("runqemu") 19*4882a593Smuzhiyun def test_non_root_user_can_connect_via_ssh_without_password(self): 20*4882a593Smuzhiyun """ 21*4882a593Smuzhiyun Summary: Check if non root user can connect via ssh without password 22*4882a593Smuzhiyun Expected: 1. Connection to the image via ssh using root user without providing a password should be allowed. 23*4882a593Smuzhiyun 2. Connection to the image via ssh using tester user without providing a password should be allowed. 24*4882a593Smuzhiyun Product: oe-core 25*4882a593Smuzhiyun Author: Ionut Chisanovici <ionutx.chisanovici@intel.com> 26*4882a593Smuzhiyun AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com> 27*4882a593Smuzhiyun """ 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh empty-root-password allow-empty-password allow-root-login"\n' 30*4882a593Smuzhiyun features += 'INHERIT += "extrausers"\n' 31*4882a593Smuzhiyun features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user) 32*4882a593Smuzhiyun self.write_config(features) 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun # Build a core-image-minimal 35*4882a593Smuzhiyun bitbake('core-image-minimal') 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun with runqemu("core-image-minimal") as qemu: 38*4882a593Smuzhiyun # Attempt to ssh with each user into qemu with empty password 39*4882a593Smuzhiyun for user in [self.root_user, self.test_user]: 40*4882a593Smuzhiyun ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user) 41*4882a593Smuzhiyun status, output = ssh.run("true") 42*4882a593Smuzhiyun self.assertEqual(status, 0, 'ssh to user %s failed with %s' % (user, output)) 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun @OETestTag("runqemu") 45*4882a593Smuzhiyun def test_all_users_can_connect_via_ssh_without_password(self): 46*4882a593Smuzhiyun """ 47*4882a593Smuzhiyun Summary: Check if all users can connect via ssh without password 48*4882a593Smuzhiyun Expected: 1. Connection to the image via ssh using root user without providing a password should NOT be allowed. 49*4882a593Smuzhiyun 2. Connection to the image via ssh using tester user without providing a password should be allowed. 50*4882a593Smuzhiyun Product: oe-core 51*4882a593Smuzhiyun Author: Ionut Chisanovici <ionutx.chisanovici@intel.com> 52*4882a593Smuzhiyun AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com> 53*4882a593Smuzhiyun """ 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh allow-empty-password allow-root-login"\n' 56*4882a593Smuzhiyun features += 'INHERIT += "extrausers"\n' 57*4882a593Smuzhiyun features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user) 58*4882a593Smuzhiyun self.write_config(features) 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun # Build a core-image-minimal 61*4882a593Smuzhiyun bitbake('core-image-minimal') 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun with runqemu("core-image-minimal") as qemu: 64*4882a593Smuzhiyun # Attempt to ssh with each user into qemu with empty password 65*4882a593Smuzhiyun for user in [self.root_user, self.test_user]: 66*4882a593Smuzhiyun ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user) 67*4882a593Smuzhiyun status, output = ssh.run("true") 68*4882a593Smuzhiyun if user == 'root': 69*4882a593Smuzhiyun self.assertNotEqual(status, 0, 'ssh to user root was allowed when it should not have been') 70*4882a593Smuzhiyun else: 71*4882a593Smuzhiyun self.assertEqual(status, 0, 'ssh to user tester failed with %s' % output) 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun def test_wayland_support_in_image(self): 75*4882a593Smuzhiyun """ 76*4882a593Smuzhiyun Summary: Check Wayland support in image 77*4882a593Smuzhiyun Expected: 1. Wayland image can be build 78*4882a593Smuzhiyun 2. Wayland feature can be installed 79*4882a593Smuzhiyun Product: oe-core 80*4882a593Smuzhiyun Author: Ionut Chisanovici <ionutx.chisanovici@intel.com> 81*4882a593Smuzhiyun AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com> 82*4882a593Smuzhiyun """ 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun distro_features = get_bb_var('DISTRO_FEATURES') 85*4882a593Smuzhiyun if not ('opengl' in distro_features and 'wayland' in distro_features): 86*4882a593Smuzhiyun self.skipTest('neither opengl nor wayland present on DISTRO_FEATURES so core-image-weston cannot be built') 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun # Build a core-image-weston 89*4882a593Smuzhiyun bitbake('core-image-weston') 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun def test_bmap(self): 92*4882a593Smuzhiyun """ 93*4882a593Smuzhiyun Summary: Check bmap support 94*4882a593Smuzhiyun Expected: 1. core-image-minimal can be build with bmap support 95*4882a593Smuzhiyun 2. core-image-minimal is sparse 96*4882a593Smuzhiyun Product: oe-core 97*4882a593Smuzhiyun Author: Ed Bartosh <ed.bartosh@linux.intel.com> 98*4882a593Smuzhiyun """ 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun features = 'IMAGE_FSTYPES += " ext4 ext4.bmap ext4.bmap.gz"' 101*4882a593Smuzhiyun self.write_config(features) 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun image_name = 'core-image-minimal' 104*4882a593Smuzhiyun bitbake(image_name) 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 107*4882a593Smuzhiyun link_name = get_bb_var('IMAGE_LINK_NAME', image_name) 108*4882a593Smuzhiyun image_path = os.path.join(deploy_dir_image, "%s.ext4" % link_name) 109*4882a593Smuzhiyun bmap_path = "%s.bmap" % image_path 110*4882a593Smuzhiyun gzip_path = "%s.gz" % bmap_path 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun # check if result image, bmap and bmap.gz files are in deploy directory 113*4882a593Smuzhiyun self.assertTrue(os.path.exists(image_path)) 114*4882a593Smuzhiyun self.assertTrue(os.path.exists(bmap_path)) 115*4882a593Smuzhiyun self.assertTrue(os.path.exists(gzip_path)) 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun # check if result image is sparse 118*4882a593Smuzhiyun image_stat = os.stat(image_path) 119*4882a593Smuzhiyun self.assertGreater(image_stat.st_size, image_stat.st_blocks * 512) 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun # check if the resulting gzip is valid 122*4882a593Smuzhiyun self.assertTrue(runCmd('gzip -t %s' % gzip_path)) 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun def test_hypervisor_fmts(self): 125*4882a593Smuzhiyun """ 126*4882a593Smuzhiyun Summary: Check various hypervisor formats 127*4882a593Smuzhiyun Expected: 1. core-image-minimal can be built with vmdk, vdi and 128*4882a593Smuzhiyun qcow2 support. 129*4882a593Smuzhiyun 2. qemu-img says each image has the expected format 130*4882a593Smuzhiyun Product: oe-core 131*4882a593Smuzhiyun Author: Tom Rini <trini@konsulko.com> 132*4882a593Smuzhiyun """ 133*4882a593Smuzhiyun 134*4882a593Smuzhiyun img_types = [ 'vmdk', 'vdi', 'qcow2' ] 135*4882a593Smuzhiyun features = "" 136*4882a593Smuzhiyun for itype in img_types: 137*4882a593Smuzhiyun features += 'IMAGE_FSTYPES += "wic.%s"\n' % itype 138*4882a593Smuzhiyun self.write_config(features) 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun image_name = 'core-image-minimal' 141*4882a593Smuzhiyun bitbake(image_name) 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 144*4882a593Smuzhiyun link_name = get_bb_var('IMAGE_LINK_NAME', image_name) 145*4882a593Smuzhiyun for itype in img_types: 146*4882a593Smuzhiyun image_path = os.path.join(deploy_dir_image, "%s.wic.%s" % 147*4882a593Smuzhiyun (link_name, itype)) 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun # check if result image file is in deploy directory 150*4882a593Smuzhiyun self.assertTrue(os.path.exists(image_path)) 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun # check if result image is vmdk 153*4882a593Smuzhiyun sysroot = get_bb_var('STAGING_DIR_NATIVE', 'core-image-minimal') 154*4882a593Smuzhiyun result = runCmd('qemu-img info --output json %s' % image_path, 155*4882a593Smuzhiyun native_sysroot=sysroot) 156*4882a593Smuzhiyun try: 157*4882a593Smuzhiyun data = json.loads(result.output) 158*4882a593Smuzhiyun self.assertEqual(data.get('format'), itype, 159*4882a593Smuzhiyun msg="Unexpected format in '%s'" % (result.output)) 160*4882a593Smuzhiyun except json.decoder.JSONDecodeError: 161*4882a593Smuzhiyun self.fail("Could not parse '%ss'" % result.output) 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun def test_long_chain_conversion(self): 164*4882a593Smuzhiyun """ 165*4882a593Smuzhiyun Summary: Check for chaining many CONVERSION_CMDs together 166*4882a593Smuzhiyun Expected: 1. core-image-minimal can be built with 167*4882a593Smuzhiyun ext4.bmap.gz.bz2.lzo.xz.u-boot and also create a 168*4882a593Smuzhiyun sha256sum 169*4882a593Smuzhiyun 2. The above image has a valid sha256sum 170*4882a593Smuzhiyun Product: oe-core 171*4882a593Smuzhiyun Author: Tom Rini <trini@konsulko.com> 172*4882a593Smuzhiyun """ 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun conv = "ext4.bmap.gz.bz2.lzo.xz.u-boot" 175*4882a593Smuzhiyun features = 'IMAGE_FSTYPES += "%s %s.sha256sum"' % (conv, conv) 176*4882a593Smuzhiyun self.write_config(features) 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun image_name = 'core-image-minimal' 179*4882a593Smuzhiyun bitbake(image_name) 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 182*4882a593Smuzhiyun link_name = get_bb_var('IMAGE_LINK_NAME', image_name) 183*4882a593Smuzhiyun image_path = os.path.join(deploy_dir_image, "%s.%s" % 184*4882a593Smuzhiyun (link_name, conv)) 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun # check if resulting image is in the deploy directory 187*4882a593Smuzhiyun self.assertTrue(os.path.exists(image_path)) 188*4882a593Smuzhiyun self.assertTrue(os.path.exists(image_path + ".sha256sum")) 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun # check if the resulting sha256sum agrees 191*4882a593Smuzhiyun self.assertTrue(runCmd('cd %s;sha256sum -c %s.%s.sha256sum' % 192*4882a593Smuzhiyun (deploy_dir_image, link_name, conv))) 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun def test_image_fstypes(self): 195*4882a593Smuzhiyun """ 196*4882a593Smuzhiyun Summary: Check if image of supported image fstypes can be built 197*4882a593Smuzhiyun Expected: core-image-minimal can be built for various image types 198*4882a593Smuzhiyun Product: oe-core 199*4882a593Smuzhiyun Author: Ed Bartosh <ed.bartosh@linux.intel.com> 200*4882a593Smuzhiyun """ 201*4882a593Smuzhiyun image_name = 'core-image-minimal' 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun all_image_types = set(get_bb_var("IMAGE_TYPES", image_name).split()) 204*4882a593Smuzhiyun skip_image_types = set(('container', 'elf', 'f2fs', 'multiubi', 'tar.zst', 'wic.zst')) 205*4882a593Smuzhiyun img_types = all_image_types - skip_image_types 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun config = 'IMAGE_FSTYPES += "%s"\n'\ 208*4882a593Smuzhiyun 'MKUBIFS_ARGS ?= "-m 2048 -e 129024 -c 2047"\n'\ 209*4882a593Smuzhiyun 'UBINIZE_ARGS ?= "-m 2048 -p 128KiB -s 512"' % ' '.join(img_types) 210*4882a593Smuzhiyun self.write_config(config) 211*4882a593Smuzhiyun 212*4882a593Smuzhiyun bitbake(image_name) 213*4882a593Smuzhiyun 214*4882a593Smuzhiyun deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 215*4882a593Smuzhiyun link_name = get_bb_var('IMAGE_LINK_NAME', image_name) 216*4882a593Smuzhiyun for itype in img_types: 217*4882a593Smuzhiyun image_path = os.path.join(deploy_dir_image, "%s.%s" % (link_name, itype)) 218*4882a593Smuzhiyun # check if result image is in deploy directory 219*4882a593Smuzhiyun self.assertTrue(os.path.exists(image_path), 220*4882a593Smuzhiyun "%s image %s doesn't exist" % (itype, image_path)) 221*4882a593Smuzhiyun 222*4882a593Smuzhiyun def test_useradd_static(self): 223*4882a593Smuzhiyun config = """ 224*4882a593SmuzhiyunUSERADDEXTENSION = "useradd-staticids" 225*4882a593SmuzhiyunUSERADD_ERROR_DYNAMIC = "skip" 226*4882a593SmuzhiyunUSERADD_UID_TABLES += "files/static-passwd" 227*4882a593SmuzhiyunUSERADD_GID_TABLES += "files/static-group" 228*4882a593Smuzhiyun""" 229*4882a593Smuzhiyun self.write_config(config) 230*4882a593Smuzhiyun bitbake("core-image-base") 231*4882a593Smuzhiyun 232*4882a593Smuzhiyun def test_no_busybox_base_utils(self): 233*4882a593Smuzhiyun config = """ 234*4882a593Smuzhiyun# Enable wayland 235*4882a593SmuzhiyunDISTRO_FEATURES:append = " pam opengl wayland" 236*4882a593Smuzhiyun 237*4882a593Smuzhiyun# Switch to systemd 238*4882a593SmuzhiyunDISTRO_FEATURES:append = " systemd" 239*4882a593SmuzhiyunVIRTUAL-RUNTIME_init_manager = "systemd" 240*4882a593SmuzhiyunVIRTUAL-RUNTIME_initscripts = "" 241*4882a593SmuzhiyunVIRTUAL-RUNTIME_syslog = "" 242*4882a593SmuzhiyunVIRTUAL-RUNTIME_login_manager = "shadow-base" 243*4882a593SmuzhiyunDISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" 244*4882a593Smuzhiyun 245*4882a593Smuzhiyun# Replace busybox 246*4882a593SmuzhiyunPREFERRED_PROVIDER_virtual/base-utils = "packagegroup-core-base-utils" 247*4882a593SmuzhiyunVIRTUAL-RUNTIME_base-utils = "packagegroup-core-base-utils" 248*4882a593SmuzhiyunVIRTUAL-RUNTIME_base-utils-hwclock = "util-linux-hwclock" 249*4882a593SmuzhiyunVIRTUAL-RUNTIME_base-utils-syslog = "" 250*4882a593Smuzhiyun 251*4882a593Smuzhiyun# Skip busybox 252*4882a593SmuzhiyunSKIP_RECIPE[busybox] = "Don't build this" 253*4882a593Smuzhiyun""" 254*4882a593Smuzhiyun self.write_config(config) 255*4882a593Smuzhiyun 256*4882a593Smuzhiyun bitbake("--graphviz core-image-weston") 257*4882a593Smuzhiyun 258*4882a593Smuzhiyun def test_image_gen_debugfs(self): 259*4882a593Smuzhiyun """ 260*4882a593Smuzhiyun Summary: Check debugfs generation 261*4882a593Smuzhiyun Expected: 1. core-image-minimal can be build with IMAGE_GEN_DEBUGFS variable set 262*4882a593Smuzhiyun 2. debug filesystem is created when variable set 263*4882a593Smuzhiyun 3. debug symbols available 264*4882a593Smuzhiyun Product: oe-core 265*4882a593Smuzhiyun Author: Humberto Ibarra <humberto.ibarra.lopez@intel.com> 266*4882a593Smuzhiyun Yeoh Ee Peng <ee.peng.yeoh@intel.com> 267*4882a593Smuzhiyun """ 268*4882a593Smuzhiyun 269*4882a593Smuzhiyun image_name = 'core-image-minimal' 270*4882a593Smuzhiyun features = 'IMAGE_GEN_DEBUGFS = "1"\n' 271*4882a593Smuzhiyun features += 'IMAGE_FSTYPES_DEBUGFS = "tar.bz2"\n' 272*4882a593Smuzhiyun features += 'MACHINE = "genericx86-64"\n' 273*4882a593Smuzhiyun self.write_config(features) 274*4882a593Smuzhiyun 275*4882a593Smuzhiyun bitbake(image_name) 276*4882a593Smuzhiyun deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 277*4882a593Smuzhiyun dbg_tar_file = os.path.join(deploy_dir_image, "*-dbg.rootfs.tar.bz2") 278*4882a593Smuzhiyun debug_files = glob.glob(dbg_tar_file) 279*4882a593Smuzhiyun self.assertNotEqual(len(debug_files), 0, 'debug filesystem not generated at %s' % dbg_tar_file) 280*4882a593Smuzhiyun result = runCmd('cd %s; tar xvf %s' % (deploy_dir_image, dbg_tar_file)) 281*4882a593Smuzhiyun self.assertEqual(result.status, 0, msg='Failed to extract %s: %s' % (dbg_tar_file, result.output)) 282*4882a593Smuzhiyun result = runCmd('find %s -name %s' % (deploy_dir_image, "udevadm")) 283*4882a593Smuzhiyun self.assertTrue("udevadm" in result.output, msg='Failed to find udevadm: %s' % result.output) 284*4882a593Smuzhiyun dbg_symbols_targets = result.output.splitlines() 285*4882a593Smuzhiyun self.assertTrue(dbg_symbols_targets, msg='Failed to split udevadm: %s' % dbg_symbols_targets) 286*4882a593Smuzhiyun for t in dbg_symbols_targets: 287*4882a593Smuzhiyun result = runCmd('objdump --syms %s | grep debug' % t) 288*4882a593Smuzhiyun self.assertTrue("debug" in result.output, msg='Failed to find debug symbol: %s' % result.output) 289*4882a593Smuzhiyun 290*4882a593Smuzhiyun def test_empty_image(self): 291*4882a593Smuzhiyun """Test creation of image with no packages""" 292*4882a593Smuzhiyun bitbake('test-empty-image') 293*4882a593Smuzhiyun res_dir = get_bb_var('DEPLOY_DIR_IMAGE') 294*4882a593Smuzhiyun images = os.path.join(res_dir, "test-empty-image-*.manifest") 295*4882a593Smuzhiyun result = glob.glob(images) 296*4882a593Smuzhiyun with open(result[1],"r") as f: 297*4882a593Smuzhiyun self.assertEqual(len(f.read().strip()),0) 298