1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# Copyright (c) 2017 Wind River Systems, Inc. 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# SPDX-License-Identifier: MIT 5*4882a593Smuzhiyun# 6*4882a593Smuzhiyun 7*4882a593Smuzhiyunimport re 8*4882a593Smuzhiyunimport tempfile 9*4882a593Smuzhiyunimport time 10*4882a593Smuzhiyunimport oe.types 11*4882a593Smuzhiyunfrom oeqa.core.decorator import OETestTag 12*4882a593Smuzhiyunfrom oeqa.selftest.case import OESelftestTestCase 13*4882a593Smuzhiyunfrom oeqa.utils.commands import bitbake, runqemu, get_bb_var, runCmd 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun@OETestTag("runqemu") 16*4882a593Smuzhiyunclass RunqemuTests(OESelftestTestCase): 17*4882a593Smuzhiyun """Runqemu test class""" 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun image_is_ready = False 20*4882a593Smuzhiyun deploy_dir_image = '' 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun def setUpLocal(self): 23*4882a593Smuzhiyun super(RunqemuTests, self).setUpLocal() 24*4882a593Smuzhiyun self.recipe = 'core-image-minimal' 25*4882a593Smuzhiyun self.machine = 'qemux86-64' 26*4882a593Smuzhiyun self.fstypes = "ext4 iso hddimg wic.vmdk wic.qcow2 wic.vdi" 27*4882a593Smuzhiyun self.cmd_common = "runqemu nographic" 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun kvm = oe.types.qemu_use_kvm(get_bb_var('QEMU_USE_KVM'), 'x86_64') 30*4882a593Smuzhiyun if kvm: 31*4882a593Smuzhiyun self.cmd_common += " kvm" 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun self.write_config( 34*4882a593Smuzhiyun""" 35*4882a593SmuzhiyunMACHINE = "%s" 36*4882a593SmuzhiyunIMAGE_FSTYPES = "%s" 37*4882a593Smuzhiyun# 10 means 1 second 38*4882a593SmuzhiyunSYSLINUX_TIMEOUT = "10" 39*4882a593Smuzhiyun""" 40*4882a593Smuzhiyun% (self.machine, self.fstypes) 41*4882a593Smuzhiyun ) 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun if not RunqemuTests.image_is_ready: 44*4882a593Smuzhiyun RunqemuTests.deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 45*4882a593Smuzhiyun bitbake(self.recipe) 46*4882a593Smuzhiyun RunqemuTests.image_is_ready = True 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun def test_boot_machine(self): 49*4882a593Smuzhiyun """Test runqemu machine""" 50*4882a593Smuzhiyun cmd = "%s %s" % (self.cmd_common, self.machine) 51*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 52*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 53*4882a593Smuzhiyun self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun def test_boot_machine_ext4(self): 56*4882a593Smuzhiyun """Test runqemu machine ext4""" 57*4882a593Smuzhiyun cmd = "%s %s ext4" % (self.cmd_common, self.machine) 58*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 59*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 60*4882a593Smuzhiyun self.assertIn('rootfs.ext4', f.read(), "Failed: %s" % cmd) 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun def test_boot_machine_iso(self): 63*4882a593Smuzhiyun """Test runqemu machine iso""" 64*4882a593Smuzhiyun cmd = "%s %s iso" % (self.cmd_common, self.machine) 65*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 66*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 67*4882a593Smuzhiyun self.assertIn('media=cdrom', f.read(), "Failed: %s" % cmd) 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun def test_boot_recipe_image(self): 70*4882a593Smuzhiyun """Test runqemu recipe-image""" 71*4882a593Smuzhiyun cmd = "%s %s" % (self.cmd_common, self.recipe) 72*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 73*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 74*4882a593Smuzhiyun self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun def test_boot_recipe_image_vmdk(self): 78*4882a593Smuzhiyun """Test runqemu recipe-image vmdk""" 79*4882a593Smuzhiyun cmd = "%s %s wic.vmdk" % (self.cmd_common, self.recipe) 80*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 81*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 82*4882a593Smuzhiyun self.assertIn('format=vmdk', f.read(), "Failed: %s" % cmd) 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun def test_boot_recipe_image_vdi(self): 85*4882a593Smuzhiyun """Test runqemu recipe-image vdi""" 86*4882a593Smuzhiyun cmd = "%s %s wic.vdi" % (self.cmd_common, self.recipe) 87*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 88*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 89*4882a593Smuzhiyun self.assertIn('format=vdi', f.read(), "Failed: %s" % cmd) 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun def test_boot_deploy(self): 92*4882a593Smuzhiyun """Test runqemu deploy_dir_image""" 93*4882a593Smuzhiyun cmd = "%s %s" % (self.cmd_common, self.deploy_dir_image) 94*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 95*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 96*4882a593Smuzhiyun self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun def test_boot_deploy_hddimg(self): 100*4882a593Smuzhiyun """Test runqemu deploy_dir_image hddimg""" 101*4882a593Smuzhiyun cmd = "%s %s hddimg" % (self.cmd_common, self.deploy_dir_image) 102*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 103*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 104*4882a593Smuzhiyun self.assertTrue(re.search('file=.*.hddimg', f.read()), "Failed: %s, %s" % (cmd, f.read())) 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun def test_boot_machine_slirp(self): 107*4882a593Smuzhiyun """Test runqemu machine slirp""" 108*4882a593Smuzhiyun cmd = "%s slirp %s" % (self.cmd_common, self.machine) 109*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 110*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 111*4882a593Smuzhiyun self.assertIn(' -netdev user', f.read(), "Failed: %s" % cmd) 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun def test_boot_machine_slirp_qcow2(self): 114*4882a593Smuzhiyun """Test runqemu machine slirp qcow2""" 115*4882a593Smuzhiyun cmd = "%s slirp wic.qcow2 %s" % (self.cmd_common, self.machine) 116*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 117*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 118*4882a593Smuzhiyun self.assertIn('format=qcow2', f.read(), "Failed: %s" % cmd) 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun def test_boot_qemu_boot(self): 121*4882a593Smuzhiyun """Test runqemu /path/to/image.qemuboot.conf""" 122*4882a593Smuzhiyun qemuboot_conf = "%s-%s.qemuboot.conf" % (self.recipe, self.machine) 123*4882a593Smuzhiyun qemuboot_conf = os.path.join(self.deploy_dir_image, qemuboot_conf) 124*4882a593Smuzhiyun if not os.path.exists(qemuboot_conf): 125*4882a593Smuzhiyun self.skipTest("%s not found" % qemuboot_conf) 126*4882a593Smuzhiyun cmd = "%s %s" % (self.cmd_common, qemuboot_conf) 127*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 128*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 129*4882a593Smuzhiyun self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun def test_boot_rootfs(self): 132*4882a593Smuzhiyun """Test runqemu /path/to/rootfs.ext4""" 133*4882a593Smuzhiyun rootfs = "%s-%s.ext4" % (self.recipe, self.machine) 134*4882a593Smuzhiyun rootfs = os.path.join(self.deploy_dir_image, rootfs) 135*4882a593Smuzhiyun if not os.path.exists(rootfs): 136*4882a593Smuzhiyun self.skipTest("%s not found" % rootfs) 137*4882a593Smuzhiyun cmd = "%s %s" % (self.cmd_common, rootfs) 138*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 139*4882a593Smuzhiyun with open(qemu.qemurunnerlog) as f: 140*4882a593Smuzhiyun self.assertTrue(qemu.runner.logged, "Failed: %s, %s" % (cmd, f.read())) 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun# This test was designed as a separate class to test that shutdown 144*4882a593Smuzhiyun# command will shutdown qemu as expected on each qemu architecture 145*4882a593Smuzhiyun# based on the MACHINE configuration inside the config file 146*4882a593Smuzhiyun# (eg. local.conf). 147*4882a593Smuzhiyun# 148*4882a593Smuzhiyun# This was different compared to RunqemuTests, where RunqemuTests was 149*4882a593Smuzhiyun# dedicated for MACHINE=qemux86-64 where it test that qemux86-64 will 150*4882a593Smuzhiyun# bootup various filesystem types, including live image(iso and hddimg) 151*4882a593Smuzhiyun# where live image was not supported on all qemu architecture. 152*4882a593Smuzhiyun@OETestTag("machine") 153*4882a593Smuzhiyun@OETestTag("runqemu") 154*4882a593Smuzhiyunclass QemuTest(OESelftestTestCase): 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun @classmethod 157*4882a593Smuzhiyun def setUpClass(cls): 158*4882a593Smuzhiyun super(QemuTest, cls).setUpClass() 159*4882a593Smuzhiyun cls.recipe = 'core-image-minimal' 160*4882a593Smuzhiyun cls.machine = get_bb_var('MACHINE') 161*4882a593Smuzhiyun cls.deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 162*4882a593Smuzhiyun cls.cmd_common = "runqemu nographic" 163*4882a593Smuzhiyun cls.qemuboot_conf = "%s-%s.qemuboot.conf" % (cls.recipe, cls.machine) 164*4882a593Smuzhiyun cls.qemuboot_conf = os.path.join(cls.deploy_dir_image, cls.qemuboot_conf) 165*4882a593Smuzhiyun bitbake(cls.recipe) 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun def _start_qemu_shutdown_check_if_shutdown_succeeded(self, qemu, timeout): 168*4882a593Smuzhiyun # Allow the runner's LoggingThread instance to exit without errors 169*4882a593Smuzhiyun # (such as the exception "Console connection closed unexpectedly") 170*4882a593Smuzhiyun # as qemu will disappear when we shut it down 171*4882a593Smuzhiyun qemu.runner.allowexit() 172*4882a593Smuzhiyun qemu.run_serial("shutdown -h now") 173*4882a593Smuzhiyun time_track = 0 174*4882a593Smuzhiyun try: 175*4882a593Smuzhiyun while True: 176*4882a593Smuzhiyun is_alive = qemu.check() 177*4882a593Smuzhiyun if not is_alive: 178*4882a593Smuzhiyun return True 179*4882a593Smuzhiyun if time_track > timeout: 180*4882a593Smuzhiyun return False 181*4882a593Smuzhiyun time.sleep(1) 182*4882a593Smuzhiyun time_track += 1 183*4882a593Smuzhiyun except SystemExit: 184*4882a593Smuzhiyun return True 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun def test_qemu_can_shutdown(self): 187*4882a593Smuzhiyun self.assertExists(self.qemuboot_conf) 188*4882a593Smuzhiyun cmd = "%s %s" % (self.cmd_common, self.qemuboot_conf) 189*4882a593Smuzhiyun shutdown_timeout = 120 190*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 191*4882a593Smuzhiyun qemu_shutdown_succeeded = self._start_qemu_shutdown_check_if_shutdown_succeeded(qemu, shutdown_timeout) 192*4882a593Smuzhiyun self.assertTrue(qemu_shutdown_succeeded, 'Failed: %s does not shutdown within timeout(%s)' % (self.machine, shutdown_timeout)) 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun # Need to have portmap/rpcbind running to allow this test to work and 195*4882a593Smuzhiyun # current autobuilder setup does not have this. 196*4882a593Smuzhiyun def disabled_test_qemu_can_boot_nfs_and_shutdown(self): 197*4882a593Smuzhiyun self.assertExists(self.qemuboot_conf) 198*4882a593Smuzhiyun bitbake('meta-ide-support') 199*4882a593Smuzhiyun rootfs_tar = "%s-%s.tar.bz2" % (self.recipe, self.machine) 200*4882a593Smuzhiyun rootfs_tar = os.path.join(self.deploy_dir_image, rootfs_tar) 201*4882a593Smuzhiyun self.assertExists(rootfs_tar) 202*4882a593Smuzhiyun tmpdir = tempfile.mkdtemp(prefix='qemu_nfs') 203*4882a593Smuzhiyun tmpdir_nfs = os.path.join(tmpdir, 'nfs') 204*4882a593Smuzhiyun cmd_extract_nfs = 'runqemu-extract-sdk %s %s' % (rootfs_tar, tmpdir_nfs) 205*4882a593Smuzhiyun result = runCmd(cmd_extract_nfs) 206*4882a593Smuzhiyun self.assertEqual(0, result.status, "runqemu-extract-sdk didn't run as expected. %s" % result.output) 207*4882a593Smuzhiyun cmd = "%s nfs %s %s" % (self.cmd_common, self.qemuboot_conf, tmpdir_nfs) 208*4882a593Smuzhiyun shutdown_timeout = 120 209*4882a593Smuzhiyun with runqemu(self.recipe, ssh=False, launch_cmd=cmd) as qemu: 210*4882a593Smuzhiyun qemu_shutdown_succeeded = self._start_qemu_shutdown_check_if_shutdown_succeeded(qemu, shutdown_timeout) 211*4882a593Smuzhiyun self.assertTrue(qemu_shutdown_succeeded, 'Failed: %s does not shutdown within timeout(%s)' % (self.machine, shutdown_timeout)) 212*4882a593Smuzhiyun runCmd('rm -rf %s' % tmpdir) 213