diff options
Diffstat (limited to 'tests')
22 files changed, 194 insertions, 28 deletions
diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 96d2828..0f8be30 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -26,7 +26,7 @@ test_timeouts = { 'arm_aspeed_witherspoon' : 120, 'arm_aspeed_ast2500' : 720, 'arm_aspeed_ast2600' : 1200, - 'arm_aspeed_bletchley' : 120, + 'arm_aspeed_bletchley' : 480, 'arm_aspeed_rainier' : 480, 'arm_bpim2u' : 500, 'arm_collie' : 180, diff --git a/tests/functional/qemu_test/__init__.py b/tests/functional/qemu_test/__init__.py index 45f7bef..af41c2c 100644 --- a/tests/functional/qemu_test/__init__.py +++ b/tests/functional/qemu_test/__init__.py @@ -15,6 +15,6 @@ from .testcase import QemuBaseTest, QemuUserTest, QemuSystemTest from .linuxkernel import LinuxKernelTest from .decorators import skipIfMissingCommands, skipIfNotMachine, \ skipFlakyTest, skipUntrustedTest, skipBigDataTest, skipSlowTest, \ - skipIfMissingImports + skipIfMissingImports, skipIfOperatingSystem from .archive import archive_extract from .uncompress import uncompress diff --git a/tests/functional/qemu_test/decorators.py b/tests/functional/qemu_test/decorators.py index 1651eb7..50d29de 100644 --- a/tests/functional/qemu_test/decorators.py +++ b/tests/functional/qemu_test/decorators.py @@ -5,7 +5,7 @@ import importlib import os import platform -from unittest import skipUnless +from unittest import skipIf, skipUnless from .cmd import which @@ -28,6 +28,19 @@ def skipIfMissingCommands(*args): ''' Decorator to skip execution of a test if the current +host operating system does match one of the prohibited +ones. +Example + + @skipIfOperatingSystem("Linux", "Darwin") +''' +def skipIfOperatingSystem(*args): + return skipIf(platform.system() in args, + 'running on an OS (%s) that is not able to run this test' % + ", ".join(args)) + +''' +Decorator to skip execution of a test if the current host machine does not match one of the permitted machines. Example diff --git a/tests/functional/test_aarch64_replay.py b/tests/functional/test_aarch64_replay.py index 04cde43..029fef3 100755 --- a/tests/functional/test_aarch64_replay.py +++ b/tests/functional/test_aarch64_replay.py @@ -5,7 +5,7 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from qemu_test import Asset +from qemu_test import Asset, skipIfOperatingSystem from replay_kernel import ReplayKernelBase @@ -16,6 +16,8 @@ class Aarch64Replay(ReplayKernelBase): 'releases/29/Everything/aarch64/os/images/pxeboot/vmlinuz'), '7e1430b81c26bdd0da025eeb8fbd77b5dc961da4364af26e771bd39f379cbbf7') + # Failing on Darwin: https://gitlab.com/qemu-project/qemu/-/issues/2907 + @skipIfOperatingSystem('Darwin') def test_aarch64_virt(self): self.set_machine('virt') self.cpu = 'cortex-a53' diff --git a/tests/functional/test_aarch64_rme_sbsaref.py b/tests/functional/test_aarch64_rme_sbsaref.py index ddcc949..0f4f610 100755 --- a/tests/functional/test_aarch64_rme_sbsaref.py +++ b/tests/functional/test_aarch64_rme_sbsaref.py @@ -33,6 +33,7 @@ class Aarch64RMESbsaRefMachine(QemuSystemTest): def test_aarch64_rme_sbsaref(self): self.set_machine('sbsa-ref') self.require_accelerator('tcg') + self.require_netdev('user') self.vm.set_console() diff --git a/tests/functional/test_aarch64_rme_virt.py b/tests/functional/test_aarch64_rme_virt.py index 38e0172..a1abf58 100755 --- a/tests/functional/test_aarch64_rme_virt.py +++ b/tests/functional/test_aarch64_rme_virt.py @@ -60,8 +60,10 @@ class Aarch64RMEVirtMachine(QemuSystemTest): # and launching a nested VM using it. def test_aarch64_rme_virt(self): self.set_machine('virt') - self.vm.set_console() self.require_accelerator('tcg') + self.require_netdev('user') + + self.vm.set_console() stack_path_tar_gz = self.ASSET_RME_STACK_VIRT.fetch() self.archive_extract(stack_path_tar_gz, format="tar") @@ -85,7 +87,9 @@ class Aarch64RMEVirtMachine(QemuSystemTest): self.vm.add_args('-fsdev', f'local,security_model=none,path={rme_stack},id=shr0') self.vm.add_args('-device', 'virtio-net-pci,netdev=net0') self.vm.add_args('-netdev', 'user,id=net0') - self.vm.add_args('-append', 'root=/dev/vda') + # We need to add nokaslr to avoid triggering this sporadic bug: + # https://gitlab.com/qemu-project/qemu/-/issues/2823 + self.vm.add_args('-append', 'root=/dev/vda nokaslr') self.vm.launch() # Wait for host VM boot to complete. diff --git a/tests/functional/test_aarch64_virt_gpu.py b/tests/functional/test_aarch64_virt_gpu.py index 314d994..3844727 100755 --- a/tests/functional/test_aarch64_virt_gpu.py +++ b/tests/functional/test_aarch64_virt_gpu.py @@ -74,6 +74,8 @@ class Aarch64VirtGPUMachine(LinuxKernelTest): self.skipTest("Can't access host DRM render node") elif "'type' does not accept value 'egl-headless'" in excp.output: self.skipTest("egl-headless support is not available") + elif "'type' does not accept value 'dbus'" in excp.output: + self.skipTest("dbus display support is not available") else: self.log.info("unhandled launch failure: %s", excp.output) raise excp diff --git a/tests/functional/test_arm_bpim2u.py b/tests/functional/test_arm_bpim2u.py index 12cd359..8de6ccb 100755 --- a/tests/functional/test_arm_bpim2u.py +++ b/tests/functional/test_arm_bpim2u.py @@ -140,6 +140,8 @@ class BananaPiMachine(LinuxKernelTest): @skipBigDataTest() def test_arm_bpim2u_openwrt_22_03_3(self): self.set_machine('bpim2u') + self.require_netdev('user') + # This test download a 8.9 MiB compressed image and expand it # to 127 MiB. image_path = self.uncompress(self.ASSET_SD_IMAGE) diff --git a/tests/functional/test_arm_cubieboard.py b/tests/functional/test_arm_cubieboard.py index 423db71..b87a281 100755 --- a/tests/functional/test_arm_cubieboard.py +++ b/tests/functional/test_arm_cubieboard.py @@ -107,6 +107,8 @@ class CubieboardMachine(LinuxKernelTest): # This test download a 7.5 MiB compressed image and expand it # to 126 MiB. self.set_machine('cubieboard') + self.require_netdev('user') + image_path = self.uncompress(self.ASSET_OPENWRT) image_pow2ceil_expand(image_path) diff --git a/tests/functional/test_arm_orangepi.py b/tests/functional/test_arm_orangepi.py index 2891939..1815f56 100755 --- a/tests/functional/test_arm_orangepi.py +++ b/tests/functional/test_arm_orangepi.py @@ -147,6 +147,8 @@ class OrangePiMachine(LinuxKernelTest): @skipBigDataTest() def test_arm_orangepi_armbian(self): self.set_machine('orangepi-pc') + self.require_netdev('user') + # This test download a 275 MiB compressed image and expand it # to 1036 MiB, but the underlying filesystem is 1552 MiB... # As we expand it to 2 GiB we are safe. @@ -181,6 +183,8 @@ class OrangePiMachine(LinuxKernelTest): @skipBigDataTest() def test_arm_orangepi_uboot_netbsd9(self): self.set_machine('orangepi-pc') + self.require_netdev('user') + # This test download a 304MB compressed image and expand it to 2GB # We use the common OrangePi PC 'plus' build of U-Boot for our secondary # program loader (SPL). We will then set the path to the more specific diff --git a/tests/functional/test_ppc64_hv.py b/tests/functional/test_ppc64_hv.py index 62f996a..1920e91 100755 --- a/tests/functional/test_ppc64_hv.py +++ b/tests/functional/test_ppc64_hv.py @@ -125,6 +125,7 @@ class HypervisorTest(QemuSystemTest): def test_hv_pseries(self): self.require_accelerator("tcg") + self.require_netdev('user') self.set_machine('pseries') self.vm.add_args("-accel", "tcg,thread=multi") self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') @@ -136,6 +137,7 @@ class HypervisorTest(QemuSystemTest): def test_hv_pseries_kvm(self): self.require_accelerator("kvm") + self.require_netdev('user') self.set_machine('pseries') self.vm.add_args("-accel", "kvm") self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') @@ -147,6 +149,7 @@ class HypervisorTest(QemuSystemTest): def test_hv_powernv(self): self.require_accelerator("tcg") + self.require_netdev('user') 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', diff --git a/tests/functional/test_ppc64_replay.py b/tests/functional/test_ppc64_replay.py index 48ce1b7..e8c9c4b 100755 --- a/tests/functional/test_ppc64_replay.py +++ b/tests/functional/test_ppc64_replay.py @@ -5,7 +5,7 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from qemu_test import Asset +from qemu_test import Asset, skipFlakyTest from replay_kernel import ReplayKernelBase @@ -16,6 +16,7 @@ class Ppc64Replay(ReplayKernelBase): 'day19.tar.xz'), '20b1bb5a8488c664defbb5d283addc91a05335a936c63b3f5ff7eee74b725755') + @skipFlakyTest('https://gitlab.com/qemu-project/qemu/-/issues/2523') def test_ppc64_e500(self): self.set_machine('ppce500') self.cpu = 'e5500' diff --git a/tests/functional/test_vnc.py b/tests/functional/test_vnc.py index 1916be0..8c9953b 100755 --- a/tests/functional/test_vnc.py +++ b/tests/functional/test_vnc.py @@ -12,6 +12,7 @@ import socket from typing import List +from qemu.machine.machine import VMLaunchFailure from qemu_test import QemuSystemTest from qemu_test.ports import Ports @@ -32,7 +33,14 @@ class Vnc(QemuSystemTest): def test_no_vnc_change_password(self): self.vm.add_args('-nodefaults', '-S') self.vm.launch() - self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled']) + + query_vnc_response = self.vm.qmp('query-vnc') + if 'error' in query_vnc_response: + self.assertEqual(query_vnc_response['error']['class'], + 'CommandNotFound') + self.skipTest('VNC support not available') + self.assertFalse(query_vnc_response['return']['enabled']) + set_password_response = self.vm.qmp('change-vnc-password', password='new_password') self.assertIn('error', set_password_response) @@ -41,9 +49,19 @@ class Vnc(QemuSystemTest): self.assertEqual(set_password_response['error']['desc'], 'Could not set password') + def launch_guarded(self): + try: + self.vm.launch() + except VMLaunchFailure as excp: + if "-vnc: invalid option" in excp.output: + self.skipTest("VNC support not available") + else: + self.log.info("unhandled launch failure: %s", excp.output) + raise excp + def test_change_password_requires_a_password(self): self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999') - self.vm.launch() + self.launch_guarded() self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) set_password_response = self.vm.qmp('change-vnc-password', password='new_password') @@ -55,7 +73,7 @@ class Vnc(QemuSystemTest): def test_change_password(self): self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999,password=on') - self.vm.launch() + self.launch_guarded() self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) self.vm.cmd('change-vnc-password', password='new_password') @@ -66,7 +84,7 @@ class Vnc(QemuSystemTest): self.assertFalse(check_connect(c)) self.vm.add_args('-nodefaults', '-S', '-vnc', f'{VNC_ADDR}:{a - 5900}') - self.vm.launch() + self.launch_guarded() self.assertEqual(self.vm.qmp('query-vnc')['return']['service'], str(a)) self.assertTrue(check_connect(a)) self.assertFalse(check_connect(b)) diff --git a/tests/functional/test_x86_64_kvm_xen.py b/tests/functional/test_x86_64_kvm_xen.py index 3bedef6..c6abf6b 100755 --- a/tests/functional/test_x86_64_kvm_xen.py +++ b/tests/functional/test_x86_64_kvm_xen.py @@ -41,6 +41,7 @@ class KVMXenGuest(QemuSystemTest): def common_vm_setup(self): # We also catch lack of KVM_XEN support if we fail to launch self.require_accelerator("kvm") + self.require_netdev('user') self.vm.set_console() diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json index 0a4f139..14b808f 100644 --- a/tests/qapi-schema/doc-good.json +++ b/tests/qapi-schema/doc-good.json @@ -212,7 +212,7 @@ # # -> "this example" # -# <- "has no title" +# <- ... has no title ... ## { 'command': 'cmd-boxed', 'boxed': true, 'data': 'Object', diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 5773f1d..dc8352e 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -217,7 +217,7 @@ another feature -> "this example" - <- "has no title" + <- ... has no title ... doc symbol=EVT_BOXED body= diff --git a/tests/qapi-schema/doc-good.txt b/tests/qapi-schema/doc-good.txt index cb37db6..17a1d56 100644 --- a/tests/qapi-schema/doc-good.txt +++ b/tests/qapi-schema/doc-good.txt @@ -264,7 +264,7 @@ Example:: -> "this example" - <- "has no title" + <- ... has no title ... "EVT_BOXED" (Event) diff --git a/tests/qemu-iotests/162 b/tests/qemu-iotests/162 index 956c2c5..94dae60 100755 --- a/tests/qemu-iotests/162 +++ b/tests/qemu-iotests/162 @@ -65,7 +65,6 @@ done $QEMU_IMG info "json:{'driver': 'nbd', 'host': 'localhost', 'port': $port}" \ | grep '^image' | sed -e "s/$port/PORT/" -_stop_nbd_server # This is a test for NBD's bdrv_refresh_filename() implementation: It expects # either host or path to be set, but it must not assume that they are set to diff --git a/tests/qemu-iotests/tests/qcow2-encryption b/tests/qemu-iotests/tests/qcow2-encryption new file mode 100755 index 0000000..95f6195 --- /dev/null +++ b/tests/qemu-iotests/tests/qcow2-encryption @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +# group: rw quick +# +# Test case for encryption support in qcow2 +# +# Copyright (C) 2025 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=kwolf@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ../common.rc +. ../common.filter + +# This tests qcow2-specific low-level functionality +_supported_fmt qcow2 +_supported_proto file +_require_working_luks + +IMG_SIZE=64M + +echo +echo "=== Create an encrypted image ===" +echo + +_make_test_img --object secret,id=sec0,data=123456 -o encrypt.format=luks,encrypt.key-secret=sec0 $IMG_SIZE +$PYTHON ../qcow2.py "$TEST_IMG" dump-header-exts +_img_info +$QEMU_IMG check \ + --object secret,id=sec0,data=123456 \ + --image-opts file.filename="$TEST_IMG",encrypt.key-secret=sec0 \ + | _filter_qemu_img_check + +echo +echo "=== Remove the header extension ===" +echo + +$PYTHON ../qcow2.py "$TEST_IMG" del-header-ext 0x0537be77 +$PYTHON ../qcow2.py "$TEST_IMG" dump-header-exts +_img_info +$QEMU_IMG check \ + --object secret,id=sec0,data=123456 \ + --image-opts file.filename="$TEST_IMG",encrypt.key-secret=sec0 2>&1 \ + | _filter_qemu_img_check \ + | _filter_testdir + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/tests/qcow2-encryption.out b/tests/qemu-iotests/tests/qcow2-encryption.out new file mode 100644 index 0000000..9b549dc2 --- /dev/null +++ b/tests/qemu-iotests/tests/qcow2-encryption.out @@ -0,0 +1,32 @@ +QA output created by qcow2-encryption + +=== Create an encrypted image === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Header extension: +magic 0x537be77 (Crypto header) +length 16 +data <binary> + +Header extension: +magic 0x6803f857 (Feature table) +length 384 +data <binary> + +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 64 MiB (67108864 bytes) +encrypted: yes +cluster_size: 65536 +No errors were found on the image. + +=== Remove the header extension === + +Header extension: +magic 0x6803f857 (Feature table) +length 384 +data <binary> + +qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Missing CRYPTO header for crypt method 2 +qemu-img: Could not open 'file.filename=TEST_DIR/t.qcow2,encrypt.key-secret=sec0': Missing CRYPTO header for crypt method 2 +*** done diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 2750067..fad307d 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -1788,6 +1788,7 @@ void qtest_cb_for_every_machine(void (*cb)(const char *machine), if (!strncmp("xenfv", machines[i].name, 5) || g_str_equal("xenpv", machines[i].name) || g_str_equal("xenpvh", machines[i].name) || + g_str_equal("vmapple", machines[i].name) || g_str_equal("nitro-enclave", machines[i].name)) { continue; } diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c index 7410e6f..290cd2a 100644 --- a/tests/unit/test-bdrv-drain.c +++ b/tests/unit/test-bdrv-drain.c @@ -632,6 +632,8 @@ typedef struct TestBlockJob { BlockDriverState *bs; int run_ret; int prepare_ret; + + /* Accessed with atomics */ bool running; bool should_complete; } TestBlockJob; @@ -667,10 +669,10 @@ static int coroutine_fn test_job_run(Job *job, Error **errp) /* We are running the actual job code past the pause point in * job_co_entry(). */ - s->running = true; + qatomic_set(&s->running, true); job_transition_to_ready(&s->common.job); - while (!s->should_complete) { + while (!qatomic_read(&s->should_complete)) { /* Avoid job_sleep_ns() because it marks the job as !busy. We want to * emulate some actual activity (probably some I/O) here so that drain * has to wait for this activity to stop. */ @@ -685,7 +687,7 @@ static int coroutine_fn test_job_run(Job *job, Error **errp) static void test_job_complete(Job *job, Error **errp) { TestBlockJob *s = container_of(job, TestBlockJob, common.job); - s->should_complete = true; + qatomic_set(&s->should_complete, true); } BlockJobDriver test_job_driver = { @@ -791,7 +793,7 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, /* job_co_entry() is run in the I/O thread, wait for the actual job * code to start (we don't want to catch the job in the pause point in * job_co_entry(). */ - while (!tjob->running) { + while (!qatomic_read(&tjob->running)) { aio_poll(qemu_get_aio_context(), false); } } @@ -799,7 +801,7 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, WITH_JOB_LOCK_GUARD() { g_assert_cmpint(job->job.pause_count, ==, 0); g_assert_false(job->job.paused); - g_assert_true(tjob->running); + g_assert_true(qatomic_read(&tjob->running)); g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */ } @@ -825,7 +827,7 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, * * paused is reset in the I/O thread, wait for it */ - while (job->job.paused) { + while (job_is_paused(&job->job)) { aio_poll(qemu_get_aio_context(), false); } } @@ -858,7 +860,7 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, * * paused is reset in the I/O thread, wait for it */ - while (job->job.paused) { + while (job_is_paused(&job->job)) { aio_poll(qemu_get_aio_context(), false); } } @@ -1411,10 +1413,12 @@ static void test_set_aio_context(void) typedef struct TestDropBackingBlockJob { BlockJob common; - bool should_complete; bool *did_complete; BlockDriverState *detach_also; BlockDriverState *bs; + + /* Accessed with atomics */ + bool should_complete; } TestDropBackingBlockJob; static int coroutine_fn test_drop_backing_job_run(Job *job, Error **errp) @@ -1422,7 +1426,7 @@ static int coroutine_fn test_drop_backing_job_run(Job *job, Error **errp) TestDropBackingBlockJob *s = container_of(job, TestDropBackingBlockJob, common.job); - while (!s->should_complete) { + while (!qatomic_read(&s->should_complete)) { job_sleep_ns(job, 0); } @@ -1541,7 +1545,7 @@ static void test_blockjob_commit_by_drained_end(void) job_start(&job->common.job); - job->should_complete = true; + qatomic_set(&job->should_complete, true); bdrv_drained_begin(bs_child); g_assert(!job_has_completed); bdrv_drained_end(bs_child); @@ -1557,15 +1561,17 @@ static void test_blockjob_commit_by_drained_end(void) typedef struct TestSimpleBlockJob { BlockJob common; - bool should_complete; bool *did_complete; + + /* Accessed with atomics */ + bool should_complete; } TestSimpleBlockJob; static int coroutine_fn test_simple_job_run(Job *job, Error **errp) { TestSimpleBlockJob *s = container_of(job, TestSimpleBlockJob, common.job); - while (!s->should_complete) { + while (!qatomic_read(&s->should_complete)) { job_sleep_ns(job, 0); } @@ -1700,7 +1706,7 @@ static void test_drop_intermediate_poll(void) job->did_complete = &job_has_completed; job_start(&job->common.job); - job->should_complete = true; + qatomic_set(&job->should_complete, true); g_assert(!job_has_completed); ret = bdrv_drop_intermediate(chain[1], chain[0], NULL, false); |