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