diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2024-09-05 18:01:51 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2024-09-05 18:01:51 +0100 |
commit | eabebca69b7fca7cf85f6cd39ac58a7f04986b47 (patch) | |
tree | 5e7bcc92e509008cc5b761fa3fbb08e69075825c /tests | |
parent | 7b87a25f49a301d3377f3e71e0b4a62540c6f6e4 (diff) | |
parent | c3e24cff2b27d63ac4b56ac6d38ef1ae3a27d92f (diff) | |
download | qemu-eabebca69b7fca7cf85f6cd39ac58a7f04986b47.zip qemu-eabebca69b7fca7cf85f6cd39ac58a7f04986b47.tar.gz qemu-eabebca69b7fca7cf85f6cd39ac58a7f04986b47.tar.bz2 |
Merge tag 'pull-request-2024-09-04' of https://gitlab.com/thuth/qemu into staging
* Bump Avocado to version 103
* Introduce new functional test framework for Python-based tests
* Convert many Avocado tests to the new functional test framework
# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmbYOEsRHHRodXRoQHJl
# ZGhhdC5jb20ACgkQLtnXdP5wLbUDAA/+Kdlak/nCrK5gXDyDasfy86IxgMD0QlDR
# U0MOpQyfXbM2EJjwCUhmgo8pui8qV23dKzfCwbDmkjB7mJ+yKi2ZdiFEp6onq/ke
# aAdaaZwENtWcFglRD80TOSQX6oyeNmE/PuvJGG0BfwWXyyhaEa6kCdytEPORipQs
# lZ+ZndHgXtcM3roXtgI3kp2V1nY5LLCJ044UrasKRq2xWfD/Ken90uWP5/nMLV7f
# 7YLRUIb0sgV7IdjZiT1UkXJZRB7MatV7+OsojYbG8BPbQEvXqpryXMIeygHVR9a0
# yxNDUpTZR6JoS1IaLKkHh1mTM+L1JpFltKadKkXa0zqJHHSur7Tp0xVO/GeqCek4
# 9N8K4zw2CoO/AKmN8JjW5i4GnMrFMdcvxxNwLdRoVgYt4YA731wnHrbosXZOXcuv
# H0z8Tm6ueKvfBtrQErdvqsGrP/8FUYRqZP4H6XaaC+wEis++7OmVR2nlQ/gAyr6/
# mMJtmxqVHCIcEVjDu1jYltrW3BN2CcxN2M9gxyOScq2/Xmzqtaeb4iyjxeCUjIBW
# Pc4LXlSafIg3hPrdH3EKN275ev8cx/5jp8oEgXD5We25Mj3W930zde6/STXoX318
# NVNlbrIQjGjQN7rN5oxTFxTlIN8ax2tuuzpQDFvS/4bLyMYXcZ4I5gUrM5tvWTGv
# +0UN45pJ7Nk=
# =l6Ki
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 04 Sep 2024 11:36:59 BST
# 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-09-04' of https://gitlab.com/thuth/qemu: (42 commits)
docs/devel/testing: Add documentation for functional tests
docs/devel/testing: Rename avocado_qemu.Test class
docs/devel/testing: Split the Avocado documentation into a separate file
docs/devel: Split testing docs from the build docs and move to separate folder
gitlab-ci: Add "check-functional" to the build tests
tests/avocado: Remove unused QemuUserTest class
tests/functional: Convert ARM bFLT linux-user avocado test
tests/functional: Add QemuUserTest class
tests/functional: Convert mips64el Fuloong2e avocado test (1/2)
tests/functional: Convert Aarch64 Virt machine avocado tests
tests/functional: Convert Aarch64 SBSA-Ref avocado tests
tests/functional: Convert ARM Integrator/CP avocado tests
tests/functional: Convert the linux_initrd avocado test into a standalone test
tests/functional: Convert the rx_gdbsim avocado test into a standalone test
tests/functional: Convert the acpi-bits test into a standalone test
tests/functional: Convert the m68k nextcube test with tesseract
tests/functional: Convert the ppc_hv avocado test into a standalone test
tests/functional: Convert the ppc_amiga avocado test into a standalone test
tests/functional: Convert most ppc avocado tests into standalone tests
tests/functional: Convert the virtio_gpu avocado test into a standalone test
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.include | 44 | ||||
-rw-r--r-- | tests/avocado/avocado_qemu/__init__.py | 17 | ||||
-rw-r--r-- | tests/avocado/avocado_qemu/linuxtest.py | 4 | ||||
-rw-r--r-- | tests/avocado/boot_linux_console.py | 20 | ||||
-rw-r--r-- | tests/avocado/boot_xen.py | 13 | ||||
-rw-r--r-- | tests/avocado/load_bflt.py | 54 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/avocado/machine_arm_n8x0.py | 0 | ||||
-rw-r--r-- | tests/avocado/machine_microblaze.py | 61 | ||||
-rw-r--r-- | tests/avocado/machine_mips_loongson3v.py | 39 | ||||
-rw-r--r-- | tests/avocado/machine_sparc64_sun4u.py | 36 | ||||
-rw-r--r-- | tests/avocado/ppc_amiga.py | 38 | ||||
-rw-r--r-- | tests/avocado/tesseract_utils.py | 46 | ||||
-rw-r--r-- | tests/functional/acpi-bits/bits-config/bits-cfg.txt (renamed from tests/avocado/acpi-bits/bits-config/bits-cfg.txt) | 0 | ||||
-rw-r--r-- | tests/functional/acpi-bits/bits-tests/smbios.py2 (renamed from tests/avocado/acpi-bits/bits-tests/smbios.py2) | 0 | ||||
-rw-r--r-- | tests/functional/acpi-bits/bits-tests/smilatency.py2 (renamed from tests/avocado/acpi-bits/bits-tests/smilatency.py2) | 0 | ||||
-rw-r--r-- | tests/functional/acpi-bits/bits-tests/testacpi.py2 (renamed from tests/avocado/acpi-bits/bits-tests/testacpi.py2) | 0 | ||||
-rw-r--r-- | tests/functional/acpi-bits/bits-tests/testcpuid.py2 (renamed from tests/avocado/acpi-bits/bits-tests/testcpuid.py2) | 0 | ||||
-rw-r--r-- | tests/functional/meson.build | 205 | ||||
-rw-r--r-- | tests/functional/qemu_test/__init__.py | 14 | ||||
-rw-r--r-- | tests/functional/qemu_test/asset.py | 171 | ||||
-rw-r--r-- | tests/functional/qemu_test/cmd.py | 193 | ||||
-rw-r--r-- | tests/functional/qemu_test/config.py | 36 | ||||
-rw-r--r-- | tests/functional/qemu_test/tesseract.py | 35 | ||||
-rw-r--r-- | tests/functional/qemu_test/testcase.py | 202 | ||||
-rw-r--r-- | tests/functional/qemu_test/utils.py | 56 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_aarch64_sbsaref.py (renamed from tests/avocado/machine_aarch64_sbsaref.py) | 148 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_aarch64_virt.py (renamed from tests/avocado/machine_aarch64_virt.py) | 71 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_acpi_bits.py (renamed from tests/avocado/acpi-bits.py) | 83 | ||||
-rwxr-xr-x | tests/functional/test_arm_bflt.py | 44 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_arm_canona1100.py (renamed from tests/avocado/machine_arm_canona1100.py) | 30 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_arm_integratorcp.py (renamed from tests/avocado/machine_arm_integratorcp.py) | 56 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_avr_mega2560.py (renamed from tests/avocado/machine_avr6.py) | 22 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_cpu_queries.py (renamed from tests/avocado/cpu_queries.py) | 12 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_empty_cpu_model.py (renamed from tests/avocado/empty_cpu_model.py) | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_info_usernet.py (renamed from tests/avocado/info_usernet.py) | 11 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_linux_initrd.py (renamed from tests/avocado/linux_initrd.py) | 37 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_loongarch64_virt.py (renamed from tests/avocado/machine_loongarch.py) | 46 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_m68k_nextcube.py (renamed from tests/avocado/machine_m68k_nextcube.py) | 29 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_mem_addr_space.py (renamed from tests/avocado/mem-addr-space-check.py) | 52 | ||||
-rwxr-xr-x | tests/functional/test_microblaze_s3adsp1800.py | 40 | ||||
-rwxr-xr-x | tests/functional/test_microblazeel_s3adsp1800.py | 42 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_mips64el_fuloong2e.py (renamed from tests/avocado/machine_mips_fuloong2e.py) | 33 | ||||
-rwxr-xr-x | tests/functional/test_mips64el_loongson3v.py | 39 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_netdev_ethtool.py (renamed from tests/avocado/netdev-ethtool.py) | 51 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_pc_cpu_hotplug_props.py (renamed from tests/avocado/pc_cpu_hotplug_props.py) | 11 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_ppc64_hv.py (renamed from tests/avocado/ppc_hv_tests.py) | 52 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_ppc64_powernv.py (renamed from tests/avocado/ppc_powernv.py) | 56 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_ppc64_pseries.py (renamed from tests/avocado/ppc_pseries.py) | 56 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_ppc_405.py (renamed from tests/avocado/ppc_405.py) | 29 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_ppc_40p.py (renamed from tests/avocado/ppc_prep_40p.py) | 65 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_ppc_74xx.py (renamed from tests/avocado/ppc_74xx.py) | 74 | ||||
-rwxr-xr-x | tests/functional/test_ppc_amiga.py | 43 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_ppc_bamboo.py (renamed from tests/avocado/ppc_bamboo.py) | 33 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_ppc_mpc8544ds.py (renamed from tests/avocado/ppc_mpc8544ds.py) | 29 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_ppc_virtex_ml507.py (renamed from tests/avocado/ppc_virtex_ml507.py) | 29 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_rx_gdbsim.py (renamed from tests/avocado/machine_rx_gdbsim.py) | 54 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_s390x_ccw_virtio.py (renamed from tests/avocado/machine_s390_ccw_virtio.py) | 81 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_s390x_topology.py (renamed from tests/avocado/s390_topology.py) | 86 | ||||
-rwxr-xr-x | tests/functional/test_sparc64_sun4u.py | 41 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_version.py (renamed from tests/avocado/version.py) | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_virtio_gpu.py (renamed from tests/avocado/virtio-gpu.py) | 64 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_virtio_version.py (renamed from tests/avocado/virtio_version.py) | 8 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/functional/test_x86_cpu_model_versions.py (renamed from tests/avocado/x86_cpu_model_versions.py) | 65 | ||||
-rw-r--r-- | tests/meson.build | 1 |
64 files changed, 1854 insertions, 1173 deletions
diff --git a/tests/Makefile.include b/tests/Makefile.include index 6618bfe..010369b 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -3,28 +3,30 @@ .PHONY: check-help check-help: @echo "Regression testing targets:" - @echo " $(MAKE) check Run block, qapi-schema, unit, softfloat, qtest and decodetree tests" - @echo " $(MAKE) bench Run speed tests" + @echo " $(MAKE) check Run block, qapi-schema, unit, softfloat, qtest and decodetree tests" + @echo " $(MAKE) bench Run speed tests" @echo @echo "Individual test suites:" - @echo " $(MAKE) check-qtest-TARGET Run qtest tests for given target" - @echo " $(MAKE) check-qtest Run qtest tests" - @echo " $(MAKE) check-unit Run qobject tests" - @echo " $(MAKE) check-qapi-schema Run QAPI schema tests" - @echo " $(MAKE) check-block Run block tests" + @echo " $(MAKE) check-qtest-TARGET Run qtest tests for given target" + @echo " $(MAKE) check-qtest Run qtest tests" + @echo " $(MAKE) check-functional Run python-based functional tests" + @echo " $(MAKE) check-functional-TARGET Run functional tests for a given target" + @echo " $(MAKE) check-unit Run qobject tests" + @echo " $(MAKE) check-qapi-schema Run QAPI schema tests" + @echo " $(MAKE) check-block Run block tests" ifneq ($(filter $(all-check-targets), check-softfloat),) - @echo " $(MAKE) check-tcg Run TCG tests" - @echo " $(MAKE) check-softfloat Run FPU emulation tests" + @echo " $(MAKE) check-tcg Run TCG tests" + @echo " $(MAKE) check-softfloat Run FPU emulation tests" endif - @echo " $(MAKE) check-avocado Run avocado (integration) tests for currently configured targets" + @echo " $(MAKE) check-avocado Run avocado (integration) tests for currently configured targets" @echo - @echo " $(MAKE) check-report.junit.xml Generates an aggregated XML test report" - @echo " $(MAKE) check-venv Creates a Python venv for tests" - @echo " $(MAKE) check-clean Clean the tests and related data" + @echo " $(MAKE) check-report.junit.xml Generates an aggregated XML test report" + @echo " $(MAKE) check-venv Creates a Python venv for tests" + @echo " $(MAKE) check-clean Clean the tests and related data" @echo @echo "The following are useful for CI builds" - @echo " $(MAKE) check-build Build most test binaries" - @echo " $(MAKE) get-vm-images Downloads all images used by avocado tests, according to configured targets (~350 MB each, 1.5 GB max)" + @echo " $(MAKE) check-build Build most test binaries" + @echo " $(MAKE) get-vm-images Downloads all images used by avocado tests, according to configured targets (~350 MB each, 1.5 GB max)" @echo @echo @echo "The variable SPEED can be set to control the gtester speed setting." @@ -141,7 +143,7 @@ check-avocado: check-venv $(TESTS_RESULTS_DIR) get-vm-images --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \ $(if $(AVOCADO_TAGS),, --filter-by-tags-include-empty \ --filter-by-tags-include-empty-key) \ - $(AVOCADO_CMDLINE_TAGS) \ + $(AVOCADO_CMDLINE_TAGS) --max-parallel-tasks=1 \ $(if $(GITLAB_CI),,--failfast) $(AVOCADO_TESTS), \ "AVOCADO", "tests/avocado") @@ -152,6 +154,16 @@ check-acceptance-deprecated-warning: check-acceptance: check-acceptance-deprecated-warning | check-avocado +FUNCTIONAL_TARGETS=$(patsubst %-softmmu,check-functional-%, $(filter %-softmmu,$(TARGETS))) +.PHONY: $(FUNCTIONAL_TARGETS) +$(FUNCTIONAL_TARGETS): + @$(MAKE) SPEED=thorough $(subst -functional,-func,$@) + +.PHONY: check-functional +check-functional: + @$(NINJA) precache-functional + @QEMU_TEST_NO_DOWNLOAD=1 $(MAKE) SPEED=thorough check-func check-func-quick + # Consolidated targets .PHONY: check check-clean get-vm-images diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index ef93561..0e4ecea 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -384,23 +384,6 @@ class QemuSystemTest(QemuBaseTest): super().tearDown() -class QemuUserTest(QemuBaseTest): - """Facilitates user-mode emulation tests.""" - - def setUp(self): - self._ldpath = [] - super().setUp('qemu-') - - def add_ldpath(self, ldpath): - self._ldpath.append(os.path.abspath(ldpath)) - - def run(self, bin_path, args=[]): - qemu_args = " ".join(["-L %s" % ldpath for ldpath in self._ldpath]) - bin_args = " ".join(args) - return process.run("%s %s %s %s" % (self.qemu_bin, qemu_args, - bin_path, bin_args)) - - class LinuxSSHMixIn: """Contains utility methods for interacting with a guest via SSH.""" diff --git a/tests/avocado/avocado_qemu/linuxtest.py b/tests/avocado/avocado_qemu/linuxtest.py index e1dc838..66fb9f1 100644 --- a/tests/avocado/avocado_qemu/linuxtest.py +++ b/tests/avocado/avocado_qemu/linuxtest.py @@ -13,8 +13,8 @@ import shutil from avocado.utils import cloudinit, datadrainer, process, vmimage -from . import LinuxSSHMixIn -from . import QemuSystemTest +from avocado_qemu import LinuxSSHMixIn +from avocado_qemu import QemuSystemTest if os.path.islink(os.path.dirname(os.path.dirname(__file__))): # The link to the avocado tests dir in the source code directory diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py index cffdd6b..18c69d6 100644 --- a/tests/avocado/boot_linux_console.py +++ b/tests/avocado/boot_linux_console.py @@ -1304,26 +1304,6 @@ class BootLinuxConsole(LinuxKernelTest): self.vm.launch() self.wait_for_console_pattern('version UEFI Firmware v1.15') - def test_s390x_s390_ccw_virtio(self): - """ - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio - """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/29/Everything/s390x/os/images' - '/kernel.img') - kernel_hash = 'e8e8439103ef8053418ef062644ffd46a7919313' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=sclp0' - self.vm.add_args('-nodefaults', - '-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) - def test_alpha_clipper(self): """ :avocado: tags=arch:alpha diff --git a/tests/avocado/boot_xen.py b/tests/avocado/boot_xen.py index f29bc58..490a127 100644 --- a/tests/avocado/boot_xen.py +++ b/tests/avocado/boot_xen.py @@ -30,23 +30,22 @@ class BootXen(LinuxKernelTest): timeout = 90 XEN_COMMON_COMMAND_LINE = 'dom0_mem=128M loglvl=all guest_loglvl=all' - def fetch_guest_kernel(self): + def setUp(self): + super(BootXen, self).setUp() + # Using my own built kernel - which works kernel_url = ('https://fileserver.linaro.org/' 's/JSsewXGZ6mqxPr5/download?path=%2F&files=' 'linux-5.9.9-arm64-ajb') kernel_sha1 = '4f92bc4b9f88d5ab792fa7a43a68555d344e1b83' - kernel_path = self.fetch_asset(kernel_url, - asset_hash=kernel_sha1) - - return kernel_path + self.kernel_path = self.fetch_asset(kernel_url, + asset_hash=kernel_sha1) def launch_xen(self, xen_path): """ Launch Xen with a dom0 guest kernel """ self.log.info("launch with xen_path: %s", xen_path) - kernel_path = self.fetch_guest_kernel() self.vm.set_console() @@ -56,7 +55,7 @@ class BootXen(LinuxKernelTest): '-append', self.XEN_COMMON_COMMAND_LINE, '-device', 'guest-loader,addr=0x47000000,kernel=%s,bootargs=console=hvc0' - % (kernel_path)) + % (self.kernel_path)) self.vm.launch() diff --git a/tests/avocado/load_bflt.py b/tests/avocado/load_bflt.py deleted file mode 100644 index bb50cec..0000000 --- a/tests/avocado/load_bflt.py +++ /dev/null @@ -1,54 +0,0 @@ -# Test the bFLT loader format -# -# Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org> -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import bz2 -import subprocess - -from avocado import skipUnless -from avocado_qemu import QemuUserTest -from avocado_qemu import has_cmd - - -class LoadBFLT(QemuUserTest): - - def extract_cpio(self, cpio_path): - """ - Extracts a cpio archive into the test workdir - - :param cpio_path: path to the cpio archive - """ - cwd = os.getcwd() - os.chdir(self.workdir) - with bz2.open(cpio_path, 'rb') as archive_cpio: - subprocess.run(['cpio', '-i'], input=archive_cpio.read(), - stderr=subprocess.DEVNULL) - os.chdir(cwd) - - @skipUnless(*has_cmd('cpio')) - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_stm32(self): - """ - :avocado: tags=arch:arm - :avocado: tags=linux_user - :avocado: tags=quick - """ - # See https://elinux.org/STM32#User_Space - rootfs_url = ('https://elinux.org/images/5/51/' - 'Stm32_mini_rootfs.cpio.bz2') - rootfs_hash = '9f065e6ba40cce7411ba757f924f30fcc57951e6' - rootfs_path_bz2 = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash) - busybox_path = os.path.join(self.workdir, "/bin/busybox") - - self.extract_cpio(rootfs_path_bz2) - - res = self.run(busybox_path) - ver = 'BusyBox v1.24.0.git (2015-02-03 22:17:13 CET) multi-call binary.' - self.assertIn(ver, res.stdout_text) - - res = self.run(busybox_path, ['uname', '-a']) - unm = 'armv7l GNU/Linux' - self.assertIn(unm, res.stdout_text) diff --git a/tests/avocado/machine_arm_n8x0.py b/tests/avocado/machine_arm_n8x0.py index 12e9a68..12e9a68 100644..100755 --- a/tests/avocado/machine_arm_n8x0.py +++ b/tests/avocado/machine_arm_n8x0.py diff --git a/tests/avocado/machine_microblaze.py b/tests/avocado/machine_microblaze.py deleted file mode 100644 index 807709c..0000000 --- a/tests/avocado/machine_microblaze.py +++ /dev/null @@ -1,61 +0,0 @@ -# Functional test that boots a microblaze Linux kernel and checks the console -# -# Copyright (c) 2018, 2021 Red Hat, Inc. -# -# 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 time -from avocado_qemu import exec_command, exec_command_and_wait_for_pattern -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive - -class MicroblazeMachine(QemuSystemTest): - - timeout = 90 - - def test_microblaze_s3adsp1800(self): - """ - :avocado: tags=arch:microblaze - :avocado: tags=machine:petalogix-s3adsp1800 - """ - - tar_url = ('https://qemu-advcal.gitlab.io' - '/qac-best-of-multiarch/download/day17.tar.xz') - tar_hash = '08bf3e3bfb6b6c7ce1e54ab65d54e189f2caf13f' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - self.vm.set_console() - self.vm.add_args('-kernel', self.workdir + '/day17/ballerina.bin') - self.vm.launch() - wait_for_console_pattern(self, 'This architecture does not have ' - 'kernel memory protection') - # Note: - # The kernel sometimes gets stuck after the "This architecture ..." - # message, that's why we don't test for a later string here. This - # needs some investigation by a microblaze wizard one day... - - def test_microblazeel_s3adsp1800(self): - """ - :avocado: tags=arch:microblazeel - :avocado: tags=machine:petalogix-s3adsp1800 - """ - - self.require_netdev('user') - tar_url = ('http://www.qemu-advent-calendar.org/2023/download/' - 'day13.tar.gz') - tar_hash = '6623d5fff5f84cfa8f34e286f32eff6a26546f44' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - 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.launch() - wait_for_console_pattern(self, 'QEMU Advent Calendar 2023') - time.sleep(0.1) - exec_command(self, 'root') - time.sleep(0.1) - exec_command_and_wait_for_pattern(self, - 'tftp -g -r xmaton.png 10.0.2.2 ; md5sum xmaton.png', - '821cd3cab8efd16ad6ee5acc3642a8ea') diff --git a/tests/avocado/machine_mips_loongson3v.py b/tests/avocado/machine_mips_loongson3v.py deleted file mode 100644 index 5194cf1..0000000 --- a/tests/avocado/machine_mips_loongson3v.py +++ /dev/null @@ -1,39 +0,0 @@ -# Functional tests for the Generic Loongson-3 Platform. -# -# Copyright (c) 2021 Jiaxun Yang <jiaxun.yang@flygoat.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. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import time - -from avocado import skipUnless -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern - -class MipsLoongson3v(QemuSystemTest): - timeout = 60 - - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') - def test_pmon_serial_console(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=endian:little - :avocado: tags=machine:loongson3-virt - :avocado: tags=cpu:Loongson-3A1000 - :avocado: tags=device:liointc - :avocado: tags=device:goldfish_rtc - """ - - pmon_hash = '7c8b45dd81ccfc55ff28f5aa267a41c3' - pmon_path = self.fetch_asset('https://github.com/loongson-community/pmon/' - 'releases/download/20210112/pmon-3avirt.bin', - asset_hash=pmon_hash, algorithm='md5') - - self.vm.set_console() - self.vm.add_args('-bios', pmon_path) - self.vm.launch() - wait_for_console_pattern(self, 'CPU GODSON3 BogoMIPS:') diff --git a/tests/avocado/machine_sparc64_sun4u.py b/tests/avocado/machine_sparc64_sun4u.py deleted file mode 100644 index d333c0a..0000000 --- a/tests/avocado/machine_sparc64_sun4u.py +++ /dev/null @@ -1,36 +0,0 @@ -# Functional test that boots a Linux kernel and checks the console -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Thomas Huth <thuth@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_qemu import wait_for_console_pattern -from avocado.utils import archive -from boot_linux_console import LinuxKernelTest - -class Sun4uMachine(LinuxKernelTest): - """Boots the Linux kernel and checks that the console is operational""" - - timeout = 90 - - def test_sparc64_sun4u(self): - """ - :avocado: tags=arch:sparc64 - :avocado: tags=machine:sun4u - """ - tar_url = ('https://qemu-advcal.gitlab.io' - '/qac-best-of-multiarch/download/day23.tar.xz') - tar_hash = '142db83cd974ffadc4f75c8a5cad5bcc5722c240' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) - self.vm.set_console() - self.vm.add_args('-kernel', self.workdir + '/day23/vmlinux', - '-append', self.KERNEL_COMMON_COMMAND_LINE) - self.vm.launch() - wait_for_console_pattern(self, 'Starting logging: OK') diff --git a/tests/avocado/ppc_amiga.py b/tests/avocado/ppc_amiga.py deleted file mode 100644 index b6f866f..0000000 --- a/tests/avocado/ppc_amiga.py +++ /dev/null @@ -1,38 +0,0 @@ -# Test AmigaNG boards -# -# Copyright (c) 2023 BALATON Zoltan -# -# 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.utils import archive -from avocado.utils import process -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern - -class AmigaOneMachine(QemuSystemTest): - - timeout = 90 - - def test_ppc_amigaone(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:amigaone - :avocado: tags=device:articia - :avocado: tags=accel:tcg - """ - self.require_accelerator("tcg") - tar_name = 'A1Firmware_Floppy_05-Mar-2005.zip' - tar_url = ('https://www.hyperion-entertainment.com/index.php/' - 'downloads?view=download&format=raw&file=25') - tar_hash = 'c52e59bc73e31d8bcc3cc2106778f7ac84f6c755' - zip_file = self.fetch_asset(tar_name, locations=tar_url, - asset_hash=tar_hash) - archive.extract(zip_file, self.workdir) - cmd = f"tail -c 524288 {self.workdir}/floppy_edition/updater.image >{self.workdir}/u-boot-amigaone.bin" - process.run(cmd, shell=True) - - self.vm.set_console() - self.vm.add_args('-bios', self.workdir + '/u-boot-amigaone.bin') - self.vm.launch() - wait_for_console_pattern(self, 'FLASH:') diff --git a/tests/avocado/tesseract_utils.py b/tests/avocado/tesseract_utils.py deleted file mode 100644 index 476f528..0000000 --- a/tests/avocado/tesseract_utils.py +++ /dev/null @@ -1,46 +0,0 @@ -# ... -# -# Copyright (c) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org> -# -# 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 avocado.utils import process -from avocado.utils.path import find_command, CmdNotFoundError - -def tesseract_available(expected_version): - try: - find_command('tesseract') - except CmdNotFoundError: - return False - res = process.run('tesseract --version') - try: - version = res.stdout_text.split()[1] - except IndexError: - version = res.stderr_text.split()[1] - return int(version.split('.')[0]) >= expected_version - - match = re.match(r'tesseract\s(\d)', res) - if match is None: - return False - # now this is guaranteed to be a digit - return int(match.groups()[0]) >= expected_version - - -def tesseract_ocr(image_path, tesseract_args='', tesseract_version=3): - console_logger = logging.getLogger('tesseract') - console_logger.debug(image_path) - if tesseract_version == 4: - tesseract_args += ' --oem 1' - proc = process.run("tesseract {} {} stdout".format(tesseract_args, - image_path)) - lines = [] - for line in proc.stdout_text.split('\n'): - sline = line.strip() - if len(sline): - console_logger.debug(sline) - lines += [sline] - return lines diff --git a/tests/avocado/acpi-bits/bits-config/bits-cfg.txt b/tests/functional/acpi-bits/bits-config/bits-cfg.txt index 8010804..8010804 100644 --- a/tests/avocado/acpi-bits/bits-config/bits-cfg.txt +++ b/tests/functional/acpi-bits/bits-config/bits-cfg.txt diff --git a/tests/avocado/acpi-bits/bits-tests/smbios.py2 b/tests/functional/acpi-bits/bits-tests/smbios.py2 index 5868a71..5868a71 100644 --- a/tests/avocado/acpi-bits/bits-tests/smbios.py2 +++ b/tests/functional/acpi-bits/bits-tests/smbios.py2 diff --git a/tests/avocado/acpi-bits/bits-tests/smilatency.py2 b/tests/functional/acpi-bits/bits-tests/smilatency.py2 index 405af67..405af67 100644 --- a/tests/avocado/acpi-bits/bits-tests/smilatency.py2 +++ b/tests/functional/acpi-bits/bits-tests/smilatency.py2 diff --git a/tests/avocado/acpi-bits/bits-tests/testacpi.py2 b/tests/functional/acpi-bits/bits-tests/testacpi.py2 index 7bf9075..7bf9075 100644 --- a/tests/avocado/acpi-bits/bits-tests/testacpi.py2 +++ b/tests/functional/acpi-bits/bits-tests/testacpi.py2 diff --git a/tests/avocado/acpi-bits/bits-tests/testcpuid.py2 b/tests/functional/acpi-bits/bits-tests/testcpuid.py2 index 7adefbe..7adefbe 100644 --- a/tests/avocado/acpi-bits/bits-tests/testcpuid.py2 +++ b/tests/functional/acpi-bits/bits-tests/testcpuid.py2 diff --git a/tests/functional/meson.build b/tests/functional/meson.build new file mode 100644 index 0000000..cda89c4 --- /dev/null +++ b/tests/functional/meson.build @@ -0,0 +1,205 @@ +# QEMU functional tests: +# Tests that are put in the 'quick' category are run by default during +# 'make check'. Everything that should not be run during 'make check' +# (e.g. tests that fetch assets from the internet) should be put into +# the 'thorough' category instead. + +# Most tests run too slow with TCI enabled, so skip the functional tests there +if get_option('tcg_interpreter') + subdir_done() +endif + +# Timeouts for individual tests that can be slow e.g. with debugging enabled +test_timeouts = { + 'aarch64_sbsaref' : 600, + 'aarch64_virt' : 360, + 'acpi_bits' : 240, + 'netdev_ethtool' : 180, + 'ppc_40p' : 240, + 'ppc64_hv' : 1000, + 'ppc64_powernv' : 120, + 'ppc64_pseries' : 120, + 's390x_ccw_virtio' : 180, +} + +tests_generic_system = [ + 'empty_cpu_model', + 'info_usernet', + 'version', +] + +tests_generic_linuxuser = [ +] + +tests_generic_bsduser = [ +] + +tests_aarch64_system_thorough = [ + 'aarch64_sbsaref', + 'aarch64_virt', +] + +tests_arm_system_thorough = [ + 'arm_canona1100', + 'arm_integratorcp', +] + +tests_arm_linuxuser_thorough = [ + 'arm_bflt', +] + +tests_avr_system_thorough = [ + 'avr_mega2560', +] + +tests_loongarch64_system_thorough = [ + 'loongarch64_virt', +] + +tests_m68k_system_thorough = [ + 'm68k_nextcube' +] + +tests_microblaze_system_thorough = [ + 'microblaze_s3adsp1800' +] + +tests_microblazeel_system_thorough = [ + 'microblazeel_s3adsp1800' +] + +tests_mips64el_system_quick = [ + 'mips64el_fuloong2e', +] + +tests_mips64el_system_thorough = [ + 'mips64el_loongson3v', +] + +tests_ppc_system_quick = [ + 'ppc_74xx', +] + +tests_ppc_system_thorough = [ + 'ppc_405', + 'ppc_40p', + 'ppc_amiga', + 'ppc_bamboo', + 'ppc_mpc8544ds', + 'ppc_virtex_ml507', +] + +tests_ppc64_system_thorough = [ + 'ppc64_hv', + 'ppc64_powernv', + 'ppc64_pseries', +] + +tests_rx_system_thorough = [ + 'rx_gdbsim', +] + +tests_s390x_system_thorough = [ + 's390x_ccw_virtio', + 's390x_topology', +] + +tests_sparc64_system_thorough = [ + 'sparc64_sun4u', +] + +tests_x86_64_system_quick = [ + 'cpu_queries', + 'mem_addr_space', + 'pc_cpu_hotplug_props', + 'virtio_version', + 'x86_cpu_model_versions', +] + +tests_x86_64_system_thorough = [ + 'acpi_bits', + 'linux_initrd', + 'netdev_ethtool', + 'virtio_gpu', +] + +precache_all = [] +foreach speed : ['quick', 'thorough'] + foreach dir : target_dirs + + target_base = dir.split('-')[0] + + if dir.endswith('-softmmu') + sysmode = 'system' + test_emulator = emulators['qemu-system-' + target_base] + elif dir.endswith('-linux-user') + sysmode = 'linuxuser' + test_emulator = emulators['qemu-' + target_base] + elif dir.endswith('-bsd-user') + sysmode = 'bsduser' + test_emulator = emulators['qemu-' + target_base] + else + continue + endif + + if speed == 'quick' + suites = ['func-quick', 'func-' + target_base] + target_tests = get_variable('tests_' + target_base + '_' + sysmode + '_quick', []) \ + + get_variable('tests_generic_' + sysmode) + else + suites = ['func-' + speed, 'func-' + target_base + '-' + speed, speed] + target_tests = get_variable('tests_' + target_base + '_' + sysmode + '_' + speed, []) + endif + + test_deps = roms + test_env = environment() + if have_tools + test_env.set('QEMU_TEST_QEMU_IMG', meson.global_build_root() / 'qemu-img') + test_deps += [qemu_img] + endif + test_env.set('QEMU_TEST_QEMU_BINARY', test_emulator.full_path()) + test_env.set('QEMU_BUILD_ROOT', meson.project_build_root()) + test_env.set('PYTHONPATH', meson.project_source_root() / 'python:' + + meson.current_source_dir()) + + foreach test : target_tests + testname = '@0@-@1@'.format(target_base, test) + testfile = 'test_' + test + '.py' + testpath = meson.current_source_dir() / testfile + teststamp = testname + '.tstamp' + test_precache_env = environment() + test_precache_env.set('QEMU_TEST_PRECACHE', meson.current_build_dir() / teststamp) + test_precache_env.set('PYTHONPATH', meson.project_source_root() / 'python:' + + meson.current_source_dir()) + precache = custom_target('func-precache-' + testname, + output: teststamp, + command: [python, testpath], + depend_files: files(testpath), + build_by_default: false, + env: test_precache_env) + precache_all += precache + + # Ideally we would add 'precache' to 'depends' here, such that + # 'build_by_default: false' lets the pre-caching automatically + # run immediately before the test runs. In practice this is + # broken in meson, with it running the pre-caching in the normal + # compile phase https://github.com/mesonbuild/meson/issues/2518 + # If the above bug ever gets fixed, when QEMU changes the min + # meson version, add the 'depends' and remove the custom + # 'run_target' logic below & in Makefile.include + test('func-' + testname, + python, + depends: [test_deps, test_emulator, emulator_modules], + env: test_env, + args: [testpath], + protocol: 'tap', + timeout: test_timeouts.get(test, 60), + priority: test_timeouts.get(test, 60), + suite: suites) + endforeach + endforeach +endforeach + +run_target('precache-functional', + depends: precache_all, + command: ['true']) diff --git a/tests/functional/qemu_test/__init__.py b/tests/functional/qemu_test/__init__.py new file mode 100644 index 0000000..f33282e --- /dev/null +++ b/tests/functional/qemu_test/__init__.py @@ -0,0 +1,14 @@ +# Test class and utilities for functional tests +# +# Copyright 2024 Red Hat, Inc. +# +# 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 .asset import Asset +from .config import BUILD_DIR +from .cmd import has_cmd, has_cmds, run_cmd, is_readable_executable_file, \ + interrupt_interactive_console_until_pattern, wait_for_console_pattern, \ + exec_command, exec_command_and_wait_for_pattern, get_qemu_img +from .testcase import QemuBaseTest, QemuUserTest, QemuSystemTest diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py new file mode 100644 index 0000000..d3be2af --- /dev/null +++ b/tests/functional/qemu_test/asset.py @@ -0,0 +1,171 @@ +# Test utilities for fetching & caching assets +# +# Copyright 2024 Red Hat, Inc. +# +# 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 logging +import os +import subprocess +import sys +import unittest +import urllib.request +from time import sleep +from pathlib import Path +from shutil import copyfileobj + + +# Instances of this class must be declared as class level variables +# starting with a name "ASSET_". This enables the pre-caching logic +# to easily find all referenced assets and download them prior to +# execution of the tests. +class Asset: + + def __init__(self, url, hashsum): + self.url = url + self.hash = hashsum + cache_dir_env = os.getenv('QEMU_TEST_CACHE_DIR') + if cache_dir_env: + self.cache_dir = Path(cache_dir_env, "download") + else: + self.cache_dir = Path(Path("~").expanduser(), + ".cache", "qemu", "download") + self.cache_file = Path(self.cache_dir, hashsum) + self.log = logging.getLogger('qemu-test') + + def __repr__(self): + return "Asset: url=%s hash=%s cache=%s" % ( + self.url, self.hash, self.cache_file) + + def _check(self, cache_file): + if self.hash is None: + return True + if len(self.hash) == 64: + sum_prog = 'sha256sum' + elif len(self.hash) == 128: + sum_prog = 'sha512sum' + else: + raise Exception("unknown hash type") + + checksum = subprocess.check_output( + [sum_prog, str(cache_file)]).split()[0] + return self.hash == checksum.decode("utf-8") + + def valid(self): + return self.cache_file.exists() and self._check(self.cache_file) + + 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 + try: + current_size = tmp_cache_file.stat().st_size + new_size = current_size + except: + if os.path.exists(self.cache_file): + return True + raise + waittime = lastchange = 600 + while waittime > 0: + sleep(1) + waittime -= 1 + try: + new_size = tmp_cache_file.stat().st_size + except: + if os.path.exists(self.cache_file): + return True + raise + if new_size != current_size: + lastchange = waittime + current_size = new_size + elif lastchange - waittime > 90: + return False + + self.log.debug("Time out while waiting for %s!", tmp_cache_file) + raise + + def fetch(self): + if not self.cache_dir.exists(): + self.cache_dir.mkdir(parents=True, exist_ok=True) + + if self.valid(): + self.log.debug("Using cached asset %s for %s", + self.cache_file, self.url) + return str(self.cache_file) + + if os.environ.get("QEMU_TEST_NO_DOWNLOAD", False): + raise Exception("Asset cache is invalid and downloads disabled") + + self.log.info("Downloading %s to %s...", self.url, self.cache_file) + tmp_cache_file = self.cache_file.with_suffix(".download") + + for retries in range(3): + try: + with tmp_cache_file.open("xb") as dst: + with urllib.request.urlopen(self.url) as resp: + copyfileobj(resp, dst) + break + except FileExistsError: + self.log.debug("%s already exists, " + "waiting for other thread to finish...", + tmp_cache_file) + if self._wait_for_other_download(tmp_cache_file): + return str(self.cache_file) + self.log.debug("%s seems to be stale, " + "deleting and retrying download...", + tmp_cache_file) + tmp_cache_file.unlink() + continue + except Exception as e: + self.log.error("Unable to download %s: %s", self.url, e) + tmp_cache_file.unlink() + raise + + try: + # Set these just for informational purposes + os.setxattr(str(tmp_cache_file), "user.qemu-asset-url", + self.url.encode('utf8')) + os.setxattr(str(tmp_cache_file), "user.qemu-asset-hash", + self.hash.encode('utf8')) + except Exception as e: + self.log.debug("Unable to set xattr on %s: %s", tmp_cache_file, e) + pass + + if not self._check(tmp_cache_file): + tmp_cache_file.unlink() + raise Exception("Hash of %s does not match %s" % + (self.url, self.hash)) + tmp_cache_file.replace(self.cache_file) + + self.log.info("Cached %s at %s" % (self.url, self.cache_file)) + return str(self.cache_file) + + def precache_test(test): + log = logging.getLogger('qemu-test') + log.setLevel(logging.DEBUG) + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(logging.DEBUG) + formatter = logging.Formatter( + '%(asctime)s - %(name)s - %(levelname)s - %(message)s') + handler.setFormatter(formatter) + log.addHandler(handler) + 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() + log.removeHandler(handler) + + def precache_suite(suite): + for test in suite: + if isinstance(test, unittest.TestSuite): + Asset.precache_suite(test) + elif isinstance(test, unittest.TestCase): + Asset.precache_test(test) + + def precache_suites(path, cacheTstamp): + loader = unittest.loader.defaultTestLoader + tests = loader.loadTestsFromNames([path], None) + + with open(cacheTstamp, "w") as fh: + Asset.precache_suite(tests) diff --git a/tests/functional/qemu_test/cmd.py b/tests/functional/qemu_test/cmd.py new file mode 100644 index 0000000..3acd617 --- /dev/null +++ b/tests/functional/qemu_test/cmd.py @@ -0,0 +1,193 @@ +# Test class and utilities for functional tests +# +# Copyright 2018, 2024 Red Hat, Inc. +# +# Original Author (Avocado-based tests): +# Cleber Rosa <crosa@redhat.com> +# +# Adaption for standalone version: +# Thomas Huth <thuth@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 logging +import os +import os.path +import subprocess + +from .config import BUILD_DIR + + +def has_cmd(name, args=None): + """ + 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) + +def is_readable_executable_file(path): + return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK) + +def _console_interaction(test, success_message, failure_message, + send_string, keep_sending=False, vm=None): + assert not keep_sending or send_string + if vm is None: + vm = test.vm + console = vm.console_file + console_logger = logging.getLogger('console') + while True: + if send_string: + vm.console_socket.sendall(send_string.encode()) + if not keep_sending: + send_string = None # send only once + + # Only consume console output if waiting for something + if success_message is None and failure_message is None: + if send_string is None: + break + continue + + try: + msg = console.readline().decode().strip() + except UnicodeDecodeError: + msg = None + if not msg: + continue + console_logger.debug(msg) + if success_message is None or success_message in msg: + break + if failure_message and failure_message in msg: + console.close() + fail = 'Failure message found in console: "%s". Expected: "%s"' % \ + (failure_message, success_message) + test.fail(fail) + +def interrupt_interactive_console_until_pattern(test, success_message, + failure_message=None, + interrupt_string='\r'): + """ + Keep sending a string to interrupt a console prompt, while logging the + console output. Typical use case is to break a boot loader prompt, such: + + Press a key within 5 seconds to interrupt boot process. + 5 + 4 + 3 + 2 + 1 + Booting default image... + + :param test: a test containing a VM that will have its console + read and probed for a success or failure message + :type test: :class:`qemu_test.QemuSystemTest` + :param success_message: if this message appears, test succeeds + :param failure_message: if this message appears, test fails + :param interrupt_string: a string to send to the console before trying + to read a new line + """ + _console_interaction(test, success_message, failure_message, + interrupt_string, True) + +def wait_for_console_pattern(test, success_message, failure_message=None, + vm=None): + """ + Waits for messages to appear on the console, while logging the content + + :param test: a test containing a VM that will have its console + read and probed for a success or failure message + :type test: :class:`qemu_test.QemuSystemTest` + :param success_message: if this message appears, test succeeds + :param failure_message: if this message appears, test fails + """ + _console_interaction(test, success_message, failure_message, None, vm=vm) + +def exec_command(test, command): + """ + Send a command to a console (appending CRLF characters), while logging + the content. + + :param test: a test containing a VM. + :type test: :class:`qemu_test.QemuSystemTest` + :param command: the command to send + :type command: str + """ + _console_interaction(test, None, None, command + '\r') + +def exec_command_and_wait_for_pattern(test, command, + success_message, failure_message=None): + """ + Send a command to a console (appending CRLF characters), then wait + for success_message to appear on the console, while logging the. + content. Mark the test as failed if failure_message is found instead. + + :param test: a test containing a VM that will have its console + read and probed for a success or failure message + :type test: :class:`qemu_test.QemuSystemTest` + :param command: the command to send + :param success_message: if this message appears, test succeeds + :param failure_message: if this message appears, test fails + """ + _console_interaction(test, success_message, failure_message, command + '\r') + +def get_qemu_img(test): + test.log.debug('Looking for and selecting a qemu-img binary') + + # 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') + if os.path.exists(qemu_img): + return qemu_img + if has_cmd('qemu-img'): + return 'qemu-img' + test.skipTest('Could not find "qemu-img", which is required to ' + 'create temporary images') diff --git a/tests/functional/qemu_test/config.py b/tests/functional/qemu_test/config.py new file mode 100644 index 0000000..edd75b7 --- /dev/null +++ b/tests/functional/qemu_test/config.py @@ -0,0 +1,36 @@ +# Test class and utilities for functional tests +# +# Copyright 2018, 2024 Red Hat, Inc. +# +# Original Author (Avocado-based tests): +# Cleber Rosa <crosa@redhat.com> +# +# Adaption for standalone version: +# Thomas Huth <thuth@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 pathlib import Path + + +def _source_dir(): + # Determine top-level directory of the QEMU sources + return Path(__file__).parent.parent.parent.parent + +def _build_dir(): + root = os.getenv('QEMU_BUILD_ROOT') + if root is not None: + return Path(root) + # Makefile.mtest only exists in build dir, so if it is available, use CWD + if os.path.exists('Makefile.mtest'): + return Path(os.getcwd()) + + root = os.path.join(_source_dir(), 'build') + if os.path.exists(root): + return Path(root) + + raise Exception("Cannot identify build dir, set QEMU_BUILD_ROOT") + +BUILD_DIR = _build_dir() diff --git a/tests/functional/qemu_test/tesseract.py b/tests/functional/qemu_test/tesseract.py new file mode 100644 index 0000000..c4087b7 --- /dev/null +++ b/tests/functional/qemu_test/tesseract.py @@ -0,0 +1,35 @@ +# ... +# +# Copyright (c) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org> +# +# 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 . import has_cmd, run_cmd + +def tesseract_available(expected_version): + if not has_cmd('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: + return None + lines = [] + for line in stdout.split('\n'): + sline = line.strip() + if len(sline): + console_logger.debug(sline) + lines += [sline] + return lines diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py new file mode 100644 index 0000000..aa01462 --- /dev/null +++ b/tests/functional/qemu_test/testcase.py @@ -0,0 +1,202 @@ +# Test class and utilities for functional tests +# +# Copyright 2018, 2024 Red Hat, Inc. +# +# Original Author (Avocado-based tests): +# Cleber Rosa <crosa@redhat.com> +# +# Adaption for standalone version: +# Thomas Huth <thuth@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 logging +import os +import subprocess +import pycotap +import sys +import unittest +import uuid + +from qemu.machine import QEMUMachine +from qemu.utils import kvm_available, tcg_available + +from .asset import Asset +from .cmd import run_cmd +from .config import BUILD_DIR + + +class QemuBaseTest(unittest.TestCase): + + qemu_bin = os.getenv('QEMU_TEST_QEMU_BINARY') + arch = None + + workdir = None + log = None + logdir = None + + 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.workdir = os.path.join(BUILD_DIR, 'tests/functional', self.arch, + self.id()) + os.makedirs(self.workdir, exist_ok=True) + + self.logdir = self.workdir + self.log = logging.getLogger('qemu-test') + self.log.setLevel(logging.DEBUG) + self._log_fh = logging.FileHandler(os.path.join(self.logdir, + 'base.log'), mode='w') + self._log_fh.setLevel(logging.DEBUG) + fileFormatter = logging.Formatter( + '%(asctime)s - %(levelname)s: %(message)s') + self._log_fh.setFormatter(fileFormatter) + self.log.addHandler(self._log_fh) + + def tearDown(self): + self.log.removeHandler(self._log_fh) + + def main(): + path = os.path.basename(sys.argv[0])[:-3] + + cache = os.environ.get("QEMU_TEST_PRECACHE", None) + if cache is not None: + Asset.precache_suites(path, cache) + return + + tr = pycotap.TAPTestRunner(message_log = pycotap.LogMode.LogToError, + test_output_log = pycotap.LogMode.LogToError) + unittest.main(module = None, testRunner = tr, argv=["__dummy__", path]) + + +class QemuUserTest(QemuBaseTest): + + def setUp(self): + super().setUp('qemu-') + self._ldpath = [] + + def add_ldpath(self, ldpath): + 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) + +class QemuSystemTest(QemuBaseTest): + """Facilitates system emulation tests.""" + + cpu = None + machine = None + _machinehelp = None + + def setUp(self): + self._vms = {} + + super().setUp('qemu-system-') + + console_log = logging.getLogger('console') + console_log.setLevel(logging.DEBUG) + self._console_log_fh = logging.FileHandler(os.path.join(self.workdir, + 'console.log'), mode='w') + self._console_log_fh.setLevel(logging.DEBUG) + fileFormatter = logging.Formatter('%(asctime)s: %(message)s') + self._console_log_fh.setFormatter(fileFormatter) + console_log.addHandler(self._console_log_fh) + + 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]; + if self._machinehelp.find(machinename) < 0: + self.skipTest('no support for machine ' + machinename) + self.machine = machinename + + def require_accelerator(self, accelerator): + """ + Requires an accelerator to be available for the test to continue + + It takes into account the currently set qemu binary. + + If the check fails, the test is canceled. If the check itself + for the given accelerator is not available, the test is also + canceled. + + :param accelerator: name of the accelerator, such as "kvm" or "tcg" + :type accelerator: str + """ + checker = {'tcg': tcg_available, + 'kvm': kvm_available}.get(accelerator) + if checker is None: + self.skipTest("Don't know how to check for the presence " + "of accelerator %s" % accelerator) + if not checker(qemu_bin=self.qemu_bin): + self.skipTest("%s accelerator does not seem to be " + "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: + 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: + self.skipTest('no support for device ' + devicename) + + def _new_vm(self, name, *args): + vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir) + self.log.debug('QEMUMachine "%s" created', name) + self.log.debug('QEMUMachine "%s" temp_dir: %s', name, vm.temp_dir) + self.log.debug('QEMUMachine "%s" log_dir: %s', name, vm.log_dir) + if args: + vm.add_args(*args) + return vm + + @property + def vm(self): + return self.get_vm(name='default') + + def get_vm(self, *args, name=None): + if not name: + name = str(uuid.uuid4()) + if self._vms.get(name) is None: + self._vms[name] = self._new_vm(name, *args) + if self.cpu is not None: + self._vms[name].add_args('-cpu', self.cpu) + if self.machine is not None: + self._vms[name].set_machine(self.machine) + return self._vms[name] + + def set_vm_arg(self, arg, value): + """ + Set an argument to list of extra arguments to be given to the QEMU + binary. If the argument already exists then its value is replaced. + + :param arg: the QEMU argument, such as "-cpu" in "-cpu host" + :type arg: str + :param value: the argument value, such as "host" in "-cpu host" + :type value: str + """ + if not arg or not value: + return + if arg not in self.vm.args: + self.vm.args.extend([arg, value]) + else: + idx = self.vm.args.index(arg) + 1 + if idx < len(self.vm.args): + self.vm.args[idx] = value + else: + self.vm.args.append(value) + + def tearDown(self): + for vm in self._vms.values(): + vm.shutdown() + logging.getLogger('console').removeHandler(self._console_log_fh) + super().tearDown() diff --git a/tests/functional/qemu_test/utils.py b/tests/functional/qemu_test/utils.py new file mode 100644 index 0000000..2a1cb60 --- /dev/null +++ b/tests/functional/qemu_test/utils.py @@ -0,0 +1,56 @@ +# Utilities for python-based QEMU tests +# +# Copyright 2024 Red Hat, Inc. +# +# Authors: +# Thomas Huth <thuth@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 gzip +import lzma +import os +import shutil +import subprocess +import tarfile + +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) diff --git a/tests/avocado/machine_aarch64_sbsaref.py b/tests/functional/test_aarch64_sbsaref.py index e920bbf..f31c2a6 100644..100755 --- a/tests/avocado/machine_aarch64_sbsaref.py +++ b/tests/functional/test_aarch64_sbsaref.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional test that boots a Linux kernel and checks the console # # SPDX-FileCopyrightText: 2023-2024 Linaro Ltd. @@ -8,26 +10,31 @@ import os -from avocado import skipUnless -from avocado.utils import archive - -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern -from avocado_qemu import interrupt_interactive_console_until_pattern +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 +from unittest import skipUnless class Aarch64SbsarefMachine(QemuSystemTest): """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:sbsa-ref - :avocado: tags=accel:tcg - As firmware runs at a higher privilege level than the hypervisor we can only run these tests under TCG emulation. """ timeout = 180 + ASSET_FLASH0 = Asset( + ('https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/' + '20240619-148232/edk2/SBSA_FLASH0.fd.xz'), + '0c954842a590988f526984de22e21ae0ab9cb351a0c99a8a58e928f0c7359cf7') + + ASSET_FLASH1 = Asset( + ('https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/' + '20240619-148232/edk2/SBSA_FLASH1.fd.xz'), + 'c6ec39374c4d79bb9e9cdeeb6db44732d90bb4a334cec92002b3f4b9cac4b5ee') + def fetch_firmware(self): """ Flash volumes generated using: @@ -44,47 +51,31 @@ class Aarch64SbsarefMachine(QemuSystemTest): """ # Secure BootRom (TF-A code) - fs0_xz_url = ( - "https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/" - "20240619-148232/edk2/SBSA_FLASH0.fd.xz" - ) - fs0_xz_hash = "0c954842a590988f526984de22e21ae0ab9cb351a0c99a8a58e928f0c7359cf7" - tar_xz_path = self.fetch_asset(fs0_xz_url, asset_hash=fs0_xz_hash, - algorithm='sha256') - archive.extract(tar_xz_path, self.workdir) + fs0_xz_path = self.ASSET_FLASH0.fetch() fs0_path = os.path.join(self.workdir, "SBSA_FLASH0.fd") + lzma_uncompress(fs0_xz_path, fs0_path) # Non-secure rom (UEFI and EFI variables) - fs1_xz_url = ( - "https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/" - "20240619-148232/edk2/SBSA_FLASH1.fd.xz" - ) - fs1_xz_hash = "c6ec39374c4d79bb9e9cdeeb6db44732d90bb4a334cec92002b3f4b9cac4b5ee" - tar_xz_path = self.fetch_asset(fs1_xz_url, asset_hash=fs1_xz_hash, - algorithm='sha256') - archive.extract(tar_xz_path, self.workdir) + fs1_xz_path = self.ASSET_FLASH1.fetch() fs1_path = os.path.join(self.workdir, "SBSA_FLASH1.fd") + lzma_uncompress(fs1_xz_path, fs1_path) for path in [fs0_path, fs1_path]: with open(path, "ab+") as fd: fd.truncate(256 << 20) # Expand volumes to 256MiB + self.set_machine('sbsa-ref') self.vm.set_console() self.vm.add_args( - "-drive", - f"if=pflash,file={fs0_path},format=raw", - "-drive", - f"if=pflash,file={fs1_path},format=raw", - "-machine", - "sbsa-ref", + "-drive", f"if=pflash,file={fs0_path},format=raw", + "-drive", f"if=pflash,file={fs1_path},format=raw", ) def test_sbsaref_edk2_firmware(self): - """ - :avocado: tags=cpu:cortex-a57 - """ self.fetch_firmware() + + self.vm.add_args('-cpu', 'cortex-a57') self.vm.launch() # TF-A boot sequence: @@ -110,87 +101,62 @@ class Aarch64SbsarefMachine(QemuSystemTest): wait_for_console_pattern(self, "UEFI firmware (version 1.0") interrupt_interactive_console_until_pattern(self, "QEMU SBSA-REF Machine") + + ASSET_ALPINE_ISO = Asset( + ('https://dl-cdn.alpinelinux.org/' + 'alpine/v3.17/releases/aarch64/alpine-standard-3.17.2-aarch64.iso'), + '5a36304ecf039292082d92b48152a9ec21009d3a62f459de623e19c4bd9dc027') + # This tests the whole boot chain from EFI to Userspace # We only boot a whole OS for the current top level CPU and GIC # Other test profiles should use more minimal boots def boot_alpine_linux(self, cpu): self.fetch_firmware() - iso_url = ( - "https://dl-cdn.alpinelinux.org/" - "alpine/v3.17/releases/aarch64/alpine-standard-3.17.2-aarch64.iso" - ) - - iso_hash = "5a36304ecf039292082d92b48152a9ec21009d3a62f459de623e19c4bd9dc027" - iso_path = self.fetch_asset(iso_url, algorithm="sha256", asset_hash=iso_hash) + iso_path = self.ASSET_ALPINE_ISO.fetch() self.vm.set_console() self.vm.add_args( - "-cpu", - cpu, - "-drive", - f"file={iso_path},format=raw", + "-cpu", cpu, + "-drive", f"file={iso_path},media=cdrom,format=raw", ) self.vm.launch() wait_for_console_pattern(self, "Welcome to Alpine Linux 3.17") def test_sbsaref_alpine_linux_cortex_a57(self): - """ - :avocado: tags=cpu:cortex-a57 - :avocado: tags=os:linux - """ self.boot_alpine_linux("cortex-a57") def test_sbsaref_alpine_linux_neoverse_n1(self): - """ - :avocado: tags=cpu:neoverse-n1 - :avocado: tags=os:linux - """ self.boot_alpine_linux("neoverse-n1") def test_sbsaref_alpine_linux_max_pauth_off(self): - """ - :avocado: tags=cpu:max - :avocado: tags=os:linux - """ self.boot_alpine_linux("max,pauth=off") def test_sbsaref_alpine_linux_max_pauth_impdef(self): - """ - :avocado: tags=cpu:max - :avocado: tags=os:linux - """ self.boot_alpine_linux("max,pauth-impdef=on") - @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') + @skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout') def test_sbsaref_alpine_linux_max(self): - """ - :avocado: tags=cpu:max - :avocado: tags=os:linux - """ self.boot_alpine_linux("max") + ASSET_OPENBSD_ISO = Asset( + ('https://cdn.openbsd.org/pub/OpenBSD/7.3/arm64/miniroot73.img'), + '7fc2c75401d6f01fbfa25f4953f72ad7d7c18650056d30755c44b9c129b707e5') + # This tests the whole boot chain from EFI to Userspace # We only boot a whole OS for the current top level CPU and GIC # Other test profiles should use more minimal boots def boot_openbsd73(self, cpu): self.fetch_firmware() - img_url = ( - "https://cdn.openbsd.org/pub/OpenBSD/7.3/arm64/miniroot73.img" - ) - - img_hash = "7fc2c75401d6f01fbfa25f4953f72ad7d7c18650056d30755c44b9c129b707e5" - img_path = self.fetch_asset(img_url, algorithm="sha256", asset_hash=img_hash) + img_path = self.ASSET_OPENBSD_ISO.fetch() self.vm.set_console() self.vm.add_args( - "-cpu", - cpu, - "-drive", - f"file={img_path},format=raw", + "-cpu", cpu, + "-drive", f"file={img_path},format=raw,snapshot=on", ) self.vm.launch() @@ -199,38 +165,22 @@ class Aarch64SbsarefMachine(QemuSystemTest): " 7.3 installation program.") def test_sbsaref_openbsd73_cortex_a57(self): - """ - :avocado: tags=cpu:cortex-a57 - :avocado: tags=os:openbsd - """ self.boot_openbsd73("cortex-a57") def test_sbsaref_openbsd73_neoverse_n1(self): - """ - :avocado: tags=cpu:neoverse-n1 - :avocado: tags=os:openbsd - """ self.boot_openbsd73("neoverse-n1") def test_sbsaref_openbsd73_max_pauth_off(self): - """ - :avocado: tags=cpu:max - :avocado: tags=os:openbsd - """ self.boot_openbsd73("max,pauth=off") - @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') + @skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout') def test_sbsaref_openbsd73_max_pauth_impdef(self): - """ - :avocado: tags=cpu:max - :avocado: tags=os:openbsd - """ self.boot_openbsd73("max,pauth-impdef=on") - @skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') + @skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout') def test_sbsaref_openbsd73_max(self): - """ - :avocado: tags=cpu:max - :avocado: tags=os:openbsd - """ self.boot_openbsd73("max") + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/machine_aarch64_virt.py b/tests/functional/test_aarch64_virt.py index a90dc6f..c967da4 100644..100755 --- a/tests/avocado/machine_aarch64_virt.py +++ b/tests/functional/test_aarch64_virt.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional test that boots a various Linux systems and checks the # console output. # @@ -12,12 +14,11 @@ import time import os import logging -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern -from avocado_qemu import exec_command -from avocado_qemu import BUILD_DIR -from avocado.utils import process -from avocado.utils.path import find_command +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 + class Aarch64VirtMachine(QemuSystemTest): KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' @@ -28,23 +29,18 @@ class Aarch64VirtMachine(QemuSystemTest): failure_message='Kernel panic - not syncing', vm=vm) + ASSET_ALPINE_ISO = Asset( + ('https://dl-cdn.alpinelinux.org/' + 'alpine/v3.17/releases/aarch64/alpine-standard-3.17.2-aarch64.iso'), + '5a36304ecf039292082d92b48152a9ec21009d3a62f459de623e19c4bd9dc027') + # This tests the whole boot chain from EFI to Userspace # We only boot a whole OS for the current top level CPU and GIC # Other test profiles should use more minimal boots def test_alpine_virt_tcg_gic_max(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=accel:tcg - """ - iso_url = ('https://dl-cdn.alpinelinux.org/' - 'alpine/v3.17/releases/aarch64/' - 'alpine-standard-3.17.2-aarch64.iso') - - # Alpine use sha256 so I recalculated this myself - iso_sha1 = '76284fcd7b41fe899b0c2375ceb8470803eea839' - iso_path = self.fetch_asset(iso_url, asset_hash=iso_sha1) + iso_path = self.ASSET_ALPINE_ISO.fetch() + self.set_machine('virt') self.vm.set_console() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyAMA0') @@ -60,7 +56,7 @@ class Aarch64VirtMachine(QemuSystemTest): 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("-drive", f"file={iso_path},format=raw") + 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') @@ -68,6 +64,11 @@ class Aarch64VirtMachine(QemuSystemTest): self.wait_for_console_pattern('Welcome to Alpine Linux 3.17') + ASSET_KERNEL = Asset( + ('https://fileserver.linaro.org/s/' + 'z6B2ARM7DQT3HWN/download'), + '12a54d4805cda6ab647cb7c7bbdb16fafb3df400e0d6f16445c1a0436100ef8d') + def common_aarch64_virt(self, machine): """ Common code to launch basic virt machine with kernel+initrd @@ -75,11 +76,9 @@ class Aarch64VirtMachine(QemuSystemTest): """ logger = logging.getLogger('aarch64_virt') - kernel_url = ('https://fileserver.linaro.org/s/' - 'z6B2ARM7DQT3HWN/download') - kernel_hash = 'ed11daab50c151dde0e1e9c9cb8b2d9bd3215347' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + kernel_path = self.ASSET_KERNEL.fetch() + self.set_machine('virt') self.vm.set_console() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyAMA0') @@ -98,14 +97,8 @@ class Aarch64VirtMachine(QemuSystemTest): # Also add a scratch block device logger.info('creating scratch qcow2 image') image_path = os.path.join(self.workdir, 'scratch.qcow2') - qemu_img = os.path.join(BUILD_DIR, 'qemu-img') - if not os.path.exists(qemu_img): - qemu_img = find_command('qemu-img', False) - if qemu_img is False: - self.cancel('Could not find "qemu-img", which is required to ' - 'create the temporary qcow2 image') - cmd = '%s create -f qcow2 %s 8M' % (qemu_img, image_path) - process.run(cmd) + qemu_img = get_qemu_img(self) + run_cmd([qemu_img, 'create', '-f', 'qcow2', image_path, '8M']) # Add the device self.vm.add_args('-blockdev', @@ -128,19 +121,11 @@ class Aarch64VirtMachine(QemuSystemTest): time.sleep(0.1) def test_aarch64_virt_gicv3(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=accel:tcg - :avocado: tags=cpu:max - """ self.common_aarch64_virt("virt,gic_version=3") def test_aarch64_virt_gicv2(self): - """ - :avocado: tags=arch:aarch64 - :avocado: tags=machine:virt - :avocado: tags=accel:tcg - :avocado: tags=cpu:max - """ self.common_aarch64_virt("virt,gic-version=2") + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/acpi-bits.py b/tests/functional/test_acpi_bits.py index efe4f52..ee40647 100644..100755 --- a/tests/avocado/acpi-bits.py +++ b/tests/functional/test_acpi_bits.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# group: rw quick +# # Exercise QEMU generated ACPI/SMBIOS tables using biosbits, # https://biosbits.org/ # @@ -24,7 +24,7 @@ # pylint: disable=consider-using-f-string """ -This is QEMU ACPI/SMBIOS avocado tests using biosbits. +This is QEMU ACPI/SMBIOS functional tests using biosbits. Biosbits is available originally at https://biosbits.org/. This test uses a fork of the upstream bits and has numerous fixes including an upgraded acpica. The fork is located here: @@ -41,15 +41,16 @@ import tarfile import tempfile import time import zipfile + +from pathlib import Path from typing import ( List, Optional, Sequence, ) from qemu.machine import QEMUMachine -from avocado import skipIf -from avocado.utils import datadrainer as drainer -from avocado_qemu import QemuBaseTest +from unittest import skipIf +from qemu_test import QemuBaseTest, Asset deps = ["xorriso", "mformat"] # dependent tools needed in the test setup/box. supported_platforms = ['x86_64'] # supported test platforms. @@ -129,34 +130,32 @@ class QEMUBitsMachine(QEMUMachine): # pylint: disable=too-few-public-methods class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes """ ACPI and SMBIOS tests using biosbits. - - :avocado: tags=arch:x86_64 - :avocado: tags=acpi - """ # in slower systems the test can take as long as 3 minutes to complete. timeout = BITS_TIMEOUT + # following are some standard configuration constants + # gitlab CI does shallow clones of depth 20 + BITS_INTERNAL_VER = 2020 + # commit hash must match the artifact tag below + BITS_COMMIT_HASH = 'c7920d2b' + # this is the latest bits release as of today. + BITS_TAG = "qemu-bits-10262023" + + ASSET_BITS = Asset(("https://gitlab.com/qemu-project/" + "biosbits-bits/-/jobs/artifacts/%s/" + "download?job=qemu-bits-build" % BITS_TAG), + '1b8dd612c6831a6b491716a77acc486666aaa867051cdc34f7ce169c2e25f487') + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._vm = None self._workDir = None self._baseDir = None - # following are some standard configuration constants - self._bitsInternalVer = 2020 # gitlab CI does shallow clones of depth 20 - self._bitsCommitHash = 'c7920d2b' # commit hash must match - # the artifact tag below - self._bitsTag = "qemu-bits-10262023" # this is the latest bits - # release as of today. - self._bitsArtSHA1Hash = 'b22cdfcfc7453875297d06d626f5474ee36a343f' - self._bitsArtURL = ("https://gitlab.com/qemu-project/" - "biosbits-bits/-/jobs/artifacts/%s/" - "download?job=qemu-bits-build" %self._bitsTag) self._debugcon_addr = '0x403' self._debugcon_log = 'debugcon-log.txt' - logging.basicConfig(level=logging.INFO) - self.logger = logging.getLogger('acpi-bits') + self.logger = self.log def _print_log(self, log): self.logger.info('\nlogs from biosbits follows:') @@ -171,7 +170,7 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes bits_config_dir = os.path.join(self._baseDir, 'acpi-bits', 'bits-config') target_config_dir = os.path.join(self._workDir, - 'bits-%d' %self._bitsInternalVer, + 'bits-%d' %self.BITS_INTERNAL_VER, 'boot') self.assertTrue(os.path.exists(bits_config_dir)) self.assertTrue(os.path.exists(target_config_dir)) @@ -188,7 +187,7 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes bits_test_dir = os.path.join(self._baseDir, 'acpi-bits', 'bits-tests') target_test_dir = os.path.join(self._workDir, - 'bits-%d' %self._bitsInternalVer, + 'bits-%d' %self.BITS_INTERNAL_VER, 'boot', 'python') self.assertTrue(os.path.exists(bits_test_dir)) @@ -248,9 +247,9 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes test scripts """ bits_dir = os.path.join(self._workDir, - 'bits-%d' %self._bitsInternalVer) + 'bits-%d' %self.BITS_INTERNAL_VER) iso_file = os.path.join(self._workDir, - 'bits-%d.iso' %self._bitsInternalVer) + 'bits-%d.iso' %self.BITS_INTERNAL_VER) mkrescue_script = os.path.join(self._workDir, 'grub-inst-x86_64-efi', 'bin', 'grub-mkrescue') @@ -264,8 +263,12 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes try: if os.getenv('V') or os.getenv('BITS_DEBUG'): - subprocess.check_call([mkrescue_script, '-o', iso_file, - bits_dir], stderr=subprocess.STDOUT) + proc = subprocess.run([mkrescue_script, '-o', iso_file, + bits_dir], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=True) + self.logger.info("grub-mkrescue output %s" % proc.stdout) else: subprocess.check_call([mkrescue_script, '-o', iso_file, bits_dir], @@ -282,8 +285,9 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes def setUp(self): # pylint: disable=arguments-differ super().setUp('qemu-system-') + self.logger = self.log - self._baseDir = os.getenv('AVOCADO_TEST_BASEDIR') + self._baseDir = Path(__file__).parent # workdir could also be avocado's own workdir in self.workdir. # At present, I prefer to maintain my own temporary working @@ -300,15 +304,14 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes os.mkdir(prebuiltDir, mode=0o775) bits_zip_file = os.path.join(prebuiltDir, 'bits-%d-%s.zip' - %(self._bitsInternalVer, - self._bitsCommitHash)) + %(self.BITS_INTERNAL_VER, + self.BITS_COMMIT_HASH)) grub_tar_file = os.path.join(prebuiltDir, 'bits-%d-%s-grub.tar.gz' - %(self._bitsInternalVer, - self._bitsCommitHash)) + %(self.BITS_INTERNAL_VER, + self.BITS_COMMIT_HASH)) - bitsLocalArtLoc = self.fetch_asset(self._bitsArtURL, - asset_hash=self._bitsArtSHA1Hash) + bitsLocalArtLoc = self.ASSET_BITS.fetch() self.logger.info("downloaded bits artifacts to %s", bitsLocalArtLoc) # extract the bits artifact in the temp working directory @@ -369,7 +372,7 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes """The main test case implementation.""" iso_file = os.path.join(self._workDir, - 'bits-%d.iso' %self._bitsInternalVer) + 'bits-%d.iso' %self.BITS_INTERNAL_VER) self.assertTrue(os.access(iso_file, os.R_OK)) @@ -393,12 +396,6 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes self._vm.set_console() self._vm.launch() - self.logger.debug("Console output from bits VM follows ...") - c_drainer = drainer.LineLogger(self._vm.console_socket.fileno(), - logger=self.logger.getChild("console"), - stop_check=(lambda : - not self._vm.is_running())) - c_drainer.start() # biosbits has been configured to run all the specified test suites # in batch mode and then automatically initiate a vm shutdown. @@ -406,4 +403,8 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes # with the avocado test timeout. self._vm.event_wait('SHUTDOWN', timeout=BITS_TIMEOUT) self._vm.wait(timeout=None) + self.logger.debug("Checking console output ...") self.parse_log() + +if __name__ == '__main__': + QemuBaseTest.main() diff --git a/tests/functional/test_arm_bflt.py b/tests/functional/test_arm_bflt.py new file mode 100755 index 0000000..281925d --- /dev/null +++ b/tests/functional/test_arm_bflt.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# +# Test the bFLT loader format +# +# Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org> +# +# 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 + + +class LoadBFLT(QemuUserTest): + + ASSET_ROOTFS = Asset( + ('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') + 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") + + with bz2.open(rootfs_path_bz2, 'rb') as cpio_handle: + cpio_extract(cpio_handle, self.workdir) + + res = self.run_cmd(busybox_path) + ver = 'BusyBox v1.24.0.git (2015-02-03 22:17:13 CET) multi-call binary.' + self.assertIn(ver, res.stdout) + + res = self.run_cmd(busybox_path, ['uname', '-a']) + unm = 'armv7l GNU/Linux' + self.assertIn(unm, res.stdout) + + +if __name__ == '__main__': + QemuUserTest.main() diff --git a/tests/avocado/machine_arm_canona1100.py b/tests/functional/test_arm_canona1100.py index a42d8b0..65f1228 100644..100755 --- a/tests/avocado/machine_arm_canona1100.py +++ b/tests/functional/test_arm_canona1100.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional test that boots the canon-a1100 machine with firmware # # Copyright (c) 2020 Red Hat, Inc. @@ -8,28 +10,30 @@ # 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 import QemuSystemTest -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive +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""" timeout = 90 + ASSET_BIOS = Asset(('https://qemu-advcal.gitlab.io' + '/qac-best-of-multiarch/download/day18.tar.xz'), + '28e71874ce985be66b7fd1345ed88cb2523b982f899c8d2900d6353054a1be49') + def test_arm_canona1100(self): - """ - :avocado: tags=arch:arm - :avocado: tags=machine:canon-a1100 - :avocado: tags=device:pflash_cfi02 - """ - tar_url = ('https://qemu-advcal.gitlab.io' - '/qac-best-of-multiarch/download/day18.tar.xz') - tar_hash = '068b5fc4242b29381acee94713509f8a876e9db6' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) + 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") self.vm.set_console() self.vm.add_args('-bios', self.workdir + '/day18/barebox.canon-a1100.bin') self.vm.launch() wait_for_console_pattern(self, 'running /env/bin/init') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/machine_arm_integratorcp.py b/tests/functional/test_arm_integratorcp.py index 87f5cf3..0fe083f 100644..100755 --- a/tests/avocado/machine_arm_integratorcp.py +++ b/tests/functional/test_arm_integratorcp.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional test that boots a Linux kernel and checks the console # # Copyright (c) 2020 Red Hat, Inc. @@ -7,13 +9,15 @@ # # This work is licensed under the terms of the GNU GPL, version 2 or # later. See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later import os import logging -from avocado import skipUnless -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from unittest import skipUnless NUMPY_AVAILABLE = True @@ -33,50 +37,49 @@ class IntegratorMachine(QemuSystemTest): timeout = 90 - def boot_integratorcp(self): - kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/' - 'arm-test/kernel/zImage.integrator') - kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + ASSET_KERNEL = Asset( + ('https://github.com/zayac/qemu-arm/raw/master/' + 'arm-test/kernel/zImage.integrator'), + '26e7c7e8f943de785d95bd3c74d66451604a9b6a7a3d25dceb279e7548fd8e78') + + ASSET_INITRD = Asset( + ('https://github.com/zayac/qemu-arm/raw/master/' + 'arm-test/kernel/arm_root.img'), + 'e187c27fb342ad148c7f33475fbed124933e0b3f4be8c74bc4f3426a4793373a') - initrd_url = ('https://github.com/zayac/qemu-arm/raw/master/' - 'arm-test/kernel/arm_root.img') - initrd_hash = 'b51e4154285bf784e017a37586428332d8c7bd8b' - initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + ASSET_TUXLOGO = Asset( + ('https://github.com/torvalds/linux/raw/v2.6.12/' + 'drivers/video/logo/logo_linux_vga16.ppm'), + 'b762f0d91ec018887ad1b334543c2fdf9be9fdfc87672b409211efaa3ea0ef79') + def boot_integratorcp(self): + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() + + self.set_machine('integratorcp') self.vm.set_console() self.vm.add_args('-kernel', kernel_path, '-initrd', initrd_path, '-append', 'printk.time=0 console=ttyAMA0') self.vm.launch() - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + @skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code') def test_integratorcp_console(self): """ Boots the Linux kernel and checks that the console is operational - :avocado: tags=arch:arm - :avocado: tags=machine:integratorcp - :avocado: tags=device:pl011 """ 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('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + @skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code') def test_framebuffer_tux_logo(self): """ Boot Linux and verify the Tux logo is displayed on the framebuffer. - :avocado: tags=arch:arm - :avocado: tags=machine:integratorcp - :avocado: tags=device:pl110 - :avocado: tags=device:framebuffer """ screendump_path = os.path.join(self.workdir, "screendump.pbm") - tuxlogo_url = ('https://github.com/torvalds/linux/raw/v2.6.12/' - 'drivers/video/logo/logo_linux_vga16.ppm') - tuxlogo_hash = '3991c2ddbd1ddaecda7601f8aafbcf5b02dc86af' - tuxlogo_path = self.fetch_asset(tuxlogo_url, asset_hash=tuxlogo_hash) + tuxlogo_path = self.ASSET_TUXLOGO.fetch() self.boot_integratorcp() framebuffer_ready = 'Console: switching to colour frame buffer device' @@ -97,3 +100,6 @@ class IntegratorMachine(QemuSystemTest): for tux_count, pt in enumerate(zip(*loc[::-1]), start=1): logger.debug('found Tux at position [x, y] = %s', pt) self.assertGreaterEqual(tux_count, cpu_count) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/machine_avr6.py b/tests/functional/test_avr_mega2560.py index 5485db7..8e47b42 100644..100755 --- a/tests/avocado/machine_avr6.py +++ b/tests/functional/test_avr_mega2560.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # # QEMU AVR integration tests # @@ -19,26 +20,24 @@ import time -from avocado_qemu import QemuSystemTest +from qemu_test import QemuSystemTest, Asset class AVR6Machine(QemuSystemTest): timeout = 5 + ASSET_ROM = Asset(('https://github.com/seharris/qemu-avr-tests' + '/raw/36c3e67b8755dcf/free-rtos/Demo' + '/AVR_ATMega2560_GCC/demo.elf'), + 'ee4833bd65fc69e84a79ed1c608affddbd499a60e63acf87d9113618401904e4') + def test_freertos(self): """ - :avocado: tags=arch:avr - :avocado: tags=machine:arduino-mega-2560-v3 - """ - """ https://github.com/seharris/qemu-avr-tests/raw/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf constantly prints out 'ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX' """ - rom_url = ('https://github.com/seharris/qemu-avr-tests' - '/raw/36c3e67b8755dcf/free-rtos/Demo' - '/AVR_ATMega2560_GCC/demo.elf') - rom_hash = '7eb521f511ca8f2622e0a3c5e8dd686efbb911d4' - rom_path = self.fetch_asset(rom_url, asset_hash=rom_hash) + rom_path = self.ASSET_ROM.fetch() + self.set_machine('arduino-mega-2560-v3') self.vm.add_args('-bios', rom_path) self.vm.add_args('-nographic') self.vm.launch() @@ -48,3 +47,6 @@ class AVR6Machine(QemuSystemTest): self.assertIn('ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX', self.vm.get_log()) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/cpu_queries.py b/tests/functional/test_cpu_queries.py index d3faa14..b1122a0 100644..100755 --- a/tests/avocado/cpu_queries.py +++ b/tests/functional/test_cpu_queries.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Sanity check of query-cpu-* results # # Copyright (c) 2019 Red Hat, Inc. @@ -8,7 +10,7 @@ # 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 import QemuSystemTest +from qemu_test import QemuSystemTest class QueryCPUModelExpansion(QemuSystemTest): """ @@ -16,10 +18,7 @@ class QueryCPUModelExpansion(QemuSystemTest): """ def test(self): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=machine:none - """ + self.set_machine('none') self.vm.add_args('-S') self.vm.launch() @@ -33,3 +32,6 @@ class QueryCPUModelExpansion(QemuSystemTest): e = self.vm.cmd('query-cpu-model-expansion', model=model, type='full') self.assertEqual(e['model']['name'], c['name']) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/empty_cpu_model.py b/tests/functional/test_empty_cpu_model.py index d906ef3..0081b06 100644..100755 --- a/tests/avocado/empty_cpu_model.py +++ b/tests/functional/test_empty_cpu_model.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Check for crash when using empty -cpu option # # Copyright (c) 2019 Red Hat, Inc. @@ -7,7 +9,7 @@ # # 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 import QemuSystemTest +from qemu_test import QemuSystemTest class EmptyCPUModel(QemuSystemTest): def test(self): @@ -17,3 +19,6 @@ class EmptyCPUModel(QemuSystemTest): self.vm.wait() self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") self.assertRegex(self.vm.get_log(), r'-cpu option cannot be empty') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/info_usernet.py b/tests/functional/test_info_usernet.py index e1aa7a6..cd37524 100644..100755 --- a/tests/avocado/info_usernet.py +++ b/tests/functional/test_info_usernet.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Test for the hmp command "info usernet" # # Copyright (c) 2021 Red Hat, Inc. @@ -8,18 +10,16 @@ # 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 import QemuSystemTest +from qemu_test import QemuSystemTest from qemu.utils import get_info_usernet_hostfwd_port class InfoUsernet(QemuSystemTest): - """ - :avocado: tags=machine:none - """ def test_hostfwd(self): self.require_netdev('user') + 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', @@ -31,3 +31,6 @@ class InfoUsernet(QemuSystemTest): self.assertGreater(port, 0, ('Found a redirected port that is not greater than' ' zero')) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/linux_initrd.py b/tests/functional/test_linux_initrd.py index 7f47b98..c71a59d 100644..100755 --- a/tests/avocado/linux_initrd.py +++ b/tests/functional/test_linux_initrd.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Linux initrd integration test. # # Copyright (c) 2018 Red Hat, Inc. @@ -12,20 +14,27 @@ import os import logging import tempfile -from avocado_qemu import QemuSystemTest -from avocado import skipUnless +from qemu_test import QemuSystemTest, Asset +from unittest import skipUnless class LinuxInitrd(QemuSystemTest): """ Checks QEMU evaluates correctly the initrd file passed as -initrd option. - - :avocado: tags=arch:x86_64 - :avocado: tags=machine:pc """ timeout = 300 + ASSET_F18_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/18/Fedora/x86_64/os/images/pxeboot/vmlinuz'), + '1a27cb42559ce29237ac186699d063556ad69c8349d732bb1bd8d614e5a8cc2e') + + ASSET_F28_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/28/Everything/x86_64/os/images/pxeboot/vmlinuz'), + 'd05909c9d4a742a6fcc84dcc0361009e4611769619cc187a07107579a035f24e') + def test_with_2gib_file_should_exit_error_msg_with_linux_v3_6(self): """ Pretends to boot QEMU with an initrd file with size of 2GiB @@ -33,10 +42,8 @@ class LinuxInitrd(QemuSystemTest): Fedora-18 shipped with linux-3.6 which have not supported xloadflags cannot support more than 2GiB initrd. """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora/li' - 'nux/releases/18/Fedora/x86_64/os/images/pxeboot/vmlinuz') - kernel_hash = '41464f68efe42b9991250bed86c7081d2ccdbb21' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.set_machine('pc') + kernel_path = self.ASSET_F18_KERNEL.fetch() max_size = 2 * (1024 ** 3) - 1 with tempfile.NamedTemporaryFile() as initrd: @@ -56,16 +63,11 @@ class LinuxInitrd(QemuSystemTest): @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') def test_with_2gib_file_should_work_with_linux_v4_16(self): """ - :avocado: tags=flaky - QEMU has supported up to 4 GiB initrd for recent kernel Expect guest can reach 'Unpacking initramfs...' """ - kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' - '/linux/releases/28/Everything/x86_64/os/images/pxeboot/' - 'vmlinuz') - kernel_hash = '238e083e114c48200f80d889f7e32eeb2793e02a' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.set_machine('pc') + kernel_path = self.ASSET_F28_KERNEL.fetch() max_size = 2 * (1024 ** 3) + 1 with tempfile.NamedTemporaryFile() as initrd: @@ -89,3 +91,6 @@ class LinuxInitrd(QemuSystemTest): break if 'Kernel panic - not syncing' in msg: self.fail("Kernel panic reached") + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/machine_loongarch.py b/tests/functional/test_loongarch64_virt.py index 8de308f..2b8baa2 100644..100755 --- a/tests/avocado/machine_loongarch.py +++ b/tests/functional/test_loongarch64_virt.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # SPDX-License-Identifier: GPL-2.0-or-later # # LoongArch virt test. @@ -5,15 +7,28 @@ # Copyright (c) 2023 Loongson Technology Corporation Limited # -from avocado_qemu import QemuSystemTest -from avocado_qemu import exec_command_and_wait_for_pattern -from avocado_qemu import wait_for_console_pattern +from qemu_test import QemuSystemTest, Asset +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern class LoongArchMachine(QemuSystemTest): KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' timeout = 120 + ASSET_KERNEL = Asset( + ('https://github.com/yangxiaojuan-loongson/qemu-binary/' + 'releases/download/2024-05-30/vmlinuz.efi'), + '08b88a45f48a5fd92260bae895be4e5175be2397481a6f7821b9f39b2965b79e') + ASSET_INITRD = Asset( + ('https://github.com/yangxiaojuan-loongson/qemu-binary/' + 'releases/download/2024-05-30/ramdisk'), + '03d6fb6f8ee64ecac961120a0bdacf741f17b3bee2141f17fa01908c8baf176a') + ASSET_BIOS = Asset( + ('https://github.com/yangxiaojuan-loongson/qemu-binary/' + 'releases/download/2024-05-30/QEMU_EFI.fd'), + '937c1e7815e2340150c194a9f8f0474259038a3d7b8845ed62cc08163c46bea1') + def wait_for_console_pattern(self, success_message, vm=None): wait_for_console_pattern(self, success_message, failure_message='Kernel panic - not syncing', @@ -21,25 +36,11 @@ class LoongArchMachine(QemuSystemTest): def test_loongarch64_devices(self): - """ - :avocado: tags=arch:loongarch64 - :avocado: tags=machine:virt - """ - - kernel_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/' - 'releases/download/2024-05-30/vmlinuz.efi') - kernel_hash = '951b485b16e3788b6db03a3e1793c067009e31a2' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.set_machine('virt') - initrd_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/' - 'releases/download/2024-05-30/ramdisk') - initrd_hash = 'c67658d9b2a447ce7db2f73ba3d373c9b2b90ab2' - initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) - - bios_url = ('https://github.com/yangxiaojuan-loongson/qemu-binary/' - 'releases/download/2024-05-30/QEMU_EFI.fd') - bios_hash = ('f4d0966b5117d4cd82327c050dd668741046be69') - bios_path = self.fetch_asset(bios_url, asset_hash=bios_hash) + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() + bios_path = self.ASSET_BIOS.fetch() self.vm.set_console() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + @@ -56,3 +57,6 @@ class LoongArchMachine(QemuSystemTest): self.wait_for_console_pattern('Run /sbin/init as init process') exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 'processor : 3') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/machine_m68k_nextcube.py b/tests/functional/test_m68k_nextcube.py index 1f3c883..89385a1 100644..100755 --- a/tests/avocado/machine_m68k_nextcube.py +++ b/tests/functional/test_m68k_nextcube.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional test that boots a VM and run OCR on the framebuffer # # Copyright (c) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org> @@ -8,10 +10,10 @@ import os import time -from avocado_qemu import QemuSystemTest -from avocado import skipUnless +from qemu_test import QemuSystemTest, Asset +from unittest import skipUnless -from tesseract_utils import tesseract_available, tesseract_ocr +from qemu_test.tesseract import tesseract_available, tesseract_ocr PIL_AVAILABLE = True try: @@ -21,19 +23,15 @@ except ImportError: class NextCubeMachine(QemuSystemTest): - """ - :avocado: tags=arch:m68k - :avocado: tags=machine:next-cube - :avocado: tags=device:framebuffer - """ timeout = 15 + ASSET_ROM = Asset(('https://sourceforge.net/p/previous/code/1350/tree/' + 'trunk/src/Rev_2.5_v66.BIN?format=raw'), + '1b753890b67095b73e104c939ddf62eca9e7d0aedde5108e3893b0ed9d8000a4') + def check_bootrom_framebuffer(self, screenshot_path): - rom_url = ('https://sourceforge.net/p/previous/code/1350/tree/' - 'trunk/src/Rev_2.5_v66.BIN?format=raw') - rom_hash = 'b3534796abae238a0111299fc406a9349f7fee24' - rom_path = self.fetch_asset(rom_url, asset_hash=rom_hash) + rom_path = self.ASSET_ROM.fetch() self.vm.add_args('-bios', rom_path) self.vm.launch() @@ -48,6 +46,7 @@ class NextCubeMachine(QemuSystemTest): @skipUnless(PIL_AVAILABLE, 'Python PIL not installed') def test_bootrom_framebuffer_size(self): + self.set_machine('next-cube') screenshot_path = os.path.join(self.workdir, "dump.ppm") self.check_bootrom_framebuffer(screenshot_path) @@ -60,11 +59,15 @@ class NextCubeMachine(QemuSystemTest): # that it is still alpha-level software. @skipUnless(tesseract_available(4), 'tesseract OCR tool not available') def test_bootrom_framebuffer_ocr_with_tesseract(self): + self.set_machine('next-cube') screenshot_path = os.path.join(self.workdir, "dump.ppm") self.check_bootrom_framebuffer(screenshot_path) - lines = tesseract_ocr(screenshot_path, tesseract_version=4) + lines = tesseract_ocr(screenshot_path) text = '\n'.join(lines) self.assertIn('Testing the FPU', text) self.assertIn('System test failed. Error code', text) self.assertIn('Boot command', text) self.assertIn('Next>', text) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/mem-addr-space-check.py b/tests/functional/test_mem_addr_space.py index d397459..bb0cf06 100644..100755 --- a/tests/avocado/mem-addr-space-check.py +++ b/tests/functional/test_mem_addr_space.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Check for crash when using memory beyond the available guest processor # address space. # @@ -8,7 +10,7 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from avocado_qemu import QemuSystemTest +from qemu_test import QemuSystemTest import time class MemAddrCheck(QemuSystemTest): @@ -22,9 +24,6 @@ class MemAddrCheck(QemuSystemTest): # for all 32-bit cases, pci64_hole_size is 0. def test_phybits_low_pse36(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - With pse36 feature ON, a processor has 36 bits of addressing. So it can access up to a maximum of 64GiB of memory. Memory hotplug region begins at 4 GiB boundary when "above_4g_mem_size" is 0 (this would be true when @@ -52,9 +51,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_low_pae(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - With pae feature ON, a processor has 36 bits of addressing. So it can access up to a maximum of 64GiB of memory. Rest is the same as the case with pse36 above. @@ -72,9 +68,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_ok_pentium_pse36(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - Setting maxmem to 59.5G and making sure that QEMU can start with the same options as the failing case above with pse36 cpu feature. """ @@ -91,9 +84,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_ok_pentium_pae(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - Test is same as above but now with pae cpu feature turned on. Setting maxmem to 59.5G and making sure that QEMU can start fine with the same options as the case above. @@ -111,9 +101,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_ok_pentium2(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - Pentium2 has 36 bits of addressing, so its same as pentium with pse36 ON. """ @@ -130,9 +117,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_low_nonpse36(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - Pentium processor has 32 bits of addressing without pse36 or pae so it can access physical address up to 4 GiB. Setting maxmem to 4 GiB should make QEMU fail to start with "phys-bits too low" @@ -153,9 +137,6 @@ class MemAddrCheck(QemuSystemTest): # now lets test some 64-bit CPU cases. def test_phybits_low_tcg_q35_70_amd(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - For q35 7.1 machines and above, there is a HT window that starts at 1024 GiB and ends at 1 TiB - 1. If the max GPA falls in this range, "above_4G" memory is adjusted to start at 1 TiB boundary for AMD cpus @@ -182,9 +163,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_low_tcg_q35_71_amd(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - AMD_HT_START is defined to be at 1012 GiB. So for q35 machines version > 7.0 and AMD cpus, instead of 1024 GiB limit for 40 bit processor address space, it has to be 1012 GiB , that is 12 GiB @@ -205,9 +183,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_ok_tcg_q35_70_amd(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - Same as q35-7.0 AMD case except that here we check that QEMU can successfully start when maxmem is < 988G. """ @@ -224,9 +199,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_ok_tcg_q35_71_amd(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - Same as q35-7.1 AMD case except that here we check that QEMU can successfully start when maxmem is < 976G. """ @@ -243,9 +215,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_ok_tcg_q35_71_intel(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - Same parameters as test_phybits_low_tcg_q35_71_amd() but use Intel cpu instead. QEMU should start fine in this case as "above_4G" memory starts at 4G. @@ -264,9 +233,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_low_tcg_q35_71_amd_41bits(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - AMD processor with 41 bits. Max cpu hw address = 2 TiB. By setting maxram above 1012 GiB - 32 GiB - 4 GiB = 976 GiB, we can force "above_4G" memory to start at 1 TiB for q35-7.1 machines @@ -291,9 +257,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_ok_tcg_q35_71_amd_41bits(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - AMD processor with 41 bits. Max cpu hw address = 2 TiB. Same as above but by setting maxram between 976 GiB and 992 Gib, QEMU should start fine. @@ -312,9 +275,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_low_tcg_q35_intel_cxl(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - cxl memory window starts after memory device range. Here, we use 1 GiB of cxl window memory. 4G_mem end aligns at 4G. pci64_hole is 32 GiB and starts after the cxl memory window. @@ -335,9 +295,6 @@ class MemAddrCheck(QemuSystemTest): def test_phybits_ok_tcg_q35_intel_cxl(self): """ - :avocado: tags=machine:q35 - :avocado: tags=arch:x86_64 - Same as above but here we do not reserve any cxl memory window. Hence, with the exact same parameters as above, QEMU should start fine even with cxl enabled. @@ -352,3 +309,6 @@ class MemAddrCheck(QemuSystemTest): time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) self.vm.shutdown() self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/test_microblaze_s3adsp1800.py b/tests/functional/test_microblaze_s3adsp1800.py new file mode 100755 index 0000000..4f692ff --- /dev/null +++ b/tests/functional/test_microblaze_s3adsp1800.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a microblaze Linux kernel and checks the console +# +# Copyright (c) 2018, 2021 Red Hat, Inc. +# +# 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 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 MicroblazeMachine(QemuSystemTest): + + timeout = 90 + + ASSET_IMAGE = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day17.tar.xz'), + '3ba7439dfbea7af4876662c97f8e1f0cdad9231fc166e4861d17042489270057') + + def test_microblaze_s3adsp1800(self): + self.set_machine('petalogix-s3adsp1800') + file_path = self.ASSET_IMAGE.fetch() + archive_extract(file_path, self.workdir) + self.vm.set_console() + self.vm.add_args('-kernel', self.workdir + '/day17/ballerina.bin') + self.vm.launch() + wait_for_console_pattern(self, 'This architecture does not have ' + 'kernel memory protection') + # Note: + # The kernel sometimes gets stuck after the "This architecture ..." + # message, that's why we don't test for a later string here. This + # needs some investigation by a microblaze wizard one day... + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/test_microblazeel_s3adsp1800.py b/tests/functional/test_microblazeel_s3adsp1800.py new file mode 100755 index 0000000..faa3927 --- /dev/null +++ b/tests/functional/test_microblazeel_s3adsp1800.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a microblaze Linux kernel and checks the console +# +# Copyright (c) 2018, 2021 Red Hat, Inc. +# +# 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 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): + + timeout = 90 + + ASSET_IMAGE = Asset( + ('http://www.qemu-advent-calendar.org/2023/download/day13.tar.gz'), + 'b9b3d43c5dd79db88ada495cc6e0d1f591153fe41355e925d791fbf44de50c22') + + 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.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.launch() + wait_for_console_pattern(self, 'QEMU Advent Calendar 2023') + time.sleep(0.1) + exec_command(self, 'root') + time.sleep(0.1) + exec_command_and_wait_for_pattern(self, + 'tftp -g -r xmaton.png 10.0.2.2 ; md5sum xmaton.png', + '821cd3cab8efd16ad6ee5acc3642a8ea') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/machine_mips_fuloong2e.py b/tests/functional/test_mips64el_fuloong2e.py index 89291f4..7688a32 100644..100755 --- a/tests/avocado/machine_mips_fuloong2e.py +++ b/tests/functional/test_mips64el_fuloong2e.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional tests for the Lemote Fuloong-2E machine. # # Copyright (c) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org> @@ -8,35 +10,36 @@ # SPDX-License-Identifier: GPL-2.0-or-later import os +import subprocess -from avocado import skipUnless -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from qemu_test import QemuSystemTest +from qemu_test import wait_for_console_pattern +from unittest import skipUnless class MipsFuloong2e(QemuSystemTest): timeout = 60 - @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + @skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code') @skipUnless(os.getenv('RESCUE_YL_PATH'), 'RESCUE_YL_PATH not available') - def test_linux_kernel_isa_serial(self): - """ - :avocado: tags=arch:mips64el - :avocado: tags=machine:fuloong2e - :avocado: tags=endian:little - :avocado: tags=device:bonito64 - :avocado: tags=device:via686b - """ + def test_linux_kernel_2_6_27_isa_serial(self): # Recovery system for the Yeeloong laptop # (enough to test the fuloong2e southbridge, accessing its ISA bus) # http://dev.lemote.com/files/resource/download/rescue/rescue-yl - kernel_hash = 'ec4d1bd89a8439c41033ca63db60160cc6d6f09a' - kernel_path = self.fetch_asset('file://' + os.getenv('RESCUE_YL_PATH'), - asset_hash=kernel_hash) + sha = 'ab588d3316777c62cc81baa20ac92e98b01955c244dff3794b711bc34e26e51d' + kernel_path = os.getenv('RESCUE_YL_PATH') + output = subprocess.check_output(['sha256sum', kernel_path]) + checksum = output.split()[0] + assert checksum.decode("utf-8") == sha + self.set_machine('fuloong2e') self.vm.set_console() self.vm.add_args('-kernel', kernel_path) self.vm.launch() wait_for_console_pattern(self, 'Linux version 2.6.27.7lemote') cpu_revision = 'CPU revision is: 00006302 (ICT Loongson-2)' wait_for_console_pattern(self, cpu_revision) + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/test_mips64el_loongson3v.py b/tests/functional/test_mips64el_loongson3v.py new file mode 100755 index 0000000..55d6292 --- /dev/null +++ b/tests/functional/test_mips64el_loongson3v.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Functional tests for the Generic Loongson-3 Platform. +# +# Copyright (c) 2021 Jiaxun Yang <jiaxun.yang@flygoat.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. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import time + +from unittest import skipUnless +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + +class MipsLoongson3v(QemuSystemTest): + timeout = 60 + + ASSET_PMON = Asset( + ('https://github.com/loongson-community/pmon/' + 'releases/download/20210112/pmon-3avirt.bin'), + 'fcdf6bb2cb7885a4a62f31fcb0d5e368bac7b6cea28f40c6dfa678af22fea20a') + + @skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_pmon_serial_console(self): + self.set_machine('loongson3-virt') + + pmon_path = self.ASSET_PMON.fetch() + + self.vm.set_console() + self.vm.add_args('-bios', pmon_path) + self.vm.launch() + wait_for_console_pattern(self, 'CPU GODSON3 BogoMIPS:') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/netdev-ethtool.py b/tests/functional/test_netdev_ethtool.py index 5f33288..d5b911c 100644..100755 --- a/tests/avocado/netdev-ethtool.py +++ b/tests/functional/test_netdev_ethtool.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # ethtool tests for emulated network devices # # This test leverages ethtool's --test sequence to validate network @@ -5,39 +7,33 @@ # # SPDX-License-Identifier: GPL-2.0-or-late -from avocado import skip -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from unittest import skip +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern class NetDevEthtool(QemuSystemTest): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=machine:q35 - """ # Runs in about 17s under KVM, 19s under TCG, 25s under GCOV timeout = 45 # Fetch assets from the netdev-ethtool subdir of my shared test # images directory on fileserver.linaro.org. - def get_asset(self, name, sha1): - base_url = ('https://fileserver.linaro.org/s/' - 'kE4nCFLdQcoBF9t/download?' - 'path=%2Fnetdev-ethtool&files=' ) - url = base_url + name - # use explicit name rather than failing to neatly parse the - # URL into a unique one - return self.fetch_asset(name=name, locations=(url), asset_hash=sha1) + ASSET_BASEURL = ('https://fileserver.linaro.org/s/kE4nCFLdQcoBF9t/' + 'download?path=%2Fnetdev-ethtool&files=') + ASSET_BZIMAGE = Asset( + ASSET_BASEURL + "bzImage", + "ed62ee06ea620b1035747f3f66a5e9fc5d3096b29f75562ada888b04cd1c4baf") + ASSET_ROOTFS = Asset( + ASSET_BASEURL + "rootfs.squashfs", + "8f0207e3c4d40832ae73c1a927e42ca30ccb1e71f047acb6ddb161ba422934e6") def common_test_code(self, netdev, extra_args=None): + self.set_machine('q35') # This custom kernel has drivers for all the supported network # devices we can emulate in QEMU - kernel = self.get_asset("bzImage", - "33469d7802732d5815226166581442395cb289e2") - - rootfs = self.get_asset("rootfs.squashfs", - "9793cea7021414ae844bda51f558bd6565b50cdc") + kernel = self.ASSET_BZIMAGE.fetch() + rootfs = self.ASSET_ROOTFS.fetch() append = 'printk.time=0 console=ttyS0 ' append += 'root=/dev/sr0 rootfstype=squashfs ' @@ -68,15 +64,9 @@ class NetDevEthtool(QemuSystemTest): self.vm.kill() def test_igb(self): - """ - :avocado: tags=device:igb - """ self.common_test_code("igb") def test_igb_nomsi(self): - """ - :avocado: tags=device:igb - """ self.common_test_code("igb", "pci=nomsi") # It seems the other popular cards we model in QEMU currently fail @@ -88,14 +78,11 @@ class NetDevEthtool(QemuSystemTest): @skip("Incomplete reg 0x00178 support") def test_e1000(self): - """ - :avocado: tags=device:e1000 - """ self.common_test_code("e1000") @skip("Incomplete reg 0x00178 support") def test_i82550(self): - """ - :avocado: tags=device:i82550 - """ self.common_test_code("i82550") + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/pc_cpu_hotplug_props.py b/tests/functional/test_pc_cpu_hotplug_props.py index 4bd3e02..9d5a37c 100644..100755 --- a/tests/avocado/pc_cpu_hotplug_props.py +++ b/tests/functional/test_pc_cpu_hotplug_props.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # # Ensure CPU die-id can be omitted on -device # @@ -20,16 +21,16 @@ # License along with this library; if not, see <http://www.gnu.org/licenses/>. # -from avocado_qemu import QemuSystemTest +from qemu_test import QemuSystemTest class OmittedCPUProps(QemuSystemTest): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=cpu:qemu64 - """ + def test_no_die_id(self): self.vm.add_args('-nodefaults', '-S') self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') self.vm.launch() self.assertEqual(len(self.vm.cmd('query-cpus-fast')), 2) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/ppc_hv_tests.py b/tests/functional/test_ppc64_hv.py index 0e83bba..1a6e4b6 100644..100755 --- a/tests/avocado/ppc_hv_tests.py +++ b/tests/functional/test_ppc64_hv.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Tests that specifically try to exercise hypervisor features of the # target machines. powernv supports the Power hypervisor ISA, and # pseries supports the nested-HV hypervisor spec. @@ -7,10 +9,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 avocado import skipIf, skipUnless -from avocado.utils import archive -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern, exec_command +from unittest import skipIf, skipUnless +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern, exec_command import os import time import subprocess @@ -45,8 +46,7 @@ def missing_deps(): # 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('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited') -@skipUnless(os.getenv('SPEED') == 'slow', 'runtime limited') +@skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 'storage limited') class HypervisorTest(QemuSystemTest): timeout = 1000 @@ -54,6 +54,11 @@ class HypervisorTest(QemuSystemTest): panic_message = 'Kernel panic - not syncing' good_message = 'VFS: Cannot open root device' + ASSET_ISO = Asset( + ('https://dl-cdn.alpinelinux.org/alpine/v3.18/' + 'releases/ppc64le/alpine-standard-3.18.4-ppc64le.iso'), + 'c26b8d3e17c2f3f0fed02b4b1296589c2390e6d5548610099af75300edd7b3ff') + def extract_from_iso(self, iso, path): """ Extracts a file from an iso file into the test workdir @@ -72,6 +77,7 @@ class HypervisorTest(QemuSystemTest): 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 @@ -83,16 +89,9 @@ class HypervisorTest(QemuSystemTest): def setUp(self): super().setUp() - iso_url = ('https://dl-cdn.alpinelinux.org/alpine/v3.18/releases/ppc64le/alpine-standard-3.18.4-ppc64le.iso') - - # Alpine use sha256 so I recalculated this myself - iso_sha256 = 'c26b8d3e17c2f3f0fed02b4b1296589c2390e6d5548610099af75300edd7b3ff' - iso_path = self.fetch_asset(iso_url, asset_hash=iso_sha256, - algorithm = "sha256") - - self.iso_path = iso_path - self.vmlinuz = self.extract_from_iso(iso_path, '/boot/vmlinuz-lts') - self.initramfs = self.extract_from_iso(iso_path, '/boot/initramfs-lts') + self.iso_path = self.ASSET_ISO.fetch() + self.vmlinuz = self.extract_from_iso(self.iso_path, '/boot/vmlinuz-lts') + self.initramfs = self.extract_from_iso(self.iso_path, '/boot/initramfs-lts') def do_start_alpine(self): self.vm.set_console() @@ -158,12 +157,8 @@ class HypervisorTest(QemuSystemTest): wait_for_console_pattern(self, 'alpine:~#') def test_hv_pseries(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - :avocado: tags=accel:tcg - """ self.require_accelerator("tcg") + self.set_machine('pseries') self.vm.add_args("-accel", "tcg,thread=multi") self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') self.vm.add_args("-machine", "x-vof=on,cap-nested-hv=on") @@ -173,12 +168,8 @@ class HypervisorTest(QemuSystemTest): self.do_stop_alpine() def test_hv_pseries_kvm(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - :avocado: tags=accel:kvm - """ self.require_accelerator("kvm") + self.set_machine('pseries') self.vm.add_args("-accel", "kvm") self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') self.vm.add_args("-machine", "x-vof=on,cap-nested-hv=on,cap-ccf-assist=off") @@ -188,12 +179,8 @@ class HypervisorTest(QemuSystemTest): self.do_stop_alpine() def test_hv_powernv(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:powernv - :avocado: tags=accel:tcg - """ self.require_accelerator("tcg") + self.set_machine('powernv') self.vm.add_args("-accel", "tcg,thread=multi") self.vm.add_args('-device', 'nvme,bus=pcie.2,addr=0x0,serial=1234,drive=drive0', '-device', 'e1000e,netdev=net0,mac=C0:FF:EE:00:00:02,bus=pcie.0,addr=0x0', @@ -203,3 +190,6 @@ class HypervisorTest(QemuSystemTest): self.do_test_kvm() self.do_test_kvm(True) self.do_stop_alpine() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/ppc_powernv.py b/tests/functional/test_ppc64_powernv.py index 4342941..67497d6 100644..100755 --- a/tests/avocado/ppc_powernv.py +++ b/tests/functional/test_ppc64_powernv.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Test that Linux kernel boots on ppc powernv machines and check the console # # Copyright (c) 2018, 2020 Red Hat, Inc. @@ -5,9 +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. -from avocado.utils import archive -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern class powernvMachine(QemuSystemTest): @@ -16,13 +17,14 @@ class powernvMachine(QemuSystemTest): panic_message = 'Kernel panic - not syncing' good_message = 'VFS: Cannot open root device' + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' + 'releases/29/Everything/ppc64le/os/ppc/ppc64/vmlinuz'), + '383c2f5c23bc0d9d32680c3924d3fd7ee25cc5ef97091ac1aa5e1d853422fc5f') + def do_test_linux_boot(self, command_line = KERNEL_COMMON_COMMAND_LINE): self.require_accelerator("tcg") - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/29/Everything/ppc64le/os' - '/ppc/ppc64/vmlinuz') - kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + kernel_path = self.ASSET_KERNEL.fetch() self.vm.set_console() self.vm.add_args('-kernel', kernel_path, @@ -30,23 +32,13 @@ class powernvMachine(QemuSystemTest): self.vm.launch() def test_linux_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:powernv - :avocado: tags=accel:tcg - """ - + self.set_machine('powernv') self.do_test_linux_boot() console_pattern = 'VFS: Cannot open root device' wait_for_console_pattern(self, console_pattern, self.panic_message) def test_linux_smp_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:powernv - :avocado: tags=accel:tcg - """ - + self.set_machine('powernv') self.vm.add_args('-smp', '4') self.do_test_linux_boot() console_pattern = 'smp: Brought up 1 node, 4 CPUs' @@ -54,12 +46,7 @@ class powernvMachine(QemuSystemTest): wait_for_console_pattern(self, self.good_message, self.panic_message) def test_linux_smp_hpt_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:powernv - :avocado: tags=accel:tcg - """ - + self.set_machine('powernv') self.vm.add_args('-smp', '4') self.do_test_linux_boot(self.KERNEL_COMMON_COMMAND_LINE + 'disable_radix') @@ -70,12 +57,7 @@ class powernvMachine(QemuSystemTest): wait_for_console_pattern(self, self.good_message, self.panic_message) def test_linux_smt_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:powernv - :avocado: tags=accel:tcg - """ - + self.set_machine('powernv') self.vm.add_args('-smp', '4,threads=4') self.do_test_linux_boot() console_pattern = 'CPU maps initialized for 4 threads per core' @@ -85,12 +67,7 @@ class powernvMachine(QemuSystemTest): wait_for_console_pattern(self, self.good_message, self.panic_message) def test_linux_big_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:powernv - :avocado: tags=accel:tcg - """ - + self.set_machine('powernv') self.vm.add_args('-smp', '16,threads=4,cores=2,sockets=2') # powernv does not support NUMA @@ -100,3 +77,6 @@ class powernvMachine(QemuSystemTest): console_pattern = 'smp: Brought up 2 nodes, 16 CPUs' wait_for_console_pattern(self, console_pattern, self.panic_message) wait_for_console_pattern(self, self.good_message, self.panic_message) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/ppc_pseries.py b/tests/functional/test_ppc64_pseries.py index 74aaa4a..fdc404e 100644..100755 --- a/tests/avocado/ppc_pseries.py +++ b/tests/functional/test_ppc64_pseries.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Test that Linux kernel boots on ppc machines and check the console # # Copyright (c) 2018, 2020 Red Hat, Inc. @@ -5,9 +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. -from avocado.utils import archive -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern class pseriesMachine(QemuSystemTest): @@ -16,12 +17,13 @@ class pseriesMachine(QemuSystemTest): panic_message = 'Kernel panic - not syncing' good_message = 'VFS: Cannot open root device' + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' + 'releases/29/Everything/ppc64le/os/ppc/ppc64/vmlinuz'), + '383c2f5c23bc0d9d32680c3924d3fd7ee25cc5ef97091ac1aa5e1d853422fc5f') + def do_test_ppc64_linux_boot(self, kernel_command_line = KERNEL_COMMON_COMMAND_LINE): - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/29/Everything/ppc64le/os' - '/ppc/ppc64/vmlinuz') - kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + kernel_path = self.ASSET_KERNEL.fetch() self.vm.set_console() self.vm.add_args('-kernel', kernel_path, @@ -29,32 +31,20 @@ class pseriesMachine(QemuSystemTest): self.vm.launch() def test_ppc64_vof_linux_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - """ - + self.set_machine('pseries') self.vm.add_args('-machine', 'x-vof=on') self.do_test_ppc64_linux_boot() console_pattern = 'VFS: Cannot open root device' wait_for_console_pattern(self, console_pattern, self.panic_message) def test_ppc64_linux_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - """ - + self.set_machine('pseries') self.do_test_ppc64_linux_boot() console_pattern = 'VFS: Cannot open root device' wait_for_console_pattern(self, console_pattern, self.panic_message) def test_ppc64_linux_smp_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - """ - + self.set_machine('pseries') self.vm.add_args('-smp', '4') self.do_test_ppc64_linux_boot() console_pattern = 'smp: Brought up 1 node, 4 CPUs' @@ -62,11 +52,7 @@ class pseriesMachine(QemuSystemTest): wait_for_console_pattern(self, self.good_message, self.panic_message) def test_ppc64_linux_hpt_smp_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - """ - + self.set_machine('pseries') self.vm.add_args('-smp', '4') self.do_test_ppc64_linux_boot(self.KERNEL_COMMON_COMMAND_LINE + 'disable_radix') @@ -77,11 +63,6 @@ class pseriesMachine(QemuSystemTest): wait_for_console_pattern(self, self.good_message, self.panic_message) def test_ppc64_linux_smt_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - """ - self.vm.add_args('-smp', '4,threads=4') self.do_test_ppc64_linux_boot() console_pattern = 'CPU maps initialized for 4 threads per core' @@ -91,11 +72,7 @@ class pseriesMachine(QemuSystemTest): wait_for_console_pattern(self, self.good_message, self.panic_message) def test_ppc64_linux_big_boot(self): - """ - :avocado: tags=arch:ppc64 - :avocado: tags=machine:pseries - """ - + self.set_machine('pseries') self.vm.add_args('-smp', '16,threads=4,cores=2,sockets=2') self.vm.add_args('-m', '512M', '-object', 'memory-backend-ram,size=256M,id=m0', @@ -108,3 +85,6 @@ class pseriesMachine(QemuSystemTest): console_pattern = 'smp: Brought up 2 nodes, 16 CPUs' wait_for_console_pattern(self, console_pattern, self.panic_message) wait_for_console_pattern(self, self.good_message, self.panic_message) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/ppc_405.py b/tests/functional/test_ppc_405.py index 4e7e01a..9851c03 100644..100755 --- a/tests/avocado/ppc_405.py +++ b/tests/functional/test_ppc_405.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Test that the U-Boot firmware boots on ppc 405 machines and check the console # # Copyright (c) 2021 Red Hat, Inc. @@ -5,20 +7,21 @@ # 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.utils import archive -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern -from avocado_qemu import exec_command_and_wait_for_pattern +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 Ppc405Machine(QemuSystemTest): timeout = 90 + ASSET_UBOOT = Asset( + ('https://gitlab.com/huth/u-boot/-/raw/taihu-2021-10-09/' + 'u-boot-taihu.bin'), + 'a076bb6cdeaafa406330e51e074b66d8878d9036d67d4caa0137be03ee4c112c') + def do_test_ppc405(self): - uboot_url = ('https://gitlab.com/huth/u-boot/-/raw/' - 'taihu-2021-10-09/u-boot-taihu.bin') - uboot_hash = ('3208940e908a5edc7c03eab072c60f0dcfadc2ab'); - file_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) + file_path = self.ASSET_UBOOT.fetch() self.vm.set_console(console_index=1) self.vm.add_args('-bios', file_path) self.vm.launch() @@ -26,11 +29,9 @@ class Ppc405Machine(QemuSystemTest): exec_command_and_wait_for_pattern(self, 'reset', 'AMCC PowerPC 405EP') def test_ppc_ref405ep(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:ref405ep - :avocado: tags=cpu:405ep - :avocado: tags=accel:tcg - """ self.require_accelerator("tcg") + self.set_machine('ref405ep') self.do_test_ppc405() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/ppc_prep_40p.py b/tests/functional/test_ppc_40p.py index d4f1eb7..c64e876 100644..100755 --- a/tests/avocado/ppc_prep_40p.py +++ b/tests/functional/test_ppc_40p.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional test that boots a PReP/40p machine and checks its serial console. # # Copyright (c) Philippe Mathieu-Daudé <f4bug@amsat.org> @@ -7,39 +9,40 @@ import os -from avocado import skipUnless -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from unittest import skipUnless +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern class IbmPrep40pMachine(QemuSystemTest): timeout = 60 + ASSET_BIOS = Asset( + ('http://ftpmirror.your.org/pub/misc/' + 'ftp.software.ibm.com/rs6000/firmware/' + '7020-40p/P12H0456.IMG'), + 'd957f79c73f760d1455d2286fcd901ed6d06167320eb73511b478a939be25b3f') + ASSET_NETBSD40 = Asset( + ('https://archive.netbsd.org/pub/NetBSD-archive/' + 'NetBSD-4.0/prep/installation/floppy/generic_com0.fs'), + 'f86236e9d01b3f0dd0f5d3b8d5bbd40c68e78b4db560a108358f5ad58e636619') + ASSET_NETBSD71 = Asset( + ('https://archive.netbsd.org/pub/NetBSD-archive/' + 'NetBSD-7.1.2/iso/NetBSD-7.1.2-prep.iso'), + 'cc7cb290b06aaa839362deb7bd9f417ac5015557db24088508330f76c3f825ec') + # 12H0455 PPS Firmware Licensed Materials # Property of IBM (C) Copyright IBM Corp. 1994. # 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('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + @skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code') def test_factory_firmware_and_netbsd(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:40p - :avocado: tags=os:netbsd - :avocado: tags=slowness:high - :avocado: tags=accel:tcg - """ + self.set_machine('40p') self.require_accelerator("tcg") - bios_url = ('http://ftpmirror.your.org/pub/misc/' - 'ftp.software.ibm.com/rs6000/firmware/' - '7020-40p/P12H0456.IMG') - bios_hash = '1775face4e6dc27f3a6ed955ef6eb331bf817f03' - bios_path = self.fetch_asset(bios_url, asset_hash=bios_hash) - drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/' - 'NetBSD-4.0/prep/installation/floppy/generic_com0.fs') - drive_hash = 'dbcfc09912e71bd5f0d82c7c1ee43082fb596ceb' - drive_path = self.fetch_asset(drive_url, asset_hash=drive_hash) + bios_path = self.ASSET_BIOS.fetch() + drive_path = self.ASSET_NETBSD40.fetch() self.vm.set_console() self.vm.add_args('-bios', bios_path, @@ -50,11 +53,7 @@ class IbmPrep40pMachine(QemuSystemTest): wait_for_console_pattern(self, 'Model: IBM PPS Model 6015') def test_openbios_192m(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:40p - :avocado: tags=accel:tcg - """ + self.set_machine('40p') self.require_accelerator("tcg") self.vm.set_console() self.vm.add_args('-m', '192') # test fw_cfg @@ -65,21 +64,15 @@ class IbmPrep40pMachine(QemuSystemTest): wait_for_console_pattern(self, '>> CPU type PowerPC,604') def test_openbios_and_netbsd(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:40p - :avocado: tags=os:netbsd - :avocado: tags=accel:tcg - """ + self.set_machine('40p') self.require_accelerator("tcg") - drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/' - 'NetBSD-7.1.2/iso/NetBSD-7.1.2-prep.iso') - drive_hash = 'ac6fa2707d888b36d6fa64de6e7fe48e' - drive_path = self.fetch_asset(drive_url, asset_hash=drive_hash, - algorithm='md5') + drive_path = self.ASSET_NETBSD71.fetch() self.vm.set_console() self.vm.add_args('-cdrom', drive_path, '-boot', 'd') self.vm.launch() wait_for_console_pattern(self, 'NetBSD/prep BOOT, Revision 1.9') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/ppc_74xx.py b/tests/functional/test_ppc_74xx.py index f54757c..5386016 100644..100755 --- a/tests/avocado/ppc_74xx.py +++ b/tests/functional/test_ppc_74xx.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Smoke tests for 74xx cpus (aka G4). # # Copyright (c) 2021, IBM Corp. @@ -5,132 +7,120 @@ # 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 import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from qemu_test import QemuSystemTest +from qemu_test import wait_for_console_pattern class ppc74xxCpu(QemuSystemTest): - """ - :avocado: tags=arch:ppc - :avocado: tags=accel:tcg - """ + timeout = 5 def test_ppc_7400(self): - """ - :avocado: tags=cpu:7400 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7400') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') def test_ppc_7410(self): - """ - :avocado: tags=cpu:7410 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7410') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,74xx') def test_ppc_7441(self): - """ - :avocado: tags=cpu:7441 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7441') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') def test_ppc_7445(self): - """ - :avocado: tags=cpu:7445 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7445') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') def test_ppc_7447(self): - """ - :avocado: tags=cpu:7447 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7447') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') def test_ppc_7447a(self): - """ - :avocado: tags=cpu:7447a - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7447a') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') def test_ppc_7448(self): - """ - :avocado: tags=cpu:7448 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7448') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,MPC86xx') def test_ppc_7450(self): - """ - :avocado: tags=cpu:7450 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7450') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') def test_ppc_7451(self): - """ - :avocado: tags=cpu:7451 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7451') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') def test_ppc_7455(self): - """ - :avocado: tags=cpu:7455 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7455') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') def test_ppc_7457(self): - """ - :avocado: tags=cpu:7457 - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7457') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') def test_ppc_7457a(self): - """ - :avocado: tags=cpu:7457a - """ self.require_accelerator("tcg") + self.set_machine('g3beige') self.vm.set_console() + self.vm.add_args('-cpu', '7457a') self.vm.launch() wait_for_console_pattern(self, '>> OpenBIOS') wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/test_ppc_amiga.py b/tests/functional/test_ppc_amiga.py new file mode 100755 index 0000000..b793b5c --- /dev/null +++ b/tests/functional/test_ppc_amiga.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# +# Test AmigaNG boards +# +# Copyright (c) 2023 BALATON Zoltan +# +# 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 subprocess + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern, run_cmd +from zipfile import ZipFile + +class AmigaOneMachine(QemuSystemTest): + + timeout = 90 + + ASSET_IMAGE = Asset( + ('https://www.hyperion-entertainment.com/index.php/' + 'downloads?view=download&format=raw&file=25'), + '8ff39330ba47d4f64de4ee8fd6809e9c010a9ef17fe51e95c3c1d53437cb481f') + + def test_ppc_amigaone(self): + 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.vm.set_console() + self.vm.add_args('-bios', self.workdir + '/u-boot-amigaone.bin') + self.vm.launch() + wait_for_console_pattern(self, 'FLASH:') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/ppc_bamboo.py b/tests/functional/test_ppc_bamboo.py index a81be3d..e72cbde 100644..100755 --- a/tests/avocado/ppc_bamboo.py +++ b/tests/functional/test_ppc_bamboo.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Test that Linux kernel boots on the ppc bamboo board and check the console # # Copyright (c) 2021 Red Hat @@ -5,30 +7,26 @@ # 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.utils import archive -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern -from avocado_qemu import exec_command_and_wait_for_pattern +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 + ASSET_IMAGE = Asset( + ('http://landley.net/aboriginal/downloads/binaries/' + 'system-image-powerpc-440fp.tar.gz'), + 'c12b58f841c775a0e6df4832a55afe6b74814d1565d08ddeafc1fb949a075c5e') + def test_ppc_bamboo(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:bamboo - :avocado: tags=cpu:440epb - :avocado: tags=device:rtl8139 - :avocado: tags=accel:tcg - """ + self.set_machine('bamboo') self.require_accelerator("tcg") self.require_netdev('user') - tar_url = ('http://landley.net/aboriginal/downloads/binaries/' - 'system-image-powerpc-440fp.tar.gz') - tar_hash = '53e5f16414b195b82d2c70272f81c2eedb39bad9' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) + file_path = self.ASSET_IMAGE.fetch() + archive_extract(file_path, self.workdir) self.vm.set_console() self.vm.add_args('-kernel', self.workdir + '/system-image-powerpc-440fp/linux', @@ -40,3 +38,6 @@ class BambooMachine(QemuSystemTest): exec_command_and_wait_for_pattern(self, 'ping 10.0.2.2', '10.0.2.2 is alive!') exec_command_and_wait_for_pattern(self, 'halt', 'System Halted') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/ppc_mpc8544ds.py b/tests/functional/test_ppc_mpc8544ds.py index b599fb1..2b3f089 100644..100755 --- a/tests/avocado/ppc_mpc8544ds.py +++ b/tests/functional/test_ppc_mpc8544ds.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Test that Linux kernel boots on ppc machines and check the console # # Copyright (c) 2018, 2020 Red Hat, Inc. @@ -5,9 +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 avocado.utils import archive -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from qemu_test.utils import archive_extract +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern class Mpc8544dsMachine(QemuSystemTest): @@ -15,20 +17,21 @@ class Mpc8544dsMachine(QemuSystemTest): KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' panic_message = 'Kernel panic - not syncing' + ASSET_IMAGE = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day04.tar.xz'), + '88bc83f3c9f3d633bcfc108a6342d677abca247066a2fb8d4636744a0d319f94') + def test_ppc_mpc8544ds(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:mpc8544ds - :avocado: tags=accel:tcg - """ self.require_accelerator("tcg") - tar_url = ('https://qemu-advcal.gitlab.io' - '/qac-best-of-multiarch/download/day04.tar.xz') - tar_hash = 'f46724d281a9f30fa892d458be7beb7d34dc25f9' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) + self.set_machine('mpc8544ds') + file_path = self.ASSET_IMAGE.fetch() + archive_extract(file_path, self.workdir, member='creek/creek.bin') self.vm.set_console() self.vm.add_args('-kernel', self.workdir + '/creek/creek.bin') self.vm.launch() wait_for_console_pattern(self, 'QEMU advent calendar 2020', self.panic_message) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/ppc_virtex_ml507.py b/tests/functional/test_ppc_virtex_ml507.py index a73f8ae..ffa9a06 100644..100755 --- a/tests/avocado/ppc_virtex_ml507.py +++ b/tests/functional/test_ppc_virtex_ml507.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Test that Linux kernel boots on ppc machines and check the console # # Copyright (c) 2018, 2020 Red Hat, Inc. @@ -5,9 +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 avocado.utils import archive -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from qemu_test.utils import archive_extract +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern class VirtexMl507Machine(QemuSystemTest): @@ -15,18 +17,16 @@ class VirtexMl507Machine(QemuSystemTest): KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' panic_message = 'Kernel panic - not syncing' + ASSET_IMAGE = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day08.tar.xz'), + 'cefe5b8aeb5e9d2d1d4fd22dcf48d917d68d5a765132bf2ddd6332dc393b824c') + def test_ppc_virtex_ml507(self): - """ - :avocado: tags=arch:ppc - :avocado: tags=machine:virtex-ml507 - :avocado: tags=accel:tcg - """ self.require_accelerator("tcg") - tar_url = ('https://qemu-advcal.gitlab.io' - '/qac-best-of-multiarch/download/day08.tar.xz') - tar_hash = '74c68f5af7a7b8f21c03097b298f3bb77ff52c1f' - file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) - archive.extract(file_path, self.workdir) + self.set_machine('virtex-ml507') + file_path = self.ASSET_IMAGE.fetch() + archive_extract(file_path, self.workdir) self.vm.set_console() self.vm.add_args('-kernel', self.workdir + '/hippo/hippo.linux', '-dtb', self.workdir + '/hippo/virtex440-ml507.dtb', @@ -34,3 +34,6 @@ class VirtexMl507Machine(QemuSystemTest): self.vm.launch() wait_for_console_pattern(self, 'QEMU advent calendar 2020', self.panic_message) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/machine_rx_gdbsim.py b/tests/functional/test_rx_gdbsim.py index 6bd9ce8..5687f75 100644..100755 --- a/tests/avocado/machine_rx_gdbsim.py +++ b/tests/functional/test_rx_gdbsim.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional test that boots a Linux kernel and checks the console # # Copyright (c) 2018 Red Hat, Inc. @@ -10,11 +12,11 @@ import os -from avocado import skipUnless -from avocado_qemu import QemuSystemTest -from avocado_qemu import exec_command_and_wait_for_pattern -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive +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 class RxGdbSimMachine(QemuSystemTest): @@ -22,19 +24,25 @@ class RxGdbSimMachine(QemuSystemTest): timeout = 30 KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + ASSET_UBOOT = Asset( + 'https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz', + '7146567d669e91dbac166384b29aeba1715beb844c8551e904b86831bfd9d046') + ASSET_DTB = Asset( + 'https://acc.dl.osdn.jp/users/23/23887/rx-virt.dtb', + 'aa278d9c1907a4501741d7ee57e7f65c02dd1b3e0323b33c6d4247f1b32cf29a') + ASSET_KERNEL = Asset( + 'http://acc.dl.osdn.jp/users/23/23845/zImage', + 'baa43205e74a7220ed8482188c5e9ce497226712abb7f4e7e4f825ce19ff9656') + def test_uboot(self): """ U-Boot and checks that the console is operational. - - :avocado: tags=arch:rx - :avocado: tags=machine:gdbsim-r5f562n8 - :avocado: tags=endian:little - :avocado: tags=flaky """ - uboot_url = ('https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz') - uboot_hash = '9b78dbd43b40b2526848c0b1ce9de02c24f4dcdb' - uboot_path = self.fetch_asset(uboot_url, asset_hash=uboot_hash) - uboot_path = archive.uncompress(uboot_path, self.workdir) + 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) self.vm.set_console() self.vm.add_args('-bios', uboot_path, @@ -50,18 +58,11 @@ class RxGdbSimMachine(QemuSystemTest): def test_linux_sash(self): """ Boots a Linux kernel and checks that the console is operational. - - :avocado: tags=arch:rx - :avocado: tags=machine:gdbsim-r5f562n7 - :avocado: tags=endian:little - :avocado: tags=flaky """ - dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-virt.dtb') - dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18' - dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash) - kernel_url = ('http://acc.dl.osdn.jp/users/23/23845/zImage') - kernel_hash = '39a81067f8d72faad90866ddfefa19165d68fc99' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.set_machine('gdbsim-r5f562n7') + + dtb_path = self.ASSET_DTB.fetch() + kernel_path = self.ASSET_KERNEL.fetch() self.vm.set_console() kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon' @@ -72,3 +73,6 @@ class RxGdbSimMachine(QemuSystemTest): wait_for_console_pattern(self, 'Sash command shell (version 1.1.1)', failure_message='Kernel panic - not syncing') exec_command_and_wait_for_pattern(self, 'printenv', 'TERM=linux') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/machine_s390_ccw_virtio.py b/tests/functional/test_s390x_ccw_virtio.py index 26e938c..f7acd90 100644..100755 --- a/tests/avocado/machine_s390_ccw_virtio.py +++ b/tests/functional/test_s390x_ccw_virtio.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional test that boots an s390x Linux guest with ccw and PCI devices # attached and checks whether the devices are recognized by Linux # @@ -12,17 +14,38 @@ import os import tempfile -from avocado import skipUnless -from avocado_qemu import QemuSystemTest -from avocado_qemu import exec_command_and_wait_for_pattern -from avocado_qemu import wait_for_console_pattern -from avocado.utils import archive +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 ' timeout = 120 + ASSET_BUSTER_KERNEL = Asset( + ('https://snapshot.debian.org/archive/debian/' + '20201126T092837Z/dists/buster/main/installer-s390x/' + '20190702+deb10u6/images/generic/kernel.debian'), + 'd411d17c39ae7ad38d27534376cbe88b68b403c325739364122c2e6f1537e818') + ASSET_BUSTER_INITRD = Asset( + ('https://snapshot.debian.org/archive/debian/' + '20201126T092837Z/dists/buster/main/installer-s390x/' + '20190702+deb10u6/images/generic/initrd.debian'), + '836bbd0fe6a5ca81274c28c2b063ea315ce1868660866e9b60180c575fef9fd5') + + ASSET_F31_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/31/Server/s390x/os' + '/images/kernel.img'), + '480859574f3f44caa6cd35c62d70e1ac0609134e22ce2a954bbed9b110c06e0b') + ASSET_F31_INITRD = Asset( + ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/31/Server/s390x/os' + '/images/initrd.img'), + '04c46095b2c49020b1c2327158898b7db747e4892ae319726192fb949716aa9c') + def wait_for_console_pattern(self, success_message, vm=None): wait_for_console_pattern(self, success_message, failure_message='Kernel panic - not syncing', @@ -41,23 +64,10 @@ class S390CCWVirtioMachine(QemuSystemTest): self.dmesg_clear_count += 1 def test_s390x_devices(self): + self.set_machine('s390-ccw-virtio') - """ - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio - """ - - kernel_url = ('https://snapshot.debian.org/archive/debian/' - '20201126T092837Z/dists/buster/main/installer-s390x/' - '20190702+deb10u6/images/generic/kernel.debian') - kernel_hash = '5821fbee57d6220a067a8b967d24595621aa1eb6' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - initrd_url = ('https://snapshot.debian.org/archive/debian/' - '20201126T092837Z/dists/buster/main/installer-s390x/' - '20190702+deb10u6/images/generic/initrd.debian') - initrd_hash = '81ba09c97bef46e8f4660ac25b4ac0a5be3a94d6' - initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + kernel_path = self.ASSET_BUSTER_KERNEL.fetch() + initrd_path = self.ASSET_BUSTER_INITRD.fetch() self.vm.set_console() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + @@ -160,29 +170,13 @@ class S390CCWVirtioMachine(QemuSystemTest): def test_s390x_fedora(self): + self.set_machine('s390-ccw-virtio') - """ - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio - :avocado: tags=device:virtio-gpu - :avocado: tags=device:virtio-crypto - :avocado: tags=device:virtio-net - :avocado: tags=flaky - """ - - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/31/Server/s390x/os' - '/images/kernel.img') - kernel_hash = 'b93d1efcafcf29c1673a4ce371a1f8b43941cfeb' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + kernel_path = self.ASSET_F31_KERNEL.fetch() - initrd_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/31/Server/s390x/os' - '/images/initrd.img') - initrd_hash = '3de45d411df5624b8d8ef21cd0b44419ab59b12f' - initrd_path_xz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path_xz = self.ASSET_F31_INITRD.fetch() initrd_path = os.path.join(self.workdir, 'initrd-raw.img') - archive.lzma_uncompress(initrd_path_xz, initrd_path) + lzma_uncompress(initrd_path_xz, initrd_path) self.vm.set_console() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + ' audit=0 ' @@ -200,6 +194,8 @@ class S390CCWVirtioMachine(QemuSystemTest): '-device', 'virtio-rng-ccw,devno=fe.1.9876', '-device', 'virtio-gpu-ccw,devno=fe.2.5432') self.vm.launch() + self.wait_for_console_pattern('Kernel command line: %s' + % kernel_command_line) self.wait_for_console_pattern('Entering emergency mode') # Some tests to see whether the CLI options have been considered: @@ -275,3 +271,6 @@ class S390CCWVirtioMachine(QemuSystemTest): exec_command_and_wait_for_pattern(self, 'while ! (dmesg -c | grep Start.virtcrypto_remove) ; do' ' sleep 1 ; done', 'Start virtcrypto_remove.') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/s390_topology.py b/tests/functional/test_s390x_topology.py index 9154ac8..20727f6 100644..100755 --- a/tests/avocado/s390_topology.py +++ b/tests/functional/test_s390x_topology.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Functional test that boots a Linux kernel and checks the console # # Copyright IBM Corp. 2023 @@ -9,16 +11,13 @@ # later. See the COPYING file in the top-level directory. import os -import shutil import time -from avocado_qemu import QemuSystemTest -from avocado_qemu import exec_command -from avocado_qemu import exec_command_and_wait_for_pattern -from avocado_qemu import interrupt_interactive_console_until_pattern -from avocado_qemu import wait_for_console_pattern -from avocado.utils import process -from avocado.utils import archive +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): @@ -47,6 +46,17 @@ class S390CPUTopology(QemuSystemTest): 'root=/dev/ram ' 'selinux=0 ' 'rdinit=/bin/sh') + ASSET_F35_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/35/Server/s390x/os' + '/images/kernel.img'), + '1f2dddfd11bb1393dd2eb2e784036fbf6fc11057a6d7d27f9eb12d3edc67ef73') + + ASSET_F35_INITRD = Asset( + ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/35/Server/s390x/os' + '/images/initrd.img'), + '1100145fbca00240c8c372ae4b89b48c99844bc189b3dfbc3f481dc60055ca46') def wait_until_booted(self): wait_for_console_pattern(self, 'no job control', @@ -78,21 +88,10 @@ class S390CPUTopology(QemuSystemTest): We need a minimal root filesystem with a shell. """ self.require_accelerator("kvm") - kernel_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/35/Server/s390x/os' - '/images/kernel.img') - kernel_hash = '0d1aaaf303f07cf0160c8c48e56fe638' - kernel_path = self.fetch_asset(kernel_url, algorithm='md5', - asset_hash=kernel_hash) - - initrd_url = ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/35/Server/s390x/os' - '/images/initrd.img') - initrd_hash = 'a122057d95725ac030e2ec51df46e172' - initrd_path_xz = self.fetch_asset(initrd_url, algorithm='md5', - asset_hash=initrd_hash) + 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') - archive.lzma_uncompress(initrd_path_xz, initrd_path) + lzma_uncompress(initrd_path_xz, initrd_path) self.vm.set_console() kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE @@ -115,10 +114,8 @@ class S390CPUTopology(QemuSystemTest): def test_single(self): """ This test checks the simplest topology with a single CPU. - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.launch() self.wait_until_booted() @@ -127,10 +124,8 @@ class S390CPUTopology(QemuSystemTest): def test_default(self): """ This test checks the implicit topology. - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.add_args('-smp', '13,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') @@ -154,10 +149,8 @@ class S390CPUTopology(QemuSystemTest): """ This test checks the topology modification by moving a CPU to another socket: CPU 0 is moved from socket 0 to socket 2. - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.add_args('-smp', '1,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') @@ -174,10 +167,8 @@ class S390CPUTopology(QemuSystemTest): """ This test verifies that a CPU defined with the '-device' command line option finds its right place inside the topology. - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.add_args('-smp', '1,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') @@ -221,10 +212,8 @@ class S390CPUTopology(QemuSystemTest): """ This test verifies that QEMU modifies the entitlement change after several guest polarization change requests. - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.launch() self.wait_until_booted() @@ -267,10 +256,8 @@ class S390CPUTopology(QemuSystemTest): """ This test verifies that QEMU modifies the entitlement after a guest request and that the guest sees the change. - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.launch() self.wait_until_booted() @@ -313,10 +300,8 @@ class S390CPUTopology(QemuSystemTest): CPU is made dedicated. QEMU retains the entitlement value when horizontal polarization is in effect. For the guest, the field shows the effective value of the entitlement. - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.launch() self.wait_until_booted() @@ -345,10 +330,8 @@ class S390CPUTopology(QemuSystemTest): This test verifies that QEMU does not accept to overload a socket. The socket-id 0 on book-id 0 already contains CPUs 0 and 1 and can not accept any new CPU while socket-id 0 on book-id 1 is free. - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.add_args('-smp', '3,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') @@ -369,10 +352,8 @@ class S390CPUTopology(QemuSystemTest): """ This test verifies that QEMU refuses to lower the entitlement of a dedicated CPU - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.launch() self.wait_until_booted() @@ -417,10 +398,8 @@ class S390CPUTopology(QemuSystemTest): """ This test verifies that QEMU refuses to move a CPU to an nonexistent location - - :avocado: tags=arch:s390x - :avocado: tags=machine:s390-ccw-virtio """ + self.set_machine('s390-ccw-virtio') self.kernel_init() self.vm.launch() self.wait_until_booted() @@ -437,3 +416,6 @@ class S390CPUTopology(QemuSystemTest): self.assertEqual(res['error']['class'], 'GenericError') self.check_topology(0, 0, 0, 0, 'medium', False) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/test_sparc64_sun4u.py b/tests/functional/test_sparc64_sun4u.py new file mode 100755 index 0000000..32e245f --- /dev/null +++ b/tests/functional/test_sparc64_sun4u.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Thomas Huth <thuth@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 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""" + + timeout = 90 + + ASSET_IMAGE = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day23.tar.xz'), + 'a3ed92450704af244178351afd0e769776e7decb298e95a63abfd9a6e3f6c854') + + 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) + self.vm.set_console() + self.vm.add_args('-kernel', os.path.join(self.workdir, kernel_name), + '-append', 'printk.time=0') + self.vm.launch() + wait_for_console_pattern(self, 'Starting logging: OK') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/version.py b/tests/functional/test_version.py index c613956..3ab3b67 100644..100755 --- a/tests/avocado/version.py +++ b/tests/functional/test_version.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # Version check example test # # Copyright (c) 2018 Red Hat, Inc. @@ -9,17 +11,18 @@ # later. See the COPYING file in the top-level directory. -from avocado_qemu import QemuSystemTest +from qemu_test import QemuSystemTest class Version(QemuSystemTest): - """ - :avocado: tags=quick - :avocado: tags=machine:none - """ + def test_qmp_human_info_version(self): + self.set_machine('none') self.vm.add_args('-nodefaults') self.vm.launch() res = self.vm.cmd('human-monitor-command', command_line='info version') self.assertRegex(res, r'^(\d+\.\d+\.\d)') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/virtio-gpu.py b/tests/functional/test_virtio_gpu.py index 6091f61..441cbdc 100644..100755 --- a/tests/avocado/virtio-gpu.py +++ b/tests/functional/test_virtio_gpu.py @@ -1,14 +1,16 @@ +#!/usr/bin/env python3 +# # virtio-gpu tests # # 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 import BUILD_DIR -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern -from avocado_qemu import exec_command_and_wait_for_pattern -from avocado_qemu import is_readable_executable_file +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 @@ -28,25 +30,18 @@ def pick_default_vug_bin(): class VirtioGPUx86(QemuSystemTest): - """ - :avocado: tags=virtio-gpu - :avocado: tags=arch:x86_64 - :avocado: tags=cpu:host - """ KERNEL_COMMAND_LINE = "printk.time=0 console=ttyS0 rdinit=/bin/bash" - KERNEL_URL = ( - "https://archives.fedoraproject.org/pub/archive/fedora" - "/linux/releases/33/Everything/x86_64/os/images" - "/pxeboot/vmlinuz" - ) - KERNEL_HASH = '1433cfe3f2ffaa44de4ecfb57ec25dc2399cdecf' - INITRD_URL = ( - "https://archives.fedoraproject.org/pub/archive/fedora" - "/linux/releases/33/Everything/x86_64/os/images" - "/pxeboot/initrd.img" - ) - INITRD_HASH = 'c828d68a027b53e5220536585efe03412332c2d9' + ASSET_KERNEL = Asset( + ("https://archives.fedoraproject.org/pub/archive/fedora" + "/linux/releases/33/Everything/x86_64/os/images" + "/pxeboot/vmlinuz"), + '2dc5fb5cfe9ac278fa45640f3602d9b7a08cc189ed63fd9b162b07073e4df397') + ASSET_INITRD = Asset( + ("https://archives.fedoraproject.org/pub/archive/fedora" + "/linux/releases/33/Everything/x86_64/os/images" + "/pxeboot/initrd.img"), + 'c49b97f893a5349e4883452178763e402bdc5caa8845b226a2d1329b5f356045') def wait_for_console_pattern(self, success_message, vm=None): wait_for_console_pattern( @@ -57,16 +52,14 @@ class VirtioGPUx86(QemuSystemTest): ) def test_virtio_vga_virgl(self): - """ - :avocado: tags=device:virtio-vga-gl - """ # FIXME: should check presence of virtio, virgl etc self.require_accelerator('kvm') - kernel_path = self.fetch_asset(self.KERNEL_URL, self.KERNEL_HASH) - initrd_path = self.fetch_asset(self.INITRD_URL, self.INITRD_HASH) + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() self.vm.set_console() + self.vm.add_args("-cpu", "host") self.vm.add_args("-m", "2G") self.vm.add_args("-machine", "pc,accel=kvm") self.vm.add_args("-device", "virtio-vga-gl") @@ -83,7 +76,7 @@ class VirtioGPUx86(QemuSystemTest): self.vm.launch() except: # TODO: probably fails because we are missing the VirGL features - self.cancel("VirGL not enabled?") + self.skipTest("VirGL not enabled?") self.wait_for_console_pattern("as init process") exec_command_and_wait_for_pattern( @@ -92,18 +85,15 @@ class VirtioGPUx86(QemuSystemTest): self.wait_for_console_pattern("features: +virgl +edid") def test_vhost_user_vga_virgl(self): - """ - :avocado: tags=device:vhost-user-vga - """ # FIXME: should check presence of vhost-user-gpu, virgl, memfd etc self.require_accelerator('kvm') vug = pick_default_vug_bin() if not vug: - self.cancel("Could not find vhost-user-gpu") + self.skipTest("Could not find vhost-user-gpu") - kernel_path = self.fetch_asset(self.KERNEL_URL, self.KERNEL_HASH) - initrd_path = self.fetch_asset(self.INITRD_URL, self.INITRD_HASH) + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() # Create socketpair to connect proxy and remote processes qemu_sock, vug_sock = socket.socketpair( @@ -129,6 +119,7 @@ class VirtioGPUx86(QemuSystemTest): ) self.vm.set_console() + self.vm.add_args("-cpu", "host") self.vm.add_args("-m", "2G") self.vm.add_args("-object", "memory-backend-memfd,id=mem,size=2G") self.vm.add_args("-machine", "pc,memory-backend=mem,accel=kvm") @@ -147,7 +138,7 @@ class VirtioGPUx86(QemuSystemTest): self.vm.launch() except: # TODO: probably fails because we are missing the VirGL features - self.cancel("VirGL not enabled?") + self.skipTest("VirGL not enabled?") self.wait_for_console_pattern("as init process") exec_command_and_wait_for_pattern(self, "/usr/sbin/modprobe virtio_gpu", "features: +virgl +edid") @@ -155,3 +146,6 @@ class VirtioGPUx86(QemuSystemTest): qemu_sock.close() vugp.terminate() vugp.wait() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/virtio_version.py b/tests/functional/test_virtio_version.py index afe5e82..eb23060 100644..100755 --- a/tests/avocado/virtio_version.py +++ b/tests/functional/test_virtio_version.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """ Check compatibility of virtio device types """ @@ -12,7 +13,7 @@ import sys import os from qemu.machine import QEMUMachine -from avocado_qemu import QemuSystemTest +from qemu_test import QemuSystemTest # Virtio Device IDs: VIRTIO_NET = 1 @@ -60,8 +61,6 @@ class VirtioVersionCheck(QemuSystemTest): Check if virtio-version-specific device types result in the same device tree created by `disable-modern` and `disable-legacy`. - - :avocado: tags=arch:x86_64 """ # just in case there are failures, show larger diff: @@ -173,3 +172,6 @@ class VirtioVersionCheck(QemuSystemTest): self.check_modern_only('virtio-mouse-pci', VIRTIO_INPUT) self.check_modern_only('virtio-tablet-pci', VIRTIO_INPUT) self.check_modern_only('virtio-keyboard-pci', VIRTIO_INPUT) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/x86_cpu_model_versions.py b/tests/functional/test_x86_cpu_model_versions.py index 11101e0..bd18acd 100644..100755 --- a/tests/avocado/x86_cpu_model_versions.py +++ b/tests/functional/test_x86_cpu_model_versions.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # # Basic validation of x86 versioned CPU models and CPU model aliases # @@ -20,15 +21,13 @@ # License along with this library; if not, see <http://www.gnu.org/licenses/>. # - -import avocado_qemu import re -class X86CPUModelAliases(avocado_qemu.QemuSystemTest): +from qemu_test import QemuSystemTest + +class X86CPUModelAliases(QemuSystemTest): """ Validation of PC CPU model versions and CPU model aliases - - :avocado: tags=arch:x86_64 """ def validate_aliases(self, cpus): for c in cpus.values(): @@ -76,9 +75,8 @@ class X86CPUModelAliases(avocado_qemu.QemuSystemTest): def test_4_0_alias_compatibility(self): """ Check if pc-*-4.0 unversioned CPU model won't be reported as aliases - - :avocado: tags=machine:pc-i440fx-4.0 """ + self.set_machine('pc-i440fx-4.0') # pc-*-4.0 won't expose non-versioned CPU models as aliases # We do this to help management software to keep compatibility # with older QEMU versions that didn't have the versioned CPU model @@ -110,9 +108,8 @@ class X86CPUModelAliases(avocado_qemu.QemuSystemTest): def test_4_1_alias(self): """ Check if unversioned CPU model is an alias pointing to right version - - :avocado: tags=machine:pc-i440fx-4.1 """ + self.set_machine('pc-i440fx-4.1') self.vm.add_args('-S') self.vm.launch() @@ -217,9 +214,8 @@ class X86CPUModelAliases(avocado_qemu.QemuSystemTest): def test_none_alias(self): """ Check if unversioned CPU model is an alias pointing to some version - - :avocado: tags=machine:none """ + self.set_machine('none') self.vm.add_args('-S') self.vm.launch() @@ -243,21 +239,16 @@ class X86CPUModelAliases(avocado_qemu.QemuSystemTest): self.validate_aliases(cpus) -class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): +class CascadelakeArchCapabilities(QemuSystemTest): """ Validation of Cascadelake arch-capabilities - - :avocado: tags=arch:x86_64 """ def get_cpu_prop(self, prop): cpu_path = self.vm.cmd('query-cpus-fast')[0].get('qom-path') return self.vm.cmd('qom-get', path=cpu_path, property=prop) def test_4_1(self): - """ - :avocado: tags=machine:pc-i440fx-4.1 - :avocado: tags=cpu:Cascadelake-Server - """ + self.set_machine('pc-i440fx-4.1') # machine-type only: self.vm.add_args('-S') self.set_vm_arg('-cpu', @@ -268,10 +259,7 @@ class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): 'pc-i440fx-4.1 + Cascadelake-Server should not have arch-capabilities') def test_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ + self.set_machine('pc-i440fx-4.0') self.vm.add_args('-S') self.set_vm_arg('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,' @@ -281,10 +269,7 @@ class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): 'pc-i440fx-4.0 + Cascadelake-Server should not have arch-capabilities') def test_set_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ + self.set_machine('pc-i440fx-4.0') # command line must override machine-type if CPU model is not versioned: self.vm.add_args('-S') self.set_vm_arg('-cpu', @@ -295,10 +280,7 @@ class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): 'pc-i440fx-4.0 + Cascadelake-Server,+arch-capabilities should have arch-capabilities') def test_unset_4_1(self): - """ - :avocado: tags=machine:pc-i440fx-4.1 - :avocado: tags=cpu:Cascadelake-Server - """ + self.set_machine('pc-i440fx-4.1') self.vm.add_args('-S') self.set_vm_arg('-cpu', 'Cascadelake-Server,x-force-features=on,check=off,' @@ -308,10 +290,7 @@ class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): 'pc-i440fx-4.1 + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') def test_v1_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ + self.set_machine('pc-i440fx-4.0') # versioned CPU model overrides machine-type: self.vm.add_args('-S') self.set_vm_arg('-cpu', @@ -322,10 +301,7 @@ class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not have arch-capabilities') def test_v2_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ + self.set_machine('pc-i440fx-4.0') self.vm.add_args('-S') self.set_vm_arg('-cpu', 'Cascadelake-Server-v2,x-force-features=on,check=off,' @@ -335,10 +311,7 @@ class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have arch-capabilities') def test_v1_set_4_0(self): - """ - :avocado: tags=machine:pc-i440fx-4.0 - :avocado: tags=cpu:Cascadelake-Server - """ + self.set_machine('pc-i440fx-4.0') # command line must override machine-type and versioned CPU model: self.vm.add_args('-S') self.set_vm_arg('-cpu', @@ -349,10 +322,7 @@ class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): 'pc-i440fx-4.0 + Cascadelake-Server-v1,+arch-capabilities should have arch-capabilities') def test_v2_unset_4_1(self): - """ - :avocado: tags=machine:pc-i440fx-4.1 - :avocado: tags=cpu:Cascadelake-Server - """ + self.set_machine('pc-i440fx-4.1') self.vm.add_args('-S') self.set_vm_arg('-cpu', 'Cascadelake-Server-v2,x-force-features=on,check=off,' @@ -360,3 +330,6 @@ class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): self.vm.launch() self.assertFalse(self.get_cpu_prop('arch-capabilities'), 'pc-i440fx-4.1 + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/meson.build b/tests/meson.build index 80dd302..907a4c1 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -85,3 +85,4 @@ subdir('unit') subdir('qapi-schema') subdir('qtest') subdir('migration') +subdir('functional') |