diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2025-09-11 12:41:01 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2025-09-11 12:41:01 +0100 |
commit | 190d5d7fd725ff754f94e8e0cbfb69f279c82b5d (patch) | |
tree | 9d75601a06184de2745c6a137a203689f8e1f6df | |
parent | 7aba16fdd88a742b3886c3bcdb9b4057c9d9658e (diff) | |
parent | 2fc170bcdc4d2f05534c68572b4f72a7d18c2119 (diff) | |
download | qemu-master.zip qemu-master.tar.gz qemu-master.tar.bz2 |
* Silence warnings from the undefined-behaviour sanitizer
* Many small improvements to various functional tests
* Remove remainders from storing avocado artifacts in the Gitlab CI
* Keep more meson log files as artifacts in the Gitlab CI instead
* Re-enable -fzero-call-used-regs on OpenBSD
# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCgAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmjAMK4RHHRodXRoQHJl
# ZGhhdC5jb20ACgkQLtnXdP5wLbX4ohAAl3AomPjCeCUEbwJqD0I8eSUeKKDNGbbI
# pwyEjg+e1nptqT7RVeS2EMKUAGT5dasZqjoMRMNS+PywCzDjkKPIjAZdatPMKMx2
# YK56qVaMcUKSDdpb/P091Bn8LLBX8kx8J0TpiRCvGH5KsflamMW7sVrAdn9X2lrM
# yTFN65asbbgfRWDW8qzXxX7JHdQZ1xwJiWSiJicTHzLRSoA4Ud6ymQxJyESgDUGs
# 44j1ieCrA7itbcUSIzYmEbcw0BgjaXSOUMXkUyZZ4GtQA7q5IVi+6iJm/3lbKEvA
# Wu3zPk1FeK6iyVGSn/fcaQfGEjTUI7zbOLN0Ub1ob9N3jO5z7EdUe7DjY2BF6L8y
# 4KYjWOcCWYL5BGNdi6ilaIk8l5sB1Vw/wIONdgqtcBJs0syiSzGqLmVttHIQlmI3
# 4tADDnINAUYi7T7q2/0F9VZB89TY7W7zAYrypTMzTIbGwEHgBj+4kq5DsplTfkg4
# LG+Vplv04NAmdgPndCj/AQ9y9ZtFjmZwuF0drLOSXFGzzfTv0g5YT3HQBbQ3gHsM
# tjeU5RSwHjr3OfvNWE1U/CIbu0Qa3CJcnco8JP5NIGCw8I0lHOnqsVq/1EC6PnGM
# 3QYvSd/z4jMO+5pXlMUQ52Lc7IRVTL8SVJf723gPV9TcV/EwLYtlv2s41GVqPwLM
# e+KxAirDD9c=
# =fJQL
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 09 Sep 2025 14:50:38 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>" [undefined]
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3 EAB9 2ED9 D774 FE70 2DB5
* tag 'pull-request-2025-09-09' of https://gitlab.com/thuth/qemu: (23 commits)
tests/functional: purge scratch dir on test startup
tests/functional: avoid tearDown failure when QEMU dies
tests/functional: avoid duplicate messages on failures
tests/functional: fix infinite loop on console EOF
tests/functional: add vm param to cmd.py helpers
tests/functional: return output from cmd.py helpers
gitlab: prevent duplicated meson log artifacts in test jobs
gitlab: include all junit XML files from meson
gitlab: always include entire of meson-logs directory
gitlab: replace avocado results files with meson results files
tests/functional/arm: Update test ASPEED SDK v09.07 for AST2700 vbootrom
tests/functional/arm: Update test ASPEED SDK v09.07 for AST2600
tests/functional/arm: Update test ASPEED SDK v09.07 for AST2500
tests/functional/arm: Update test ASPEED SDK v03.02 for AST1030
tests/functional: handle URLError when fetching assets
tests/functional: fix formatting of exception args
tests/functional: enable force refresh of cached assets
tests/functional/m68k: Avoid ResourceWarning in the nextcube test
ui/vnc: Fix crash when specifying [vnc] without id in the config file
system/physmem: Silence warning from ubsan
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | .gitlab-ci.d/buildtest-template.yml | 16 | ||||
-rw-r--r-- | .gitlab-ci.d/buildtest.yml | 4 | ||||
-rw-r--r-- | .gitlab-ci.d/crossbuild-template.yml | 4 | ||||
-rw-r--r-- | .gitlab-ci.d/custom-runners.yml | 2 | ||||
-rw-r--r-- | .gitlab-ci.d/windows.yml | 4 | ||||
-rw-r--r-- | docs/devel/testing/functional.rst | 3 | ||||
-rw-r--r-- | hw/display/bcm2835_fb.c | 1 | ||||
-rw-r--r-- | hw/mips/malta.c | 2 | ||||
-rw-r--r-- | include/hw/display/bcm2835_fb.h | 1 | ||||
-rw-r--r-- | meson.build | 6 | ||||
-rw-r--r-- | system/physmem.c | 4 | ||||
-rwxr-xr-x | tests/functional/aarch64/test_aspeed_ast2700.py | 8 | ||||
-rwxr-xr-x | tests/functional/arm/test_aspeed_ast1030.py | 12 | ||||
-rwxr-xr-x | tests/functional/arm/test_aspeed_ast2500.py | 8 | ||||
-rwxr-xr-x | tests/functional/arm/test_aspeed_ast2600.py | 8 | ||||
-rwxr-xr-x | tests/functional/m68k/test_nextcube.py | 3 | ||||
-rw-r--r-- | tests/functional/qemu_test/asset.py | 16 | ||||
-rw-r--r-- | tests/functional/qemu_test/cmd.py | 67 | ||||
-rw-r--r-- | tests/functional/qemu_test/testcase.py | 14 | ||||
-rw-r--r-- | ui/vnc.c | 18 |
20 files changed, 137 insertions, 64 deletions
diff --git a/.gitlab-ci.d/buildtest-template.yml b/.gitlab-ci.d/buildtest-template.yml index 038c3c9..d866cb1 100644 --- a/.gitlab-ci.d/buildtest-template.yml +++ b/.gitlab-ci.d/buildtest-template.yml @@ -83,14 +83,18 @@ .native_test_job_template: extends: .common_test_job_template + before_script: + # Prevent logs from the build job that run earlier + # from being duplicated in the test job artifacts + - rm -f build/meson-logs/* artifacts: name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" when: always expire_in: 7 days paths: - - build/meson-logs/testlog.txt + - build/meson-logs reports: - junit: build/meson-logs/testlog.junit.xml + junit: build/meson-logs/*.junit.xml .functional_test_job_template: extends: .common_test_job_template @@ -104,14 +108,16 @@ when: always expire_in: 7 days paths: - - build/tests/results/latest/results.xml - - build/tests/results/latest/test-results + - build/meson-logs - build/tests/functional/*/*/*.log reports: - junit: build/tests/results/latest/results.xml + junit: build/meson-logs/*.junit.xml before_script: - export QEMU_TEST_ALLOW_UNTRUSTED_CODE=1 - export QEMU_TEST_CACHE_DIR=${CI_PROJECT_DIR}/functional-cache + # Prevent logs from the build job that run earlier + # from being duplicated in the test job artifacts + - rm -f build/meson-logs/* after_script: - cd build - du -chs ${CI_PROJECT_DIR}/*-cache diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index d888a60..83c2867 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -613,9 +613,9 @@ gcov: when: always expire_in: 2 days paths: - - build/meson-logs/testlog.txt + - build/meson-logs reports: - junit: build/meson-logs/testlog.junit.xml + junit: build/meson-logs/*.junit.xml coverage_report: coverage_format: cobertura path: build/coverage.xml diff --git a/.gitlab-ci.d/crossbuild-template.yml b/.gitlab-ci.d/crossbuild-template.yml index 303943f..58136d0 100644 --- a/.gitlab-ci.d/crossbuild-template.yml +++ b/.gitlab-ci.d/crossbuild-template.yml @@ -128,6 +128,6 @@ when: always expire_in: 7 days paths: - - build/meson-logs/testlog.txt + - build/meson-logs reports: - junit: build/meson-logs/testlog.junit.xml + junit: build/meson-logs/*.junit.xml diff --git a/.gitlab-ci.d/custom-runners.yml b/.gitlab-ci.d/custom-runners.yml index 1aa3c60..2d493f7 100644 --- a/.gitlab-ci.d/custom-runners.yml +++ b/.gitlab-ci.d/custom-runners.yml @@ -26,7 +26,7 @@ - build/build.ninja - build/meson-logs reports: - junit: build/meson-logs/testlog.junit.xml + junit: build/meson-logs/*.junit.xml include: - local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-s390x.yml' diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml index beac39e..1e6a01b 100644 --- a/.gitlab-ci.d/windows.yml +++ b/.gitlab-ci.d/windows.yml @@ -24,9 +24,9 @@ msys2-64bit: name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" expire_in: 7 days paths: - - build/meson-logs/testlog.txt + - build/meson-logs reports: - junit: "build/meson-logs/testlog.junit.xml" + junit: build/meson-logs/*.junit.xml before_script: - Write-Output "Acquiring msys2.exe installer at $(Get-Date -Format u)" - If ( !(Test-Path -Path msys64\var\cache ) ) { diff --git a/docs/devel/testing/functional.rst b/docs/devel/testing/functional.rst index 3728bab..fdeaeba 100644 --- a/docs/devel/testing/functional.rst +++ b/docs/devel/testing/functional.rst @@ -312,6 +312,9 @@ The cache is populated in the ``~/.cache/qemu/download`` directory by default, but the location can be changed by setting the ``QEMU_TEST_CACHE_DIR`` environment variable. +To force the test suite to re-download the cache, even if still valid, +set the ``QEMU_TEST_REFRESH_CACHE`` environment variable. + Skipping tests -------------- diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c index 820e67a..1bb2ee4 100644 --- a/hw/display/bcm2835_fb.c +++ b/hw/display/bcm2835_fb.c @@ -27,6 +27,7 @@ #include "hw/display/bcm2835_fb.h" #include "hw/hw.h" #include "hw/irq.h" +#include "ui/console.h" #include "framebuffer.h" #include "ui/pixel_ops.h" #include "hw/misc/bcm2835_mbox_defs.h" diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 344dc8c..02da629 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1191,7 +1191,7 @@ void mips_malta_init(MachineState *machine) * In little endian mode the 32bit words in the bios are swapped, * a neat trick which allows bi-endian firmware. */ - if (!TARGET_BIG_ENDIAN) { + if (!TARGET_BIG_ENDIAN && bios_size > 0) { uint32_t *end, *addr; const size_t swapsize = MIN(bios_size, 0x3e0000); addr = rom_ptr(FLASH_ADDRESS, swapsize); diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h index 49541bf..acc9230 100644 --- a/include/hw/display/bcm2835_fb.h +++ b/include/hw/display/bcm2835_fb.h @@ -13,7 +13,6 @@ #define BCM2835_FB_H #include "hw/sysbus.h" -#include "ui/console.h" #include "qom/object.h" #define UPPER_RAM_BASE 0x40000000 diff --git a/meson.build b/meson.build index fa6186d..3d73873 100644 --- a/meson.build +++ b/meson.build @@ -709,11 +709,7 @@ hardening_flags = [ # # NB: Clang 17 is broken and SEGVs # https://github.com/llvm/llvm-project/issues/75168 -# -# NB2: This clashes with the "retguard" extension of OpenBSD's Clang -# https://gitlab.com/qemu-project/qemu/-/issues/2278 -if host_os != 'openbsd' and \ - cc.compiles('extern struct { void (*cb)(void); } s; void f(void) { s.cb(); }', +if cc.compiles('extern struct { void (*cb)(void); } s; void f(void) { s.cb(); }', name: '-fzero-call-used-regs=used-gpr', args: ['-O2', '-fzero-call-used-regs=used-gpr']) hardening_flags += '-fzero-call-used-regs=used-gpr' diff --git a/system/physmem.c b/system/physmem.c index f498572..3110111 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -3231,8 +3231,10 @@ static inline MemTxResult address_space_write_rom_internal(AddressSpace *as, } } len -= l; - buf += l; addr += l; + if (buf) { + buf += l; + } } return MEMTX_OK; } diff --git a/tests/functional/aarch64/test_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py index d02dc79..8a08bc4 100755 --- a/tests/functional/aarch64/test_aspeed_ast2700.py +++ b/tests/functional/aarch64/test_aspeed_ast2700.py @@ -54,6 +54,10 @@ class AST2x00MachineSDK(QemuSystemTest): 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2700-default-obmc.tar.gz', 'f1d53e0be8a404ecce3e105f72bc50fa4e090ad13160ffa91b10a6e0233a9dc6') + ASSET_SDK_V907_AST2700A1_VBOOROM = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.07/ast2700-default-obmc.tar.gz', + '6e9e0c4b13e0f26040eca3f4a7f17cf09fc0f5c37c820500ff79370cc3c44add') + def do_ast2700_i2c_test(self): exec_command_and_wait_for_pattern(self, 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ', @@ -127,10 +131,10 @@ class AST2x00MachineSDK(QemuSystemTest): self.verify_openbmc_boot_and_login('ast2700-default') self.do_ast2700_i2c_test() - def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_06(self): + def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_07(self): self.set_machine('ast2700a1-evb') - self.archive_extract(self.ASSET_SDK_V906_AST2700A1) + self.archive_extract(self.ASSET_SDK_V907_AST2700A1_VBOOROM) self.start_ast2700_test_vbootrom('ast2700-default') self.verify_vbootrom_firmware_flow() self.verify_openbmc_boot_and_login('ast2700-default') diff --git a/tests/functional/arm/test_aspeed_ast1030.py b/tests/functional/arm/test_aspeed_ast1030.py index 77037f0..42126b5 100755 --- a/tests/functional/arm/test_aspeed_ast1030.py +++ b/tests/functional/arm/test_aspeed_ast1030.py @@ -12,17 +12,17 @@ from qemu_test import exec_command_and_wait_for_pattern class AST1030Machine(LinuxKernelTest): - ASSET_ZEPHYR_3_00 = Asset( + ASSET_ZEPHYR_3_02 = Asset( ('https://github.com/AspeedTech-BMC' - '/zephyr/releases/download/v00.03.00/ast1030-evb-demo.zip'), - '37fe3ecd4a1b9d620971a15b96492a81093435396eeac69b6f3e384262ff555f') + '/zephyr/releases/download/v00.03.02/ast1030-evb-demo.zip'), + '1ec83caab3ddd5d09481772801be7210e222cb015ce22ec6fffb8a76956dcd4f') - def test_ast1030_zephyros_3_00(self): + def test_ast1030_zephyros_3_02(self): self.set_machine('ast1030-evb') - kernel_name = "ast1030-evb-demo/zephyr.elf" + kernel_name = "ast1030-evb-demo-3/zephyr.elf" kernel_file = self.archive_extract( - self.ASSET_ZEPHYR_3_00, member=kernel_name) + self.ASSET_ZEPHYR_3_02, member=kernel_name) self.vm.set_console() self.vm.add_args('-kernel', kernel_file, '-nographic') diff --git a/tests/functional/arm/test_aspeed_ast2500.py b/tests/functional/arm/test_aspeed_ast2500.py index 6923fe8..4fdd81e 100755 --- a/tests/functional/arm/test_aspeed_ast2500.py +++ b/tests/functional/arm/test_aspeed_ast2500.py @@ -37,14 +37,14 @@ class AST2500Machine(AspeedTest): self.do_test_arm_aspeed_buildroot_poweroff() - ASSET_SDK_V906_AST2500 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2500-default-obmc.tar.gz', - '542db84645b4efd8aed50385d7f4dd1caff379a987032311cfa7b563a3addb2a') + ASSET_SDK_V907_AST2500 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.07/ast2500-default-obmc.tar.gz', + 'd52bcc279a37c8d7679b3e4ef22cc77c36f0f6624c687b37334f798828afb077') def test_arm_ast2500_evb_sdk(self): self.set_machine('ast2500-evb') - self.archive_extract(self.ASSET_SDK_V906_AST2500) + self.archive_extract(self.ASSET_SDK_V907_AST2500) self.do_test_arm_aspeed_sdk_start( self.scratch_file("ast2500-default", "image-bmc")) diff --git a/tests/functional/arm/test_aspeed_ast2600.py b/tests/functional/arm/test_aspeed_ast2600.py index fdae4c9..129695c 100755 --- a/tests/functional/arm/test_aspeed_ast2600.py +++ b/tests/functional/arm/test_aspeed_ast2600.py @@ -97,14 +97,14 @@ class AST2600Machine(AspeedTest): self.do_test_arm_aspeed_buildroot_poweroff() - ASSET_SDK_V906_AST2600 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2600-default-obmc.tar.gz', - '768d76e247896ad78c154b9cff4f766da2ce65f217d620b286a4a03a8a4f68f5') + ASSET_SDK_V907_AST2600 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.07/ast2600-default-obmc.tar.gz', + 'cb6c08595bcbba1672ce716b068ba4e48eda1ed9abe78a07b30392ba2278feba') def test_arm_ast2600_evb_sdk(self): self.set_machine('ast2600-evb') - self.archive_extract(self.ASSET_SDK_V906_AST2600) + self.archive_extract(self.ASSET_SDK_V907_AST2600) self.vm.add_args('-device', 'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test') diff --git a/tests/functional/m68k/test_nextcube.py b/tests/functional/m68k/test_nextcube.py index 13c72bd..c1610e5 100755 --- a/tests/functional/m68k/test_nextcube.py +++ b/tests/functional/m68k/test_nextcube.py @@ -44,7 +44,8 @@ class NextCubeMachine(QemuSystemTest): self.check_bootrom_framebuffer(screenshot_path) from PIL import Image - width, height = Image.open(screenshot_path).size + with Image.open(screenshot_path) as image: + width, height = image.size self.assertEqual(width, 1120) self.assertEqual(height, 832) diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py index 704b84d..2dd32bf 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -15,7 +15,7 @@ import urllib.request from time import sleep from pathlib import Path from shutil import copyfileobj -from urllib.error import HTTPError +from urllib.error import HTTPError, URLError class AssetError(Exception): def __init__(self, asset, msg, transient=False): @@ -72,6 +72,10 @@ class Asset: return self.hash == hl.hexdigest() def valid(self): + if os.getenv("QEMU_TEST_REFRESH_CACHE", None) is not None: + self.log.info("Force refresh of asset %s", self.url) + return False + return self.cache_file.exists() and self._check(self.cache_file) def fetchable(self): @@ -167,9 +171,17 @@ class Asset: raise AssetError(self, "Unable to download: " "HTTP error %d" % e.code) continue + except URLError as e: + # This is typically a network/service level error + # eg urlopen error [Errno 110] Connection timed out> + tmp_cache_file.unlink() + self.log.error("Unable to download %s: URL error %s", + self.url, e.reason) + raise AssetError(self, "Unable to download: URL error %s" % + e.reason, transient=True) except Exception as e: tmp_cache_file.unlink() - raise AssetError(self, "Unable to download: " % e) + raise AssetError(self, "Unable to download: %s" % e) if not os.path.exists(tmp_cache_file): raise AssetError(self, "Download retries exceeded", transient=True) diff --git a/tests/functional/qemu_test/cmd.py b/tests/functional/qemu_test/cmd.py index dc5f422..f544566 100644 --- a/tests/functional/qemu_test/cmd.py +++ b/tests/functional/qemu_test/cmd.py @@ -45,13 +45,16 @@ def is_readable_executable_file(path): # If end of line is seen, with neither @success or @failure # return False # +# In both cases, also return the contents of the line (in bytes) +# up to that point. +# # If @failure is seen, then mark @test as failed def _console_read_line_until_match(test, vm, success, failure): msg = bytes([]) done = False while True: c = vm.console_socket.recv(1) - if c is None: + if not c: done = True test.fail( f"EOF in console, expected '{success}'") @@ -76,10 +79,23 @@ def _console_read_line_until_match(test, vm, success, failure): except: console_logger.debug(msg) - return done + return done, msg def _console_interaction(test, success_message, failure_message, send_string, keep_sending=False, vm=None): + """ + Interact with the console until either message is seen. + + :param success_message: if this message appears, finish interaction + :param failure_message: if this message appears, test fails + :param send_string: a string to send to the console before trying + to read a new line + :param keep_sending: keep sending the send string each time + :param vm: the VM to interact with + + :return: The collected output (in bytes form). + """ + assert not keep_sending or send_string assert success_message or send_string @@ -101,6 +117,8 @@ def _console_interaction(test, success_message, failure_message, if failure_message is not None: failure_message_b = failure_message.encode() + out = bytes([]) + while True: if send_string: vm.console_socket.sendall(send_string.encode()) @@ -113,14 +131,21 @@ def _console_interaction(test, success_message, failure_message, break continue - if _console_read_line_until_match(test, vm, - success_message_b, - failure_message_b): + done, line = _console_read_line_until_match(test, vm, + success_message_b, + failure_message_b) + + out += line + + if done: break + return out + def interrupt_interactive_console_until_pattern(test, success_message, failure_message=None, - interrupt_string='\r'): + interrupt_string='\r', + vm=None): """ 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: @@ -140,10 +165,13 @@ def interrupt_interactive_console_until_pattern(test, success_message, :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 + :param vm: VM to use + + :return: The collected output (in bytes form). """ assert success_message - _console_interaction(test, success_message, failure_message, - interrupt_string, True) + return _console_interaction(test, success_message, failure_message, + interrupt_string, True, vm=vm) def wait_for_console_pattern(test, success_message, failure_message=None, vm=None): @@ -155,11 +183,15 @@ def wait_for_console_pattern(test, success_message, failure_message=None, :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 vm: VM to use + + :return: The collected output (in bytes form). """ assert success_message - _console_interaction(test, success_message, failure_message, None, vm=vm) + return _console_interaction(test, success_message, failure_message, + None, vm=vm) -def exec_command(test, command): +def exec_command(test, command, vm=None): """ Send a command to a console (appending CRLF characters), while logging the content. @@ -167,12 +199,16 @@ def exec_command(test, command): :param test: a test containing a VM. :type test: :class:`qemu_test.QemuSystemTest` :param command: the command to send + :param vm: VM to use :type command: str + + :return: The collected output (in bytes form). """ - _console_interaction(test, None, None, command + '\r') + return _console_interaction(test, None, None, command + '\r', vm=vm) def exec_command_and_wait_for_pattern(test, command, - success_message, failure_message=None): + success_message, failure_message=None, + vm=None): """ Send a command to a console (appending CRLF characters), then wait for success_message to appear on the console, while logging the. @@ -184,9 +220,14 @@ def exec_command_and_wait_for_pattern(test, command, :param command: the command to send :param success_message: if this message appears, test succeeds :param failure_message: if this message appears, test fails + :param vm: VM to use + + :return: The collected output (in bytes form). """ assert success_message - _console_interaction(test, success_message, failure_message, command + '\r') + + return _console_interaction(test, success_message, failure_message, + command + '\r', vm=vm) def get_qemu_img(test): test.log.debug('Looking for and selecting a qemu-img binary') diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py index fbeb171..2c0abde 100644 --- a/tests/functional/qemu_test/testcase.py +++ b/tests/functional/qemu_test/testcase.py @@ -205,6 +205,10 @@ class QemuBaseTest(unittest.TestCase): self.outputdir = self.build_file('tests', 'functional', self.arch, self.id()) self.workdir = os.path.join(self.outputdir, 'scratch') + if os.path.exists(self.workdir): + # Purge as safety net in case of unclean termination of + # previous test, or use of QEMU_TEST_KEEP_SCRATCH + shutil.rmtree(self.workdir) os.makedirs(self.workdir, exist_ok=True) self.log_filename = self.log_file('base.log') @@ -251,13 +255,14 @@ class QemuBaseTest(unittest.TestCase): test_output_log = pycotap.LogMode.LogToError) res = unittest.main(module = None, testRunner = tr, exit = False, argv=[sys.argv[0], path] + sys.argv[1:]) + failed = {} for (test, message) in res.result.errors + res.result.failures: - - if hasattr(test, "log_filename"): + if hasattr(test, "log_filename") and not test.id() in failed: print('More information on ' + test.id() + ' could be found here:' '\n %s' % test.log_filename, file=sys.stderr) if hasattr(test, 'console_log_name'): print(' %s' % test.console_log_name, file=sys.stderr) + failed[test.id()] = True sys.exit(not res.result.wasSuccessful()) @@ -403,7 +408,10 @@ class QemuSystemTest(QemuBaseTest): def tearDown(self): for vm in self._vms.values(): - vm.shutdown() + try: + vm.shutdown() + except Exception as ex: + self.log.error("Failed to teardown VM: %s" % ex) logging.getLogger('console').removeHandler(self._console_log_fh) self._console_log_fh.close() super().tearDown() @@ -4309,8 +4309,9 @@ void vnc_display_add_client(const char *id, int csock, bool skipauth) } } -static void vnc_auto_assign_id(QemuOptsList *olist, QemuOpts *opts) +static char *vnc_auto_assign_id(QemuOpts *opts) { + QemuOptsList *olist = qemu_find_opts("vnc"); int i = 2; char *id; @@ -4320,23 +4321,18 @@ static void vnc_auto_assign_id(QemuOptsList *olist, QemuOpts *opts) id = g_strdup_printf("vnc%d", i++); } qemu_opts_set_id(opts, id); + + return id; } void vnc_parse(const char *str) { QemuOptsList *olist = qemu_find_opts("vnc"); QemuOpts *opts = qemu_opts_parse_noisily(olist, str, !is_help_option(str)); - const char *id; if (!opts) { exit(1); } - - id = qemu_opts_id(opts); - if (!id) { - /* auto-assign id if not present */ - vnc_auto_assign_id(olist, opts); - } } int vnc_init_func(void *opaque, QemuOpts *opts, Error **errp) @@ -4344,7 +4340,11 @@ int vnc_init_func(void *opaque, QemuOpts *opts, Error **errp) Error *local_err = NULL; char *id = (char *)qemu_opts_id(opts); - assert(id); + if (!id) { + /* auto-assign id if not present */ + id = vnc_auto_assign_id(opts); + } + vnc_display_init(id, &local_err); if (local_err) { error_propagate(errp, local_err); |