mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 16:23:55 -06:00
* Lots of functional test improvements (clean-ups, don't fail on
temporary download errors, etc.) * Convert some more avocado tests to the functional framework * Disallow building with libnfs v6 due to an API breakage -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmdirOIRHHRodXRoQHJl ZGhhdC5jb20ACgkQLtnXdP5wLbU0NRAAke8X0B6OOD+99lY5nc7Hrh7N1m+sw5Lw TVwIpxdhxU11vgdlCodfdoVJCV1NGVHwkR57lLNr+bdspWDBBwlmUWn0+t2QCXGe oyQsV+boznsjG9pan6v6DcU/gOu7/7ZydhJi+M8Msf8ah0lcn/otAdC4ZFB93JLh 6xPnj69y8HomCW+wMyXl7WTjcWX0wQFzweEYY8p7X7p1rtjYyseiZlRjNAvPgTMI jznZ6v9/qU54xR9RnKdW+0m1Qu06nx26Wz+ZBlvrJS1Llloe23X9+LY1tDD0Xh1D 9P0v9PuaBWRRF+UjVjl37LMyn9h1aaKFKBoWQiKMbyvOVr4ncobjRgN8r5kdNxDP FZ/fA1GiX8O3foN9uB9JLKd6Hl49LAqQSPzAneEc3pfQLH3NdAjPxJDbJH5fyMa7 qVOQC0Bdy8+2kCxFfKbemrwDOFcyq1fVYcADPDZySjMiPnwFJ1Qpni1tXY1PZ+Tl Q18AsFJanyAAn7L+8R3Yl54983SuR5eXIFxO+Tq9mw1V1V2h+Cm09HGcS8y5bxFG Xh+jhMsMB98NFLR87W6olwl57gKllSbTYuGtiz9TrbnuT/THhUJ0k/B76L7C9HWE ZefkFxC5Zy8jrcz3pgarO+19V+eXg5rwGtEngRQrji/3cY5CbK7Jeh5nvZQeASpb nZ/gJ/gC8Gs= =SWw6 -----END PGP SIGNATURE----- Merge tag 'pull-request-2024-12-18' of https://gitlab.com/thuth/qemu into staging * Lots of functional test improvements (clean-ups, don't fail on temporary download errors, etc.) * Convert some more avocado tests to the functional framework * Disallow building with libnfs v6 due to an API breakage # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmdirOIRHHRodXRoQHJl # ZGhhdC5jb20ACgkQLtnXdP5wLbU0NRAAke8X0B6OOD+99lY5nc7Hrh7N1m+sw5Lw # TVwIpxdhxU11vgdlCodfdoVJCV1NGVHwkR57lLNr+bdspWDBBwlmUWn0+t2QCXGe # oyQsV+boznsjG9pan6v6DcU/gOu7/7ZydhJi+M8Msf8ah0lcn/otAdC4ZFB93JLh # 6xPnj69y8HomCW+wMyXl7WTjcWX0wQFzweEYY8p7X7p1rtjYyseiZlRjNAvPgTMI # jznZ6v9/qU54xR9RnKdW+0m1Qu06nx26Wz+ZBlvrJS1Llloe23X9+LY1tDD0Xh1D # 9P0v9PuaBWRRF+UjVjl37LMyn9h1aaKFKBoWQiKMbyvOVr4ncobjRgN8r5kdNxDP # FZ/fA1GiX8O3foN9uB9JLKd6Hl49LAqQSPzAneEc3pfQLH3NdAjPxJDbJH5fyMa7 # qVOQC0Bdy8+2kCxFfKbemrwDOFcyq1fVYcADPDZySjMiPnwFJ1Qpni1tXY1PZ+Tl # Q18AsFJanyAAn7L+8R3Yl54983SuR5eXIFxO+Tq9mw1V1V2h+Cm09HGcS8y5bxFG # Xh+jhMsMB98NFLR87W6olwl57gKllSbTYuGtiz9TrbnuT/THhUJ0k/B76L7C9HWE # ZefkFxC5Zy8jrcz3pgarO+19V+eXg5rwGtEngRQrji/3cY5CbK7Jeh5nvZQeASpb # nZ/gJ/gC8Gs= # =SWw6 # -----END PGP SIGNATURE----- # gpg: Signature made Wed 18 Dec 2024 06:07:14 EST # gpg: using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5 # gpg: issuer "thuth@redhat.com" # gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full] # gpg: aka "Thomas Huth <thuth@redhat.com>" [full] # gpg: aka "Thomas Huth <huth@tuxfamily.org>" [full] # gpg: aka "Thomas Huth <th.huth@posteo.de>" [unknown] # Primary key fingerprint: 27B8 8847 EEE0 2501 18F3 EAB9 2ED9 D774 FE70 2DB5 * tag 'pull-request-2024-12-18' of https://gitlab.com/thuth/qemu: (38 commits) meson.build: Disallow libnfs v6 to fix the broken macOS build tests/functional: Convert the hotplug_cpu avocado test tests/functional: Convert the intel_iommu avocado test tests/functional: Add a helper function for retrieving the hostfwd port tests/functional: Convert the arm virt avocado test tests/functional: Convert the quanta-gsj avocado test MAINTAINERS: add myself as reviewer for functional test suite tests/functional: ignore errors when caching assets, except for 404 tests/functional: skip tests if assets are not available tests/functional: remove now unused 'run_cmd' helper tests/functional: replace 'run_cmd' with subprocess helpers tests/functional: drop back compat imports from utils.py tests/functional: convert tests to new uncompress helper tests/functional: add 'uncompress' to QemuBaseTest tests/functional: add a generalized uncompress helper tests/functional: convert tests to new archive_extract helper tests/functional: add 'archive_extract' to QemuBaseTest tests/functional: add a generalized archive_extract tests/functional: let cpio_extract accept filenames tests/functional: add common deb_extract helper ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
ba182a693f
79 changed files with 1275 additions and 1029 deletions
|
@ -872,6 +872,7 @@ F: tests/qtest/adm1266-test.c
|
|||
F: pc-bios/npcm7xx_bootrom.bin
|
||||
F: roms/vbootrom
|
||||
F: docs/system/arm/nuvoton.rst
|
||||
F: tests/functional/test_arm_quanta_gsj.py
|
||||
|
||||
Raspberry Pi
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
|
@ -3681,6 +3682,7 @@ S: Supported
|
|||
F: hw/i386/intel_iommu.c
|
||||
F: hw/i386/intel_iommu_internal.h
|
||||
F: include/hw/i386/intel_iommu.h
|
||||
F: tests/functional/test_intel_iommu.py
|
||||
|
||||
AMD-Vi Emulation
|
||||
S: Orphan
|
||||
|
@ -4157,6 +4159,7 @@ W: https://cirrus-ci.com/github/qemu/qemu
|
|||
Functional testing framework
|
||||
M: Thomas Huth <thuth@redhat.com>
|
||||
R: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
R: Daniel P. Berrange <berrange@redhat.com>
|
||||
F: tests/functional/qemu_test/
|
||||
|
||||
Windows Hosted Continuous Integration
|
||||
|
|
|
@ -1145,7 +1145,7 @@ endif
|
|||
|
||||
libnfs = not_found
|
||||
if not get_option('libnfs').auto() or have_block
|
||||
libnfs = dependency('libnfs', version: '>=1.9.3',
|
||||
libnfs = dependency('libnfs', version: ['>=1.9.3', '<6.0.0'],
|
||||
required: get_option('libnfs'),
|
||||
method: 'pkg-config')
|
||||
endif
|
||||
|
|
|
@ -94,110 +94,3 @@ class BootLinuxConsole(LinuxKernelTest):
|
|||
self.vm.launch()
|
||||
console_pattern = 'Kernel command line: %s' % kernel_command_line
|
||||
self.wait_for_console_pattern(console_pattern)
|
||||
|
||||
def test_arm_virt(self):
|
||||
"""
|
||||
:avocado: tags=arch:arm
|
||||
:avocado: tags=machine:virt
|
||||
:avocado: tags=accel:tcg
|
||||
"""
|
||||
kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora'
|
||||
'/linux/releases/29/Everything/armhfp/os/images/pxeboot'
|
||||
'/vmlinuz')
|
||||
kernel_hash = 'e9826d741b4fb04cadba8d4824d1ed3b7fb8b4d4'
|
||||
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
'console=ttyAMA0')
|
||||
self.vm.add_args('-kernel', kernel_path,
|
||||
'-append', kernel_command_line)
|
||||
self.vm.launch()
|
||||
console_pattern = 'Kernel command line: %s' % kernel_command_line
|
||||
self.wait_for_console_pattern(console_pattern)
|
||||
|
||||
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
|
||||
def test_arm_quanta_gsj(self):
|
||||
"""
|
||||
:avocado: tags=arch:arm
|
||||
:avocado: tags=machine:quanta-gsj
|
||||
:avocado: tags=accel:tcg
|
||||
"""
|
||||
# 25 MiB compressed, 32 MiB uncompressed.
|
||||
image_url = (
|
||||
'https://github.com/hskinnemoen/openbmc/releases/download/'
|
||||
'20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
|
||||
image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
|
||||
image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
|
||||
image_name = 'obmc.mtd'
|
||||
image_path = os.path.join(self.workdir, image_name)
|
||||
archive.gzip_uncompress(image_path_gz, image_path)
|
||||
|
||||
self.vm.set_console()
|
||||
drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
|
||||
self.vm.add_args('-drive', drive_args)
|
||||
self.vm.launch()
|
||||
|
||||
# Disable drivers and services that stall for a long time during boot,
|
||||
# to avoid running past the 90-second timeout. These may be removed
|
||||
# as the corresponding device support is added.
|
||||
kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
|
||||
'console=${console} '
|
||||
'mem=${mem} '
|
||||
'initcall_blacklist=npcm_i2c_bus_driver_init '
|
||||
'systemd.mask=systemd-random-seed.service '
|
||||
'systemd.mask=dropbearkey.service '
|
||||
)
|
||||
|
||||
self.wait_for_console_pattern('> BootBlock by Nuvoton')
|
||||
self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
|
||||
self.wait_for_console_pattern('>Skip DDR init.')
|
||||
self.wait_for_console_pattern('U-Boot ')
|
||||
interrupt_interactive_console_until_pattern(
|
||||
self, 'Hit any key to stop autoboot:', 'U-Boot>')
|
||||
exec_command_and_wait_for_pattern(
|
||||
self, "setenv bootargs ${bootargs} " + kernel_command_line,
|
||||
'U-Boot>')
|
||||
exec_command_and_wait_for_pattern(
|
||||
self, 'run romboot', 'Booting Kernel from flash')
|
||||
self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
|
||||
self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
|
||||
self.wait_for_console_pattern('OpenBMC Project Reference Distro')
|
||||
self.wait_for_console_pattern('gsj login:')
|
||||
|
||||
def test_arm_quanta_gsj_initrd(self):
|
||||
"""
|
||||
:avocado: tags=arch:arm
|
||||
:avocado: tags=machine:quanta-gsj
|
||||
:avocado: tags=accel:tcg
|
||||
"""
|
||||
initrd_url = (
|
||||
'https://github.com/hskinnemoen/openbmc/releases/download/'
|
||||
'20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
|
||||
initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
|
||||
initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
|
||||
kernel_url = (
|
||||
'https://github.com/hskinnemoen/openbmc/releases/download/'
|
||||
'20200711-gsj-qemu-0/uImage-gsj.bin')
|
||||
kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
|
||||
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
|
||||
dtb_url = (
|
||||
'https://github.com/hskinnemoen/openbmc/releases/download/'
|
||||
'20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
|
||||
dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
|
||||
dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
'console=ttyS0,115200n8 '
|
||||
'earlycon=uart8250,mmio32,0xf0001000')
|
||||
self.vm.add_args('-kernel', kernel_path,
|
||||
'-initrd', initrd_path,
|
||||
'-dtb', dtb_path,
|
||||
'-append', kernel_command_line)
|
||||
self.vm.launch()
|
||||
|
||||
self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
|
||||
self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
|
||||
self.wait_for_console_pattern(
|
||||
'Give root password for system maintenance')
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
# Functional test that hotplugs a CPU and checks it on a Linux guest
|
||||
#
|
||||
# Copyright (c) 2021 Red Hat, Inc.
|
||||
#
|
||||
# Author:
|
||||
# Cleber Rosa <crosa@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
from avocado_qemu.linuxtest import LinuxTest
|
||||
|
||||
|
||||
class HotPlugCPU(LinuxTest):
|
||||
|
||||
def test(self):
|
||||
"""
|
||||
:avocado: tags=arch:x86_64
|
||||
:avocado: tags=machine:q35
|
||||
:avocado: tags=accel:kvm
|
||||
"""
|
||||
self.require_accelerator('kvm')
|
||||
self.vm.add_args('-accel', 'kvm')
|
||||
self.vm.add_args('-cpu', 'Haswell')
|
||||
self.vm.add_args('-smp', '1,sockets=1,cores=2,threads=1,maxcpus=2')
|
||||
self.launch_and_wait()
|
||||
|
||||
self.ssh_command('test -e /sys/devices/system/cpu/cpu0')
|
||||
with self.assertRaises(AssertionError):
|
||||
self.ssh_command('test -e /sys/devices/system/cpu/cpu1')
|
||||
|
||||
self.vm.cmd('device_add',
|
||||
driver='Haswell-x86_64-cpu',
|
||||
socket_id=0,
|
||||
core_id=1,
|
||||
thread_id=0)
|
||||
self.ssh_command('test -e /sys/devices/system/cpu/cpu1')
|
|
@ -1,122 +0,0 @@
|
|||
# INTEL_IOMMU Functional tests
|
||||
#
|
||||
# Copyright (c) 2021 Red Hat, Inc.
|
||||
#
|
||||
# Author:
|
||||
# Eric Auger <eric.auger@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
import os
|
||||
|
||||
from avocado import skipUnless
|
||||
from avocado_qemu.linuxtest import LinuxTest
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
|
||||
class IntelIOMMU(LinuxTest):
|
||||
"""
|
||||
:avocado: tags=arch:x86_64
|
||||
:avocado: tags=distro:fedora
|
||||
:avocado: tags=distro_version:31
|
||||
:avocado: tags=machine:q35
|
||||
:avocado: tags=accel:kvm
|
||||
:avocado: tags=intel_iommu
|
||||
:avocado: tags=flaky
|
||||
"""
|
||||
|
||||
IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on'
|
||||
kernel_path = None
|
||||
initrd_path = None
|
||||
kernel_params = None
|
||||
|
||||
def set_up_boot(self):
|
||||
path = self.download_boot()
|
||||
self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' +
|
||||
'drive=drv0,id=virtio-disk0,bootindex=1,'
|
||||
'werror=stop,rerror=stop' + self.IOMMU_ADDON)
|
||||
self.vm.add_args('-device', 'virtio-gpu-pci' + self.IOMMU_ADDON)
|
||||
self.vm.add_args('-drive',
|
||||
'file=%s,if=none,cache=writethrough,id=drv0' % path)
|
||||
|
||||
def setUp(self):
|
||||
super(IntelIOMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON)
|
||||
|
||||
def add_common_args(self):
|
||||
self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0')
|
||||
self.vm.add_args('-object',
|
||||
'rng-random,id=rng0,filename=/dev/urandom')
|
||||
|
||||
def common_vm_setup(self, custom_kernel=None):
|
||||
self.require_accelerator("kvm")
|
||||
self.add_common_args()
|
||||
self.vm.add_args("-accel", "kvm")
|
||||
|
||||
if custom_kernel is None:
|
||||
return
|
||||
|
||||
kernel_url = self.distro.pxeboot_url + 'vmlinuz'
|
||||
kernel_hash = '5b6f6876e1b5bda314f93893271da0d5777b1f3c'
|
||||
initrd_url = self.distro.pxeboot_url + 'initrd.img'
|
||||
initrd_hash = 'dd0340a1b39bd28f88532babd4581c67649ec5b1'
|
||||
self.kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
|
||||
self.initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
|
||||
|
||||
def run_and_check(self):
|
||||
if self.kernel_path:
|
||||
self.vm.add_args('-kernel', self.kernel_path,
|
||||
'-append', self.kernel_params,
|
||||
'-initrd', self.initrd_path)
|
||||
self.launch_and_wait()
|
||||
self.ssh_command('cat /proc/cmdline')
|
||||
self.ssh_command('dmesg | grep -e DMAR -e IOMMU')
|
||||
self.ssh_command('find /sys/kernel/iommu_groups/ -type l')
|
||||
self.ssh_command('dnf -y install numactl-devel')
|
||||
|
||||
def test_intel_iommu(self):
|
||||
"""
|
||||
:avocado: tags=intel_iommu_intremap
|
||||
"""
|
||||
|
||||
self.common_vm_setup(True)
|
||||
self.vm.add_args('-device', 'intel-iommu,intremap=on')
|
||||
self.vm.add_args('-machine', 'kernel_irqchip=split')
|
||||
|
||||
self.kernel_params = (self.distro.default_kernel_params +
|
||||
' quiet intel_iommu=on')
|
||||
self.run_and_check()
|
||||
|
||||
def test_intel_iommu_strict(self):
|
||||
"""
|
||||
:avocado: tags=intel_iommu_strict
|
||||
"""
|
||||
|
||||
self.common_vm_setup(True)
|
||||
self.vm.add_args('-device', 'intel-iommu,intremap=on')
|
||||
self.vm.add_args('-machine', 'kernel_irqchip=split')
|
||||
self.kernel_params = (self.distro.default_kernel_params +
|
||||
' quiet intel_iommu=on,strict')
|
||||
self.run_and_check()
|
||||
|
||||
def test_intel_iommu_strict_cm(self):
|
||||
"""
|
||||
:avocado: tags=intel_iommu_strict_cm
|
||||
"""
|
||||
|
||||
self.common_vm_setup(True)
|
||||
self.vm.add_args('-device', 'intel-iommu,intremap=on,caching-mode=on')
|
||||
self.vm.add_args('-machine', 'kernel_irqchip=split')
|
||||
self.kernel_params = (self.distro.default_kernel_params +
|
||||
' quiet intel_iommu=on,strict')
|
||||
self.run_and_check()
|
||||
|
||||
def test_intel_iommu_pt(self):
|
||||
"""
|
||||
:avocado: tags=intel_iommu_pt
|
||||
"""
|
||||
|
||||
self.common_vm_setup(True)
|
||||
self.vm.add_args('-device', 'intel-iommu,intremap=on')
|
||||
self.vm.add_args('-machine', 'kernel_irqchip=split')
|
||||
self.kernel_params = (self.distro.default_kernel_params +
|
||||
' quiet intel_iommu=on iommu=pt')
|
||||
self.run_and_check()
|
|
@ -27,9 +27,11 @@ test_timeouts = {
|
|||
'arm_collie' : 180,
|
||||
'arm_cubieboard' : 360,
|
||||
'arm_orangepi' : 540,
|
||||
'arm_quanta_gsj' : 240,
|
||||
'arm_raspi2' : 120,
|
||||
'arm_tuxrun' : 240,
|
||||
'arm_sx1' : 360,
|
||||
'intel_iommu': 300,
|
||||
'mips_malta' : 120,
|
||||
'netdev_ethtool' : 180,
|
||||
'ppc_40p' : 240,
|
||||
|
@ -85,10 +87,12 @@ tests_arm_system_thorough = [
|
|||
'arm_emcraft_sf2',
|
||||
'arm_integratorcp',
|
||||
'arm_orangepi',
|
||||
'arm_quanta_gsj',
|
||||
'arm_raspi2',
|
||||
'arm_smdkc210',
|
||||
'arm_sx1',
|
||||
'arm_vexpress',
|
||||
'arm_virt',
|
||||
'arm_tuxrun',
|
||||
]
|
||||
|
||||
|
@ -224,11 +228,13 @@ tests_x86_64_system_quick = [
|
|||
|
||||
tests_x86_64_system_thorough = [
|
||||
'acpi_bits',
|
||||
'x86_64_tuxrun',
|
||||
'intel_iommu',
|
||||
'linux_initrd',
|
||||
'multiprocess',
|
||||
'netdev_ethtool',
|
||||
'virtio_gpu',
|
||||
'x86_64_hotplug_cpu',
|
||||
'x86_64_tuxrun',
|
||||
]
|
||||
|
||||
tests_xtensa_system_thorough = [
|
||||
|
|
|
@ -8,8 +8,13 @@
|
|||
|
||||
from .asset import Asset
|
||||
from .config import BUILD_DIR
|
||||
from .cmd import has_cmd, has_cmds, run_cmd, is_readable_executable_file, \
|
||||
from .cmd import is_readable_executable_file, \
|
||||
interrupt_interactive_console_until_pattern, wait_for_console_pattern, \
|
||||
exec_command, exec_command_and_wait_for_pattern, get_qemu_img
|
||||
exec_command, exec_command_and_wait_for_pattern, get_qemu_img, which
|
||||
from .testcase import QemuBaseTest, QemuUserTest, QemuSystemTest
|
||||
from .linuxkernel import LinuxKernelTest
|
||||
from .decorators import skipIfMissingCommands, skipIfNotMachine, \
|
||||
skipFlakyTest, skipUntrustedTest, skipBigDataTest, \
|
||||
skipIfMissingImports
|
||||
from .archive import archive_extract
|
||||
from .uncompress import uncompress
|
||||
|
|
117
tests/functional/qemu_test/archive.py
Normal file
117
tests/functional/qemu_test/archive.py
Normal file
|
@ -0,0 +1,117 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# Utilities for python-based QEMU tests
|
||||
#
|
||||
# Copyright 2024 Red Hat, Inc.
|
||||
#
|
||||
# Authors:
|
||||
# Thomas Huth <thuth@redhat.com>
|
||||
|
||||
import os
|
||||
from subprocess import check_call, run, DEVNULL
|
||||
import tarfile
|
||||
from urllib.parse import urlparse
|
||||
import zipfile
|
||||
|
||||
from .asset import Asset
|
||||
|
||||
|
||||
def tar_extract(archive, dest_dir, member=None):
|
||||
with tarfile.open(archive) as tf:
|
||||
if hasattr(tarfile, 'data_filter'):
|
||||
tf.extraction_filter = getattr(tarfile, 'data_filter',
|
||||
(lambda member, path: member))
|
||||
if member:
|
||||
tf.extract(member=member, path=dest_dir)
|
||||
else:
|
||||
tf.extractall(path=dest_dir)
|
||||
|
||||
def cpio_extract(archive, output_path):
|
||||
cwd = os.getcwd()
|
||||
os.chdir(output_path)
|
||||
# Not passing 'check=True' as cpio exits with non-zero
|
||||
# status if the archive contains any device nodes :-(
|
||||
if type(archive) == str:
|
||||
run(['cpio', '-i', '-F', archive],
|
||||
stdout=DEVNULL, stderr=DEVNULL)
|
||||
else:
|
||||
run(['cpio', '-i'],
|
||||
input=archive.read(),
|
||||
stdout=DEVNULL, stderr=DEVNULL)
|
||||
os.chdir(cwd)
|
||||
|
||||
def zip_extract(archive, dest_dir, member=None):
|
||||
with zipfile.ZipFile(archive, 'r') as zf:
|
||||
if member:
|
||||
zf.extract(member=member, path=dest_dir)
|
||||
else:
|
||||
zf.extractall(path=dest_dir)
|
||||
|
||||
def deb_extract(archive, dest_dir, member=None):
|
||||
cwd = os.getcwd()
|
||||
os.chdir(dest_dir)
|
||||
try:
|
||||
proc = run(['ar', 't', archive],
|
||||
check=True, capture_output=True, encoding='utf8')
|
||||
file_path = proc.stdout.split()[2]
|
||||
check_call(['ar', 'x', archive, file_path],
|
||||
stdout=DEVNULL, stderr=DEVNULL)
|
||||
tar_extract(file_path, dest_dir, member)
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
'''
|
||||
@params archive: filename, Asset, or file-like object to extract
|
||||
@params dest_dir: target directory to extract into
|
||||
@params member: optional member file to limit extraction to
|
||||
|
||||
Extracts @archive into @dest_dir. All files are extracted
|
||||
unless @member specifies a limit.
|
||||
|
||||
If @format is None, heuristics will be applied to guess the format
|
||||
from the filename or Asset URL. @format must be non-None if @archive
|
||||
is a file-like object.
|
||||
'''
|
||||
def archive_extract(archive, dest_dir, format=None, member=None):
|
||||
if format is None:
|
||||
format = guess_archive_format(archive)
|
||||
if type(archive) == Asset:
|
||||
archive = str(archive)
|
||||
|
||||
if format == "tar":
|
||||
tar_extract(archive, dest_dir, member)
|
||||
elif format == "zip":
|
||||
zip_extract(archive, dest_dir, member)
|
||||
elif format == "cpio":
|
||||
if member is not None:
|
||||
raise Exception("Unable to filter cpio extraction")
|
||||
cpio_extract(archive, dest_dir)
|
||||
elif format == "deb":
|
||||
if type(archive) != str:
|
||||
raise Exception("Unable to use file-like object with deb archives")
|
||||
deb_extract(archive, dest_dir, "./" + member)
|
||||
else:
|
||||
raise Exception(f"Unknown archive format {format}")
|
||||
|
||||
'''
|
||||
@params archive: filename, or Asset to guess
|
||||
|
||||
Guess the format of @compressed, raising an exception if
|
||||
no format can be determined
|
||||
'''
|
||||
def guess_archive_format(archive):
|
||||
if type(archive) == Asset:
|
||||
archive = urlparse(archive.url).path
|
||||
elif type(archive) != str:
|
||||
raise Exception(f"Unable to guess archive format for {archive}")
|
||||
|
||||
if ".tar." in archive or archive.endswith("tgz"):
|
||||
return "tar"
|
||||
elif archive.endswith(".zip"):
|
||||
return "zip"
|
||||
elif archive.endswith(".cpio"):
|
||||
return "cpio"
|
||||
elif archive.endswith(".deb") or archive.endswith(".udeb"):
|
||||
return "deb"
|
||||
else:
|
||||
raise Exception(f"Unknown archive format for {archive}")
|
|
@ -9,13 +9,13 @@ import hashlib
|
|||
import logging
|
||||
import os
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
import urllib.request
|
||||
from time import sleep
|
||||
from pathlib import Path
|
||||
from shutil import copyfileobj
|
||||
from urllib.error import HTTPError
|
||||
|
||||
|
||||
# Instances of this class must be declared as class level variables
|
||||
|
@ -40,6 +40,9 @@ class Asset:
|
|||
return "Asset: url=%s hash=%s cache=%s" % (
|
||||
self.url, self.hash, self.cache_file)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.cache_file)
|
||||
|
||||
def _check(self, cache_file):
|
||||
if self.hash is None:
|
||||
return True
|
||||
|
@ -63,6 +66,12 @@ class Asset:
|
|||
def valid(self):
|
||||
return self.cache_file.exists() and self._check(self.cache_file)
|
||||
|
||||
def fetchable(self):
|
||||
return not os.environ.get("QEMU_TEST_NO_DOWNLOAD", False)
|
||||
|
||||
def available(self):
|
||||
return self.valid() or self.fetchable()
|
||||
|
||||
def _wait_for_other_download(self, tmp_cache_file):
|
||||
# Another thread already seems to download the asset, so wait until
|
||||
# it is done, while also checking the size to see whether it is stuck
|
||||
|
@ -101,7 +110,7 @@ class Asset:
|
|||
self.cache_file, self.url)
|
||||
return str(self.cache_file)
|
||||
|
||||
if os.environ.get("QEMU_TEST_NO_DOWNLOAD", False):
|
||||
if not self.fetchable():
|
||||
raise Exception("Asset cache is invalid and downloads disabled")
|
||||
|
||||
self.log.info("Downloading %s to %s...", self.url, self.cache_file)
|
||||
|
@ -162,7 +171,18 @@ class Asset:
|
|||
for name, asset in vars(test.__class__).items():
|
||||
if name.startswith("ASSET_") and type(asset) == Asset:
|
||||
log.info("Attempting to cache '%s'" % asset)
|
||||
asset.fetch()
|
||||
try:
|
||||
asset.fetch()
|
||||
except HTTPError as e:
|
||||
# Treat 404 as fatal, since it is highly likely to
|
||||
# indicate a broken test rather than a transient
|
||||
# server or networking problem
|
||||
if e.code == 404:
|
||||
raise
|
||||
|
||||
log.debug(f"HTTP error {e.code} from {asset.url} " +
|
||||
"skipping asset precache")
|
||||
|
||||
log.removeHandler(handler)
|
||||
|
||||
def precache_suite(suite):
|
||||
|
|
|
@ -14,66 +14,18 @@
|
|||
import logging
|
||||
import os
|
||||
import os.path
|
||||
import subprocess
|
||||
|
||||
from .config import BUILD_DIR
|
||||
|
||||
|
||||
def has_cmd(name, args=None):
|
||||
def which(tool):
|
||||
""" looks up the full path for @tool, returns None if not found
|
||||
or if @tool does not have executable permissions.
|
||||
"""
|
||||
This function is for use in a @skipUnless decorator, e.g.:
|
||||
|
||||
@skipUnless(*has_cmd('sudo -n', ('sudo', '-n', 'true')))
|
||||
def test_something_that_needs_sudo(self):
|
||||
...
|
||||
"""
|
||||
|
||||
if args is None:
|
||||
args = ('which', name)
|
||||
|
||||
try:
|
||||
_, stderr, exitcode = run_cmd(args)
|
||||
except Exception as e:
|
||||
exitcode = -1
|
||||
stderr = str(e)
|
||||
|
||||
if exitcode != 0:
|
||||
cmd_line = ' '.join(args)
|
||||
err = f'{name} required, but "{cmd_line}" failed: {stderr.strip()}'
|
||||
return (False, err)
|
||||
else:
|
||||
return (True, '')
|
||||
|
||||
def has_cmds(*cmds):
|
||||
"""
|
||||
This function is for use in a @skipUnless decorator and
|
||||
allows checking for the availability of multiple commands, e.g.:
|
||||
|
||||
@skipUnless(*has_cmds(('cmd1', ('cmd1', '--some-parameter')),
|
||||
'cmd2', 'cmd3'))
|
||||
def test_something_that_needs_cmd1_and_cmd2(self):
|
||||
...
|
||||
"""
|
||||
|
||||
for cmd in cmds:
|
||||
if isinstance(cmd, str):
|
||||
cmd = (cmd,)
|
||||
|
||||
ok, errstr = has_cmd(*cmd)
|
||||
if not ok:
|
||||
return (False, errstr)
|
||||
|
||||
return (True, '')
|
||||
|
||||
def run_cmd(args):
|
||||
subp = subprocess.Popen(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
stdout, stderr = subp.communicate()
|
||||
ret = subp.returncode
|
||||
|
||||
return (stdout, stderr, ret)
|
||||
paths=os.getenv('PATH')
|
||||
for p in paths.split(os.path.pathsep):
|
||||
p = os.path.join(p, tool)
|
||||
if os.access(p, os.X_OK):
|
||||
return p
|
||||
return None
|
||||
|
||||
def is_readable_executable_file(path):
|
||||
return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK)
|
||||
|
@ -241,10 +193,10 @@ def get_qemu_img(test):
|
|||
|
||||
# If qemu-img has been built, use it, otherwise the system wide one
|
||||
# will be used.
|
||||
qemu_img = os.path.join(BUILD_DIR, 'qemu-img')
|
||||
qemu_img = test.build_file('qemu-img')
|
||||
if os.path.exists(qemu_img):
|
||||
return qemu_img
|
||||
(has_system_qemu_img, errmsg) = has_cmd('qemu-img')
|
||||
if has_system_qemu_img:
|
||||
return 'qemu-img'
|
||||
test.skipTest(errmsg)
|
||||
qemu_img = which('qemu-img')
|
||||
if qemu_img is not None:
|
||||
return qemu_img
|
||||
test.skipTest(f"qemu-img not found in build dir or '$PATH'")
|
||||
|
|
107
tests/functional/qemu_test/decorators.py
Normal file
107
tests/functional/qemu_test/decorators.py
Normal file
|
@ -0,0 +1,107 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# Decorators useful in functional tests
|
||||
|
||||
import os
|
||||
import platform
|
||||
from unittest import skipUnless
|
||||
|
||||
from .cmd import which
|
||||
|
||||
'''
|
||||
Decorator to skip execution of a test if the list
|
||||
of command binaries is not available in $PATH.
|
||||
Example:
|
||||
|
||||
@skipIfMissingCommands("mkisofs", "losetup")
|
||||
'''
|
||||
def skipIfMissingCommands(*args):
|
||||
def has_cmds(cmdlist):
|
||||
for cmd in cmdlist:
|
||||
if not which(cmd):
|
||||
return False
|
||||
return True
|
||||
|
||||
return skipUnless(lambda: has_cmds(args),
|
||||
'required command(s) "%s" not installed' %
|
||||
", ".join(args))
|
||||
|
||||
'''
|
||||
Decorator to skip execution of a test if the current
|
||||
host machine does not match one of the permitted
|
||||
machines.
|
||||
Example
|
||||
|
||||
@skipIfNotMachine("x86_64", "aarch64")
|
||||
'''
|
||||
def skipIfNotMachine(*args):
|
||||
return skipUnless(lambda: platform.machine() in args,
|
||||
'not running on one of the required machine(s) "%s"' %
|
||||
", ".join(args))
|
||||
|
||||
'''
|
||||
Decorator to skip execution of flaky tests, unless
|
||||
the $QEMU_TEST_FLAKY_TESTS environment variable is set.
|
||||
A bug URL must be provided that documents the observed
|
||||
failure behaviour, so it can be tracked & re-evaluated
|
||||
in future.
|
||||
|
||||
Historical tests may be providing "None" as the bug_url
|
||||
but this should not be done for new test.
|
||||
|
||||
Example:
|
||||
|
||||
@skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/NNN")
|
||||
'''
|
||||
def skipFlakyTest(bug_url):
|
||||
if bug_url is None:
|
||||
bug_url = "FIXME: reproduce flaky test and file bug report or remove"
|
||||
return skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'),
|
||||
f'Test is unstable: {bug_url}')
|
||||
|
||||
'''
|
||||
Decorator to skip execution of tests which are likely
|
||||
to execute untrusted commands on the host, or commands
|
||||
which process untrusted code, unless the
|
||||
$QEMU_TEST_ALLOW_UNTRUSTED_CODE env var is set.
|
||||
Example:
|
||||
|
||||
@skipUntrustedTest()
|
||||
'''
|
||||
def skipUntrustedTest():
|
||||
return skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'),
|
||||
'Test runs untrusted code / processes untrusted data')
|
||||
|
||||
'''
|
||||
Decorator to skip execution of tests which need large
|
||||
data storage (over around 500MB-1GB mark) on the host,
|
||||
unless the $QEMU_TEST_ALLOW_LARGE_STORAGE environment
|
||||
variable is set
|
||||
|
||||
Example:
|
||||
|
||||
@skipBigDataTest()
|
||||
'''
|
||||
def skipBigDataTest():
|
||||
return skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'),
|
||||
'Test requires large host storage space')
|
||||
|
||||
'''
|
||||
Decorator to skip execution of a test if the list
|
||||
of python imports is not available.
|
||||
Example:
|
||||
|
||||
@skipIfMissingImports("numpy", "cv2")
|
||||
'''
|
||||
def skipIfMissingImports(*args):
|
||||
def has_imports(importlist):
|
||||
for impname in importlist:
|
||||
try:
|
||||
import impname
|
||||
except ImportError:
|
||||
return False
|
||||
return True
|
||||
|
||||
return skipUnless(lambda: has_imports(args),
|
||||
'required import(s) "%s" not installed' %
|
||||
", ".join(args))
|
|
@ -3,11 +3,9 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import os
|
||||
|
||||
from .testcase import QemuSystemTest
|
||||
from .cmd import run_cmd, wait_for_console_pattern
|
||||
from .utils import archive_extract
|
||||
from .cmd import wait_for_console_pattern
|
||||
|
||||
|
||||
class LinuxKernelTest(QemuSystemTest):
|
||||
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
|
||||
|
@ -28,26 +26,3 @@ class LinuxKernelTest(QemuSystemTest):
|
|||
self.vm.launch()
|
||||
if wait_for:
|
||||
self.wait_for_console_pattern(wait_for)
|
||||
|
||||
def extract_from_deb(self, deb_path, path):
|
||||
"""
|
||||
Extracts a file from a deb package into the test workdir
|
||||
|
||||
:param deb_path: path to the deb archive
|
||||
:param path: path within the deb archive of the file to be extracted
|
||||
:returns: path of the extracted file
|
||||
"""
|
||||
cwd = os.getcwd()
|
||||
os.chdir(self.workdir)
|
||||
(stdout, stderr, ret) = run_cmd(['ar', 't', deb_path])
|
||||
file_path = stdout.split()[2]
|
||||
run_cmd(['ar', 'x', deb_path, file_path])
|
||||
archive_extract(file_path, self.workdir)
|
||||
os.chdir(cwd)
|
||||
# Return complete path to extracted file. Because callers to
|
||||
# extract_from_deb() specify 'path' with a leading slash, it is
|
||||
# necessary to use os.path.relpath() as otherwise os.path.join()
|
||||
# interprets it as an absolute path and drops the self.workdir part.
|
||||
return os.path.normpath(os.path.join(self.workdir,
|
||||
os.path.relpath(path, '/')))
|
||||
|
||||
|
|
|
@ -5,30 +5,19 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import re
|
||||
import logging
|
||||
from subprocess import run
|
||||
|
||||
from . import has_cmd, run_cmd
|
||||
|
||||
def tesseract_available(expected_version):
|
||||
(has_tesseract, _) = has_cmd('tesseract')
|
||||
if not has_tesseract:
|
||||
return False
|
||||
(stdout, stderr, ret) = run_cmd([ 'tesseract', '--version'])
|
||||
if ret:
|
||||
return False
|
||||
version = stdout.split()[1]
|
||||
return int(version.split('.')[0]) >= expected_version
|
||||
|
||||
def tesseract_ocr(image_path, tesseract_args=''):
|
||||
console_logger = logging.getLogger('console')
|
||||
console_logger.debug(image_path)
|
||||
(stdout, stderr, ret) = run_cmd(['tesseract', image_path,
|
||||
'stdout'])
|
||||
if ret:
|
||||
proc = run(['tesseract', image_path, 'stdout'],
|
||||
capture_output=True, encoding='utf8')
|
||||
if proc.returncode:
|
||||
return None
|
||||
lines = []
|
||||
for line in stdout.split('\n'):
|
||||
for line in proc.stdout.split('\n'):
|
||||
sline = line.strip()
|
||||
if len(sline):
|
||||
console_logger.debug(sline)
|
||||
|
|
|
@ -13,19 +13,22 @@
|
|||
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
import pycotap
|
||||
import shutil
|
||||
import subprocess
|
||||
from subprocess import run
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import uuid
|
||||
|
||||
from qemu.machine import QEMUMachine
|
||||
from qemu.utils import kvm_available, tcg_available
|
||||
|
||||
from .archive import archive_extract
|
||||
from .asset import Asset
|
||||
from .cmd import run_cmd
|
||||
from .config import BUILD_DIR
|
||||
from .uncompress import uncompress
|
||||
|
||||
|
||||
class QemuBaseTest(unittest.TestCase):
|
||||
|
@ -37,17 +40,169 @@ class QemuBaseTest(unittest.TestCase):
|
|||
log = None
|
||||
logdir = None
|
||||
|
||||
'''
|
||||
@params compressed: filename, Asset, or file-like object to uncompress
|
||||
@params format: optional compression format (gzip, lzma)
|
||||
|
||||
Uncompresses @compressed into the scratch directory.
|
||||
|
||||
If @format is None, heuristics will be applied to guess the format
|
||||
from the filename or Asset URL. @format must be non-None if @uncompressed
|
||||
is a file-like object.
|
||||
|
||||
Returns the fully qualified path to the uncompressed file
|
||||
'''
|
||||
def uncompress(self, compressed, format=None):
|
||||
self.log.debug(f"Uncompress {compressed} format={format}")
|
||||
if type(compressed) == Asset:
|
||||
compressed.fetch()
|
||||
|
||||
(name, ext) = os.path.splitext(str(compressed))
|
||||
uncompressed = self.scratch_file(os.path.basename(name))
|
||||
|
||||
uncompress(compressed, uncompressed, format)
|
||||
|
||||
return uncompressed
|
||||
|
||||
'''
|
||||
@params archive: filename, Asset, or file-like object to extract
|
||||
@params format: optional archive format (tar, zip, deb, cpio)
|
||||
@params sub_dir: optional sub-directory to extract into
|
||||
@params member: optional member file to limit extraction to
|
||||
|
||||
Extracts @archive into the scratch directory, or a directory beneath
|
||||
named by @sub_dir. All files are extracted unless @member specifies
|
||||
a limit.
|
||||
|
||||
If @format is None, heuristics will be applied to guess the format
|
||||
from the filename or Asset URL. @format must be non-None if @archive
|
||||
is a file-like object.
|
||||
|
||||
If @member is non-None, returns the fully qualified path to @member
|
||||
'''
|
||||
def archive_extract(self, archive, format=None, sub_dir=None, member=None):
|
||||
self.log.debug(f"Extract {archive} format={format}" +
|
||||
f"sub_dir={sub_dir} member={member}")
|
||||
if type(archive) == Asset:
|
||||
archive.fetch()
|
||||
if sub_dir is None:
|
||||
archive_extract(archive, self.scratch_file(), format, member)
|
||||
else:
|
||||
archive_extract(archive, self.scratch_file(sub_dir),
|
||||
format, member)
|
||||
|
||||
if member is not None:
|
||||
return self.scratch_file(member)
|
||||
return None
|
||||
|
||||
'''
|
||||
Create a temporary directory suitable for storing UNIX
|
||||
socket paths.
|
||||
|
||||
Returns: a tempfile.TemporaryDirectory instance
|
||||
'''
|
||||
def socket_dir(self):
|
||||
if self.socketdir is None:
|
||||
self.socketdir = tempfile.TemporaryDirectory(
|
||||
prefix="qemu_func_test_sock_")
|
||||
return self.socketdir
|
||||
|
||||
'''
|
||||
@params args list of zero or more subdirectories or file
|
||||
|
||||
Construct a path for accessing a data file located
|
||||
relative to the source directory that is the root for
|
||||
functional tests.
|
||||
|
||||
@args may be an empty list to reference the root dir
|
||||
itself, may be a single element to reference a file in
|
||||
the root directory, or may be multiple elements to
|
||||
reference a file nested below. The path components
|
||||
will be joined using the platform appropriate path
|
||||
separator.
|
||||
|
||||
Returns: string representing a file path
|
||||
'''
|
||||
def data_file(self, *args):
|
||||
return str(Path(Path(__file__).parent.parent, *args))
|
||||
|
||||
'''
|
||||
@params args list of zero or more subdirectories or file
|
||||
|
||||
Construct a path for accessing a data file located
|
||||
relative to the build directory root.
|
||||
|
||||
@args may be an empty list to reference the build dir
|
||||
itself, may be a single element to reference a file in
|
||||
the build directory, or may be multiple elements to
|
||||
reference a file nested below. The path components
|
||||
will be joined using the platform appropriate path
|
||||
separator.
|
||||
|
||||
Returns: string representing a file path
|
||||
'''
|
||||
def build_file(self, *args):
|
||||
return str(Path(BUILD_DIR, *args))
|
||||
|
||||
'''
|
||||
@params args list of zero or more subdirectories or file
|
||||
|
||||
Construct a path for accessing/creating a scratch file
|
||||
located relative to a temporary directory dedicated to
|
||||
this test case. The directory and its contents will be
|
||||
purged upon completion of the test.
|
||||
|
||||
@args may be an empty list to reference the scratch dir
|
||||
itself, may be a single element to reference a file in
|
||||
the scratch directory, or may be multiple elements to
|
||||
reference a file nested below. The path components
|
||||
will be joined using the platform appropriate path
|
||||
separator.
|
||||
|
||||
Returns: string representing a file path
|
||||
'''
|
||||
def scratch_file(self, *args):
|
||||
return str(Path(self.workdir, *args))
|
||||
|
||||
'''
|
||||
@params args list of zero or more subdirectories or file
|
||||
|
||||
Construct a path for accessing/creating a log file
|
||||
located relative to a temporary directory dedicated to
|
||||
this test case. The directory and its log files will be
|
||||
preserved upon completion of the test.
|
||||
|
||||
@args may be an empty list to reference the log dir
|
||||
itself, may be a single element to reference a file in
|
||||
the log directory, or may be multiple elements to
|
||||
reference a file nested below. The path components
|
||||
will be joined using the platform appropriate path
|
||||
separator.
|
||||
|
||||
Returns: string representing a file path
|
||||
'''
|
||||
def log_file(self, *args):
|
||||
return str(Path(self.outputdir, *args))
|
||||
|
||||
def assets_available(self):
|
||||
for name, asset in vars(self.__class__).items():
|
||||
if name.startswith("ASSET_") and type(asset) == Asset:
|
||||
if not asset.available():
|
||||
self.log.debug(f"Asset {asset.url} not available")
|
||||
return False
|
||||
return True
|
||||
|
||||
def setUp(self, bin_prefix):
|
||||
self.assertIsNotNone(self.qemu_bin, 'QEMU_TEST_QEMU_BINARY must be set')
|
||||
self.arch = self.qemu_bin.split('-')[-1]
|
||||
self.socketdir = None
|
||||
|
||||
self.outputdir = os.path.join(BUILD_DIR, 'tests', 'functional',
|
||||
self.arch, self.id())
|
||||
self.outputdir = self.build_file('tests', 'functional',
|
||||
self.arch, self.id())
|
||||
self.workdir = os.path.join(self.outputdir, 'scratch')
|
||||
os.makedirs(self.workdir, exist_ok=True)
|
||||
|
||||
self.logdir = self.outputdir
|
||||
self.log_filename = os.path.join(self.logdir, 'base.log')
|
||||
self.log_filename = self.log_file('base.log')
|
||||
self.log = logging.getLogger('qemu-test')
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
self._log_fh = logging.FileHandler(self.log_filename, mode='w')
|
||||
|
@ -62,9 +217,15 @@ class QemuBaseTest(unittest.TestCase):
|
|||
self.machinelog.setLevel(logging.DEBUG)
|
||||
self.machinelog.addHandler(self._log_fh)
|
||||
|
||||
if not self.assets_available():
|
||||
self.skipTest('One or more assets is not available')
|
||||
|
||||
def tearDown(self):
|
||||
if "QEMU_TEST_KEEP_SCRATCH" not in os.environ:
|
||||
shutil.rmtree(self.workdir)
|
||||
if self.socketdir is not None:
|
||||
shutil.rmtree(self.socketdir.name)
|
||||
self.socketdir = None
|
||||
self.machinelog.removeHandler(self._log_fh)
|
||||
self.log.removeHandler(self._log_fh)
|
||||
|
||||
|
@ -100,11 +261,11 @@ class QemuUserTest(QemuBaseTest):
|
|||
self._ldpath.append(os.path.abspath(ldpath))
|
||||
|
||||
def run_cmd(self, bin_path, args=[]):
|
||||
return subprocess.run([self.qemu_bin]
|
||||
+ ["-L %s" % ldpath for ldpath in self._ldpath]
|
||||
+ [bin_path]
|
||||
+ args,
|
||||
text=True, capture_output=True)
|
||||
return run([self.qemu_bin]
|
||||
+ ["-L %s" % ldpath for ldpath in self._ldpath]
|
||||
+ [bin_path]
|
||||
+ args,
|
||||
text=True, capture_output=True)
|
||||
|
||||
class QemuSystemTest(QemuBaseTest):
|
||||
"""Facilitates system emulation tests."""
|
||||
|
@ -120,7 +281,7 @@ class QemuSystemTest(QemuBaseTest):
|
|||
|
||||
console_log = logging.getLogger('console')
|
||||
console_log.setLevel(logging.DEBUG)
|
||||
self.console_log_name = os.path.join(self.logdir, 'console.log')
|
||||
self.console_log_name = self.log_file('console.log')
|
||||
self._console_log_fh = logging.FileHandler(self.console_log_name,
|
||||
mode='w')
|
||||
self._console_log_fh.setLevel(logging.DEBUG)
|
||||
|
@ -131,7 +292,9 @@ class QemuSystemTest(QemuBaseTest):
|
|||
def set_machine(self, machinename):
|
||||
# TODO: We should use QMP to get the list of available machines
|
||||
if not self._machinehelp:
|
||||
self._machinehelp = run_cmd([self.qemu_bin, '-M', 'help'])[0];
|
||||
self._machinehelp = run(
|
||||
[self.qemu_bin, '-M', 'help'],
|
||||
capture_output=True, check=True, encoding='utf8').stdout
|
||||
if self._machinehelp.find(machinename) < 0:
|
||||
self.skipTest('no support for machine ' + machinename)
|
||||
self.machine = machinename
|
||||
|
@ -159,22 +322,24 @@ class QemuSystemTest(QemuBaseTest):
|
|||
"available" % accelerator)
|
||||
|
||||
def require_netdev(self, netdevname):
|
||||
netdevhelp = run_cmd([self.qemu_bin,
|
||||
'-M', 'none', '-netdev', 'help'])[0];
|
||||
if netdevhelp.find('\n' + netdevname + '\n') < 0:
|
||||
help = run([self.qemu_bin,
|
||||
'-M', 'none', '-netdev', 'help'],
|
||||
capture_output=True, check=True, encoding='utf8').stdout;
|
||||
if help.find('\n' + netdevname + '\n') < 0:
|
||||
self.skipTest('no support for " + netdevname + " networking')
|
||||
|
||||
def require_device(self, devicename):
|
||||
devhelp = run_cmd([self.qemu_bin,
|
||||
'-M', 'none', '-device', 'help'])[0];
|
||||
if devhelp.find(devicename) < 0:
|
||||
help = run([self.qemu_bin,
|
||||
'-M', 'none', '-device', 'help'],
|
||||
capture_output=True, check=True, encoding='utf8').stdout;
|
||||
if help.find(devicename) < 0:
|
||||
self.skipTest('no support for device ' + devicename)
|
||||
|
||||
def _new_vm(self, name, *args):
|
||||
vm = QEMUMachine(self.qemu_bin,
|
||||
name=name,
|
||||
base_temp_dir=self.workdir,
|
||||
log_dir=self.logdir)
|
||||
log_dir=self.log_file())
|
||||
self.log.debug('QEMUMachine "%s" created', name)
|
||||
self.log.debug('QEMUMachine "%s" temp_dir: %s', name, vm.temp_dir)
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
|
||||
import os
|
||||
import stat
|
||||
import time
|
||||
from subprocess import check_call, DEVNULL
|
||||
|
||||
from qemu_test import QemuSystemTest
|
||||
from qemu_test import exec_command, exec_command_and_wait_for_pattern
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import has_cmd, run_cmd, get_qemu_img
|
||||
from qemu_test import which, get_qemu_img
|
||||
|
||||
class TuxRunBaselineTest(QemuSystemTest):
|
||||
|
||||
|
@ -39,10 +39,8 @@ class TuxRunBaselineTest(QemuSystemTest):
|
|||
super().setUp()
|
||||
|
||||
# We need zstd for all the tuxrun tests
|
||||
(has_zstd, msg) = has_cmd('zstd')
|
||||
if has_zstd is False:
|
||||
self.skipTest(msg)
|
||||
self.zstd = 'zstd'
|
||||
if which('zstd') is None:
|
||||
self.skipTest("zstd not found in $PATH")
|
||||
|
||||
# Pre-init TuxRun specific settings: Most machines work with
|
||||
# reasonable defaults but we sometimes need to tweak the
|
||||
|
@ -77,10 +75,11 @@ class TuxRunBaselineTest(QemuSystemTest):
|
|||
kernel_image = kernel_asset.fetch()
|
||||
disk_image_zst = rootfs_asset.fetch()
|
||||
|
||||
disk_image = self.workdir + "/rootfs.ext4"
|
||||
disk_image = self.scratch_file("rootfs.ext4")
|
||||
|
||||
run_cmd([self.zstd, "-f", "-d", disk_image_zst,
|
||||
"-o", disk_image])
|
||||
check_call(['zstd', "-f", "-d", disk_image_zst,
|
||||
"-o", disk_image],
|
||||
stdout=DEVNULL, stderr=DEVNULL)
|
||||
# zstd copies source archive permissions for the output
|
||||
# file, so must make this writable for QEMU
|
||||
os.chmod(disk_image, stat.S_IRUSR | stat.S_IWUSR)
|
||||
|
|
83
tests/functional/qemu_test/uncompress.py
Normal file
83
tests/functional/qemu_test/uncompress.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# Utilities for python-based QEMU tests
|
||||
#
|
||||
# Copyright 2024 Red Hat, Inc.
|
||||
#
|
||||
# Authors:
|
||||
# Thomas Huth <thuth@redhat.com>
|
||||
|
||||
import gzip
|
||||
import lzma
|
||||
import os
|
||||
import shutil
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from .asset import Asset
|
||||
|
||||
|
||||
def gzip_uncompress(gz_path, output_path):
|
||||
if os.path.exists(output_path):
|
||||
return
|
||||
with gzip.open(gz_path, 'rb') as gz_in:
|
||||
try:
|
||||
with open(output_path, 'wb') as raw_out:
|
||||
shutil.copyfileobj(gz_in, raw_out)
|
||||
except:
|
||||
os.remove(output_path)
|
||||
raise
|
||||
|
||||
def lzma_uncompress(xz_path, output_path):
|
||||
if os.path.exists(output_path):
|
||||
return
|
||||
with lzma.open(xz_path, 'rb') as lzma_in:
|
||||
try:
|
||||
with open(output_path, 'wb') as raw_out:
|
||||
shutil.copyfileobj(lzma_in, raw_out)
|
||||
except:
|
||||
os.remove(output_path)
|
||||
raise
|
||||
|
||||
'''
|
||||
@params compressed: filename, Asset, or file-like object to uncompress
|
||||
@params uncompressed: filename to uncompress into
|
||||
@params format: optional compression format (gzip, lzma)
|
||||
|
||||
Uncompresses @compressed into @uncompressed
|
||||
|
||||
If @format is None, heuristics will be applied to guess the format
|
||||
from the filename or Asset URL. @format must be non-None if @uncompressed
|
||||
is a file-like object.
|
||||
|
||||
Returns the fully qualified path to the uncompessed file
|
||||
'''
|
||||
def uncompress(compressed, uncompressed, format=None):
|
||||
if format is None:
|
||||
format = guess_uncompress_format(compressed)
|
||||
|
||||
if format == "xz":
|
||||
lzma_uncompress(str(compressed), uncompressed)
|
||||
elif format == "gz":
|
||||
gzip_uncompress(str(compressed), uncompressed)
|
||||
else:
|
||||
raise Exception(f"Unknown compression format {format}")
|
||||
|
||||
'''
|
||||
@params compressed: filename, Asset, or file-like object to guess
|
||||
|
||||
Guess the format of @compressed, raising an exception if
|
||||
no format can be determined
|
||||
'''
|
||||
def guess_uncompress_format(compressed):
|
||||
if type(compressed) == Asset:
|
||||
compressed = urlparse(compressed.url).path
|
||||
elif type(compressed) != str:
|
||||
raise Exception(f"Unable to guess compression cformat for {compressed}")
|
||||
|
||||
(name, ext) = os.path.splitext(compressed)
|
||||
if ext == ".xz":
|
||||
return "xz"
|
||||
elif ext == ".gz":
|
||||
return "gz"
|
||||
else:
|
||||
raise Exception(f"Unknown compression format for {compressed}")
|
|
@ -8,12 +8,14 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import gzip
|
||||
import lzma
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tarfile
|
||||
|
||||
from qemu.utils import get_info_usernet_hostfwd_port
|
||||
|
||||
|
||||
def get_usernet_hostfwd_port(vm):
|
||||
res = vm.cmd('human-monitor-command', command_line='info usernet')
|
||||
return get_info_usernet_hostfwd_port(res)
|
||||
|
||||
"""
|
||||
Round up to next power of 2
|
||||
|
@ -35,43 +37,3 @@ def image_pow2ceil_expand(path):
|
|||
if size != size_aligned:
|
||||
with open(path, 'ab+') as fd:
|
||||
fd.truncate(size_aligned)
|
||||
|
||||
def archive_extract(archive, dest_dir, member=None):
|
||||
with tarfile.open(archive) as tf:
|
||||
if hasattr(tarfile, 'data_filter'):
|
||||
tf.extraction_filter = getattr(tarfile, 'data_filter',
|
||||
(lambda member, path: member))
|
||||
if member:
|
||||
tf.extract(member=member, path=dest_dir)
|
||||
else:
|
||||
tf.extractall(path=dest_dir)
|
||||
|
||||
def gzip_uncompress(gz_path, output_path):
|
||||
if os.path.exists(output_path):
|
||||
return
|
||||
with gzip.open(gz_path, 'rb') as gz_in:
|
||||
try:
|
||||
with open(output_path, 'wb') as raw_out:
|
||||
shutil.copyfileobj(gz_in, raw_out)
|
||||
except:
|
||||
os.remove(output_path)
|
||||
raise
|
||||
|
||||
def lzma_uncompress(xz_path, output_path):
|
||||
if os.path.exists(output_path):
|
||||
return
|
||||
with lzma.open(xz_path, 'rb') as lzma_in:
|
||||
try:
|
||||
with open(output_path, 'wb') as raw_out:
|
||||
shutil.copyfileobj(lzma_in, raw_out)
|
||||
except:
|
||||
os.remove(output_path)
|
||||
raise
|
||||
|
||||
def cpio_extract(cpio_handle, output_path):
|
||||
cwd = os.getcwd()
|
||||
os.chdir(output_path)
|
||||
subprocess.run(['cpio', '-i'],
|
||||
input=cpio_handle.read(),
|
||||
stderr=subprocess.DEVNULL)
|
||||
os.chdir(cwd)
|
||||
|
|
23
tests/functional/test_aarch64_aspeed.py
Normal file → Executable file
23
tests/functional/test_aarch64_aspeed.py
Normal file → Executable file
|
@ -6,13 +6,12 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class AST2x00MachineSDK(QemuSystemTest):
|
||||
|
||||
|
@ -35,30 +34,31 @@ class AST2x00MachineSDK(QemuSystemTest):
|
|||
def test_aarch64_ast2700_evb_sdk_v09_02(self):
|
||||
self.set_machine('ast2700-evb')
|
||||
|
||||
image_path = self.ASSET_SDK_V902_AST2700.fetch()
|
||||
archive_extract(image_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_SDK_V902_AST2700)
|
||||
|
||||
num_cpu = 4
|
||||
image_dir = self.workdir + '/ast2700-default/'
|
||||
uboot_size = os.path.getsize(image_dir + 'u-boot-nodtb.bin')
|
||||
uboot_size = os.path.getsize(self.scratch_file('ast2700-default',
|
||||
'u-boot-nodtb.bin'))
|
||||
uboot_dtb_load_addr = hex(0x400000000 + uboot_size)
|
||||
|
||||
load_images_list = [
|
||||
{
|
||||
'addr': '0x400000000',
|
||||
'file': image_dir + 'u-boot-nodtb.bin'
|
||||
'file': self.scratch_file('ast2700-default',
|
||||
'u-boot-nodtb.bin')
|
||||
},
|
||||
{
|
||||
'addr': str(uboot_dtb_load_addr),
|
||||
'file': image_dir + 'u-boot.dtb'
|
||||
'file': self.scratch_file('ast2700-default', 'u-boot.dtb')
|
||||
},
|
||||
{
|
||||
'addr': '0x430000000',
|
||||
'file': image_dir + 'bl31.bin'
|
||||
'file': self.scratch_file('ast2700-default', 'bl31.bin')
|
||||
},
|
||||
{
|
||||
'addr': '0x430080000',
|
||||
'file': image_dir + 'optee/tee-raw.bin'
|
||||
'file': self.scratch_file('ast2700-default', 'optee',
|
||||
'tee-raw.bin')
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -75,7 +75,8 @@ class AST2x00MachineSDK(QemuSystemTest):
|
|||
self.vm.add_args('-smp', str(num_cpu))
|
||||
self.vm.add_args('-device',
|
||||
'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
|
||||
self.do_test_aarch64_aspeed_sdk_start(image_dir + 'image-bmc')
|
||||
self.do_test_aarch64_aspeed_sdk_start(
|
||||
self.scratch_file('ast2700-default', 'image-bmc'))
|
||||
|
||||
wait_for_console_pattern(self, 'ast2700-default login:')
|
||||
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
from zipfile import ZipFile
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
|
||||
|
||||
|
@ -22,11 +19,7 @@ class Aarch64Raspi3Machine(LinuxKernelTest):
|
|||
|
||||
def test_aarch64_raspi3_atf(self):
|
||||
efi_name = 'RPI_EFI.fd'
|
||||
zip_path = self.ASSET_RPI3_UEFI.fetch()
|
||||
|
||||
with ZipFile(zip_path, 'r') as zf:
|
||||
zf.extract(efi_name, path=self.workdir)
|
||||
efi_fd = os.path.join(self.workdir, efi_name)
|
||||
efi_fd = self.archive_extract(self.ASSET_RPI3_UEFI, member=efi_name)
|
||||
|
||||
self.set_machine('raspi3b')
|
||||
self.vm.set_console(console_index=1)
|
||||
|
|
|
@ -5,11 +5,8 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test.utils import gzip_uncompress
|
||||
|
||||
|
||||
class Aarch64Raspi4Machine(LinuxKernelTest):
|
||||
|
@ -32,9 +29,10 @@ class Aarch64Raspi4Machine(LinuxKernelTest):
|
|||
'7c0b16d1853772f6f4c3ca63e789b3b9ff4936efac9c8a01fb0c98c05c7a7648')
|
||||
|
||||
def test_arm_raspi4(self):
|
||||
deb_path = self.ASSET_KERNEL_20190215.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
|
||||
dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
|
||||
kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215,
|
||||
member='boot/kernel8.img')
|
||||
dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215,
|
||||
member='boot/bcm2711-rpi-4-b.dtb')
|
||||
|
||||
self.set_machine('raspi4b')
|
||||
self.vm.set_console()
|
||||
|
@ -60,12 +58,11 @@ class Aarch64Raspi4Machine(LinuxKernelTest):
|
|||
|
||||
|
||||
def test_arm_raspi4_initrd(self):
|
||||
deb_path = self.ASSET_KERNEL_20190215.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
|
||||
dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
|
||||
initrd_path_gz = self.ASSET_INITRD.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
gzip_uncompress(initrd_path_gz, initrd_path)
|
||||
kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215,
|
||||
member='boot/kernel8.img')
|
||||
dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215,
|
||||
member='boot/bcm2711-rpi-4-b.dtb')
|
||||
initrd_path = self.uncompress(self.ASSET_INITRD)
|
||||
|
||||
self.set_machine('raspi4b')
|
||||
self.vm.set_console()
|
||||
|
|
|
@ -8,12 +8,10 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import interrupt_interactive_console_until_pattern
|
||||
from qemu_test.utils import lzma_uncompress
|
||||
|
||||
|
||||
def fetch_firmware(test):
|
||||
"""
|
||||
|
@ -31,14 +29,10 @@ def fetch_firmware(test):
|
|||
"""
|
||||
|
||||
# Secure BootRom (TF-A code)
|
||||
fs0_xz_path = Aarch64SbsarefMachine.ASSET_FLASH0.fetch()
|
||||
fs0_path = os.path.join(test.workdir, "SBSA_FLASH0.fd")
|
||||
lzma_uncompress(fs0_xz_path, fs0_path)
|
||||
fs0_path = test.uncompress(Aarch64SbsarefMachine.ASSET_FLASH0)
|
||||
|
||||
# Non-secure rom (UEFI and EFI variables)
|
||||
fs1_xz_path = Aarch64SbsarefMachine.ASSET_FLASH1.fetch()
|
||||
fs1_path = os.path.join(test.workdir, "SBSA_FLASH1.fd")
|
||||
lzma_uncompress(fs1_xz_path, fs1_path)
|
||||
fs1_path = test.uncompress(Aarch64SbsarefMachine.ASSET_FLASH1)
|
||||
|
||||
for path in [fs0_path, fs1_path]:
|
||||
with open(path, "ab+") as fd:
|
||||
|
|
|
@ -12,7 +12,6 @@ import os
|
|||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import interrupt_interactive_console_until_pattern
|
||||
from unittest import skipUnless
|
||||
from test_aarch64_sbsaref import fetch_firmware
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import os
|
|||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import interrupt_interactive_console_until_pattern
|
||||
from unittest import skipUnless
|
||||
from test_aarch64_sbsaref import fetch_firmware
|
||||
|
||||
|
|
|
@ -11,13 +11,12 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import time
|
||||
import os
|
||||
import logging
|
||||
from subprocess import check_call, DEVNULL
|
||||
|
||||
from qemu_test import BUILD_DIR
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import exec_command, wait_for_console_pattern
|
||||
from qemu_test import get_qemu_img, run_cmd
|
||||
from qemu_test import get_qemu_img
|
||||
|
||||
|
||||
class Aarch64VirtMachine(QemuSystemTest):
|
||||
|
@ -54,8 +53,8 @@ class Aarch64VirtMachine(QemuSystemTest):
|
|||
"mte=on,"
|
||||
"gic-version=max,iommu=smmuv3")
|
||||
self.vm.add_args("-smp", "2", "-m", "1024")
|
||||
self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios',
|
||||
'edk2-aarch64-code.fd'))
|
||||
self.vm.add_args('-bios', self.build_file('pc-bios',
|
||||
'edk2-aarch64-code.fd'))
|
||||
self.vm.add_args("-drive", f"file={iso_path},media=cdrom,format=raw")
|
||||
self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0')
|
||||
self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom')
|
||||
|
@ -96,9 +95,10 @@ class Aarch64VirtMachine(QemuSystemTest):
|
|||
|
||||
# Also add a scratch block device
|
||||
logger.info('creating scratch qcow2 image')
|
||||
image_path = os.path.join(self.workdir, 'scratch.qcow2')
|
||||
image_path = self.scratch_file('scratch.qcow2')
|
||||
qemu_img = get_qemu_img(self)
|
||||
run_cmd([qemu_img, 'create', '-f', 'qcow2', image_path, '8M'])
|
||||
check_call([qemu_img, 'create', '-f', 'qcow2', image_path, '8M'],
|
||||
stdout=DEVNULL, stderr=DEVNULL)
|
||||
|
||||
# Add the device
|
||||
self.vm.add_args('-blockdev',
|
||||
|
|
|
@ -31,56 +31,24 @@ including an upgraded acpica. The fork is located here:
|
|||
https://gitlab.com/qemu-project/biosbits-bits .
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tarfile
|
||||
import tempfile
|
||||
import zipfile
|
||||
|
||||
from pathlib import Path
|
||||
from typing import (
|
||||
List,
|
||||
Optional,
|
||||
Sequence,
|
||||
)
|
||||
from qemu.machine import QEMUMachine
|
||||
from unittest import skipIf
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import (QemuSystemTest, Asset, skipIfMissingCommands,
|
||||
skipIfNotMachine)
|
||||
|
||||
deps = ["xorriso", "mformat"] # dependent tools needed in the test setup/box.
|
||||
supported_platforms = ['x86_64'] # supported test platforms.
|
||||
|
||||
# default timeout of 120 secs is sometimes not enough for bits test.
|
||||
BITS_TIMEOUT = 200
|
||||
|
||||
def which(tool):
|
||||
""" looks up the full path for @tool, returns None if not found
|
||||
or if @tool does not have executable permissions.
|
||||
"""
|
||||
paths=os.getenv('PATH')
|
||||
for p in paths.split(os.path.pathsep):
|
||||
p = os.path.join(p, tool)
|
||||
if os.path.exists(p) and os.access(p, os.X_OK):
|
||||
return p
|
||||
return None
|
||||
|
||||
def missing_deps():
|
||||
""" returns True if any of the test dependent tools are absent.
|
||||
"""
|
||||
for dep in deps:
|
||||
if which(dep) is None:
|
||||
return True
|
||||
return False
|
||||
|
||||
def supported_platform():
|
||||
""" checks if the test is running on a supported platform.
|
||||
"""
|
||||
return platform.machine() in supported_platforms
|
||||
|
||||
class QEMUBitsMachine(QEMUMachine): # pylint: disable=too-few-public-methods
|
||||
"""
|
||||
A QEMU VM, with isa-debugcon enabled and bits iso passed
|
||||
|
@ -123,9 +91,8 @@ class QEMUBitsMachine(QEMUMachine): # pylint: disable=too-few-public-methods
|
|||
"""return the base argument to QEMU binary"""
|
||||
return self._base_args
|
||||
|
||||
@skipIf(not supported_platform() or missing_deps(),
|
||||
'unsupported platform or dependencies (%s) not installed' \
|
||||
% ','.join(deps))
|
||||
@skipIfMissingCommands("xorriso", "mformat")
|
||||
@skipIfNotMachine("x86_64")
|
||||
class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attributes
|
||||
"""
|
||||
ACPI and SMBIOS tests using biosbits.
|
||||
|
@ -149,7 +116,6 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
|
|||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._vm = None
|
||||
self._baseDir = None
|
||||
|
||||
self._debugcon_addr = '0x403'
|
||||
self._debugcon_log = 'debugcon-log.txt'
|
||||
|
@ -164,29 +130,24 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
|
|||
def copy_bits_config(self):
|
||||
""" copies the bios bits config file into bits.
|
||||
"""
|
||||
config_file = 'bits-cfg.txt'
|
||||
bits_config_dir = os.path.join(self._baseDir, 'acpi-bits',
|
||||
'bits-config')
|
||||
target_config_dir = os.path.join(self.workdir,
|
||||
'bits-%d' %self.BITS_INTERNAL_VER,
|
||||
'boot')
|
||||
self.assertTrue(os.path.exists(bits_config_dir))
|
||||
bits_config_file = self.data_file('acpi-bits',
|
||||
'bits-config',
|
||||
'bits-cfg.txt')
|
||||
target_config_dir = self.scratch_file('bits-%d' %
|
||||
self.BITS_INTERNAL_VER,
|
||||
'boot')
|
||||
self.assertTrue(os.path.exists(bits_config_file))
|
||||
self.assertTrue(os.path.exists(target_config_dir))
|
||||
self.assertTrue(os.access(os.path.join(bits_config_dir,
|
||||
config_file), os.R_OK))
|
||||
shutil.copy2(os.path.join(bits_config_dir, config_file),
|
||||
target_config_dir)
|
||||
shutil.copy2(bits_config_file, target_config_dir)
|
||||
self.logger.info('copied config file %s to %s',
|
||||
config_file, target_config_dir)
|
||||
bits_config_file, target_config_dir)
|
||||
|
||||
def copy_test_scripts(self):
|
||||
"""copies the python test scripts into bits. """
|
||||
|
||||
bits_test_dir = os.path.join(self._baseDir, 'acpi-bits',
|
||||
'bits-tests')
|
||||
target_test_dir = os.path.join(self.workdir,
|
||||
'bits-%d' %self.BITS_INTERNAL_VER,
|
||||
'boot', 'python')
|
||||
bits_test_dir = self.data_file('acpi-bits', 'bits-tests')
|
||||
target_test_dir = self.scratch_file('bits-%d' % self.BITS_INTERNAL_VER,
|
||||
'boot', 'python')
|
||||
|
||||
self.assertTrue(os.path.exists(bits_test_dir))
|
||||
self.assertTrue(os.path.exists(target_test_dir))
|
||||
|
@ -223,8 +184,8 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
|
|||
the directory where we have extracted our pre-built bits grub
|
||||
tarball.
|
||||
"""
|
||||
grub_x86_64_mods = os.path.join(self.workdir, 'grub-inst-x86_64-efi')
|
||||
grub_i386_mods = os.path.join(self.workdir, 'grub-inst')
|
||||
grub_x86_64_mods = self.scratch_file('grub-inst-x86_64-efi')
|
||||
grub_i386_mods = self.scratch_file('grub-inst')
|
||||
|
||||
self.assertTrue(os.path.exists(grub_x86_64_mods))
|
||||
self.assertTrue(os.path.exists(grub_i386_mods))
|
||||
|
@ -245,13 +206,11 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
|
|||
""" Uses grub-mkrescue to generate a fresh bits iso with the python
|
||||
test scripts
|
||||
"""
|
||||
bits_dir = os.path.join(self.workdir,
|
||||
'bits-%d' %self.BITS_INTERNAL_VER)
|
||||
iso_file = os.path.join(self.workdir,
|
||||
'bits-%d.iso' %self.BITS_INTERNAL_VER)
|
||||
mkrescue_script = os.path.join(self.workdir,
|
||||
'grub-inst-x86_64-efi', 'bin',
|
||||
'grub-mkrescue')
|
||||
bits_dir = self.scratch_file('bits-%d' % self.BITS_INTERNAL_VER)
|
||||
iso_file = self.scratch_file('bits-%d.iso' % self.BITS_INTERNAL_VER)
|
||||
mkrescue_script = self.scratch_file('grub-inst-x86_64-efi',
|
||||
'bin',
|
||||
'grub-mkrescue')
|
||||
|
||||
self.assertTrue(os.access(mkrescue_script,
|
||||
os.R_OK | os.W_OK | os.X_OK))
|
||||
|
@ -286,33 +245,25 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
|
|||
super().setUp()
|
||||
self.logger = self.log
|
||||
|
||||
self._baseDir = Path(__file__).parent
|
||||
|
||||
prebuiltDir = os.path.join(self.workdir, 'prebuilt')
|
||||
prebuiltDir = self.scratch_file('prebuilt')
|
||||
if not os.path.isdir(prebuiltDir):
|
||||
os.mkdir(prebuiltDir, mode=0o775)
|
||||
|
||||
bits_zip_file = os.path.join(prebuiltDir, 'bits-%d-%s.zip'
|
||||
%(self.BITS_INTERNAL_VER,
|
||||
self.BITS_COMMIT_HASH))
|
||||
grub_tar_file = os.path.join(prebuiltDir,
|
||||
'bits-%d-%s-grub.tar.gz'
|
||||
%(self.BITS_INTERNAL_VER,
|
||||
self.BITS_COMMIT_HASH))
|
||||
|
||||
bitsLocalArtLoc = self.ASSET_BITS.fetch()
|
||||
self.logger.info("downloaded bits artifacts to %s", bitsLocalArtLoc)
|
||||
bits_zip_file = self.scratch_file('prebuilt',
|
||||
'bits-%d-%s.zip'
|
||||
%(self.BITS_INTERNAL_VER,
|
||||
self.BITS_COMMIT_HASH))
|
||||
grub_tar_file = self.scratch_file('prebuilt',
|
||||
'bits-%d-%s-grub.tar.gz'
|
||||
%(self.BITS_INTERNAL_VER,
|
||||
self.BITS_COMMIT_HASH))
|
||||
|
||||
# extract the bits artifact in the temp working directory
|
||||
with zipfile.ZipFile(bitsLocalArtLoc, 'r') as zref:
|
||||
zref.extractall(prebuiltDir)
|
||||
self.archive_extract(self.ASSET_BITS, sub_dir='prebuilt', format='zip')
|
||||
|
||||
# extract the bits software in the temp working directory
|
||||
with zipfile.ZipFile(bits_zip_file, 'r') as zref:
|
||||
zref.extractall(self.workdir)
|
||||
|
||||
with tarfile.open(grub_tar_file, 'r', encoding='utf-8') as tarball:
|
||||
tarball.extractall(self.workdir)
|
||||
self.archive_extract(bits_zip_file)
|
||||
self.archive_extract(grub_tar_file)
|
||||
|
||||
self.copy_test_scripts()
|
||||
self.copy_bits_config()
|
||||
|
@ -322,7 +273,7 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
|
|||
"""parse the log generated by running bits tests and
|
||||
check for failures.
|
||||
"""
|
||||
debugconf = os.path.join(self.workdir, self._debugcon_log)
|
||||
debugconf = self.scratch_file(self._debugcon_log)
|
||||
log = ""
|
||||
with open(debugconf, 'r', encoding='utf-8') as filehandle:
|
||||
log = filehandle.read()
|
||||
|
@ -354,8 +305,7 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
|
|||
"""The main test case implementation."""
|
||||
|
||||
self.set_machine('pc')
|
||||
iso_file = os.path.join(self.workdir,
|
||||
'bits-%d.iso' %self.BITS_INTERNAL_VER)
|
||||
iso_file = self.scratch_file('bits-%d.iso' % self.BITS_INTERNAL_VER)
|
||||
|
||||
self.assertTrue(os.access(iso_file, os.R_OK))
|
||||
|
||||
|
|
|
@ -5,10 +5,7 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import gzip_uncompress
|
||||
|
||||
|
||||
class AlphaClipperTest(LinuxKernelTest):
|
||||
|
@ -22,8 +19,7 @@ class AlphaClipperTest(LinuxKernelTest):
|
|||
self.set_machine('clipper')
|
||||
kernel_path = self.ASSET_KERNEL.fetch()
|
||||
|
||||
uncompressed_kernel = os.path.join(self.workdir, 'vmlinux')
|
||||
gzip_uncompress(kernel_path, uncompressed_kernel)
|
||||
uncompressed_kernel = self.uncompress(self.ASSET_KERNEL, format="gz")
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0'
|
||||
|
|
18
tests/functional/test_arm_aspeed_ast1030.py
Normal file → Executable file
18
tests/functional/test_arm_aspeed_ast1030.py
Normal file → Executable file
|
@ -6,11 +6,9 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from zipfile import ZipFile
|
||||
|
||||
|
||||
class AST1030Machine(LinuxKernelTest):
|
||||
|
||||
|
@ -22,12 +20,9 @@ class AST1030Machine(LinuxKernelTest):
|
|||
def test_ast1030_zephyros_1_04(self):
|
||||
self.set_machine('ast1030-evb')
|
||||
|
||||
zip_file = self.ASSET_ZEPHYR_1_04.fetch()
|
||||
|
||||
kernel_name = "ast1030-evb-demo/zephyr.elf"
|
||||
with ZipFile(zip_file, 'r') as zf:
|
||||
zf.extract(kernel_name, path=self.workdir)
|
||||
kernel_file = os.path.join(self.workdir, kernel_name)
|
||||
kernel_file = self.archive_extract(
|
||||
self.ASSET_ZEPHYR_1_04, member=kernel_name)
|
||||
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', kernel_file, '-nographic')
|
||||
|
@ -44,12 +39,9 @@ class AST1030Machine(LinuxKernelTest):
|
|||
def test_ast1030_zephyros_1_07(self):
|
||||
self.set_machine('ast1030-evb')
|
||||
|
||||
zip_file = self.ASSET_ZEPHYR_1_07.fetch()
|
||||
|
||||
kernel_name = "ast1030-evb-demo/zephyr.bin"
|
||||
with ZipFile(zip_file, 'r') as zf:
|
||||
zf.extract(kernel_name, path=self.workdir)
|
||||
kernel_file = os.path.join(self.workdir, kernel_name)
|
||||
kernel_file = self.archive_extract(
|
||||
self.ASSET_ZEPHYR_1_07, member=kernel_name)
|
||||
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', kernel_file, '-nographic')
|
||||
|
|
8
tests/functional/test_arm_aspeed_ast2500.py
Normal file → Executable file
8
tests/functional/test_arm_aspeed_ast2500.py
Normal file → Executable file
|
@ -7,7 +7,7 @@
|
|||
from qemu_test import Asset
|
||||
from aspeed import AspeedTest
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class AST2500Machine(AspeedTest):
|
||||
|
||||
|
@ -45,12 +45,10 @@ class AST2500Machine(AspeedTest):
|
|||
def test_arm_ast2500_evb_sdk(self):
|
||||
self.set_machine('ast2500-evb')
|
||||
|
||||
image_path = self.ASSET_SDK_V806_AST2500.fetch()
|
||||
|
||||
archive_extract(image_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_SDK_V806_AST2500)
|
||||
|
||||
self.do_test_arm_aspeed_sdk_start(
|
||||
self.workdir + '/ast2500-default/image-bmc')
|
||||
self.scratch_file("ast2500-default", "image-bmc"))
|
||||
|
||||
self.wait_for_console_pattern('ast2500-default login:')
|
||||
|
||||
|
|
14
tests/functional/test_arm_aspeed_ast2600.py
Normal file → Executable file
14
tests/functional/test_arm_aspeed_ast2600.py
Normal file → Executable file
|
@ -11,10 +11,8 @@ import subprocess
|
|||
|
||||
from qemu_test import Asset
|
||||
from aspeed import AspeedTest
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test import has_cmd
|
||||
from qemu_test.utils import archive_extract
|
||||
from unittest import skipUnless
|
||||
from qemu_test import exec_command_and_wait_for_pattern, skipIfMissingCommands
|
||||
|
||||
|
||||
class AST2600Machine(AspeedTest):
|
||||
|
||||
|
@ -68,7 +66,7 @@ class AST2600Machine(AspeedTest):
|
|||
'images/ast2600-evb/buildroot-2023.02-tpm/flash.img'),
|
||||
'a46009ae8a5403a0826d607215e731a8c68d27c14c41e55331706b8f9c7bd997')
|
||||
|
||||
@skipUnless(*has_cmd('swtpm'))
|
||||
@skipIfMissingCommands('swtpm')
|
||||
def test_arm_ast2600_evb_buildroot_tpm(self):
|
||||
self.set_machine('ast2600-evb')
|
||||
|
||||
|
@ -106,16 +104,14 @@ class AST2600Machine(AspeedTest):
|
|||
def test_arm_ast2600_evb_sdk(self):
|
||||
self.set_machine('ast2600-evb')
|
||||
|
||||
image_path = self.ASSET_SDK_V806_AST2600_A2.fetch()
|
||||
|
||||
archive_extract(image_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_SDK_V806_AST2600_A2)
|
||||
|
||||
self.vm.add_args('-device',
|
||||
'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test');
|
||||
self.vm.add_args('-device',
|
||||
'ds1338,bus=aspeed.i2c.bus.5,address=0x32');
|
||||
self.do_test_arm_aspeed_sdk_start(
|
||||
self.workdir + '/ast2600-a2/image-bmc')
|
||||
self.scratch_file("ast2600-a2", "image-bmc"))
|
||||
|
||||
self.wait_for_console_pattern('ast2600-a2 login:')
|
||||
|
||||
|
|
0
tests/functional/test_arm_aspeed_palmetto.py
Normal file → Executable file
0
tests/functional/test_arm_aspeed_palmetto.py
Normal file → Executable file
11
tests/functional/test_arm_aspeed_rainier.py
Normal file → Executable file
11
tests/functional/test_arm_aspeed_rainier.py
Normal file → Executable file
|
@ -43,11 +43,12 @@ class RainierMachine(AspeedTest):
|
|||
def test_arm_debian_kernel_boot(self):
|
||||
self.set_machine('rainier-bmc')
|
||||
|
||||
deb_path = self.ASSET_DEBIAN_LINUX_ARMHF_DEB.fetch()
|
||||
|
||||
kernel_path = self.extract_from_deb(deb_path, '/boot/vmlinuz-5.17.0-2-armmp')
|
||||
dtb_path = self.extract_from_deb(deb_path,
|
||||
'/usr/lib/linux-image-5.17.0-2-armmp/aspeed-bmc-ibm-rainier.dtb')
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_DEBIAN_LINUX_ARMHF_DEB,
|
||||
member='boot/vmlinuz-5.17.0-2-armmp')
|
||||
dtb_path = self.archive_extract(
|
||||
self.ASSET_DEBIAN_LINUX_ARMHF_DEB,
|
||||
member='usr/lib/linux-image-5.17.0-2-armmp/aspeed-bmc-ibm-rainier.dtb')
|
||||
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', kernel_path,
|
||||
|
|
0
tests/functional/test_arm_aspeed_romulus.py
Normal file → Executable file
0
tests/functional/test_arm_aspeed_romulus.py
Normal file → Executable file
|
@ -6,13 +6,10 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import bz2
|
||||
|
||||
from qemu_test import QemuUserTest, Asset
|
||||
from qemu_test import has_cmd
|
||||
from qemu_test.utils import cpio_extract
|
||||
from unittest import skipUnless
|
||||
from qemu_test import skipIfMissingCommands, skipUntrustedTest
|
||||
|
||||
|
||||
class LoadBFLT(QemuUserTest):
|
||||
|
@ -21,15 +18,15 @@ class LoadBFLT(QemuUserTest):
|
|||
('https://elinux.org/images/5/51/Stm32_mini_rootfs.cpio.bz2'),
|
||||
'eefb788e4980c9e8d6c9d60ce7d15d4da6bf4fbc6a80f487673824600d5ba9cc')
|
||||
|
||||
@skipUnless(*has_cmd('cpio'))
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
|
||||
@skipIfMissingCommands('cpio')
|
||||
@skipUntrustedTest()
|
||||
def test_stm32(self):
|
||||
# See https://elinux.org/STM32#User_Space
|
||||
rootfs_path_bz2 = self.ASSET_ROOTFS.fetch()
|
||||
busybox_path = os.path.join(self.workdir, "bin/busybox")
|
||||
busybox_path = self.scratch_file("bin", "busybox")
|
||||
|
||||
with bz2.open(rootfs_path_bz2, 'rb') as cpio_handle:
|
||||
cpio_extract(cpio_handle, self.workdir)
|
||||
self.archive_extract(cpio_handle, format="cpio")
|
||||
|
||||
res = self.run_cmd(busybox_path)
|
||||
ver = 'BusyBox v1.24.0.git (2015-02-03 22:17:13 CET) multi-call binary.'
|
||||
|
|
|
@ -9,9 +9,9 @@ import os
|
|||
|
||||
from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern
|
||||
from qemu_test import Asset, interrupt_interactive_console_until_pattern
|
||||
from qemu_test.utils import archive_extract, gzip_uncompress, lzma_uncompress
|
||||
from qemu_test import skipBigDataTest
|
||||
from qemu_test.utils import image_pow2ceil_expand
|
||||
from unittest import skipUnless
|
||||
|
||||
|
||||
class BananaPiMachine(LinuxKernelTest):
|
||||
|
||||
|
@ -38,12 +38,11 @@ class BananaPiMachine(LinuxKernelTest):
|
|||
|
||||
def test_arm_bpim2u(self):
|
||||
self.set_machine('bpim2u')
|
||||
deb_path = self.ASSET_DEB.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/'
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/'
|
||||
'sun8i-r40-bananapi-m2-ultra.dtb')
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
|
@ -60,15 +59,12 @@ class BananaPiMachine(LinuxKernelTest):
|
|||
|
||||
def test_arm_bpim2u_initrd(self):
|
||||
self.set_machine('bpim2u')
|
||||
deb_path = self.ASSET_DEB.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/'
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/'
|
||||
'sun8i-r40-bananapi-m2-ultra.dtb')
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
initrd_path_gz = self.ASSET_INITRD.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
gzip_uncompress(initrd_path_gz, initrd_path)
|
||||
dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
|
||||
initrd_path = self.uncompress(self.ASSET_INITRD)
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
|
@ -99,14 +95,12 @@ class BananaPiMachine(LinuxKernelTest):
|
|||
self.require_netdev('user')
|
||||
|
||||
deb_path = self.ASSET_DEB.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/'
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/'
|
||||
'sun8i-r40-bananapi-m2-ultra.dtb')
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
rootfs_path_xz = self.ASSET_ROOTFS.fetch()
|
||||
rootfs_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
lzma_uncompress(rootfs_path_xz, rootfs_path)
|
||||
dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
|
||||
rootfs_path = self.uncompress(self.ASSET_ROOTFS)
|
||||
image_pow2ceil_expand(rootfs_path)
|
||||
|
||||
self.vm.set_console()
|
||||
|
@ -143,14 +137,12 @@ class BananaPiMachine(LinuxKernelTest):
|
|||
os.remove(dtb_path)
|
||||
os.remove(rootfs_path)
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 'storage limited')
|
||||
@skipBigDataTest()
|
||||
def test_arm_bpim2u_openwrt_22_03_3(self):
|
||||
self.set_machine('bpim2u')
|
||||
# This test download a 8.9 MiB compressed image and expand it
|
||||
# to 127 MiB.
|
||||
image_path_gz = self.ASSET_SD_IMAGE.fetch()
|
||||
image_path = os.path.join(self.workdir, 'sdcard.img')
|
||||
gzip_uncompress(image_path_gz, image_path)
|
||||
image_path = self.uncompress(self.ASSET_SD_IMAGE)
|
||||
image_pow2ceil_expand(image_path)
|
||||
|
||||
self.vm.set_console()
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class CanonA1100Machine(QemuSystemTest):
|
||||
"""Boots the barebox firmware and checks that the console is operational"""
|
||||
|
@ -26,12 +26,10 @@ class CanonA1100Machine(QemuSystemTest):
|
|||
def test_arm_canona1100(self):
|
||||
self.set_machine('canon-a1100')
|
||||
|
||||
file_path = self.ASSET_BIOS.fetch()
|
||||
archive_extract(file_path, dest_dir=self.workdir,
|
||||
member="day18/barebox.canon-a1100.bin")
|
||||
bios = self.archive_extract(self.ASSET_BIOS,
|
||||
member="day18/barebox.canon-a1100.bin")
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-bios',
|
||||
self.workdir + '/day18/barebox.canon-a1100.bin')
|
||||
self.vm.add_args('-bios', bios)
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self, 'running /env/bin/init')
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class CollieTest(LinuxKernelTest):
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
|
||||
from qemu_test import interrupt_interactive_console_until_pattern
|
||||
from qemu_test.utils import gzip_uncompress, image_pow2ceil_expand
|
||||
from unittest import skipUnless
|
||||
from qemu_test import skipBigDataTest
|
||||
from qemu_test.utils import image_pow2ceil_expand
|
||||
|
||||
|
||||
class CubieboardMachine(LinuxKernelTest):
|
||||
|
||||
|
@ -38,14 +38,12 @@ class CubieboardMachine(LinuxKernelTest):
|
|||
|
||||
def test_arm_cubieboard_initrd(self):
|
||||
self.set_machine('cubieboard')
|
||||
deb_path = self.ASSET_DEB.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
initrd_path_gz = self.ASSET_INITRD.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
gzip_uncompress(initrd_path_gz, initrd_path)
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
|
||||
'sun4i-a10-cubieboard.dtb')
|
||||
dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
|
||||
initrd_path = self.uncompress(self.ASSET_INITRD)
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
|
@ -71,15 +69,13 @@ class CubieboardMachine(LinuxKernelTest):
|
|||
|
||||
def test_arm_cubieboard_sata(self):
|
||||
self.set_machine('cubieboard')
|
||||
deb_path = self.ASSET_DEB.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
|
||||
'sun4i-a10-cubieboard.dtb')
|
||||
dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
|
||||
|
||||
rootfs_path_gz = self.ASSET_SATA_ROOTFS.fetch()
|
||||
rootfs_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
gzip_uncompress(rootfs_path_gz, rootfs_path)
|
||||
rootfs_path = self.uncompress(self.ASSET_SATA_ROOTFS)
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
|
@ -106,14 +102,12 @@ class CubieboardMachine(LinuxKernelTest):
|
|||
# Wait for VM to shut down gracefully
|
||||
self.vm.wait()
|
||||
|
||||
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
|
||||
@skipBigDataTest()
|
||||
def test_arm_cubieboard_openwrt_22_03_2(self):
|
||||
# This test download a 7.5 MiB compressed image and expand it
|
||||
# to 126 MiB.
|
||||
self.set_machine('cubieboard')
|
||||
image_path_gz = self.ASSET_OPENWRT.fetch()
|
||||
image_path = os.path.join(self.workdir, 'sdcard.img')
|
||||
gzip_uncompress(image_path_gz, image_path)
|
||||
image_path = self.uncompress(self.ASSET_OPENWRT)
|
||||
image_pow2ceil_expand(image_path)
|
||||
|
||||
self.vm.set_console()
|
||||
|
|
|
@ -28,7 +28,7 @@ class EmcraftSf2Machine(LinuxKernelTest):
|
|||
|
||||
uboot_path = self.ASSET_UBOOT.fetch()
|
||||
spi_path = self.ASSET_SPI.fetch()
|
||||
spi_path_rw = os.path.join(self.workdir, 'spi.bin')
|
||||
spi_path_rw = self.scratch_file('spi.bin')
|
||||
shutil.copy(spi_path, spi_path_rw)
|
||||
os.chmod(spi_path_rw, 0o600)
|
||||
|
||||
|
|
|
@ -12,25 +12,11 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import logging
|
||||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from unittest import skipUnless
|
||||
|
||||
|
||||
NUMPY_AVAILABLE = True
|
||||
try:
|
||||
import numpy as np
|
||||
except ImportError:
|
||||
NUMPY_AVAILABLE = False
|
||||
|
||||
CV2_AVAILABLE = True
|
||||
try:
|
||||
import cv2
|
||||
except ImportError:
|
||||
CV2_AVAILABLE = False
|
||||
from qemu_test import skipIfMissingImports, skipUntrustedTest
|
||||
|
||||
|
||||
class IntegratorMachine(QemuSystemTest):
|
||||
|
@ -63,7 +49,7 @@ class IntegratorMachine(QemuSystemTest):
|
|||
'-append', 'printk.time=0 console=ttyAMA0')
|
||||
self.vm.launch()
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
|
||||
@skipUntrustedTest()
|
||||
def test_integratorcp_console(self):
|
||||
"""
|
||||
Boots the Linux kernel and checks that the console is operational
|
||||
|
@ -71,14 +57,16 @@ class IntegratorMachine(QemuSystemTest):
|
|||
self.boot_integratorcp()
|
||||
wait_for_console_pattern(self, 'Log in as root')
|
||||
|
||||
@skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed')
|
||||
@skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed')
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
|
||||
@skipIfMissingImports("numpy", "cv2")
|
||||
@skipUntrustedTest()
|
||||
def test_framebuffer_tux_logo(self):
|
||||
"""
|
||||
Boot Linux and verify the Tux logo is displayed on the framebuffer.
|
||||
"""
|
||||
screendump_path = os.path.join(self.workdir, "screendump.pbm")
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
screendump_path = self.scratch_file("screendump.pbm")
|
||||
tuxlogo_path = self.ASSET_TUXLOGO.fetch()
|
||||
|
||||
self.boot_integratorcp()
|
||||
|
|
|
@ -10,10 +10,9 @@ import shutil
|
|||
|
||||
from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern
|
||||
from qemu_test import Asset, interrupt_interactive_console_until_pattern
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test.utils import archive_extract, gzip_uncompress, lzma_uncompress
|
||||
from qemu_test import wait_for_console_pattern, skipBigDataTest
|
||||
from qemu_test.utils import image_pow2ceil_expand
|
||||
from unittest import skipUnless
|
||||
|
||||
|
||||
class BananaPiMachine(LinuxKernelTest):
|
||||
|
||||
|
@ -50,11 +49,11 @@ class BananaPiMachine(LinuxKernelTest):
|
|||
|
||||
def test_arm_orangepi(self):
|
||||
self.set_machine('orangepi-pc')
|
||||
deb_path = self.ASSET_DEB.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
|
||||
'sun8i-h3-orangepi-pc.dtb')
|
||||
dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
|
@ -71,14 +70,12 @@ class BananaPiMachine(LinuxKernelTest):
|
|||
|
||||
def test_arm_orangepi_initrd(self):
|
||||
self.set_machine('orangepi-pc')
|
||||
deb_path = self.ASSET_DEB.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
initrd_path_gz = self.ASSET_INITRD.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
gzip_uncompress(initrd_path_gz, initrd_path)
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
|
||||
'sun8i-h3-orangepi-pc.dtb')
|
||||
dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
|
||||
initrd_path = self.uncompress(self.ASSET_INITRD)
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
|
@ -107,14 +104,12 @@ class BananaPiMachine(LinuxKernelTest):
|
|||
def test_arm_orangepi_sd(self):
|
||||
self.set_machine('orangepi-pc')
|
||||
self.require_netdev('user')
|
||||
deb_path = self.ASSET_DEB.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
rootfs_path_xz = self.ASSET_ROOTFS.fetch()
|
||||
rootfs_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
lzma_uncompress(rootfs_path_xz, rootfs_path)
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
|
||||
dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
|
||||
'sun8i-h3-orangepi-pc.dtb')
|
||||
dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
|
||||
rootfs_path = self.uncompress(self.ASSET_ROOTFS)
|
||||
image_pow2ceil_expand(rootfs_path)
|
||||
|
||||
self.vm.set_console()
|
||||
|
@ -149,15 +144,13 @@ class BananaPiMachine(LinuxKernelTest):
|
|||
os.remove(dtb_path)
|
||||
os.remove(rootfs_path)
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 'storage limited')
|
||||
@skipBigDataTest()
|
||||
def test_arm_orangepi_armbian(self):
|
||||
self.set_machine('orangepi-pc')
|
||||
# This test download a 275 MiB compressed image and expand it
|
||||
# to 1036 MiB, but the underlying filesystem is 1552 MiB...
|
||||
# As we expand it to 2 GiB we are safe.
|
||||
image_path_xz = self.ASSET_ARMBIAN.fetch()
|
||||
image_path = os.path.join(self.workdir, 'armbian.img')
|
||||
lzma_uncompress(image_path_xz, image_path)
|
||||
image_path = self.uncompress(self.ASSET_ARMBIAN)
|
||||
image_pow2ceil_expand(image_path)
|
||||
|
||||
self.vm.set_console()
|
||||
|
@ -185,20 +178,17 @@ class BananaPiMachine(LinuxKernelTest):
|
|||
'to <orangepipc>')
|
||||
self.wait_for_console_pattern('Starting Load Kernel Modules...')
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 'storage limited')
|
||||
@skipBigDataTest()
|
||||
def test_arm_orangepi_uboot_netbsd9(self):
|
||||
self.set_machine('orangepi-pc')
|
||||
# This test download a 304MB compressed image and expand it to 2GB
|
||||
deb_path = self.ASSET_UBOOT.fetch()
|
||||
# We use the common OrangePi PC 'plus' build of U-Boot for our secondary
|
||||
# program loader (SPL). We will then set the path to the more specific
|
||||
# OrangePi "PC" device tree blob with 'setenv fdtfile' in U-Boot prompt,
|
||||
# before to boot NetBSD.
|
||||
uboot_path = '/usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin'
|
||||
uboot_path = self.extract_from_deb(deb_path, uboot_path)
|
||||
image_path_gz = self.ASSET_NETBSD.fetch()
|
||||
image_path = os.path.join(self.workdir, 'armv7.img')
|
||||
gzip_uncompress(image_path_gz, image_path)
|
||||
uboot_path = 'usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin'
|
||||
uboot_path = self.archive_extract(self.ASSET_UBOOT, member=uboot_path)
|
||||
image_path = self.uncompress(self.ASSET_NETBSD)
|
||||
image_pow2ceil_expand(image_path)
|
||||
image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path
|
||||
|
||||
|
|
94
tests/functional/test_arm_quanta_gsj.py
Executable file
94
tests/functional/test_arm_quanta_gsj.py
Executable file
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Functional test that boots a Linux kernel and checks the console
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
|
||||
from qemu_test import interrupt_interactive_console_until_pattern
|
||||
from unittest import skipUnless
|
||||
|
||||
class EmcraftSf2Machine(LinuxKernelTest):
|
||||
|
||||
ASSET_IMAGE = Asset(
|
||||
('https://github.com/hskinnemoen/openbmc/releases/download/'
|
||||
'20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz'),
|
||||
'eccd4e375cde53034c84aece5c511932cacf838d9fd3f63da368a511757da72b')
|
||||
|
||||
ASSET_INITRD = Asset(
|
||||
('https://github.com/hskinnemoen/openbmc/releases/download/'
|
||||
'20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz'),
|
||||
'37b05009fc54db1434beac12bd7ff99a2e751a2f032ee18d9042f991dd0cdeaa')
|
||||
|
||||
ASSET_KERNEL = Asset(
|
||||
('https://github.com/hskinnemoen/openbmc/releases/download/'
|
||||
'20200711-gsj-qemu-0/uImage-gsj.bin'),
|
||||
'ce6d6b37bff46c74fc7b1e90da10a431cc37a62cdb35ec199fa73473d0790110')
|
||||
|
||||
ASSET_DTB = Asset(
|
||||
('https://github.com/hskinnemoen/openbmc/releases/download/'
|
||||
'20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb'),
|
||||
'3249b2da787d4b9ad4e61f315b160abfceb87b5e1895a7ce898ce7f40c8d4045')
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout')
|
||||
def test_arm_quanta_gsj(self):
|
||||
self.set_machine('quanta-gsj')
|
||||
image_path = self.uncompress(ASSET_IMAGE, 'obmc.mtd', format='gz')
|
||||
|
||||
self.vm.set_console()
|
||||
drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
|
||||
self.vm.add_args('-drive', drive_args)
|
||||
self.vm.launch()
|
||||
|
||||
# Disable drivers and services that stall for a long time during boot,
|
||||
# to avoid running past the 90-second timeout. These may be removed
|
||||
# as the corresponding device support is added.
|
||||
kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
|
||||
'console=${console} '
|
||||
'mem=${mem} '
|
||||
'initcall_blacklist=npcm_i2c_bus_driver_init '
|
||||
'systemd.mask=systemd-random-seed.service '
|
||||
'systemd.mask=dropbearkey.service '
|
||||
)
|
||||
|
||||
self.wait_for_console_pattern('> BootBlock by Nuvoton')
|
||||
self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
|
||||
self.wait_for_console_pattern('>Skip DDR init.')
|
||||
self.wait_for_console_pattern('U-Boot ')
|
||||
interrupt_interactive_console_until_pattern(
|
||||
self, 'Hit any key to stop autoboot:', 'U-Boot>')
|
||||
exec_command_and_wait_for_pattern(
|
||||
self, "setenv bootargs ${bootargs} " + kernel_command_line,
|
||||
'U-Boot>')
|
||||
exec_command_and_wait_for_pattern(
|
||||
self, 'run romboot', 'Booting Kernel from flash')
|
||||
self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
|
||||
self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
|
||||
self.wait_for_console_pattern('OpenBMC Project Reference Distro')
|
||||
self.wait_for_console_pattern('gsj login:')
|
||||
|
||||
def test_arm_quanta_gsj_initrd(self):
|
||||
self.set_machine('quanta-gsj')
|
||||
initrd_path = self.ASSET_INITRD.fetch()
|
||||
kernel_path = self.ASSET_KERNEL.fetch()
|
||||
dtb_path = self.ASSET_DTB.fetch()
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
'console=ttyS0,115200n8 '
|
||||
'earlycon=uart8250,mmio32,0xf0001000')
|
||||
self.vm.add_args('-kernel', kernel_path,
|
||||
'-initrd', initrd_path,
|
||||
'-dtb', dtb_path,
|
||||
'-append', kernel_command_line)
|
||||
self.vm.launch()
|
||||
|
||||
self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
|
||||
self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
|
||||
self.wait_for_console_pattern(
|
||||
'Give root password for system maintenance')
|
||||
|
||||
if __name__ == '__main__':
|
||||
LinuxKernelTest.main()
|
|
@ -7,11 +7,8 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test.utils import gzip_uncompress
|
||||
|
||||
|
||||
class ArmRaspi2Machine(LinuxKernelTest):
|
||||
|
@ -37,9 +34,10 @@ class ArmRaspi2Machine(LinuxKernelTest):
|
|||
serial_kernel_cmdline = {
|
||||
0: 'earlycon=pl011,0x3f201000 console=ttyAMA0',
|
||||
}
|
||||
deb_path = self.ASSET_KERNEL_20190215.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path, '/boot/kernel7.img')
|
||||
dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2709-rpi-2-b.dtb')
|
||||
kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215,
|
||||
member='boot/kernel7.img')
|
||||
dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215,
|
||||
member='boot/bcm2709-rpi-2-b.dtb')
|
||||
|
||||
self.set_machine('raspi2b')
|
||||
self.vm.set_console()
|
||||
|
@ -61,12 +59,11 @@ class ArmRaspi2Machine(LinuxKernelTest):
|
|||
self.do_test_arm_raspi2(0)
|
||||
|
||||
def test_arm_raspi2_initrd(self):
|
||||
deb_path = self.ASSET_KERNEL_20190215.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path, '/boot/kernel7.img')
|
||||
dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2709-rpi-2-b.dtb')
|
||||
initrd_path_gz = self.ASSET_INITRD.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
gzip_uncompress(initrd_path_gz, initrd_path)
|
||||
kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215,
|
||||
member='boot/kernel7.img')
|
||||
dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215,
|
||||
member='boot/bcm2709-rpi-2-b.dtb')
|
||||
initrd_path = self.uncompress(self.ASSET_INITRD)
|
||||
|
||||
self.set_machine('raspi2b')
|
||||
self.vm.set_console()
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
|
||||
from qemu_test.utils import gzip_uncompress
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
|
||||
|
||||
class Smdkc210Machine(LinuxKernelTest):
|
||||
|
||||
|
@ -26,15 +25,12 @@ class Smdkc210Machine(LinuxKernelTest):
|
|||
def test_arm_exynos4210_initrd(self):
|
||||
self.set_machine('smdkc210')
|
||||
|
||||
deb_path = self.ASSET_DEB.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinuz-4.19.0-6-armmp')
|
||||
dtb_path = '/usr/lib/linux-image-4.19.0-6-armmp/exynos4210-smdkv310.dtb'
|
||||
dtb_path = self.extract_from_deb(deb_path, dtb_path)
|
||||
kernel_path = self.archive_extract(self.ASSET_DEB,
|
||||
member='boot/vmlinuz-4.19.0-6-armmp')
|
||||
dtb_path = 'usr/lib/linux-image-4.19.0-6-armmp/exynos4210-smdkv310.dtb'
|
||||
dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
|
||||
|
||||
initrd_path_gz = self.ASSET_ROOTFS.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
gzip_uncompress(initrd_path_gz, initrd_path)
|
||||
initrd_path = self.uncompress(self.ASSET_ROOTFS)
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class SX1Test(LinuxKernelTest):
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class VExpressTest(LinuxKernelTest):
|
||||
|
||||
|
@ -16,10 +16,10 @@ class VExpressTest(LinuxKernelTest):
|
|||
|
||||
def test_arm_vexpressa9(self):
|
||||
self.set_machine('vexpress-a9')
|
||||
file_path = self.ASSET_DAY16.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.launch_kernel(self.workdir + '/day16/winter.zImage',
|
||||
dtb=self.workdir + '/day16/vexpress-v2p-ca9.dtb',
|
||||
self.archive_extract(self.ASSET_DAY16)
|
||||
self.launch_kernel(self.scratch_file('day16', 'winter.zImage'),
|
||||
dtb=self.scratch_file('day16',
|
||||
'vexpress-v2p-ca9.dtb'),
|
||||
wait_for='QEMU advent calendar')
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
30
tests/functional/test_arm_virt.py
Executable file
30
tests/functional/test_arm_virt.py
Executable file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Functional test that boots a Linux kernel and checks the console
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
|
||||
class ArmVirtMachine(LinuxKernelTest):
|
||||
|
||||
ASSET_KERNEL = Asset(
|
||||
('https://archives.fedoraproject.org/pub/archive/fedora/linux/'
|
||||
'releases/29/Everything/armhfp/os/images/pxeboot/vmlinuz'),
|
||||
'18dd5f1a9a28bd539f9d047f7c0677211bae528e8712b40ca5a229a4ad8e2591')
|
||||
|
||||
def test_arm_virt(self):
|
||||
self.set_machine('virt')
|
||||
kernel_path = self.ASSET_KERNEL.fetch()
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
'console=ttyAMA0')
|
||||
self.vm.add_args('-kernel', kernel_path,
|
||||
'-append', kernel_command_line)
|
||||
self.vm.launch()
|
||||
console_pattern = 'Kernel command line: %s' % kernel_command_line
|
||||
self.wait_for_console_pattern(console_pattern)
|
||||
|
||||
if __name__ == '__main__':
|
||||
LinuxKernelTest.main()
|
|
@ -11,8 +11,7 @@
|
|||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
from qemu_test import QemuSystemTest
|
||||
|
||||
from qemu.utils import get_info_usernet_hostfwd_port
|
||||
from qemu_test.utils import get_usernet_hostfwd_port
|
||||
|
||||
|
||||
class InfoUsernet(QemuSystemTest):
|
||||
|
@ -22,9 +21,8 @@ class InfoUsernet(QemuSystemTest):
|
|||
self.set_machine('none')
|
||||
self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22')
|
||||
self.vm.launch()
|
||||
res = self.vm.cmd('human-monitor-command',
|
||||
command_line='info usernet')
|
||||
port = get_info_usernet_hostfwd_port(res)
|
||||
|
||||
port = get_usernet_hostfwd_port(self.vm)
|
||||
self.assertIsNotNone(port,
|
||||
('"info usernet" output content does not seem to '
|
||||
'contain the redirected port'))
|
||||
|
|
175
tests/functional/test_intel_iommu.py
Executable file
175
tests/functional/test_intel_iommu.py
Executable file
|
@ -0,0 +1,175 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# INTEL_IOMMU Functional tests
|
||||
#
|
||||
# Copyright (c) 2021 Red Hat, Inc.
|
||||
#
|
||||
# Author:
|
||||
# Eric Auger <eric.auger@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import hashlib
|
||||
import urllib.request
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
|
||||
from qemu_test.utils import get_usernet_hostfwd_port
|
||||
|
||||
|
||||
class IntelIOMMU(LinuxKernelTest):
|
||||
|
||||
ASSET_KERNEL = Asset(
|
||||
('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
|
||||
'/31/Server/x86_64/os/images/pxeboot/vmlinuz'),
|
||||
'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129')
|
||||
|
||||
ASSET_INITRD = Asset(
|
||||
('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
|
||||
'/31/Server/x86_64/os/images/pxeboot/initrd.img'),
|
||||
'277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b')
|
||||
|
||||
ASSET_DISKIMAGE = Asset(
|
||||
('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
|
||||
'/31/Cloud/x86_64/images/Fedora-Cloud-Base-31-1.9.x86_64.qcow2'),
|
||||
'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0')
|
||||
|
||||
DEFAULT_KERNEL_PARAMS = ('root=/dev/vda1 console=ttyS0 net.ifnames=0 '
|
||||
'quiet rd.rescue ')
|
||||
GUEST_PORT = 8080
|
||||
IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on'
|
||||
kernel_path = None
|
||||
initrd_path = None
|
||||
kernel_params = None
|
||||
|
||||
def add_common_args(self, path):
|
||||
self.vm.add_args('-drive', f'file={path},if=none,id=drv0,snapshot=on')
|
||||
self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' +
|
||||
'drive=drv0,id=virtio-disk0,bootindex=1,'
|
||||
'werror=stop,rerror=stop' + self.IOMMU_ADDON)
|
||||
self.vm.add_args('-device', 'virtio-gpu-pci' + self.IOMMU_ADDON)
|
||||
|
||||
self.vm.add_args('-netdev',
|
||||
'user,id=n1,hostfwd=tcp:127.0.0.1:0-:%d' %
|
||||
self.GUEST_PORT)
|
||||
self.vm.add_args('-device',
|
||||
'virtio-net-pci,netdev=n1' + self.IOMMU_ADDON)
|
||||
|
||||
self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0')
|
||||
self.vm.add_args('-object',
|
||||
'rng-random,id=rng0,filename=/dev/urandom')
|
||||
self.vm.add_args("-m", "1G")
|
||||
self.vm.add_args("-accel", "kvm")
|
||||
|
||||
def common_vm_setup(self):
|
||||
self.set_machine('q35')
|
||||
self.require_accelerator("kvm")
|
||||
self.require_netdev('user')
|
||||
|
||||
self.kernel_path = self.ASSET_KERNEL.fetch()
|
||||
self.initrd_path = self.ASSET_INITRD.fetch()
|
||||
image_path = self.ASSET_DISKIMAGE.fetch()
|
||||
self.add_common_args(image_path)
|
||||
self.kernel_params = self.DEFAULT_KERNEL_PARAMS
|
||||
|
||||
def run_and_check(self):
|
||||
if self.kernel_path:
|
||||
self.vm.add_args('-kernel', self.kernel_path,
|
||||
'-append', self.kernel_params,
|
||||
'-initrd', self.initrd_path)
|
||||
self.vm.set_console()
|
||||
self.vm.launch()
|
||||
self.wait_for_console_pattern('Entering emergency mode.')
|
||||
prompt = '# '
|
||||
self.wait_for_console_pattern(prompt)
|
||||
|
||||
# Copy a file (checked later), umount afterwards to drop disk cache:
|
||||
exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot',
|
||||
prompt)
|
||||
filename = '/boot/initramfs-5.3.7-301.fc31.x86_64.img'
|
||||
exec_command_and_wait_for_pattern(self, (f'cp /sysroot{filename}'
|
||||
' /sysroot/root/data'),
|
||||
prompt)
|
||||
exec_command_and_wait_for_pattern(self, 'umount /sysroot', prompt)
|
||||
|
||||
# Switch from initrd to the cloud image filesystem:
|
||||
exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot',
|
||||
prompt)
|
||||
exec_command_and_wait_for_pattern(self,
|
||||
('for d in dev proc sys run ; do '
|
||||
'mount -o bind /$d /sysroot/$d ; done'), prompt)
|
||||
exec_command_and_wait_for_pattern(self, 'chroot /sysroot', prompt)
|
||||
|
||||
# Checking for IOMMU enablement:
|
||||
self.log.info("Checking whether IOMMU has been enabled...")
|
||||
exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline',
|
||||
'intel_iommu=on')
|
||||
self.wait_for_console_pattern(prompt)
|
||||
exec_command_and_wait_for_pattern(self, 'dmesg | grep DMAR:',
|
||||
'IOMMU enabled')
|
||||
self.wait_for_console_pattern(prompt)
|
||||
exec_command_and_wait_for_pattern(self,
|
||||
'find /sys/kernel/iommu_groups/ -type l',
|
||||
'devices/0000:00:')
|
||||
self.wait_for_console_pattern(prompt)
|
||||
|
||||
# Check hard disk device via sha256sum:
|
||||
self.log.info("Checking hard disk...")
|
||||
hashsum = '0dc7472f879be70b2f3daae279e3ae47175ffe249691e7d97f47222b65b8a720'
|
||||
exec_command_and_wait_for_pattern(self, 'sha256sum ' + filename,
|
||||
hashsum)
|
||||
self.wait_for_console_pattern(prompt)
|
||||
exec_command_and_wait_for_pattern(self, 'sha256sum /root/data',
|
||||
hashsum)
|
||||
self.wait_for_console_pattern(prompt)
|
||||
|
||||
# Check virtio-net via HTTP:
|
||||
exec_command_and_wait_for_pattern(self, 'dhclient eth0', prompt)
|
||||
exec_command_and_wait_for_pattern(self,
|
||||
f'python3 -m http.server {self.GUEST_PORT} & sleep 1',
|
||||
f'Serving HTTP on 0.0.0.0 port {self.GUEST_PORT}')
|
||||
hl = hashlib.sha256()
|
||||
hostport = get_usernet_hostfwd_port(self.vm)
|
||||
url = f'http://localhost:{hostport}{filename}'
|
||||
self.log.info(f'Downloading {url} ...')
|
||||
with urllib.request.urlopen(url) as response:
|
||||
while True:
|
||||
chunk = response.read(1 << 20)
|
||||
if not chunk:
|
||||
break
|
||||
hl.update(chunk)
|
||||
|
||||
digest = hl.hexdigest()
|
||||
self.log.info(f'sha256sum of download is {digest}.')
|
||||
self.assertEqual(digest, hashsum)
|
||||
|
||||
def test_intel_iommu(self):
|
||||
self.common_vm_setup()
|
||||
self.vm.add_args('-device', 'intel-iommu,intremap=on')
|
||||
self.vm.add_args('-machine', 'kernel_irqchip=split')
|
||||
self.kernel_params += 'intel_iommu=on'
|
||||
self.run_and_check()
|
||||
|
||||
def test_intel_iommu_strict(self):
|
||||
self.common_vm_setup()
|
||||
self.vm.add_args('-device', 'intel-iommu,intremap=on')
|
||||
self.vm.add_args('-machine', 'kernel_irqchip=split')
|
||||
self.kernel_params += 'intel_iommu=on,strict'
|
||||
self.run_and_check()
|
||||
|
||||
def test_intel_iommu_strict_cm(self):
|
||||
self.common_vm_setup()
|
||||
self.vm.add_args('-device', 'intel-iommu,intremap=on,caching-mode=on')
|
||||
self.vm.add_args('-machine', 'kernel_irqchip=split')
|
||||
self.kernel_params += 'intel_iommu=on,strict'
|
||||
self.run_and_check()
|
||||
|
||||
def test_intel_iommu_pt(self):
|
||||
self.common_vm_setup()
|
||||
self.vm.add_args('-device', 'intel-iommu,intremap=on')
|
||||
self.vm.add_args('-machine', 'kernel_irqchip=split')
|
||||
self.kernel_params += 'intel_iommu=on iommu=pt'
|
||||
self.run_and_check()
|
||||
|
||||
if __name__ == '__main__':
|
||||
LinuxKernelTest.main()
|
|
@ -10,12 +10,10 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import os
|
||||
import logging
|
||||
import tempfile
|
||||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from unittest import skipUnless
|
||||
from qemu_test import QemuSystemTest, Asset, skipFlakyTest
|
||||
|
||||
|
||||
class LinuxInitrd(QemuSystemTest):
|
||||
|
@ -60,7 +58,8 @@ class LinuxInitrd(QemuSystemTest):
|
|||
max_size + 1)
|
||||
self.assertRegex(self.vm.get_log(), expected_msg)
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
|
||||
# XXX file tracking bug
|
||||
@skipFlakyTest(bug_url=None)
|
||||
def test_with_2gib_file_should_work_with_linux_v4_16(self):
|
||||
"""
|
||||
QEMU has supported up to 4 GiB initrd for recent kernel
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class Mcf5208EvbTest(LinuxKernelTest):
|
||||
|
||||
|
@ -16,10 +16,10 @@ class Mcf5208EvbTest(LinuxKernelTest):
|
|||
|
||||
def test_m68k_mcf5208evb(self):
|
||||
self.set_machine('mcf5208evb')
|
||||
file_path = self.ASSET_DAY07.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_DAY07)
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', self.workdir + '/day07/sanity-clause.elf')
|
||||
self.vm.add_args('-kernel',
|
||||
self.scratch_file('day07', 'sanity-clause.elf'))
|
||||
self.vm.launch()
|
||||
self.wait_for_console_pattern('QEMU advent calendar')
|
||||
|
||||
|
|
|
@ -7,19 +7,11 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from unittest import skipUnless
|
||||
|
||||
from qemu_test.tesseract import tesseract_available, tesseract_ocr
|
||||
|
||||
PIL_AVAILABLE = True
|
||||
try:
|
||||
from PIL import Image
|
||||
except ImportError:
|
||||
PIL_AVAILABLE = False
|
||||
from qemu_test import skipIfMissingImports, skipIfMissingCommands
|
||||
from qemu_test.tesseract import tesseract_ocr
|
||||
|
||||
|
||||
class NextCubeMachine(QemuSystemTest):
|
||||
|
@ -43,23 +35,21 @@ class NextCubeMachine(QemuSystemTest):
|
|||
self.vm.cmd('human-monitor-command',
|
||||
command_line='screendump %s' % screenshot_path)
|
||||
|
||||
@skipUnless(PIL_AVAILABLE, 'Python PIL not installed')
|
||||
@skipIfMissingImports("PIL")
|
||||
def test_bootrom_framebuffer_size(self):
|
||||
self.set_machine('next-cube')
|
||||
screenshot_path = os.path.join(self.workdir, "dump.ppm")
|
||||
screenshot_path = self.scratch_file("dump.ppm")
|
||||
self.check_bootrom_framebuffer(screenshot_path)
|
||||
|
||||
from PIL import Image
|
||||
width, height = Image.open(screenshot_path).size
|
||||
self.assertEqual(width, 1120)
|
||||
self.assertEqual(height, 832)
|
||||
|
||||
# Tesseract 4 adds a new OCR engine based on LSTM neural networks. The
|
||||
# new version is faster and more accurate than version 3. The drawback is
|
||||
# that it is still alpha-level software.
|
||||
@skipUnless(tesseract_available(4), 'tesseract OCR tool not available')
|
||||
@skipIfMissingCommands('tesseract')
|
||||
def test_bootrom_framebuffer_ocr_with_tesseract(self):
|
||||
self.set_machine('next-cube')
|
||||
screenshot_path = os.path.join(self.workdir, "dump.ppm")
|
||||
screenshot_path = self.scratch_file("dump.ppm")
|
||||
self.check_bootrom_framebuffer(screenshot_path)
|
||||
lines = tesseract_ocr(screenshot_path)
|
||||
text = '\n'.join(lines)
|
||||
|
|
|
@ -18,9 +18,8 @@ class Q800MachineTest(LinuxKernelTest):
|
|||
def test_m68k_q800(self):
|
||||
self.set_machine('q800')
|
||||
|
||||
deb_path = self.ASSET_KERNEL.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinux-5.3.0-1-m68k')
|
||||
kernel_path = self.archive_extract(self.ASSET_KERNEL,
|
||||
member='boot/vmlinux-5.3.0-1-m68k')
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
|
||||
|
|
|
@ -7,10 +7,9 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
from qemu_test import exec_command, exec_command_and_wait_for_pattern
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class MicroblazeMachine(QemuSystemTest):
|
||||
|
||||
|
@ -23,10 +22,10 @@ class MicroblazeMachine(QemuSystemTest):
|
|||
|
||||
def test_microblaze_s3adsp1800(self):
|
||||
self.set_machine('petalogix-s3adsp1800')
|
||||
file_path = self.ASSET_IMAGE.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_IMAGE)
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', self.workdir + '/day17/ballerina.bin')
|
||||
self.vm.add_args('-kernel',
|
||||
self.scratch_file('day17', 'ballerina.bin'))
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self, 'This architecture does not have '
|
||||
'kernel memory protection')
|
||||
|
|
|
@ -11,7 +11,7 @@ import time
|
|||
from qemu_test import exec_command, exec_command_and_wait_for_pattern
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class MicroblazeelMachine(QemuSystemTest):
|
||||
|
||||
|
@ -24,11 +24,11 @@ class MicroblazeelMachine(QemuSystemTest):
|
|||
def test_microblazeel_s3adsp1800(self):
|
||||
self.require_netdev('user')
|
||||
self.set_machine('petalogix-s3adsp1800')
|
||||
file_path = self.ASSET_IMAGE.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_IMAGE)
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', self.workdir + '/day13/xmaton.bin')
|
||||
self.vm.add_args('-nic', 'user,tftp=' + self.workdir + '/day13/')
|
||||
self.vm.add_args('-kernel', self.scratch_file('day13', 'xmaton.bin'))
|
||||
tftproot = self.scratch_file('day13')
|
||||
self.vm.add_args('-nic', f'user,tftp={tftproot}')
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self, 'QEMU Advent Calendar 2023')
|
||||
time.sleep(0.1)
|
||||
|
|
|
@ -13,7 +13,7 @@ import os
|
|||
import subprocess
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import wait_for_console_pattern, skipUntrustedTest
|
||||
from unittest import skipUnless
|
||||
|
||||
class MipsFuloong2e(LinuxKernelTest):
|
||||
|
@ -26,9 +26,9 @@ class MipsFuloong2e(LinuxKernelTest):
|
|||
'2a70f15b397f4ced632b0c15cb22660394190644146d804d60a4796eefbe1f50')
|
||||
|
||||
def test_linux_kernel_3_16(self):
|
||||
deb_path = self.ASSET_KERNEL.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinux-3.16.0-6-loongson-2e')
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_KERNEL,
|
||||
member='boot/vmlinux-3.16.0-6-loongson-2e')
|
||||
|
||||
self.set_machine('fuloong2e')
|
||||
self.vm.set_console()
|
||||
|
@ -39,7 +39,7 @@ class MipsFuloong2e(LinuxKernelTest):
|
|||
console_pattern = 'Kernel command line: %s' % kernel_command_line
|
||||
self.wait_for_console_pattern(console_pattern)
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
|
||||
@skipUntrustedTest()
|
||||
@skipUnless(os.getenv('RESCUE_YL_PATH'), 'RESCUE_YL_PATH not available')
|
||||
def test_linux_kernel_2_6_27_isa_serial(self):
|
||||
# Recovery system for the Yeeloong laptop
|
||||
|
|
|
@ -9,11 +9,9 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from unittest import skipUnless
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import wait_for_console_pattern, skipUntrustedTest
|
||||
|
||||
|
||||
class MipsLoongson3v(QemuSystemTest):
|
||||
timeout = 60
|
||||
|
@ -23,7 +21,7 @@ class MipsLoongson3v(QemuSystemTest):
|
|||
'releases/download/20210112/pmon-3avirt.bin'),
|
||||
'fcdf6bb2cb7885a4a62f31fcb0d5e368bac7b6cea28f40c6dfa678af22fea20a')
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
|
||||
@skipUntrustedTest()
|
||||
def test_pmon_serial_console(self):
|
||||
self.set_machine('loongson3-virt')
|
||||
|
||||
|
|
|
@ -14,20 +14,7 @@ import logging
|
|||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test.utils import gzip_uncompress
|
||||
from unittest import skipUnless
|
||||
|
||||
NUMPY_AVAILABLE = True
|
||||
try:
|
||||
import numpy as np
|
||||
except ImportError:
|
||||
NUMPY_AVAILABLE = False
|
||||
|
||||
CV2_AVAILABLE = True
|
||||
try:
|
||||
import cv2
|
||||
except ImportError:
|
||||
CV2_AVAILABLE = False
|
||||
from qemu_test import skipIfMissingImports, skipFlakyTest, skipUntrustedTest
|
||||
|
||||
|
||||
class MaltaMachineConsole(LinuxKernelTest):
|
||||
|
@ -51,9 +38,9 @@ class MaltaMachineConsole(LinuxKernelTest):
|
|||
[2] https://kernel-team.pages.debian.net/kernel-handbook/
|
||||
ch-common-tasks.html#s-common-official
|
||||
"""
|
||||
deb_path = self.ASSET_KERNEL_2_63_2.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinux-2.6.32-5-5kc-malta')
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_KERNEL_2_63_2,
|
||||
member='boot/vmlinux-2.6.32-5-5kc-malta')
|
||||
|
||||
self.set_machine('malta')
|
||||
self.vm.set_console()
|
||||
|
@ -76,12 +63,10 @@ class MaltaMachineConsole(LinuxKernelTest):
|
|||
'rootfs.mipsel64r1.cpio.gz'),
|
||||
'75ba10cd35fb44e32948eeb26974f061b703c81c4ba2fab1ebcacf1d1bec3b61')
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
|
||||
@skipUntrustedTest()
|
||||
def test_mips64el_malta_5KEc_cpio(self):
|
||||
kernel_path = self.ASSET_KERNEL_3_19_3.fetch()
|
||||
initrd_path_gz = self.ASSET_CPIO_R1.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
gzip_uncompress(initrd_path_gz, initrd_path)
|
||||
initrd_path = self.uncompress(self.ASSET_CPIO_R1)
|
||||
|
||||
self.set_machine('malta')
|
||||
self.vm.set_console()
|
||||
|
@ -106,8 +91,7 @@ class MaltaMachineConsole(LinuxKernelTest):
|
|||
self.vm.wait()
|
||||
|
||||
|
||||
@skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed')
|
||||
@skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed')
|
||||
@skipIfMissingImports('numpy', 'cv2')
|
||||
class MaltaMachineFramebuffer(LinuxKernelTest):
|
||||
|
||||
timeout = 30
|
||||
|
@ -126,11 +110,13 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
|
|||
"""
|
||||
Boot Linux kernel and check Tux logo is displayed on the framebuffer.
|
||||
"""
|
||||
screendump_path = os.path.join(self.workdir, 'screendump.pbm')
|
||||
|
||||
kernel_path_gz = self.ASSET_KERNEL_4_7_0.fetch()
|
||||
kernel_path = self.workdir + "/vmlinux"
|
||||
gzip_uncompress(kernel_path_gz, kernel_path)
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
screendump_path = self.scratch_file('screendump.pbm')
|
||||
|
||||
kernel_path = self.uncompress(self.ASSET_KERNEL_4_7_0)
|
||||
|
||||
tuxlogo_path = self.ASSET_TUXLOGO.fetch()
|
||||
|
||||
|
@ -171,11 +157,12 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
|
|||
def test_mips_malta_i6400_framebuffer_logo_1core(self):
|
||||
self.do_test_i6400_framebuffer_logo(1)
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
|
||||
# XXX file tracking bug
|
||||
@skipFlakyTest(bug_url=None)
|
||||
def test_mips_malta_i6400_framebuffer_logo_7cores(self):
|
||||
self.do_test_i6400_framebuffer_logo(7)
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
|
||||
@skipFlakyTest(bug_url=None)
|
||||
def test_mips_malta_i6400_framebuffer_logo_8cores(self):
|
||||
self.do_test_i6400_framebuffer_logo(8)
|
||||
|
||||
|
|
|
@ -6,11 +6,8 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test.utils import gzip_uncompress
|
||||
|
||||
|
||||
class MaltaMachineConsole(LinuxKernelTest):
|
||||
|
@ -22,9 +19,9 @@ class MaltaMachineConsole(LinuxKernelTest):
|
|||
'16ca524148afb0626f483163e5edf352bc1ab0e4fc7b9f9d473252762f2c7a43')
|
||||
|
||||
def test_mips_malta(self):
|
||||
deb_path = self.ASSET_KERNEL_2_63_2.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinux-2.6.32-5-4kc-malta')
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_KERNEL_2_63_2,
|
||||
member='boot/vmlinux-2.6.32-5-4kc-malta')
|
||||
|
||||
self.set_machine('malta')
|
||||
self.vm.set_console()
|
||||
|
@ -48,12 +45,10 @@ class MaltaMachineConsole(LinuxKernelTest):
|
|||
'dcfe3a7fe3200da3a00d176b95caaa086495eb158f2bff64afc67d7e1eb2cddc')
|
||||
|
||||
def test_mips_malta_cpio(self):
|
||||
deb_path = self.ASSET_KERNEL_4_5_0.fetch()
|
||||
kernel_path = self.extract_from_deb(deb_path,
|
||||
'/boot/vmlinux-4.5.0-2-4kc-malta')
|
||||
initrd_path_gz = self.ASSET_INITRD.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
|
||||
gzip_uncompress(initrd_path_gz, initrd_path)
|
||||
kernel_path = self.archive_extract(
|
||||
self.ASSET_KERNEL_4_5_0,
|
||||
member='boot/vmlinux-4.5.0-2-4kc-malta')
|
||||
initrd_path = self.uncompress(self.ASSET_INITRD)
|
||||
|
||||
self.set_machine('malta')
|
||||
self.vm.set_console()
|
||||
|
|
|
@ -9,13 +9,9 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import QemuSystemTest, LinuxKernelTest, Asset
|
||||
from qemu_test import interrupt_interactive_console_until_pattern
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test.utils import lzma_uncompress
|
||||
from zipfile import ZipFile
|
||||
|
||||
|
||||
class MaltaMachineConsole(LinuxKernelTest):
|
||||
|
@ -36,9 +32,8 @@ class MaltaMachineConsole(LinuxKernelTest):
|
|||
'generic_nano32r6el_page64k_dbg.xz'),
|
||||
'ce21ff4b07a981ecb8a39db2876616f5a2473eb2ab459c6f67465b9914b0c6b6')
|
||||
|
||||
def do_test_mips_malta32el_nanomips(self, kernel_path_xz):
|
||||
kernel_path = os.path.join(self.workdir, 'kernel')
|
||||
lzma_uncompress(kernel_path_xz, kernel_path)
|
||||
def do_test_mips_malta32el_nanomips(self, kernel):
|
||||
kernel_path = self.uncompress(kernel)
|
||||
|
||||
self.set_machine('malta')
|
||||
self.vm.set_console()
|
||||
|
@ -54,16 +49,13 @@ class MaltaMachineConsole(LinuxKernelTest):
|
|||
self.wait_for_console_pattern(console_pattern)
|
||||
|
||||
def test_mips_malta32el_nanomips_4k(self):
|
||||
kernel_path_xz = self.ASSET_KERNEL_4K.fetch()
|
||||
self.do_test_mips_malta32el_nanomips(kernel_path_xz)
|
||||
self.do_test_mips_malta32el_nanomips(self.ASSET_KERNEL_4K)
|
||||
|
||||
def test_mips_malta32el_nanomips_16k_up(self):
|
||||
kernel_path_xz = self.ASSET_KERNEL_16K.fetch()
|
||||
self.do_test_mips_malta32el_nanomips(kernel_path_xz)
|
||||
self.do_test_mips_malta32el_nanomips(self.ASSET_KERNEL_16K)
|
||||
|
||||
def test_mips_malta32el_nanomips_64k_dbg(self):
|
||||
kernel_path_xz = self.ASSET_KERNEL_16K.fetch()
|
||||
self.do_test_mips_malta32el_nanomips(kernel_path_xz)
|
||||
self.do_test_mips_malta32el_nanomips(self.ASSET_KERNEL_64K)
|
||||
|
||||
|
||||
class MaltaMachineYAMON(QemuSystemTest):
|
||||
|
@ -75,10 +67,8 @@ class MaltaMachineYAMON(QemuSystemTest):
|
|||
|
||||
def test_mipsel_malta_yamon(self):
|
||||
yamon_bin = 'yamon-02.22.bin'
|
||||
zip_path = self.ASSET_YAMON_ROM.fetch()
|
||||
with ZipFile(zip_path, 'r') as zf:
|
||||
zf.extract(yamon_bin, path=self.workdir)
|
||||
yamon_path = os.path.join(self.workdir, yamon_bin)
|
||||
self.archive_extract(self.ASSET_YAMON_ROM)
|
||||
yamon_path = self.scratch_file(yamon_bin)
|
||||
|
||||
self.set_machine('malta')
|
||||
self.vm.set_console()
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class OpenRISC1kSimTest(LinuxKernelTest):
|
||||
|
||||
|
@ -16,10 +16,9 @@ class OpenRISC1kSimTest(LinuxKernelTest):
|
|||
|
||||
def test_or1k_sim(self):
|
||||
self.set_machine('or1k-sim')
|
||||
file_path = self.ASSET_DAY20.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_DAY20)
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', self.workdir + '/day20/vmlinux')
|
||||
self.vm.add_args('-kernel', self.scratch_file('day20', 'vmlinux'))
|
||||
self.vm.launch()
|
||||
self.wait_for_console_pattern('QEMU advent calendar')
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class E500Test(LinuxKernelTest):
|
||||
|
||||
|
@ -16,9 +16,8 @@ class E500Test(LinuxKernelTest):
|
|||
def test_ppc64_e500(self):
|
||||
self.set_machine('ppce500')
|
||||
self.cpu = 'e5500'
|
||||
file_path = self.ASSET_DAY19.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.launch_kernel(self.workdir + '/day19/uImage',
|
||||
self.archive_extract(self.ASSET_DAY19)
|
||||
self.launch_kernel(self.scratch_file('day19', 'uImage'),
|
||||
wait_for='QEMU advent calendar')
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -9,35 +9,14 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
from unittest import skipIf, skipUnless
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern, exec_command
|
||||
from qemu_test import skipIfMissingCommands, skipBigDataTest
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
deps = ["xorriso"] # dependent tools needed in the test setup/box.
|
||||
|
||||
def which(tool):
|
||||
""" looks up the full path for @tool, returns None if not found
|
||||
or if @tool does not have executable permissions.
|
||||
"""
|
||||
paths=os.getenv('PATH')
|
||||
for p in paths.split(os.path.pathsep):
|
||||
p = os.path.join(p, tool)
|
||||
if os.path.exists(p) and os.access(p, os.X_OK):
|
||||
return p
|
||||
return None
|
||||
|
||||
def missing_deps():
|
||||
""" returns True if any of the test dependent tools are absent.
|
||||
"""
|
||||
for dep in deps:
|
||||
if which(dep) is None:
|
||||
return True
|
||||
return False
|
||||
|
||||
# Alpine is a light weight distro that supports QEMU. These tests boot
|
||||
# that on the machine then run a QEMU guest inside it in KVM mode,
|
||||
# that runs the same Alpine distro image.
|
||||
|
@ -45,8 +24,8 @@ def missing_deps():
|
|||
# large download, but it may be more polite to create qcow2 image with
|
||||
# QEMU already installed and use that.
|
||||
# XXX: The order of these tests seems to matter, see git blame.
|
||||
@skipIf(missing_deps(), 'dependencies (%s) not installed' % ','.join(deps))
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 'storage limited')
|
||||
@skipIfMissingCommands("xorriso")
|
||||
@skipBigDataTest()
|
||||
class HypervisorTest(QemuSystemTest):
|
||||
|
||||
timeout = 1000
|
||||
|
@ -67,23 +46,15 @@ class HypervisorTest(QemuSystemTest):
|
|||
:param path: path within the iso file of the file to be extracted
|
||||
:returns: path of the extracted file
|
||||
"""
|
||||
filename = os.path.basename(path)
|
||||
|
||||
cwd = os.getcwd()
|
||||
os.chdir(self.workdir)
|
||||
filename = self.scratch_file(os.path.basename(path))
|
||||
|
||||
cmd = "xorriso -osirrox on -indev %s -cpx %s %s" % (iso, path, filename)
|
||||
subprocess.run(cmd.split(),
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
os.chmod(filename, 0o600)
|
||||
os.chdir(cwd)
|
||||
|
||||
# Return complete path to extracted file. Because callers to
|
||||
# extract_from_iso() specify 'path' with a leading slash, it is
|
||||
# necessary to use os.path.relpath() as otherwise os.path.join()
|
||||
# interprets it as an absolute path and drops the self.workdir part.
|
||||
return os.path.normpath(os.path.join(self.workdir, filename))
|
||||
return filename
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
|
|
@ -11,9 +11,10 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from subprocess import check_call, DEVNULL
|
||||
import tempfile
|
||||
|
||||
from qemu_test import run_cmd, Asset
|
||||
from qemu_test import Asset
|
||||
from qemu_test.tuxruntest import TuxRunBaselineTest
|
||||
|
||||
class TuxRunPPC64Test(TuxRunBaselineTest):
|
||||
|
@ -70,7 +71,9 @@ class TuxRunPPC64Test(TuxRunBaselineTest):
|
|||
# Create a temporary qcow2 and launch the test-case
|
||||
with tempfile.NamedTemporaryFile(prefix=prefix,
|
||||
suffix='.qcow2') as qcow2:
|
||||
run_cmd([self.qemu_img, 'create', '-f', 'qcow2', qcow2.name, ' 1G'])
|
||||
check_call([self.qemu_img, 'create', '-f', 'qcow2',
|
||||
qcow2.name, ' 1G'],
|
||||
stdout=DEVNULL, stderr=DEVNULL)
|
||||
|
||||
self.vm.add_args('-drive', 'file=' + qcow2.name +
|
||||
',format=qcow2,if=none,id='
|
||||
|
|
|
@ -7,11 +7,8 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import os
|
||||
|
||||
from unittest import skipUnless
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import wait_for_console_pattern, skipUntrustedTest
|
||||
|
||||
|
||||
class IbmPrep40pMachine(QemuSystemTest):
|
||||
|
@ -37,7 +34,7 @@ class IbmPrep40pMachine(QemuSystemTest):
|
|||
# All rights reserved.
|
||||
# U.S. Government Users Restricted Rights - Use, duplication or disclosure
|
||||
# restricted by GSA ADP Schedule Contract with IBM Corp.
|
||||
@skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
|
||||
@skipUntrustedTest()
|
||||
def test_factory_firmware_and_netbsd(self):
|
||||
self.set_machine('40p')
|
||||
self.require_accelerator("tcg")
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
import subprocess
|
||||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern, run_cmd
|
||||
from zipfile import ZipFile
|
||||
from qemu_test import wait_for_console_pattern
|
||||
|
||||
|
||||
class AmigaOneMachine(QemuSystemTest):
|
||||
|
||||
|
@ -26,16 +26,16 @@ class AmigaOneMachine(QemuSystemTest):
|
|||
self.require_accelerator("tcg")
|
||||
self.set_machine('amigaone')
|
||||
tar_name = 'A1Firmware_Floppy_05-Mar-2005.zip'
|
||||
zip_file = self.ASSET_IMAGE.fetch()
|
||||
with ZipFile(zip_file, 'r') as zf:
|
||||
zf.extractall(path=self.workdir)
|
||||
bios_fh = open(self.workdir + "/u-boot-amigaone.bin", "wb")
|
||||
subprocess.run(['tail', '-c', '524288',
|
||||
self.workdir + "/floppy_edition/updater.image"],
|
||||
stdout=bios_fh)
|
||||
self.archive_extract(self.ASSET_IMAGE, format="zip")
|
||||
bios = self.scratch_file("u-boot-amigaone.bin")
|
||||
with open(bios, "wb") as bios_fh:
|
||||
subprocess.run(['tail', '-c', '524288',
|
||||
self.scratch_file("floppy_edition",
|
||||
"updater.image")],
|
||||
stdout=bios_fh)
|
||||
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-bios', self.workdir + '/u-boot-amigaone.bin')
|
||||
self.vm.add_args('-bios', bios)
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self, 'FLASH:')
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
from qemu_test.utils import archive_extract
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
|
||||
|
||||
class BambooMachine(QemuSystemTest):
|
||||
|
||||
timeout = 90
|
||||
|
@ -25,13 +25,14 @@ class BambooMachine(QemuSystemTest):
|
|||
self.set_machine('bamboo')
|
||||
self.require_accelerator("tcg")
|
||||
self.require_netdev('user')
|
||||
file_path = self.ASSET_IMAGE.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_IMAGE)
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', self.workdir +
|
||||
'/system-image-powerpc-440fp/linux',
|
||||
'-initrd', self.workdir +
|
||||
'/system-image-powerpc-440fp/rootfs.cpio.gz',
|
||||
self.vm.add_args('-kernel',
|
||||
self.scratch_file('system-image-powerpc-440fp',
|
||||
'linux'),
|
||||
'-initrd',
|
||||
self.scratch_file('system-image-powerpc-440fp',
|
||||
'rootfs.cpio.gz'),
|
||||
'-nic', 'user,model=rtl8139,restrict=on')
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self, 'Type exit when done')
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class MacTest(LinuxKernelTest):
|
||||
|
||||
|
@ -19,11 +19,9 @@ class MacTest(LinuxKernelTest):
|
|||
# we're running kvm_hv or kvm_pr. For now let's disable this test
|
||||
# if we don't have TCG support.
|
||||
self.require_accelerator("tcg")
|
||||
|
||||
file_path = self.ASSET_DAY15.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_DAY15)
|
||||
self.vm.add_args('-M', 'graphics=off')
|
||||
self.launch_kernel(self.workdir + '/day15/invaders.elf',
|
||||
self.launch_kernel(self.scratch_file('day15', 'invaders.elf'),
|
||||
wait_for='QEMU advent calendar')
|
||||
|
||||
def test_ppc_g3beige(self):
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
from qemu_test.utils import archive_extract
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
|
||||
|
||||
class Mpc8544dsMachine(QemuSystemTest):
|
||||
|
||||
timeout = 90
|
||||
|
@ -25,10 +25,10 @@ class Mpc8544dsMachine(QemuSystemTest):
|
|||
def test_ppc_mpc8544ds(self):
|
||||
self.require_accelerator("tcg")
|
||||
self.set_machine('mpc8544ds')
|
||||
file_path = self.ASSET_IMAGE.fetch()
|
||||
archive_extract(file_path, self.workdir, member='creek/creek.bin')
|
||||
kernel_file = self.archive_extract(self.ASSET_IMAGE,
|
||||
member='creek/creek.bin')
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', self.workdir + '/creek/creek.bin')
|
||||
self.vm.add_args('-kernel', kernel_file)
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self, 'QEMU advent calendar 2020',
|
||||
self.panic_message)
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
from qemu_test.utils import archive_extract
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
|
||||
|
||||
class VirtexMl507Machine(QemuSystemTest):
|
||||
|
||||
timeout = 90
|
||||
|
@ -25,11 +25,11 @@ class VirtexMl507Machine(QemuSystemTest):
|
|||
def test_ppc_virtex_ml507(self):
|
||||
self.require_accelerator("tcg")
|
||||
self.set_machine('virtex-ml507')
|
||||
file_path = self.ASSET_IMAGE.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_IMAGE)
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', self.workdir + '/hippo/hippo.linux',
|
||||
'-dtb', self.workdir + '/hippo/virtex440-ml507.dtb',
|
||||
self.vm.add_args('-kernel', self.scratch_file('hippo', 'hippo.linux'),
|
||||
'-dtb', self.scratch_file('hippo',
|
||||
'virtex440-ml507.dtb'),
|
||||
'-m', '512')
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self, 'QEMU advent calendar 2020',
|
||||
|
|
|
@ -10,13 +10,9 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import os
|
||||
|
||||
from unittest import skipUnless
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test.utils import gzip_uncompress
|
||||
from qemu_test import wait_for_console_pattern, skipFlakyTest
|
||||
|
||||
|
||||
class RxGdbSimMachine(QemuSystemTest):
|
||||
|
@ -40,9 +36,7 @@ class RxGdbSimMachine(QemuSystemTest):
|
|||
"""
|
||||
self.set_machine('gdbsim-r5f562n8')
|
||||
|
||||
uboot_path_gz = self.ASSET_UBOOT.fetch()
|
||||
uboot_path = os.path.join(self.workdir, 'u-boot.bin')
|
||||
gzip_uncompress(uboot_path_gz, uboot_path)
|
||||
uboot_path = self.uncompress(self.ASSET_UBOOT)
|
||||
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-bios', uboot_path,
|
||||
|
@ -52,9 +46,10 @@ class RxGdbSimMachine(QemuSystemTest):
|
|||
wait_for_console_pattern(self, uboot_version)
|
||||
gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)'
|
||||
# FIXME limit baudrate on chardev, else we type too fast
|
||||
# https://gitlab.com/qemu-project/qemu/-/issues/2691
|
||||
#exec_command_and_wait_for_pattern(self, 'version', gcc_version)
|
||||
|
||||
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
|
||||
@skipFlakyTest(bug_url="https://gitlab.com/qemu-project/qemu/-/issues/2691")
|
||||
def test_linux_sash(self):
|
||||
"""
|
||||
Boots a Linux kernel and checks that the console is operational.
|
||||
|
|
|
@ -17,7 +17,7 @@ import tempfile
|
|||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test.utils import lzma_uncompress
|
||||
|
||||
|
||||
class S390CCWVirtioMachine(QemuSystemTest):
|
||||
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
|
||||
|
@ -174,9 +174,7 @@ class S390CCWVirtioMachine(QemuSystemTest):
|
|||
|
||||
kernel_path = self.ASSET_F31_KERNEL.fetch()
|
||||
|
||||
initrd_path_xz = self.ASSET_F31_INITRD.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'initrd-raw.img')
|
||||
lzma_uncompress(initrd_path_xz, initrd_path)
|
||||
initrd_path = self.uncompress(self.ASSET_F31_INITRD, format="xz")
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + ' audit=0 '
|
||||
|
|
|
@ -10,13 +10,10 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import exec_command
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test.utils import lzma_uncompress
|
||||
|
||||
|
||||
class S390CPUTopology(QemuSystemTest):
|
||||
|
@ -88,9 +85,7 @@ class S390CPUTopology(QemuSystemTest):
|
|||
"""
|
||||
self.require_accelerator("kvm")
|
||||
kernel_path = self.ASSET_F35_KERNEL.fetch()
|
||||
initrd_path_xz = self.ASSET_F35_INITRD.fetch()
|
||||
initrd_path = os.path.join(self.workdir, 'initrd-raw.img')
|
||||
lzma_uncompress(initrd_path_xz, initrd_path)
|
||||
initrd_path = self.uncompress(self.ASSET_F35_INITRD, format="xz")
|
||||
|
||||
self.vm.set_console()
|
||||
kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE
|
||||
|
|
|
@ -4,11 +4,8 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
from qemu_test import LinuxKernelTest, Asset, skipFlakyTest
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
from unittest import skipUnless
|
||||
|
||||
class R2dTest(LinuxKernelTest):
|
||||
|
||||
|
@ -18,13 +15,14 @@ class R2dTest(LinuxKernelTest):
|
|||
|
||||
# This test has a 6-10% failure rate on various hosts that look
|
||||
# like issues with a buggy kernel.
|
||||
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable')
|
||||
# XXX file tracking bug
|
||||
@skipFlakyTest(bug_url=None)
|
||||
def test_r2d(self):
|
||||
self.set_machine('r2d')
|
||||
file_path = self.ASSET_DAY09.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_DAY09)
|
||||
self.vm.add_args('-append', 'console=ttySC1')
|
||||
self.launch_kernel(self.workdir + '/day09/zImage', console_index=1,
|
||||
self.launch_kernel(self.scratch_file('day09', 'zImage'),
|
||||
console_index=1,
|
||||
wait_for='QEMU advent calendar')
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -4,12 +4,9 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class R2dEBTest(LinuxKernelTest):
|
||||
|
||||
|
@ -19,14 +16,13 @@ class R2dEBTest(LinuxKernelTest):
|
|||
|
||||
def test_sh4eb_r2d(self):
|
||||
self.set_machine('r2d')
|
||||
file_path = self.ASSET_TGZ.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.archive_extract(self.ASSET_TGZ)
|
||||
self.vm.add_args('-append', 'console=ttySC1 noiotrap')
|
||||
self.launch_kernel(os.path.join(self.workdir, 'sh4eb/linux-kernel'),
|
||||
initrd=os.path.join(self.workdir, 'sh4eb/initramfs.cpio.gz'),
|
||||
self.launch_kernel(self.scratch_file('sh4eb', 'linux-kernel'),
|
||||
initrd=self.scratch_file('sh4eb',
|
||||
'initramfs.cpio.gz'),
|
||||
console_index=1, wait_for='Type exit when done')
|
||||
exec_command_and_wait_for_pattern(self, 'exit', 'Restarting system')
|
||||
shutil.rmtree(os.path.join(self.workdir, 'sh4eb'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
LinuxKernelTest.main()
|
||||
|
|
|
@ -10,11 +10,9 @@
|
|||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import os
|
||||
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class Sun4uMachine(QemuSystemTest):
|
||||
"""Boots the Linux kernel and checks that the console is operational"""
|
||||
|
@ -28,11 +26,10 @@ class Sun4uMachine(QemuSystemTest):
|
|||
|
||||
def test_sparc64_sun4u(self):
|
||||
self.set_machine('sun4u')
|
||||
file_path = self.ASSET_IMAGE.fetch()
|
||||
kernel_name = 'day23/vmlinux'
|
||||
archive_extract(file_path, self.workdir, kernel_name)
|
||||
kernel_file = self.archive_extract(self.ASSET_IMAGE,
|
||||
member='day23/vmlinux')
|
||||
self.vm.set_console()
|
||||
self.vm.add_args('-kernel', os.path.join(self.workdir, kernel_name),
|
||||
self.vm.add_args('-kernel', kernel_file,
|
||||
'-append', 'printk.time=0')
|
||||
self.vm.launch()
|
||||
wait_for_console_pattern(self, 'Starting logging: OK')
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class Sun4mTest(LinuxKernelTest):
|
||||
|
||||
|
@ -16,9 +16,8 @@ class Sun4mTest(LinuxKernelTest):
|
|||
|
||||
def test_sparc_ss20(self):
|
||||
self.set_machine('SS-20')
|
||||
file_path = self.ASSET_DAY11.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.launch_kernel(self.workdir + '/day11/zImage.elf',
|
||||
self.archive_extract(self.ASSET_DAY11)
|
||||
self.launch_kernel(self.scratch_file('day11', 'zImage.elf'),
|
||||
wait_for='QEMU advent calendar')
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -6,25 +6,19 @@
|
|||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
|
||||
from qemu_test import BUILD_DIR
|
||||
from qemu_test import QemuSystemTest, Asset
|
||||
from qemu_test import wait_for_console_pattern
|
||||
from qemu_test import exec_command_and_wait_for_pattern
|
||||
from qemu_test import is_readable_executable_file
|
||||
|
||||
from qemu.utils import kvm_available
|
||||
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
|
||||
|
||||
def pick_default_vug_bin():
|
||||
relative_path = "./contrib/vhost-user-gpu/vhost-user-gpu"
|
||||
if is_readable_executable_file(relative_path):
|
||||
return relative_path
|
||||
|
||||
bld_dir_path = os.path.join(BUILD_DIR, relative_path)
|
||||
def pick_default_vug_bin(test):
|
||||
bld_dir_path = test.build_file("contrib", "vhost-user-gpu", "vhost-user-gpu")
|
||||
if is_readable_executable_file(bld_dir_path):
|
||||
return bld_dir_path
|
||||
|
||||
|
@ -87,7 +81,7 @@ class VirtioGPUx86(QemuSystemTest):
|
|||
# FIXME: should check presence of vhost-user-gpu, virgl, memfd etc
|
||||
self.require_accelerator('kvm')
|
||||
|
||||
vug = pick_default_vug_bin()
|
||||
vug = pick_default_vug_bin(self)
|
||||
if not vug:
|
||||
self.skipTest("Could not find vhost-user-gpu")
|
||||
|
||||
|
@ -101,9 +95,7 @@ class VirtioGPUx86(QemuSystemTest):
|
|||
os.set_inheritable(qemu_sock.fileno(), True)
|
||||
os.set_inheritable(vug_sock.fileno(), True)
|
||||
|
||||
self._vug_log_path = os.path.join(
|
||||
self.logdir, "vhost-user-gpu.log"
|
||||
)
|
||||
self._vug_log_path = self.log_file("vhost-user-gpu.log")
|
||||
self._vug_log_file = open(self._vug_log_path, "wb")
|
||||
self.log.info('Complete vhost-user-gpu.log file can be '
|
||||
'found at %s', self._vug_log_path)
|
||||
|
|
69
tests/functional/test_x86_64_hotplug_cpu.py
Executable file
69
tests/functional/test_x86_64_hotplug_cpu.py
Executable file
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Functional test that hotplugs a CPU and checks it on a Linux guest
|
||||
#
|
||||
# Copyright (c) 2021 Red Hat, Inc.
|
||||
#
|
||||
# Author:
|
||||
# Cleber Rosa <crosa@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
|
||||
|
||||
|
||||
class HotPlugCPU(LinuxKernelTest):
|
||||
|
||||
ASSET_KERNEL = Asset(
|
||||
('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
|
||||
'/31/Server/x86_64/os/images/pxeboot/vmlinuz'),
|
||||
'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129')
|
||||
|
||||
ASSET_INITRD = Asset(
|
||||
('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
|
||||
'/31/Server/x86_64/os/images/pxeboot/initrd.img'),
|
||||
'277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b')
|
||||
|
||||
def test_hotplug(self):
|
||||
|
||||
self.require_accelerator('kvm')
|
||||
self.vm.add_args('-accel', 'kvm')
|
||||
self.vm.add_args('-cpu', 'Haswell')
|
||||
self.vm.add_args('-smp', '1,sockets=1,cores=2,threads=1,maxcpus=2')
|
||||
self.vm.add_args('-m', '1G')
|
||||
self.vm.add_args('-append', 'console=ttyS0 rd.rescue')
|
||||
|
||||
self.launch_kernel(self.ASSET_KERNEL.fetch(),
|
||||
self.ASSET_INITRD.fetch(),
|
||||
wait_for='Entering emergency mode.')
|
||||
prompt = '# '
|
||||
self.wait_for_console_pattern(prompt)
|
||||
|
||||
exec_command_and_wait_for_pattern(self,
|
||||
'cd /sys/devices/system/cpu/cpu0',
|
||||
'cpu0#')
|
||||
exec_command_and_wait_for_pattern(self,
|
||||
'cd /sys/devices/system/cpu/cpu1',
|
||||
'No such file or directory')
|
||||
|
||||
self.vm.cmd('device_add',
|
||||
driver='Haswell-x86_64-cpu',
|
||||
id='c1',
|
||||
socket_id=0,
|
||||
core_id=1,
|
||||
thread_id=0)
|
||||
self.wait_for_console_pattern('CPU1 has been hot-added')
|
||||
|
||||
exec_command_and_wait_for_pattern(self,
|
||||
'cd /sys/devices/system/cpu/cpu1',
|
||||
'cpu1#')
|
||||
|
||||
self.vm.cmd('device_del', id='c1')
|
||||
|
||||
exec_command_and_wait_for_pattern(self,
|
||||
'cd /sys/devices/system/cpu/cpu1',
|
||||
'No such file or directory')
|
||||
|
||||
if __name__ == '__main__':
|
||||
LinuxKernelTest.main()
|
|
@ -6,7 +6,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
from qemu_test import LinuxKernelTest, Asset
|
||||
from qemu_test.utils import archive_extract
|
||||
|
||||
|
||||
class XTensaLX60Test(LinuxKernelTest):
|
||||
|
||||
|
@ -17,9 +17,9 @@ class XTensaLX60Test(LinuxKernelTest):
|
|||
def test_xtensa_lx60(self):
|
||||
self.set_machine('lx60')
|
||||
self.cpu = 'dc233c'
|
||||
file_path = self.ASSET_DAY02.fetch()
|
||||
archive_extract(file_path, self.workdir)
|
||||
self.launch_kernel(self.workdir + '/day02/santas-sleigh-ride.elf',
|
||||
self.archive_extract(self.ASSET_DAY02)
|
||||
self.launch_kernel(self.scratch_file('day02',
|
||||
'santas-sleigh-ride.elf'),
|
||||
wait_for='QEMU advent calendar')
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue