* New functional tests to check via the vmstate-static-checker.py script

* New functional tests for CD-ROM boot on hppa
 * Skip functional tests on more exotic network errors, too
 * Fix another issue with htags in the gitlab CI
 * Some additional minor fixes to various functional tests
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmjTkIkRHHRodXRoQHJl
 ZGhhdC5jb20ACgkQLtnXdP5wLbUZCA/9Fb3bVlK108aD5ipuMLlgsXlRI+leEQC6
 h8BJgrb1GvYLlxEguHZJcSIxQN0F6TZsj31xWjpsSMNQro7tbmBcDZtj9FkCrAuG
 E99tG67A6RCTeFbqCfi19QlU9C0UOhJPPEkzZ56D+jik9NJKSG0fM0OFVEt0vBEt
 NLFrfOS6Tgc4XP6qXDXQ7v61SldZtJdDEvkMo2CkXqxu8pDz4vw8G6CSMWPfCH5v
 vkZydxLw38mkp8OtGX/tYiGn5s7/N59B29nlDkfuyOaJXjjKb+kid1XE58Y5R3Lm
 FYEuyGYgOcycH/hLiFtAFQpYYxy2yrbaHnySCP/GkMftmynz2w49hCvXca6gtcxO
 MFwzxdzDkGpPGhgANP9P3xNuZceObq6nKOdlo/tI5vG3rQp5V/n6A8T3JWIWgRHd
 71HNPYlLf53lYLbiOPAZ9SRaPjElcnJoIF0jrplOWfz8vo1NzanPV4MMOw480uFW
 HDD77dZWrFTox1Unmv1E/TS/85h5b93dbnG9XRiUUn+k8TGtBA71kDme2KEdTZzw
 3eNkOHUyc6RIwaSjBHWKOfXsaxa9EmS33dfg/jiJ9EpyGie30/faGhK1SiMr9HEp
 35s4qcpFE71eZKRqXojv8XQJmc5uRCIa30MWGwl0QoU1XaLrF2NUEPECdZRNOBCO
 Jrb+UWMEIsE=
 =RTPq
 -----END PGP SIGNATURE-----

Merge tag 'pull-request-2025-09-24' of https://gitlab.com/thuth/qemu into staging

* New functional tests to check via the vmstate-static-checker.py script
* New functional tests for CD-ROM boot on hppa
* Skip functional tests on more exotic network errors, too
* Fix another issue with htags in the gitlab CI
* Some additional minor fixes to various functional tests

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCgAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmjTkIkRHHRodXRoQHJl
# ZGhhdC5jb20ACgkQLtnXdP5wLbUZCA/9Fb3bVlK108aD5ipuMLlgsXlRI+leEQC6
# h8BJgrb1GvYLlxEguHZJcSIxQN0F6TZsj31xWjpsSMNQro7tbmBcDZtj9FkCrAuG
# E99tG67A6RCTeFbqCfi19QlU9C0UOhJPPEkzZ56D+jik9NJKSG0fM0OFVEt0vBEt
# NLFrfOS6Tgc4XP6qXDXQ7v61SldZtJdDEvkMo2CkXqxu8pDz4vw8G6CSMWPfCH5v
# vkZydxLw38mkp8OtGX/tYiGn5s7/N59B29nlDkfuyOaJXjjKb+kid1XE58Y5R3Lm
# FYEuyGYgOcycH/hLiFtAFQpYYxy2yrbaHnySCP/GkMftmynz2w49hCvXca6gtcxO
# MFwzxdzDkGpPGhgANP9P3xNuZceObq6nKOdlo/tI5vG3rQp5V/n6A8T3JWIWgRHd
# 71HNPYlLf53lYLbiOPAZ9SRaPjElcnJoIF0jrplOWfz8vo1NzanPV4MMOw480uFW
# HDD77dZWrFTox1Unmv1E/TS/85h5b93dbnG9XRiUUn+k8TGtBA71kDme2KEdTZzw
# 3eNkOHUyc6RIwaSjBHWKOfXsaxa9EmS33dfg/jiJ9EpyGie30/faGhK1SiMr9HEp
# 35s4qcpFE71eZKRqXojv8XQJmc5uRCIa30MWGwl0QoU1XaLrF2NUEPECdZRNOBCO
# Jrb+UWMEIsE=
# =RTPq
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 23 Sep 2025 11:32:41 PM PDT
# gpg:                using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg:                issuer "thuth@redhat.com"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [unknown]
# gpg:                 aka "Thomas Huth <thuth@redhat.com>" [unknown]
# gpg:                 aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# gpg:                 aka "Thomas Huth <huth@tuxfamily.org>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3  EAB9 2ED9 D774 FE70 2DB5

* tag 'pull-request-2025-09-24' of https://gitlab.com/thuth/qemu:
  tests/functional: treat unknown exceptions as transient faults
  tests/functional: retry when seeing ConnectionError exception
  tests: Fix "make check-functional" for targets without thorough tests
  tests/functional/hppa: Add a CD-ROM boot test for qemu-system-hppa
  .gitlab-ci.d/buildtest.yml: Unset CI_COMMIT_DESCRIPTION for htags
  tests/functional: use self.log for all logging
  tests/functional: Use vmstate-static-checker.py to test data from v7.2
  tests/data/vmstate-static-checker: Add dump files from QEMU 7.2.17
  tests/functional: Test whether the vmstate-static-checker script works fine
  tests: Move the old vmstate-static-checker files to tests/data/
  tests/functional/s390x/test_pxelinux: Fix warnings from pylint
  tests/functional/m68k: Use proper polling in the next-cube test

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-09-24 12:03:29 -07:00
commit 687a9b8383
27 changed files with 10599 additions and 49 deletions

View file

@ -736,7 +736,7 @@ pages:
- make gtags
# We unset variables to work around a bug in some htags versions
# which causes it to fail when the environment is large
- CI_COMMIT_MESSAGE= CI_COMMIT_TAG_MESSAGE= htags
- CI_COMMIT_MESSAGE= CI_COMMIT_TAG_MESSAGE= CI_COMMIT_DESCRIPTION= htags
-anT --tree-view=filetree -m qemu_init
-t "Welcome to the QEMU sourcecode"
- mv HTML public/src

View file

@ -1276,7 +1276,7 @@ F: include/hw/pci-host/astro.h
F: include/hw/pci-host/dino.h
F: pc-bios/hppa-firmware.img
F: roms/seabios-hppa/
F: tests/functional/hppa/test_seabios.py
F: tests/functional/hppa/
LoongArch Machines
------------------
@ -3613,7 +3613,9 @@ F: migration/
F: scripts/vmstate-static-checker.py
F: tests/functional/migration.py
F: tests/functional/*/*migration.py
F: tests/vmstate-static-checker-data/
F: tests/functional/generic/test_vmstate.py
F: tests/functional/x86_64/test_bad_vmstate.py
F: tests/data/vmstate-static-checker/
F: tests/qtest/migration/
F: tests/qtest/migration-*
F: docs/devel/migration/

View file

@ -113,6 +113,9 @@ check-functional:
@$(NINJA) precache-functional
@QEMU_TEST_NO_DOWNLOAD=1 $(MAKE) SPEED=thorough check-func check-func-quick
.PHONY: check-func check-func-quick
check-func check-func-quick:
# Consolidated targets
.PHONY: check check-clean

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,475 @@
{
"vmschkmachine": {
"Name": "s390-ccw-virtio-7.2"
},
"sclpquiesce": {
"Name": "sclpquiesce",
"version_id": 0,
"minimum_version_id": 0,
"Description": {
"name": "sclpquiesce",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "event_pending",
"version_id": 0,
"field_exists": false,
"size": 1
}
]
}
},
"s390-sclp-event-facility": {
"Name": "s390-sclp-event-facility",
"version_id": 0,
"minimum_version_id": 0,
"Description": {
"name": "vmstate-event-facility",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "receive_mask_pieces[1]",
"version_id": 0,
"field_exists": false,
"size": 4
}
],
"Subsections": [
{
"name": "vmstate-event-facility/mask64",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "receive_mask_pieces[0]",
"version_id": 0,
"field_exists": false,
"size": 4
}
]
},
{
"name": "vmstate-event-facility/mask_length",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "mask_length",
"version_id": 0,
"field_exists": false,
"size": 2
}
]
}
]
}
},
"zpci": {
"Name": "zpci",
"version_id": 0,
"minimum_version_id": 0,
"Description": {
"name": "zpci",
"version_id": 0,
"minimum_version_id": 0
}
},
"sclpconsole": {
"Name": "sclpconsole",
"version_id": 0,
"minimum_version_id": 0,
"Description": {
"name": "sclpconsole",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "event.event_pending",
"version_id": 0,
"field_exists": false,
"size": 1
},
{
"field": "iov",
"version_id": 0,
"field_exists": false,
"size": 1
},
{
"field": "iov_sclp",
"version_id": 0,
"field_exists": false,
"size": 4
},
{
"field": "iov_bs",
"version_id": 0,
"field_exists": false,
"size": 4
},
{
"field": "iov_data_len",
"version_id": 0,
"field_exists": false,
"size": 4
},
{
"field": "iov_sclp_rest",
"version_id": 0,
"field_exists": false,
"size": 4
}
]
}
},
"virtio-serial-device": {
"Name": "virtio-serial-device",
"version_id": 3,
"minimum_version_id": 3,
"Description": {
"name": "virtio-console",
"version_id": 3,
"minimum_version_id": 3,
"Fields": [
{
"field": "virtio",
"version_id": 0,
"field_exists": false,
"size": 0
}
]
}
},
"sclplmconsole": {
"Name": "sclplmconsole",
"version_id": 0,
"minimum_version_id": 0,
"Description": {
"name": "sclplmconsole",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "event.event_pending",
"version_id": 0,
"field_exists": false,
"size": 1
},
{
"field": "write_errors",
"version_id": 0,
"field_exists": false,
"size": 4
},
{
"field": "length",
"version_id": 0,
"field_exists": false,
"size": 4
},
{
"field": "buf",
"version_id": 0,
"field_exists": false,
"size": 1
}
]
}
},
"s390-pcihost": {
"Name": "s390-pcihost",
"version_id": 1,
"minimum_version_id": 1,
"Description": {
"name": "PCIHost",
"version_id": 1,
"minimum_version_id": 1,
"Fields": [
{
"field": "config_reg",
"version_id": 0,
"field_exists": false,
"size": 4
}
]
}
},
"s390-flic-qemu": {
"Name": "s390-flic-qemu",
"version_id": 1,
"minimum_version_id": 1,
"Description": {
"name": "qemu-s390-flic",
"version_id": 1,
"minimum_version_id": 1,
"Fields": [
{
"field": "simm",
"version_id": 0,
"field_exists": false,
"size": 1
},
{
"field": "nimm",
"version_id": 0,
"field_exists": false,
"size": 1
}
]
}
},
"fw_cfg_io": {
"Name": "fw_cfg_io",
"version_id": 2,
"minimum_version_id": 1,
"Description": {
"name": "fw_cfg",
"version_id": 2,
"minimum_version_id": 1,
"Fields": [
{
"field": "cur_entry",
"version_id": 0,
"field_exists": false,
"size": 2
},
{
"field": "cur_offset",
"version_id": 0,
"field_exists": true,
"size": 4
},
{
"field": "cur_offset",
"version_id": 2,
"field_exists": false,
"size": 4
}
],
"Subsections": [
{
"name": "fw_cfg/dma",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "dma_addr",
"version_id": 0,
"field_exists": false,
"size": 8
}
]
},
{
"name": "fw_cfg/acpi_mr",
"version_id": 1,
"minimum_version_id": 1,
"Fields": [
{
"field": "table_mr_size",
"version_id": 0,
"field_exists": false,
"size": 8
},
{
"field": "linker_mr_size",
"version_id": 0,
"field_exists": false,
"size": 8
},
{
"field": "rsdp_mr_size",
"version_id": 0,
"field_exists": false,
"size": 8
}
]
}
]
}
},
"s390-ipl": {
"Name": "s390-ipl",
"version_id": 0,
"minimum_version_id": 0,
"Description": {
"name": "ipl",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "compat_start_addr",
"version_id": 0,
"field_exists": false,
"size": 8
},
{
"field": "compat_bios_start_addr",
"version_id": 0,
"field_exists": false,
"size": 8
},
{
"field": "iplb",
"version_id": 0,
"field_exists": false,
"size": 4096,
"Description": {
"name": "ipl/iplb",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "reserved1",
"version_id": 0,
"field_exists": false,
"size": 1
},
{
"field": "devno",
"version_id": 0,
"field_exists": false,
"size": 2
},
{
"field": "reserved2",
"version_id": 0,
"field_exists": false,
"size": 1
}
],
"Subsections": [
{
"name": "ipl/iplb_extended",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "reserved_ext",
"version_id": 0,
"field_exists": false,
"size": 1
}
]
}
]
}
},
{
"field": "iplb_valid",
"version_id": 0,
"field_exists": false,
"size": 1
},
{
"field": "cssid",
"version_id": 0,
"field_exists": false,
"size": 1
},
{
"field": "ssid",
"version_id": 0,
"field_exists": false,
"size": 1
},
{
"field": "devno",
"version_id": 0,
"field_exists": false,
"size": 2
}
]
}
},
"pci-host-bridge": {
"Name": "pci-host-bridge",
"version_id": 1,
"minimum_version_id": 1,
"Description": {
"name": "PCIHost",
"version_id": 1,
"minimum_version_id": 1,
"Fields": [
{
"field": "config_reg",
"version_id": 0,
"field_exists": false,
"size": 4
}
]
}
},
"fw_cfg_mem": {
"Name": "fw_cfg_mem",
"version_id": 2,
"minimum_version_id": 1,
"Description": {
"name": "fw_cfg",
"version_id": 2,
"minimum_version_id": 1,
"Fields": [
{
"field": "cur_entry",
"version_id": 0,
"field_exists": false,
"size": 2
},
{
"field": "cur_offset",
"version_id": 0,
"field_exists": true,
"size": 4
},
{
"field": "cur_offset",
"version_id": 2,
"field_exists": false,
"size": 4
}
],
"Subsections": [
{
"name": "fw_cfg/dma",
"version_id": 0,
"minimum_version_id": 0,
"Fields": [
{
"field": "dma_addr",
"version_id": 0,
"field_exists": false,
"size": 8
}
]
},
{
"name": "fw_cfg/acpi_mr",
"version_id": 1,
"minimum_version_id": 1,
"Fields": [
{
"field": "table_mr_size",
"version_id": 0,
"field_exists": false,
"size": 8
},
{
"field": "linker_mr_size",
"version_id": 0,
"field_exists": false,
"size": 8
},
{
"field": "rsdp_mr_size",
"version_id": 0,
"field_exists": false,
"size": 8
}
]
}
]
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,7 @@ test_aarch64_timeouts = {
tests_aarch64_system_quick = [
'migration',
'vmstate',
]
tests_aarch64_system_thorough = [

View file

@ -72,8 +72,6 @@ class Aarch64VirtMachine(QemuSystemTest):
self.set_machine('virt')
self.require_accelerator("tcg")
logger = logging.getLogger('aarch64_virt')
kernel_path = self.ASSET_KERNEL.fetch()
self.vm.set_console()
@ -91,7 +89,7 @@ class Aarch64VirtMachine(QemuSystemTest):
'rng-random,id=rng0,filename=/dev/urandom')
# Also add a scratch block device
logger.info('creating scratch qcow2 image')
self.log.info('creating scratch qcow2 image')
image_path = self.scratch_file('scratch.qcow2')
qemu_img = get_qemu_img(self)
check_call([qemu_img, 'create', '-f', 'qcow2', image_path, '8M'],

View file

@ -77,7 +77,6 @@ class IntegratorMachine(QemuSystemTest):
command_line='screendump %s' % screendump_path)
if 'unknown command' in res:
self.skipTest('screendump not available')
logger = logging.getLogger('framebuffer')
cpu_count = 1
match_threshold = 0.92
@ -88,7 +87,7 @@ class IntegratorMachine(QemuSystemTest):
loc = np.where(result >= match_threshold)
tux_count = 0
for tux_count, pt in enumerate(zip(*loc[::-1]), start=1):
logger.debug('found Tux at position [x, y] = %s', pt)
self.log.debug('found Tux at position [x, y] = %s', pt)
self.assertGreaterEqual(tux_count, cpu_count)
if __name__ == '__main__':

View file

@ -0,0 +1,67 @@
#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
'''This test runs the vmstate-static-checker script with the current QEMU'''
import subprocess
from qemu_test import QemuSystemTest, skipFlakyTest
@skipFlakyTest("vmstate-static-checker can produce false positives")
class VmStateTest(QemuSystemTest):
'''
This test helps to check whether there are problems between old
reference data and the current QEMU
'''
def test_vmstate_7_2(self):
'''Check reference data from QEMU v7.2'''
target_machine = {
'aarch64': 'virt-7.2',
'm68k': 'virt-7.2',
'ppc64': 'pseries-7.2',
's390x': 's390-ccw-virtio-7.2',
'x86_64': 'pc-q35-7.2',
}
self.set_machine(target_machine[self.arch])
# Run QEMU to get the current vmstate json file:
dst_json = self.scratch_file('dest.json')
self.log.info('Dumping vmstate from %s', self.qemu_bin)
cp = subprocess.run([self.qemu_bin, '-nodefaults',
'-M', target_machine[self.arch],
'-dump-vmstate', dst_json],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True, check=True)
if cp.stdout:
self.log.info('QEMU output: %s', cp.stdout)
# Check whether the old vmstate json file is still compatible:
src_json = self.data_file('..', 'data', 'vmstate-static-checker',
self.arch,
target_machine[self.arch] + '.json')
self.log.info('Comparing vmstate with %s', src_json)
checkerscript = self.data_file('..', '..', 'scripts',
'vmstate-static-checker.py')
cp = subprocess.run([checkerscript, '-s', src_json, '-d', dst_json],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True, check=False)
if cp.returncode != 0:
self.fail('Running vmstate-static-checker failed:\n' + cp.stdout +
'\nThis either means that there is a migration bug '
'that needs to be fixed, or\nvmstate-static-checker.py '
'needs to be improved (e.g. extend the changed_names\n'
'in case a field has been renamed), or drop the '
'problematic field from\n' + src_json +
'\nin case the script cannot be fixed easily.')
if cp.stdout:
self.log.warning('vmstate-static-checker output: %s', cp.stdout)
if __name__ == '__main__':
QemuSystemTest.main()

View file

@ -3,3 +3,7 @@
tests_hppa_system_quick = [
'seabios',
]
tests_hppa_system_thorough = [
'cdboot',
]

View file

@ -0,0 +1,38 @@
#!/usr/bin/env python3
#
# CD boot test for HPPA machines
#
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern
from qemu_test import wait_for_console_pattern
class HppaCdBoot(QemuSystemTest):
ASSET_CD = Asset(
('https://github.com/philmd/qemu-testing-blob/raw/ec1b741/'
'hppa/hp9000/712/C7120023.frm'),
'32c612ad2074516986bdc27768903c561fa92af2ca48e5ac3f3359ade1c42f70')
def test_cdboot(self):
self.set_machine('B160L')
cdrom_path = self.ASSET_CD.fetch()
self.vm.set_console()
self.vm.add_args('-cdrom', cdrom_path,
'-boot', 'd',
'-no-reboot')
self.vm.launch()
wait_for_console_pattern(self, 'Unrecognized MODEL TYPE = 502')
wait_for_console_pattern(self, 'UPDATE PAUSED>')
exec_command_and_wait_for_pattern(self, 'exit\r', 'UPDATE>')
exec_command_and_wait_for_pattern(self, 'ls\r', 'IMAGE1B')
wait_for_console_pattern(self, 'UPDATE>')
exec_command_and_wait_for_pattern(self, 'exit\r',
'THIS UTILITY WILL NOW RESET THE SYSTEM.....')
if __name__ == '__main__':
QemuSystemTest.main()

View file

@ -1,5 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-or-later
tests_m68k_system_quick = [
'vmstate',
]
tests_m68k_system_thorough = [
'mcf5208evb',
'nextcube',

View file

@ -29,8 +29,15 @@ class NextCubeMachine(QemuSystemTest):
self.vm.launch()
self.log.info('VM launched, waiting for display')
# TODO: wait for the 'displaysurface_create 1120x832' trace-event.
time.sleep(2)
# Wait for the FPU test to finish, then the display is available, too:
while True:
res = self.vm.cmd('human-monitor-command',
command_line='info registers')
if ("F0 = 400e 8400000000000000" in res and
"F1 = 400e 83ff000000000000" in res and
"F2 = 400e 83ff000000000000" in res):
break
time.sleep(0.1)
res = self.vm.cmd('human-monitor-command',
command_line='screendump %s' % screenshot_path)
@ -56,10 +63,10 @@ class NextCubeMachine(QemuSystemTest):
self.check_bootrom_framebuffer(screenshot_path)
lines = tesseract_ocr(screenshot_path)
text = '\n'.join(lines)
self.assertIn('Backplane slot', text)
self.assertIn('Ethernet address', text)
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()

View file

@ -159,7 +159,6 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
command_line='screendump %s' % screendump_path)
if 'unknown command' in res:
self.skipTest('screendump not available')
logger = logging.getLogger('framebuffer')
match_threshold = 0.95
screendump_bgr = cv2.imread(screendump_path, cv2.IMREAD_COLOR)
@ -171,7 +170,7 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
h, w = tuxlogo_bgr.shape[:2]
debug_png = os.getenv('QEMU_TEST_CV2_SCREENDUMP_PNG_PATH')
for tuxlogo_count, pt in enumerate(zip(*loc[::-1]), start=1):
logger.debug('found Tux at position (x, y) = %s', pt)
self.log.debug('found Tux at position (x, y) = %s', pt)
cv2.rectangle(screendump_bgr, pt,
(pt[0] + w, pt[1] + h), (0, 0, 255), 2)
if debug_png:

View file

@ -11,6 +11,7 @@ test_ppc64_timeouts = {
tests_ppc64_system_quick = [
'migration',
'vmstate',
]
tests_ppc64_system_thorough = [

View file

@ -179,9 +179,17 @@ class Asset:
self.url, e.reason)
raise AssetError(self, "Unable to download: URL error %s" %
e.reason, transient=True)
except ConnectionError as e:
# A socket connection failure, such as dropped conn
# or refused conn
tmp_cache_file.unlink()
self.log.error("Unable to download %s: Connection error %s",
self.url, e)
continue
except Exception as e:
tmp_cache_file.unlink()
raise AssetError(self, "Unable to download: %s" % e)
raise AssetError(self, "Unable to download: %s" % e,
transient=True)
if not os.path.exists(tmp_cache_file):
raise AssetError(self, "Download retries exceeded", transient=True)

View file

@ -32,15 +32,14 @@ class ReplayKernelBase(LinuxKernelTest):
# icount requires TCG to be available
self.require_accelerator('tcg')
logger = logging.getLogger('replay')
start_time = time.time()
vm = self.get_vm(name='recording' if record else 'replay')
vm.set_console()
if record:
logger.info('recording the execution...')
self.log.info('recording the execution...')
mode = 'record'
else:
logger.info('replaying the execution...')
self.log.info('replaying the execution...')
mode = 'replay'
vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' %
(shift, mode, replay_path),
@ -54,15 +53,15 @@ class ReplayKernelBase(LinuxKernelTest):
self.wait_for_console_pattern(console_pattern, vm)
if record:
vm.shutdown()
logger.info('finished the recording with log size %s bytes'
self.log.info('finished the recording with log size %s bytes'
% os.path.getsize(replay_path))
self.run_replay_dump(replay_path)
logger.info('successfully tested replay-dump.py')
self.log.info('successfully tested replay-dump.py')
else:
vm.wait()
logger.info('successfully finished the replay')
self.log.info('successfully finished the replay')
elapsed = time.time() - start_time
logger.info('elapsed time %.2f sec' % elapsed)
self.log.info('elapsed time %.2f sec' % elapsed)
return elapsed
def run_replay_dump(self, replay_path):
@ -80,5 +79,4 @@ class ReplayKernelBase(LinuxKernelTest):
True, shift, args, replay_path)
t2 = self.run_vm(kernel_path, kernel_command_line, console_pattern,
False, shift, args, replay_path)
logger = logging.getLogger('replay')
logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1))
self.log.info('replay overhead {:.2%}'.format(t2 / t1 - 1))

View file

@ -4,6 +4,10 @@ test_s390x_timeouts = {
'ccw_virtio' : 420,
}
tests_s390x_system_quick = [
'vmstate',
]
tests_s390x_system_thorough = [
'ccw_virtio',
'pxelinux',

View file

@ -1,10 +1,11 @@
#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Functional test that checks the pxelinux.cfg network booting of a s390x VM
# (TFTP booting without config file is already tested by the pxe qtest, so
# we don't repeat that here).
'''
Functional test that checks the pxelinux.cfg network booting of a s390x VM
(TFTP booting without config file is already tested by the pxe qtest, so
we don't repeat that here).
'''
import os
import shutil
@ -12,7 +13,7 @@ import shutil
from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern
pxelinux_cfg_contents='''# pxelinux.cfg style config file
PXELINUX_CFG_CONTENTS='''# pxelinux.cfg style config file
default Debian
label Nonexisting
kernel kernel.notavailable
@ -26,6 +27,10 @@ kernel kernel.fedora
'''
class S390PxeLinux(QemuSystemTest):
'''
Test various ways of booting via a pxelinux.cfg file, for details see:
https://wiki.syslinux.org/wiki/index.php?title=PXELINUX#Configuration
'''
ASSET_DEBIAN_KERNEL = Asset(
('https://snapshot.debian.org/archive/debian/'
@ -46,6 +51,7 @@ class S390PxeLinux(QemuSystemTest):
'480859574f3f44caa6cd35c62d70e1ac0609134e22ce2a954bbed9b110c06e0b')
def pxelinux_launch(self, pl_name='default', extra_opts=None):
'''Create a pxelinux.cfg file in the right location and launch QEMU'''
self.require_netdev('user')
self.set_machine('s390-ccw-virtio')
@ -66,11 +72,11 @@ class S390PxeLinux(QemuSystemTest):
cfg_fname = self.scratch_file('tftp', 'pxelinux.cfg', pl_name)
with open(cfg_fname, 'w', encoding='utf-8') as f:
f.write(pxelinux_cfg_contents)
f.write(PXELINUX_CFG_CONTENTS)
virtio_net_dev = 'virtio-net-ccw,netdev=n1,bootindex=1'
if extra_opts:
virtio_net_dev += ',' + extra_opts
virtio_net_dev += ',' + extra_opts
self.vm.add_args('-m', '384',
'-netdev', f'user,id=n1,tftp={tftpdir}',
@ -80,6 +86,7 @@ class S390PxeLinux(QemuSystemTest):
def test_default(self):
'''Check whether the guest uses the "default" file name'''
self.pxelinux_launch()
# The kernel prints its arguments to the console, so we can use
# this to check whether the kernel parameters are correctly handled:
@ -89,11 +96,13 @@ class S390PxeLinux(QemuSystemTest):
wait_for_console_pattern(self, 'Run /init as init process')
def test_mac(self):
'''Check whether the guest uses file name based on its MAC address'''
self.pxelinux_launch(pl_name='01-02-ca-fe-ba-be-42',
extra_opts='mac=02:ca:fe:ba:be:42,loadparm=3')
wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x')
def test_uuid(self):
'''Check whether the guest uses file name based on its UUID'''
# Also add a non-bootable disk to check the fallback to network boot:
self.vm.add_args('-blockdev', 'null-co,size=65536,node-name=d1',
'-device', 'virtio-blk,drive=d1,bootindex=0,loadparm=1',
@ -102,11 +111,13 @@ class S390PxeLinux(QemuSystemTest):
wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)')
def test_ip(self):
'''Check whether the guest uses file name based on its IP address'''
self.vm.add_args('-M', 'loadparm=3')
self.pxelinux_launch(pl_name='0A00020F')
wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x')
def test_menu(self):
'''Check whether the boot menu works for pxelinux.cfg booting'''
self.vm.add_args('-boot', 'menu=on,splash-time=10')
self.pxelinux_launch(pl_name='0A00')
wait_for_console_pattern(self, '[1] Nonexisting')

View file

@ -10,13 +10,15 @@ test_x86_64_timeouts = {
}
tests_x86_64_system_quick = [
'bad_vmstate',
'cpu_model_versions',
'cpu_queries',
'mem_addr_space',
'memlock',
'migration',
'pc_cpu_hotplug_props',
'virtio_version',
'memlock',
'vmstate',
]
tests_x86_64_system_thorough = [

View file

@ -121,10 +121,10 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
self._debugcon_log = 'debugcon-log.txt'
def _print_log(self, log):
self.logger.info('\nlogs from biosbits follows:')
self.logger.info('==========================================\n')
self.logger.info(log)
self.logger.info('==========================================\n')
self.log.info('\nlogs from biosbits follows:')
self.log.info('==========================================\n')
self.log.info(log)
self.log.info('==========================================\n')
def copy_bits_config(self):
""" copies the bios bits config file into bits.
@ -138,8 +138,8 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
self.assertTrue(os.path.exists(bits_config_file))
self.assertTrue(os.path.exists(target_config_dir))
shutil.copy2(bits_config_file, target_config_dir)
self.logger.info('copied config file %s to %s',
bits_config_file, target_config_dir)
self.log.info('copied config file %s to %s',
bits_config_file, target_config_dir)
def copy_test_scripts(self):
"""copies the python test scripts into bits. """
@ -163,8 +163,8 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
newfilename = os.path.splitext(filename)[0] + '.py'
shutil.copy2(os.path.join(bits_test_dir, filename),
os.path.join(target_test_dir, newfilename))
self.logger.info('copied test file %s to %s',
filename, target_test_dir)
self.log.info('copied test file %s to %s',
filename, target_test_dir)
# now remove the pyc test file if it exists, otherwise the
# changes in the python test script won't be executed.
@ -172,9 +172,9 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
if os.access(os.path.join(target_test_dir, testfile_pyc),
os.F_OK):
os.remove(os.path.join(target_test_dir, testfile_pyc))
self.logger.info('removed compiled file %s',
os.path.join(target_test_dir,
testfile_pyc))
self.log.info('removed compiled file %s',
os.path.join(target_test_dir,
testfile_pyc))
def fix_mkrescue(self, mkrescue):
""" grub-mkrescue is a bash script with two variables, 'prefix' and
@ -216,7 +216,7 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
self.fix_mkrescue(mkrescue_script)
self.logger.info('using grub-mkrescue for generating biosbits iso ...')
self.log.info('using grub-mkrescue for generating biosbits iso ...')
try:
if os.getenv('V') or os.getenv('BITS_DEBUG'):
@ -225,7 +225,7 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=True)
self.logger.info("grub-mkrescue output %s" % proc.stdout)
self.log.info("grub-mkrescue output %s" % proc.stdout)
else:
subprocess.check_call([mkrescue_script, '-o',
iso_file, bits_dir],
@ -238,11 +238,10 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
self.assertTrue(os.access(iso_file, os.R_OK))
self.logger.info('iso file %s successfully generated.', iso_file)
self.log.info('iso file %s successfully generated.', iso_file)
def setUp(self): # pylint: disable=arguments-differ
super().setUp()
self.logger = self.log
prebuiltDir = self.scratch_file('prebuilt')
if not os.path.isdir(prebuiltDir):
@ -333,7 +332,7 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
# in batch mode and then automatically initiate a vm shutdown.
self._vm.event_wait('SHUTDOWN', timeout=BITS_TIMEOUT)
self._vm.wait(timeout=None)
self.logger.debug("Checking console output ...")
self.log.debug("Checking console output ...")
self.parse_log()
if __name__ == '__main__':

View file

@ -0,0 +1,58 @@
#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
'''Test whether the vmstate-static-checker script detects problems correctly'''
import subprocess
from qemu_test import QemuBaseTest
EXPECTED_OUTPUT='''Warning: checking incompatible machine types: "pc-i440fx-2.1", "pc-i440fx-2.2"
Section "fw_cfg" does not exist in dest
Section "fusbh200-ehci-usb" version error: 2 > 1
Section "fusbh200-ehci-usb", Description "ehci-core": expected field "usbsts", got "usbsts_pending"; skipping rest
Section "pci-serial-4x" Description "pci-serial-multi": Entry "Fields" missing
Section "intel-hda-generic", Description "intel-hda", Field "pci": missing description
Section "cfi.pflash01": Entry "Description" missing
Section "megasas", Description "PCIDevice": expected field "irq_state", while dest has no further fields
Section "PIIX3-xen" Description "PIIX3": minimum version error: 1 < 2
Section "PIIX3-xen" Description "PIIX3": Entry "Subsections" missing
Section "tpci200": Description "tpci200" missing, got "tpci2002" instead; skipping
Section "sun-fdtwo" Description "fdc": version error: 2 > 1
Section "sun-fdtwo", Description "fdrive": Subsection "fdrive/media_rate" not found
Section "usb-kbd" Description "usb-kbd" Field "kbd.keycodes" size mismatch: 4 , 2
'''
class BadVmStateTest(QemuBaseTest):
'''Test class for testing vmstat-static-checker script with bad input'''
def test_checker(self):
"""
Test whether the checker script correctly detects the changes
between dump1.json and dump2.json.
"""
src_json = self.data_file('..', 'data', 'vmstate-static-checker',
'dump1.json')
dst_json = self.data_file('..', 'data', 'vmstate-static-checker',
'dump2.json')
checkerscript = self.data_file('..', '..', 'scripts',
'vmstate-static-checker.py')
self.log.info('Comparing %s with %s', src_json, dst_json)
cp = subprocess.run([checkerscript, '-s', src_json, '-d', dst_json],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True, check=False)
if cp.returncode != 13:
self.fail('Unexpected return code of vmstate-static-checker: ' +
cp.returncode)
if cp.stdout != EXPECTED_OUTPUT:
self.log.info('vmstate-static-checker output:\n%s', cp.stdout)
self.log.info('expected output:\n%s', EXPECTED_OUTPUT)
self.fail('Unexpected vmstate-static-checker output!')
if __name__ == '__main__':
QemuBaseTest.main()