testing, docs and plugin updates for rc2

- cleanup leftover avocado bits from functional test
   - ensure we keep functional logs for tests
   - improve test console handling to detect prompts
   - remove hacking timer.sleep() usage in functional tests
   - convert Aarch64 tuxrun tests to functional test
   - update Aarch64 tuxrun images to avoid corrupt blk I/O ops
   - auto-generate the TCG plugin API symbols to avoid missing them
   - fix rust pl011 model handling of DeviceID regs
   - update docs to refer to "commonly known identity"
   - convert aspeed tests to functional framework and remove hacky sleeps
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmdEZXEACgkQ+9DbCVqe
 KkRdMAf+JoSdKn3ck/eji270bZ2Y3evgDuP/qOZlcBtUJJ7+bUvhEOnBMApwKRD8
 u63hz7M4LIV5k3mezlEADf+oEpZ2FR3nIDM0dTY2CXYZm6av+0dNV0qFhXwjkslk
 aqJLiJYgNl3wsyn/ftYNLiBhCid0sOGMvEOFZI6ELBh5KH8eiNdyrsaD0GSmpwZi
 BsZUi8TOKy6EBeWnco/FLBV8ZVZUHuHNBl84jUY/8g7cxGMJfK8KoqMJ5XYoiQoJ
 1dYDqFmoP24iQRks6K6beFRdS/CBet36Nhsv7We/gf17Msw5uFo7Cho+touRCMrK
 AmVKFdOX/OqJAHqlEKquYAD7bPjpaA==
 =Xa/M
 -----END PGP SIGNATURE-----

Merge tag 'pull-9.2-rc2-updates-251124-1' of https://gitlab.com/stsquad/qemu into staging

testing, docs and plugin updates for rc2

  - cleanup leftover avocado bits from functional test
  - ensure we keep functional logs for tests
  - improve test console handling to detect prompts
  - remove hacking timer.sleep() usage in functional tests
  - convert Aarch64 tuxrun tests to functional test
  - update Aarch64 tuxrun images to avoid corrupt blk I/O ops
  - auto-generate the TCG plugin API symbols to avoid missing them
  - fix rust pl011 model handling of DeviceID regs
  - update docs to refer to "commonly known identity"
  - convert aspeed tests to functional framework and remove hacky sleeps

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmdEZXEACgkQ+9DbCVqe
# KkRdMAf+JoSdKn3ck/eji270bZ2Y3evgDuP/qOZlcBtUJJ7+bUvhEOnBMApwKRD8
# u63hz7M4LIV5k3mezlEADf+oEpZ2FR3nIDM0dTY2CXYZm6av+0dNV0qFhXwjkslk
# aqJLiJYgNl3wsyn/ftYNLiBhCid0sOGMvEOFZI6ELBh5KH8eiNdyrsaD0GSmpwZi
# BsZUi8TOKy6EBeWnco/FLBV8ZVZUHuHNBl84jUY/8g7cxGMJfK8KoqMJ5XYoiQoJ
# 1dYDqFmoP24iQRks6K6beFRdS/CBet36Nhsv7We/gf17Msw5uFo7Cho+touRCMrK
# AmVKFdOX/OqJAHqlEKquYAD7bPjpaA==
# =Xa/M
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 25 Nov 2024 11:54:25 GMT
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* tag 'pull-9.2-rc2-updates-251124-1' of https://gitlab.com/stsquad/qemu: (28 commits)
  tests/functional: Remove sleep workarounds from Aspeed tests
  tests/functional: Convert Aspeed arm SDK tests
  tests/functional: Convert Aspeed aarch64 SDK tests
  docs: explicitly permit a "commonly known identity" with SoB
  rust/pl011: Fix range checks for device ID accesses
  plugins: eradicate qemu-plugins.symbols static file
  plugins: detect qemu plugin API symbols from header
  plugins: add missing export for qemu_plugin_num_vcpus
  tests/functional: update the aarch64 tuxrun tests
  tests/functional: Convert the Avocado aarch64 tuxrun tests
  tests/functional: avoid accessing log_filename on earlier failures
  tests/functional: add a QMP backdoor for debugging stalled tests
  tests/functional: remove time.sleep usage from tuxrun tests
  tests/functional: rewrite console handling to be bytewise
  tests/functional: require non-NULL success_message for console wait
  tests/functional: don't try to wait for the empty string
  tests/functional: logs details of console interaction operations
  tests/functional: enable debug logging for QEMUMachine
  tests/functional: honour requested test VM name in QEMUMachine
  tests/functional: put QEMUMachine logs in testcase log directory
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2024-11-26 11:33:48 +00:00
commit b8ee011e40
24 changed files with 446 additions and 630 deletions

View File

@ -78,7 +78,10 @@ of Origin 1.1 (DCO):
To indicate acceptance of the DCO every commit must have a tag
Signed-off-by: REAL NAME <EMAIL>
Signed-off-by: YOUR NAME <EMAIL>
where "YOUR NAME" is your commonly known identity in the context
of the community.
This can be achieved by passing the "-s" flag to the "git commit" command.

View File

@ -994,6 +994,7 @@ F: hw/arm/virt*
F: include/hw/arm/virt.h
F: docs/system/arm/virt.rst
F: tests/functional/test_aarch64_virt.py
F: tests/functional/test_aarch64_tuxrun.py
F: tests/functional/test_arm_tuxrun.py
Xilinx Zynq
@ -3751,6 +3752,7 @@ F: plugins/
F: tests/tcg/plugins/
F: tests/functional/test_aarch64_tcg_plugins.py
F: contrib/plugins/
F: scripts/qemu-plugin-symbols.py
AArch64 TCG target
M: Richard Henderson <richard.henderson@linaro.org>
@ -4129,7 +4131,7 @@ F: scripts/ci/
F: tests/docker/
F: tests/vm/
F: tests/lcitool/
F: tests/avocado/tuxrun_baselines.py
F: tests/functional/test_*_tuxrun.py
F: scripts/archive-source.sh
F: docs/devel/testing.rst
W: https://gitlab.com/qemu-project/qemu/pipelines

View File

@ -18,7 +18,7 @@ one-shot fix, the bare minimum we ask is that:
* - Check
- Reason
* - Patches contain Signed-off-by: Real Name <author@email>
* - Patches contain Signed-off-by: Your Name <author@email>
- States you are legally able to contribute the code. See :ref:`patch_emails_must_include_a_signed_off_by_line`
* - Sent as patch emails to ``qemu-devel@nongnu.org``
- The project uses an email list based workflow. See :ref:`submitting_your_patches`
@ -335,6 +335,11 @@ include a "From:" line in the body of the email (different from your
envelope From:) that will give credit to the correct author; but again,
that author's Signed-off-by: line is mandatory, with the same spelling.
The name used with "Signed-off-by" does not need to be your legal name,
nor birth name, nor appear on any government ID. It is the identity you
choose to be known by in the community, but should not be anonymous,
nor misrepresent whom you are.
There are various tooling options for automatically adding these tags
include using ``git commit -s`` or ``git format-patch -s``. For more
information see `SubmittingPatches 1.12

View File

@ -65,6 +65,12 @@ to the QEMU binary that should be used for the test, for example::
$ export QEMU_TEST_QEMU_BINARY=$PWD/qemu-system-x86_64
$ python3 ../tests/functional/test_file.py
The test framework will automatically purge any scratch files created during
the tests. If needing to debug a failed test, it is possible to keep these
files around on disk by setting ```QEMU_TEST_KEEP_SCRATCH=1``` as an env
variable. Any preserved files will be deleted the next time the test is run
without this variable set.
Overview
--------
@ -170,6 +176,16 @@ primarily depend on the value of the ``qemu_bin`` class attribute.
If it is not explicitly set by the test code, its default value will
be the result the QEMU_TEST_QEMU_BINARY environment variable.
Debugging hung QEMU
^^^^^^^^^^^^^^^^^^^
When test cases go wrong it may be helpful to debug a stalled QEMU
process. While the QEMUMachine class owns the primary QMP monitor
socket, it is possible to request a second QMP monitor be created
by setting the ``QEMU_TEST_QMP_BACKDOOR`` env variable to refer
to a UNIX socket name. The ``qmp-shell`` command can then be
attached to the stalled QEMU to examine its live state.
Attribute reference
-------------------

View File

@ -803,6 +803,7 @@ void qemu_plugin_register_atexit_cb(qemu_plugin_id_t id,
qemu_plugin_udata_cb_t cb, void *userdata);
/* returns how many vcpus were started at this point */
QEMU_PLUGIN_API
int qemu_plugin_num_vcpus(void);
/**

View File

@ -2,17 +2,23 @@ if not get_option('plugins')
subdir_done()
endif
qemu_plugin_symbols = configure_file(
input: files('../include/qemu/qemu-plugin.h'),
output: 'qemu-plugin.symbols',
capture: true,
command: [files('../scripts/qemu-plugin-symbols.py'), '@INPUT@'])
# Modules need more symbols than just those in plugins/qemu-plugins.symbols
if not enable_modules
if host_os == 'darwin'
configure_file(
input: files('qemu-plugins.symbols'),
input: qemu_plugin_symbols,
output: 'qemu-plugins-ld64.symbols',
capture: true,
command: ['sed', '-ne', 's/^[[:space:]]*\\(qemu_.*\\);/_\\1/p', '@INPUT@'])
emulator_link_args += ['-Wl,-exported_symbols_list,plugins/qemu-plugins-ld64.symbols']
else
emulator_link_args += ['-Xlinker', '--dynamic-list=' + (meson.project_source_root() / 'plugins/qemu-plugins.symbols')]
emulator_link_args += ['-Xlinker', '--dynamic-list=' + qemu_plugin_symbols.full_path()]
endif
endif
@ -23,7 +29,7 @@ if host_os == 'windows'
# First, create a .def file listing all the symbols a plugin should expect to have
# available in qemu
win32_plugin_def = configure_file(
input: files('qemu-plugins.symbols'),
input: qemu_plugin_symbols,
output: 'qemu_plugin_api.def',
capture: true,
command: ['sed', '-e', '0,/^/s//EXPORTS/; s/[{};]//g', '@INPUT@'])

View File

@ -1,59 +0,0 @@
{
qemu_plugin_bool_parse;
qemu_plugin_end_code;
qemu_plugin_entry_code;
qemu_plugin_get_hwaddr;
qemu_plugin_get_registers;
qemu_plugin_hwaddr_device_name;
qemu_plugin_hwaddr_is_io;
qemu_plugin_hwaddr_phys_addr;
qemu_plugin_insn_data;
qemu_plugin_insn_disas;
qemu_plugin_insn_haddr;
qemu_plugin_insn_size;
qemu_plugin_insn_symbol;
qemu_plugin_insn_vaddr;
qemu_plugin_mem_get_value;
qemu_plugin_mem_is_big_endian;
qemu_plugin_mem_is_sign_extended;
qemu_plugin_mem_is_store;
qemu_plugin_mem_size_shift;
qemu_plugin_num_vcpus;
qemu_plugin_outs;
qemu_plugin_path_to_binary;
qemu_plugin_read_memory_vaddr;
qemu_plugin_read_register;
qemu_plugin_register_atexit_cb;
qemu_plugin_register_flush_cb;
qemu_plugin_register_vcpu_exit_cb;
qemu_plugin_register_vcpu_idle_cb;
qemu_plugin_register_vcpu_init_cb;
qemu_plugin_register_vcpu_insn_exec_cb;
qemu_plugin_register_vcpu_insn_exec_cond_cb;
qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu;
qemu_plugin_register_vcpu_mem_cb;
qemu_plugin_register_vcpu_mem_inline_per_vcpu;
qemu_plugin_register_vcpu_resume_cb;
qemu_plugin_register_vcpu_syscall_cb;
qemu_plugin_register_vcpu_syscall_ret_cb;
qemu_plugin_register_vcpu_tb_exec_cb;
qemu_plugin_register_vcpu_tb_exec_cond_cb;
qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu;
qemu_plugin_register_vcpu_tb_trans_cb;
qemu_plugin_request_time_control;
qemu_plugin_reset;
qemu_plugin_scoreboard_free;
qemu_plugin_scoreboard_find;
qemu_plugin_scoreboard_new;
qemu_plugin_start_code;
qemu_plugin_tb_get_insn;
qemu_plugin_tb_n_insns;
qemu_plugin_tb_vaddr;
qemu_plugin_u64_add;
qemu_plugin_u64_get;
qemu_plugin_u64_set;
qemu_plugin_u64_sum;
qemu_plugin_uninstall;
qemu_plugin_update_ns;
qemu_plugin_vcpu_for_each;
};

View File

@ -182,7 +182,7 @@ impl PL011State {
use RegisterOffset::*;
std::ops::ControlFlow::Break(match RegisterOffset::try_from(offset) {
Err(v) if (0x3f8..0x400).contains(&v) => {
Err(v) if (0x3f8..0x400).contains(&(v >> 2)) => {
u64::from(self.device_id[(offset - 0xfe0) >> 2])
}
Err(_) => {

45
scripts/qemu-plugin-symbols.py Executable file
View File

@ -0,0 +1,45 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Extract QEMU Plugin API symbols from a header file
#
# Copyright 2024 Linaro Ltd
#
# Author: Pierrick Bouvier <pierrick.bouvier@linaro.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.
#
# SPDX-License-Identifier: GPL-2.0-or-later
import argparse
import re
def extract_symbols(plugin_header):
with open(plugin_header) as file:
content = file.read()
# Remove QEMU_PLUGIN_API macro definition.
content = content.replace('#define QEMU_PLUGIN_API', '')
expected = content.count('QEMU_PLUGIN_API')
# Find last word between QEMU_PLUGIN_API and (, matching on several lines.
# We use *? non-greedy quantifier.
syms = re.findall(r'QEMU_PLUGIN_API.*?(\w+)\s*\(', content, re.DOTALL)
syms.sort()
# Ensure we found as many symbols as API markers.
assert len(syms) == expected
return syms
def main() -> None:
parser = argparse.ArgumentParser(description='Extract QEMU plugin symbols')
parser.add_argument('plugin_header', help='Path to QEMU plugin header.')
args = parser.parse_args()
syms = extract_symbols(args.plugin_header)
print('{')
for s in syms:
print(" {};".format(s))
print('};')
if __name__ == '__main__':
main()

View File

@ -1,202 +0,0 @@
# Functional test that boots the ASPEED SoCs with firmware
#
# Copyright (C) 2022 ASPEED Technology 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
import os
import tempfile
import subprocess
from avocado_qemu import LinuxSSHMixIn
from avocado_qemu import QemuSystemTest
from avocado_qemu import wait_for_console_pattern
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 has_cmd
from avocado.utils import archive
from avocado import skipUnless
class AST2x00MachineSDK(QemuSystemTest, LinuxSSHMixIn):
EXTRA_BOOTARGS = (
'quiet '
'systemd.mask=org.openbmc.HostIpmi.service '
'systemd.mask=xyz.openbmc_project.Chassis.Control.Power@0.service '
'systemd.mask=modprobe@fuse.service '
'systemd.mask=rngd.service '
'systemd.mask=obmc-console@ttyS2.service '
)
# FIXME: Although these tests boot a whole distro they are still
# slower than comparable machine models. There may be some
# optimisations which bring down the runtime. In the meantime they
# have generous timeouts and are disable for CI which aims for all
# tests to run in less than 60 seconds.
timeout = 240
def wait_for_console_pattern(self, success_message, vm=None):
wait_for_console_pattern(self, success_message,
failure_message='Kernel panic - not syncing',
vm=vm)
def do_test_arm_aspeed_sdk_start(self, image):
self.require_netdev('user')
self.vm.set_console()
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
'-net', 'nic', '-net', 'user,hostfwd=:127.0.0.1:0-:22')
self.vm.launch()
self.wait_for_console_pattern('U-Boot 2019.04')
interrupt_interactive_console_until_pattern(
self, 'Hit any key to stop autoboot:', 'ast#')
exec_command_and_wait_for_pattern(
self, 'setenv bootargs ${bootargs} ' + self.EXTRA_BOOTARGS, 'ast#')
exec_command_and_wait_for_pattern(
self, 'boot', '## Loading kernel from FIT Image')
self.wait_for_console_pattern('Starting kernel ...')
def do_test_aarch64_aspeed_sdk_start(self, image):
self.vm.set_console()
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
'-net', 'nic', '-net', 'user,hostfwd=:127.0.0.1:0-:22')
self.vm.launch()
self.wait_for_console_pattern('U-Boot 2023.10')
self.wait_for_console_pattern('## Loading kernel from FIT Image')
self.wait_for_console_pattern('Starting kernel ...')
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
def test_arm_ast2500_evb_sdk(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:ast2500-evb
:avocado: tags=flaky
"""
image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
'download/v08.06/ast2500-default-obmc.tar.gz')
image_hash = ('e1755f3cadff69190438c688d52dd0f0d399b70a1e14b1d3d5540fc4851d38ca')
image_path = self.fetch_asset(image_url, asset_hash=image_hash,
algorithm='sha256')
archive.extract(image_path, self.workdir)
self.do_test_arm_aspeed_sdk_start(
self.workdir + '/ast2500-default/image-bmc')
self.wait_for_console_pattern('nodistro.0 ast2500-default ttyS4')
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
def test_arm_ast2600_evb_sdk(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:ast2600-evb
:avocado: tags=flaky
"""
image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
'download/v08.06/ast2600-a2-obmc.tar.gz')
image_hash = ('9083506135f622d5e7351fcf7d4e1c7125cee5ba16141220c0ba88931f3681a4')
image_path = self.fetch_asset(image_url, asset_hash=image_hash,
algorithm='sha256')
archive.extract(image_path, self.workdir)
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test');
self.vm.add_args('-device',
'ds1338,bus=aspeed.i2c.bus.5,address=0x32');
self.do_test_arm_aspeed_sdk_start(
self.workdir + '/ast2600-a2/image-bmc')
self.wait_for_console_pattern('nodistro.0 ast2600-a2 ttyS4')
self.ssh_connect('root', '0penBmc', False)
self.ssh_command('dmesg -c > /dev/null')
self.ssh_command_output_contains(
'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device ; '
'dmesg -c',
'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d');
self.ssh_command_output_contains(
'cat /sys/class/hwmon/hwmon19/temp1_input', '0')
self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
property='temperature', value=18000);
self.ssh_command_output_contains(
'cat /sys/class/hwmon/hwmon19/temp1_input', '18000')
self.ssh_command_output_contains(
'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device ; '
'dmesg -c',
'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32');
year = time.strftime("%Y")
self.ssh_command_output_contains('/sbin/hwclock -f /dev/rtc1', year);
def test_aarch64_ast2700_evb_sdk_v09_02(self):
"""
:avocado: tags=arch:aarch64
:avocado: tags=machine:ast2700-evb
"""
image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/'
'download/v09.02/ast2700-default-obmc.tar.gz')
image_hash = 'ac969c2602f4e6bdb69562ff466b89ae3fe1d86e1f6797bb7969d787f82116a7'
image_path = self.fetch_asset(image_url, asset_hash=image_hash,
algorithm='sha256')
archive.extract(image_path, self.workdir)
num_cpu = 4
image_dir = self.workdir + '/ast2700-default/'
uboot_size = os.path.getsize(image_dir + 'u-boot-nodtb.bin')
uboot_dtb_load_addr = hex(0x400000000 + uboot_size)
load_images_list = [
{
'addr': '0x400000000',
'file': image_dir + 'u-boot-nodtb.bin'
},
{
'addr': str(uboot_dtb_load_addr),
'file': image_dir + 'u-boot.dtb'
},
{
'addr': '0x430000000',
'file': image_dir + 'bl31.bin'
},
{
'addr': '0x430080000',
'file': image_dir + 'optee/tee-raw.bin'
}
]
for load_image in load_images_list:
addr = load_image['addr']
file = load_image['file']
self.vm.add_args('-device',
f'loader,force-raw=on,addr={addr},file={file}')
for i in range(num_cpu):
self.vm.add_args('-device',
f'loader,addr=0x430000000,cpu-num={i}')
self.vm.add_args('-smp', str(num_cpu))
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
self.do_test_aarch64_aspeed_sdk_start(image_dir + 'image-bmc')
self.wait_for_console_pattern('nodistro.0 ast2700-default ttyS12')
self.ssh_connect('root', '0penBmc', False)
self.ssh_command('dmesg -c > /dev/null')
self.ssh_command_output_contains(
'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device '
'&& dmesg -c',
'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d');
self.ssh_command_output_contains(
'cat /sys/class/hwmon/hwmon20/temp1_input', '0')
self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
property='temperature', value=18000)
self.ssh_command_output_contains(
'cat /sys/class/hwmon/hwmon20/temp1_input', '18000')

View File

@ -1,224 +0,0 @@
# Functional test that boots known good tuxboot images the same way
# that tuxrun (www.tuxrun.org) does. This tool is used by things like
# the LKFT project to run regression tests on kernels.
#
# Copyright (c) 2023 Linaro Ltd.
#
# Author:
# Alex Bennée <alex.bennee@linaro.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later
import os
import time
import tempfile
from avocado import skip, skipUnless
from avocado_qemu import QemuSystemTest
from avocado_qemu import exec_command, exec_command_and_wait_for_pattern
from avocado_qemu import wait_for_console_pattern
from avocado.utils import process
from avocado.utils.path import find_command
class TuxRunBaselineTest(QemuSystemTest):
"""
:avocado: tags=accel:tcg
"""
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0'
# Tests are ~10-40s, allow for --debug/--enable-gcov overhead
timeout = 100
def get_tag(self, tagname, default=None):
"""
Get the metadata tag or return the default.
"""
utag = self._get_unique_tag_val(tagname)
print(f"{tagname}/{default} -> {utag}")
if utag:
return utag
return default
def setUp(self):
super().setUp()
# We need zstd for all the tuxrun tests
# See https://github.com/avocado-framework/avocado/issues/5609
zstd = find_command('zstd', False)
if zstd is False:
self.cancel('Could not find "zstd", which is required to '
'decompress rootfs')
self.zstd = zstd
# Process the TuxRun specific tags, most machines work with
# reasonable defaults but we sometimes need to tweak the
# config. To avoid open coding everything we store all these
# details in the metadata for each test.
# The tuxboot tag matches the root directory
self.tuxboot = self.get_tag('tuxboot')
# Most Linux's use ttyS0 for their serial port
self.console = self.get_tag('console', "ttyS0")
# Does the machine shutdown QEMU nicely on "halt"
self.shutdown = self.get_tag('shutdown')
# The name of the kernel Image file
self.image = self.get_tag('image', "Image")
self.root = self.get_tag('root', "vda")
# Occasionally we need extra devices to hook things up
self.extradev = self.get_tag('extradev')
self.qemu_img = super().get_qemu_img()
def wait_for_console_pattern(self, success_message, vm=None):
wait_for_console_pattern(self, success_message,
failure_message='Kernel panic - not syncing',
vm=vm)
def fetch_tuxrun_assets(self, csums=None, dt=None):
"""
Fetch the TuxBoot assets. They are stored in a standard way so we
use the per-test tags to fetch details.
"""
base_url = f"https://storage.tuxboot.com/20230331/{self.tuxboot}/"
# empty hash if we weren't passed one
csums = {} if csums is None else csums
ksum = csums.get(self.image, None)
isum = csums.get("rootfs.ext4.zst", None)
kernel_image = self.fetch_asset(base_url + self.image,
asset_hash = ksum,
algorithm = "sha256")
disk_image_zst = self.fetch_asset(base_url + "rootfs.ext4.zst",
asset_hash = isum,
algorithm = "sha256")
cmd = f"{self.zstd} -d {disk_image_zst} -o {self.workdir}/rootfs.ext4"
process.run(cmd)
if dt:
dsum = csums.get(dt, None)
dtb = self.fetch_asset(base_url + dt,
asset_hash = dsum,
algorithm = "sha256")
else:
dtb = None
return (kernel_image, self.workdir + "/rootfs.ext4", dtb)
def prepare_run(self, kernel, disk, drive, dtb=None, console_index=0):
"""
Setup to run and add the common parameters to the system
"""
self.vm.set_console(console_index=console_index)
# all block devices are raw ext4's
blockdev = "driver=raw,file.driver=file," \
+ f"file.filename={disk},node-name=hd0"
kcmd_line = self.KERNEL_COMMON_COMMAND_LINE
kcmd_line += f" root=/dev/{self.root}"
kcmd_line += f" console={self.console}"
self.vm.add_args('-kernel', kernel,
'-append', kcmd_line,
'-blockdev', blockdev)
# Sometimes we need extra devices attached
if self.extradev:
self.vm.add_args('-device', self.extradev)
self.vm.add_args('-device',
f"{drive},drive=hd0")
# Some machines need an explicit DTB
if dtb:
self.vm.add_args('-dtb', dtb)
def run_tuxtest_tests(self, haltmsg):
"""
Wait for the system to boot up, wait for the login prompt and
then do a few things on the console. Trigger a shutdown and
wait to exit cleanly.
"""
self.wait_for_console_pattern("Welcome to TuxTest")
time.sleep(0.2)
exec_command(self, 'root')
time.sleep(0.2)
exec_command(self, 'cat /proc/interrupts')
time.sleep(0.1)
exec_command(self, 'cat /proc/self/maps')
time.sleep(0.1)
exec_command(self, 'uname -a')
time.sleep(0.1)
exec_command_and_wait_for_pattern(self, 'halt', haltmsg)
# Wait for VM to shut down gracefully if it can
if self.shutdown == "nowait":
self.vm.shutdown()
else:
self.vm.wait()
def common_tuxrun(self,
csums=None,
dt=None,
drive="virtio-blk-device",
haltmsg="reboot: System halted",
console_index=0):
"""
Common path for LKFT tests. Unless we need to do something
special with the command line we can process most things using
the tag metadata.
"""
(kernel, disk, dtb) = self.fetch_tuxrun_assets(csums, dt)
self.prepare_run(kernel, disk, drive, dtb, console_index)
self.vm.launch()
self.run_tuxtest_tests(haltmsg)
#
# The tests themselves. The configuration is derived from how
# tuxrun invokes qemu (with minor tweaks like using -blockdev
# consistently). The tuxrun equivalent is something like:
#
# tuxrun --device qemu-{ARCH} \
# --kernel https://storage.tuxboot.com/{TUXBOOT}/{IMAGE}
#
def test_arm64(self):
"""
:avocado: tags=arch:aarch64
:avocado: tags=cpu:cortex-a57
:avocado: tags=machine:virt
:avocado: tags=tuxboot:arm64
:avocado: tags=console:ttyAMA0
:avocado: tags=shutdown:nowait
"""
sums = {"Image" :
"ce95a7101a5fecebe0fe630deee6bd97b32ba41bc8754090e9ad8961ea8674c7",
"rootfs.ext4.zst" :
"bbd5ed4b9c7d3f4ca19ba71a323a843c6b585e880115df3b7765769dbd9dd061"}
self.common_tuxrun(csums=sums)
def test_arm64be(self):
"""
:avocado: tags=arch:aarch64
:avocado: tags=cpu:cortex-a57
:avocado: tags=endian:big
:avocado: tags=machine:virt
:avocado: tags=tuxboot:arm64be
:avocado: tags=console:ttyAMA0
:avocado: tags=shutdown:nowait
"""
sums = { "Image" :
"e0df4425eb2cd9ea9a283e808037f805641c65d8fcecc8f6407d8f4f339561b4",
"rootfs.ext4.zst" :
"e6ffd8813c8a335bc15728f2835f90539c84be7f8f5f691a8b01451b47fb4bd7"}
self.common_tuxrun(csums=sums)

View File

@ -11,9 +11,11 @@ endif
# Timeouts for individual tests that can be slow e.g. with debugging enabled
test_timeouts = {
'aarch64_aspeed' : 600,
'aarch64_raspi4' : 480,
'aarch64_sbsaref_alpine' : 720,
'aarch64_sbsaref_freebsd' : 720,
'aarch64_tuxrun' : 240,
'aarch64_virt' : 720,
'acpi_bits' : 420,
'arm_aspeed' : 600,
@ -47,11 +49,13 @@ tests_generic_bsduser = [
]
tests_aarch64_system_thorough = [
'aarch64_aspeed',
'aarch64_raspi3',
'aarch64_raspi4',
'aarch64_sbsaref',
'aarch64_sbsaref_alpine',
'aarch64_sbsaref_freebsd',
'aarch64_tuxrun',
'aarch64_virt',
'multiprocess',
]

View File

@ -78,13 +78,77 @@ def run_cmd(args):
def is_readable_executable_file(path):
return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK)
# @test: functional test to fail if @failure is seen
# @vm: the VM whose console to process
# @success: a non-None string to look for
# @failure: a string to look for that triggers test failure, or None
#
# Read up to 1 line of text from @vm, looking for @success
# and optionally @failure.
#
# If @success or @failure are seen, immediately return True,
# even if end of line is not yet seen. ie remainder of the
# line is left unread.
#
# If end of line is seen, with neither @success or @failure
# return False
#
# 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:
done = True
test.fail(
f"EOF in console, expected '{success}'")
break
msg += c
if success in msg:
done = True
break
if failure and failure in msg:
done = True
vm.console_socket.close()
test.fail(
f"'{failure}' found in console, expected '{success}'")
if c == b'\n':
break
console_logger = logging.getLogger('console')
try:
console_logger.debug(msg.decode().strip())
except:
console_logger.debug(msg)
return done
def _console_interaction(test, success_message, failure_message,
send_string, keep_sending=False, vm=None):
assert not keep_sending or send_string
assert success_message or send_string
if vm is None:
vm = test.vm
console = vm.console_file
console_logger = logging.getLogger('console')
test.log.debug(
f"Console interaction: success_msg='{success_message}' " +
f"failure_msg='{failure_message}' send_string='{send_string}'")
# We'll process console in bytes, to avoid having to
# deal with unicode decode errors from receiving
# partial utf8 byte sequences
success_message_b = None
if success_message is not None:
success_message_b = success_message.encode()
failure_message_b = None
if failure_message is not None:
failure_message_b = failure_message.encode()
while True:
if send_string:
vm.console_socket.sendall(send_string.encode())
@ -92,25 +156,15 @@ def _console_interaction(test, success_message, failure_message,
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 success_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:
if _console_read_line_until_match(test, vm,
success_message_b,
failure_message_b):
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,
@ -135,6 +189,7 @@ def interrupt_interactive_console_until_pattern(test, success_message,
:param interrupt_string: a string to send to the console before trying
to read a new line
"""
assert success_message
_console_interaction(test, success_message, failure_message,
interrupt_string, True)
@ -149,6 +204,7 @@ def wait_for_console_pattern(test, success_message, failure_message=None,
:param success_message: if this message appears, test succeeds
:param failure_message: if this message appears, test fails
"""
assert success_message
_console_interaction(test, success_message, failure_message, None, vm=vm)
def exec_command(test, command):
@ -177,6 +233,7 @@ def exec_command_and_wait_for_pattern(test, command,
:param success_message: if this message appears, test succeeds
:param failure_message: if this message appears, test fails
"""
assert success_message
_console_interaction(test, success_message, failure_message, command + '\r')
def get_qemu_img(test):

View File

@ -13,8 +13,9 @@
import logging
import os
import subprocess
import pycotap
import shutil
import subprocess
import sys
import unittest
import uuid
@ -40,11 +41,12 @@ class QemuBaseTest(unittest.TestCase):
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())
self.outputdir = os.path.join(BUILD_DIR, 'tests', 'functional',
self.arch, self.id())
self.workdir = os.path.join(self.outputdir, 'scratch')
os.makedirs(self.workdir, exist_ok=True)
self.logdir = self.workdir
self.logdir = self.outputdir
self.log_filename = os.path.join(self.logdir, 'base.log')
self.log = logging.getLogger('qemu-test')
self.log.setLevel(logging.DEBUG)
@ -55,7 +57,15 @@ class QemuBaseTest(unittest.TestCase):
self._log_fh.setFormatter(fileFormatter)
self.log.addHandler(self._log_fh)
# Capture QEMUMachine logging
self.machinelog = logging.getLogger('qemu.machine')
self.machinelog.setLevel(logging.DEBUG)
self.machinelog.addHandler(self._log_fh)
def tearDown(self):
if "QEMU_TEST_KEEP_SCRATCH" not in os.environ:
shutil.rmtree(self.workdir)
self.machinelog.removeHandler(self._log_fh)
self.log.removeHandler(self._log_fh)
def main():
@ -71,10 +81,12 @@ class QemuBaseTest(unittest.TestCase):
res = unittest.main(module = None, testRunner = tr, exit = False,
argv=["__dummy__", path])
for (test, message) in res.result.errors + res.result.failures:
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)
if hasattr(test, "log_filename"):
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)
sys.exit(not res.result.wasSuccessful())
@ -108,7 +120,7 @@ class QemuSystemTest(QemuBaseTest):
console_log = logging.getLogger('console')
console_log.setLevel(logging.DEBUG)
self.console_log_name = os.path.join(self.workdir, 'console.log')
self.console_log_name = os.path.join(self.logdir, 'console.log')
self._console_log_fh = logging.FileHandler(self.console_log_name,
mode='w')
self._console_log_fh.setLevel(logging.DEBUG)
@ -159,10 +171,19 @@ class QemuSystemTest(QemuBaseTest):
self.skipTest('no support for device ' + devicename)
def _new_vm(self, name, *args):
vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir)
vm = QEMUMachine(self.qemu_bin,
name=name,
base_temp_dir=self.workdir,
log_dir=self.logdir)
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)
sockpath = os.environ.get("QEMU_TEST_QMP_BACKDOOR", None)
if sockpath is not None:
vm.add_args("-chardev",
f"socket,id=backdoor,path={sockpath},server=on,wait=off",
"-mon", "chardev=backdoor,mode=control")
if args:
vm.add_args(*args)
return vm

View File

@ -39,7 +39,6 @@ class TuxRunBaselineTest(QemuSystemTest):
super().setUp()
# We need zstd for all the tuxrun tests
# See https://github.com/avocado-framework/avocado/issues/5609
(has_zstd, msg) = has_cmd('zstd')
if has_zstd is False:
self.skipTest(msg)
@ -125,16 +124,12 @@ class TuxRunBaselineTest(QemuSystemTest):
then do a few things on the console. Trigger a shutdown and
wait to exit cleanly.
"""
self.wait_for_console_pattern("Welcome to TuxTest")
time.sleep(0.2)
exec_command(self, 'root')
time.sleep(0.2)
exec_command(self, 'cat /proc/interrupts')
time.sleep(0.1)
exec_command(self, 'cat /proc/self/maps')
time.sleep(0.1)
exec_command(self, 'uname -a')
time.sleep(0.1)
ps1='root@tuxtest:~#'
self.wait_for_console_pattern('tuxtest login:')
exec_command_and_wait_for_pattern(self, 'root', ps1)
exec_command_and_wait_for_pattern(self, 'cat /proc/interrupts', ps1)
exec_command_and_wait_for_pattern(self, 'cat /proc/self/maps', ps1)
exec_command_and_wait_for_pattern(self, 'uname -a', ps1)
exec_command_and_wait_for_pattern(self, 'halt', haltmsg)
# Wait for VM to shut down gracefully if it can

View File

@ -0,0 +1,98 @@
#!/usr/bin/env python3
#
# Functional test that boots the ASPEED SoCs with firmware
#
# Copyright (C) 2022 ASPEED Technology Inc
#
# SPDX-License-Identifier: GPL-2.0-or-later
import sys
import os
from qemu_test import QemuSystemTest, Asset
from qemu_test import wait_for_console_pattern
from qemu_test import exec_command_and_wait_for_pattern
from qemu_test.utils import archive_extract
class AST2x00MachineSDK(QemuSystemTest):
def do_test_aarch64_aspeed_sdk_start(self, image):
self.require_netdev('user')
self.vm.set_console()
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
'-net', 'nic', '-net', 'user', '-snapshot')
self.vm.launch()
wait_for_console_pattern(self, 'U-Boot 2023.10')
wait_for_console_pattern(self, '## Loading kernel from FIT Image')
wait_for_console_pattern(self, 'Starting kernel ...')
ASSET_SDK_V902_AST2700 = Asset(
'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.02/ast2700-default-obmc.tar.gz',
'ac969c2602f4e6bdb69562ff466b89ae3fe1d86e1f6797bb7969d787f82116a7')
def test_aarch64_ast2700_evb_sdk_v09_02(self):
self.set_machine('ast2700-evb')
image_path = self.ASSET_SDK_V902_AST2700.fetch()
archive_extract(image_path, self.workdir)
num_cpu = 4
image_dir = self.workdir + '/ast2700-default/'
uboot_size = os.path.getsize(image_dir + 'u-boot-nodtb.bin')
uboot_dtb_load_addr = hex(0x400000000 + uboot_size)
load_images_list = [
{
'addr': '0x400000000',
'file': image_dir + 'u-boot-nodtb.bin'
},
{
'addr': str(uboot_dtb_load_addr),
'file': image_dir + 'u-boot.dtb'
},
{
'addr': '0x430000000',
'file': image_dir + 'bl31.bin'
},
{
'addr': '0x430080000',
'file': image_dir + 'optee/tee-raw.bin'
}
]
for load_image in load_images_list:
addr = load_image['addr']
file = load_image['file']
self.vm.add_args('-device',
f'loader,force-raw=on,addr={addr},file={file}')
for i in range(num_cpu):
self.vm.add_args('-device',
f'loader,addr=0x430000000,cpu-num={i}')
self.vm.add_args('-smp', str(num_cpu))
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
self.do_test_aarch64_aspeed_sdk_start(image_dir + 'image-bmc')
wait_for_console_pattern(self, 'ast2700-default login:')
exec_command_and_wait_for_pattern(self, 'root', 'Password:')
exec_command_and_wait_for_pattern(self,
'0penBmc', 'root@ast2700-default:~#')
exec_command_and_wait_for_pattern(self,
'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ',
'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d');
exec_command_and_wait_for_pattern(self,
'cat /sys/class/hwmon/hwmon20/temp1_input', '0')
self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
property='temperature', value=18000)
exec_command_and_wait_for_pattern(self,
'cat /sys/class/hwmon/hwmon20/temp1_input', '18000')
if __name__ == '__main__':
QemuSystemTest.main()

View File

@ -0,0 +1,50 @@
#!/usr/bin/env python3
#
# Functional test that boots known good tuxboot images the same way
# that tuxrun (www.tuxrun.org) does. This tool is used by things like
# the LKFT project to run regression tests on kernels.
#
# Copyright (c) 2023 Linaro Ltd.
#
# Author:
# Alex Bennée <alex.bennee@linaro.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import Asset
from qemu_test.tuxruntest import TuxRunBaselineTest
class TuxRunAarch64Test(TuxRunBaselineTest):
ASSET_ARM64_KERNEL = Asset(
'https://storage.tuxboot.com/buildroot/20241119/arm64/Image',
'b74743c5e89e1cea0f73368d24ae0ae85c5204ff84be3b5e9610417417d2f235')
ASSET_ARM64_ROOTFS = Asset(
'https://storage.tuxboot.com/buildroot/20241119/arm64/rootfs.ext4.zst',
'a1acaaae2068df4648d04ff75f532aaa8c5edcd6b936122b6f0db4848a07b465')
def test_arm64(self):
self.set_machine('virt')
self.cpu='cortex-a57'
self.console='ttyAMA0'
self.wait_for_shutdown=False
self.common_tuxrun(kernel_asset=self.ASSET_ARM64_KERNEL,
rootfs_asset=self.ASSET_ARM64_ROOTFS)
ASSET_ARM64BE_KERNEL = Asset(
'https://storage.tuxboot.com/buildroot/20241119/arm64be/Image',
'fd6af4f16689d17a2c24fe0053cc212edcdf77abdcaf301800b8d38fa9f6e109')
ASSET_ARM64BE_ROOTFS = Asset(
'https://storage.tuxboot.com/buildroot/20241119/arm64be/rootfs.ext4.zst',
'f5e9371b62701aab8dead52592ca7488c8a9e255c9be8d7635c7f30f477c2c21')
def test_arm64be(self):
self.set_machine('virt')
self.cpu='cortex-a57'
self.console='ttyAMA0'
self.wait_for_shutdown=False
self.common_tuxrun(kernel_asset=self.ASSET_ARM64BE_KERNEL,
rootfs_asset=self.ASSET_ARM64BE_ROOTFS)
if __name__ == '__main__':
TuxRunBaselineTest.main()

View File

@ -150,7 +150,6 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._vm = None
self._workDir = None
self._baseDir = None
self._debugcon_addr = '0x403'
@ -169,7 +168,7 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
config_file = 'bits-cfg.txt'
bits_config_dir = os.path.join(self._baseDir, 'acpi-bits',
'bits-config')
target_config_dir = os.path.join(self._workDir,
target_config_dir = os.path.join(self.workdir,
'bits-%d' %self.BITS_INTERNAL_VER,
'boot')
self.assertTrue(os.path.exists(bits_config_dir))
@ -186,7 +185,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,
target_test_dir = os.path.join(self.workdir,
'bits-%d' %self.BITS_INTERNAL_VER,
'boot', 'python')
@ -196,11 +195,12 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
for filename in os.listdir(bits_test_dir):
if os.path.isfile(os.path.join(bits_test_dir, filename)) and \
filename.endswith('.py2'):
# all test scripts are named with extension .py2 so that
# avocado does not try to load them. These scripts are
# written for python 2.7 not python 3 and hence if avocado
# loaded them, it would complain about python 3 specific
# syntaxes.
# All test scripts are named with extension .py2 so that
# they are not run by accident.
#
# These scripts are intended to run inside the test VM
# and are written for python 2.7 not python 3, hence
# would cause syntax errors if loaded ouside the VM.
newfilename = os.path.splitext(filename)[0] + '.py'
shutil.copy2(os.path.join(bits_test_dir, filename),
os.path.join(target_test_dir, newfilename))
@ -224,8 +224,8 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
the directory where we have extracted our pre-built bits grub
tarball.
"""
grub_x86_64_mods = os.path.join(self._workDir, 'grub-inst-x86_64-efi')
grub_i386_mods = os.path.join(self._workDir, 'grub-inst')
grub_x86_64_mods = os.path.join(self.workdir, 'grub-inst-x86_64-efi')
grub_i386_mods = os.path.join(self.workdir, 'grub-inst')
self.assertTrue(os.path.exists(grub_x86_64_mods))
self.assertTrue(os.path.exists(grub_i386_mods))
@ -246,11 +246,11 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
""" Uses grub-mkrescue to generate a fresh bits iso with the python
test scripts
"""
bits_dir = os.path.join(self._workDir,
bits_dir = os.path.join(self.workdir,
'bits-%d' %self.BITS_INTERNAL_VER)
iso_file = os.path.join(self._workDir,
iso_file = os.path.join(self.workdir,
'bits-%d.iso' %self.BITS_INTERNAL_VER)
mkrescue_script = os.path.join(self._workDir,
mkrescue_script = os.path.join(self.workdir,
'grub-inst-x86_64-efi', 'bin',
'grub-mkrescue')
@ -289,17 +289,7 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
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
# directory. It gives us more control over the generated bits
# log files and also for debugging, we may chose not to remove
# this working directory so that the logs and iso can be
# inspected manually and archived if needed.
self._workDir = tempfile.mkdtemp(prefix='acpi-bits-',
suffix='.tmp')
self.logger.info('working dir: %s', self._workDir)
prebuiltDir = os.path.join(self._workDir, 'prebuilt')
prebuiltDir = os.path.join(self.workdir, 'prebuilt')
if not os.path.isdir(prebuiltDir):
os.mkdir(prebuiltDir, mode=0o775)
@ -320,10 +310,10 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
# extract the bits software in the temp working directory
with zipfile.ZipFile(bits_zip_file, 'r') as zref:
zref.extractall(self._workDir)
zref.extractall(self.workdir)
with tarfile.open(grub_tar_file, 'r', encoding='utf-8') as tarball:
tarball.extractall(self._workDir)
tarball.extractall(self.workdir)
self.copy_test_scripts()
self.copy_bits_config()
@ -333,7 +323,7 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
"""parse the log generated by running bits tests and
check for failures.
"""
debugconf = os.path.join(self._workDir, self._debugcon_log)
debugconf = os.path.join(self.workdir, self._debugcon_log)
log = ""
with open(debugconf, 'r', encoding='utf-8') as filehandle:
log = filehandle.read()
@ -359,25 +349,18 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
"""
if self._vm:
self.assertFalse(not self._vm.is_running)
if not os.getenv('BITS_DEBUG') and self._workDir:
self.logger.info('removing the work directory %s', self._workDir)
shutil.rmtree(self._workDir)
else:
self.logger.info('not removing the work directory %s ' \
'as BITS_DEBUG is ' \
'passed in the environment', self._workDir)
super().tearDown()
def test_acpi_smbios_bits(self):
"""The main test case implementation."""
iso_file = os.path.join(self._workDir,
iso_file = os.path.join(self.workdir,
'bits-%d.iso' %self.BITS_INTERNAL_VER)
self.assertTrue(os.access(iso_file, os.R_OK))
self._vm = QEMUBitsMachine(binary=self.qemu_bin,
base_temp_dir=self._workDir,
base_temp_dir=self.workdir,
debugcon_log=self._debugcon_log,
debugcon_addr=self._debugcon_addr)
@ -399,8 +382,6 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
# biosbits has been configured to run all the specified test suites
# in batch mode and then automatically initiate a vm shutdown.
# Set timeout to BITS_TIMEOUT for SHUTDOWN event from bits VM at par
# with the avocado test timeout.
self._vm.event_wait('SHUTDOWN', timeout=BITS_TIMEOUT)
self._vm.wait(timeout=None)
self.logger.debug("Checking console output ...")

View File

@ -14,7 +14,6 @@ import tempfile
from qemu_test import LinuxKernelTest, Asset
from qemu_test import exec_command_and_wait_for_pattern
from qemu_test import interrupt_interactive_console_until_pattern
from qemu_test import exec_command
from qemu_test import has_cmd
from qemu_test.utils import archive_extract
from zipfile import ZipFile
@ -136,10 +135,8 @@ class AST2x00Machine(LinuxKernelTest):
self.wait_for_console_pattern('lease of 10.0.2.15')
# the line before login:
self.wait_for_console_pattern(pattern)
time.sleep(0.1)
exec_command(self, 'root')
time.sleep(0.1)
exec_command(self, "passw0rd")
exec_command_and_wait_for_pattern(self, 'root', 'Password:')
exec_command_and_wait_for_pattern(self, 'passw0rd', '#')
def do_test_arm_aspeed_buildroot_poweroff(self):
exec_command_and_wait_for_pattern(self, 'poweroff',
@ -158,7 +155,7 @@ class AST2x00Machine(LinuxKernelTest):
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test');
self.do_test_arm_aspeed_buildroot_start(image_path, '0x0',
'Aspeed AST2500 EVB')
'ast2500-evb login:')
exec_command_and_wait_for_pattern(self,
'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device',
@ -188,7 +185,8 @@ class AST2x00Machine(LinuxKernelTest):
'ds1338,bus=aspeed.i2c.bus.3,address=0x32');
self.vm.add_args('-device',
'i2c-echo,bus=aspeed.i2c.bus.3,address=0x42');
self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed AST2600 EVB')
self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00',
'ast2600-evb login:')
exec_command_and_wait_for_pattern(self,
'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device',
@ -209,8 +207,8 @@ class AST2x00Machine(LinuxKernelTest):
exec_command_and_wait_for_pattern(self,
'echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-3/new_device',
'i2c i2c-3: new_device: Instantiated device slave-24c02 at 0x64');
exec_command(self, 'i2cset -y 3 0x42 0x64 0x00 0xaa i');
time.sleep(0.1)
exec_command_and_wait_for_pattern(self,
'i2cset -y 3 0x42 0x64 0x00 0xaa i', '#');
exec_command_and_wait_for_pattern(self,
'hexdump /sys/bus/i2c/devices/3-1064/slave-eeprom',
'0000000 ffaa ffff ffff ffff ffff ffff ffff ffff');
@ -252,6 +250,74 @@ class AST2x00Machine(LinuxKernelTest):
self.do_test_arm_aspeed_buildroot_poweroff()
def do_test_arm_aspeed_sdk_start(self, image):
self.require_netdev('user')
self.vm.set_console()
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
'-net', 'nic', '-net', 'user', '-snapshot')
self.vm.launch()
self.wait_for_console_pattern('U-Boot 2019.04')
self.wait_for_console_pattern('## Loading kernel from FIT Image')
self.wait_for_console_pattern('Starting kernel ...')
ASSET_SDK_V806_AST2500 = Asset(
'https://github.com/AspeedTech-BMC/openbmc/releases/download/v08.06/ast2500-default-obmc.tar.gz',
'e1755f3cadff69190438c688d52dd0f0d399b70a1e14b1d3d5540fc4851d38ca')
def test_arm_ast2500_evb_sdk(self):
self.set_machine('ast2500-evb')
image_path = self.ASSET_SDK_V806_AST2500.fetch()
archive_extract(image_path, self.workdir)
self.do_test_arm_aspeed_sdk_start(
self.workdir + '/ast2500-default/image-bmc')
self.wait_for_console_pattern('ast2500-default login:')
ASSET_SDK_V806_AST2600_A2 = Asset(
'https://github.com/AspeedTech-BMC/openbmc/releases/download/v08.06/ast2600-a2-obmc.tar.gz',
'9083506135f622d5e7351fcf7d4e1c7125cee5ba16141220c0ba88931f3681a4')
def test_arm_ast2600_evb_sdk(self):
self.set_machine('ast2600-evb')
image_path = self.ASSET_SDK_V806_AST2600_A2.fetch()
archive_extract(image_path, self.workdir)
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test');
self.vm.add_args('-device',
'ds1338,bus=aspeed.i2c.bus.5,address=0x32');
self.do_test_arm_aspeed_sdk_start(
self.workdir + '/ast2600-a2/image-bmc')
self.wait_for_console_pattern('ast2600-a2 login:')
exec_command_and_wait_for_pattern(self, 'root', 'Password:')
exec_command_and_wait_for_pattern(self, '0penBmc', 'root@ast2600-a2:~#')
exec_command_and_wait_for_pattern(self,
'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device',
'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d');
exec_command_and_wait_for_pattern(self,
'cat /sys/class/hwmon/hwmon19/temp1_input', '0')
self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
property='temperature', value=18000);
exec_command_and_wait_for_pattern(self,
'cat /sys/class/hwmon/hwmon19/temp1_input', '18000')
exec_command_and_wait_for_pattern(self,
'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device',
'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32');
year = time.strftime("%Y")
exec_command_and_wait_for_pattern(self,
'/sbin/hwclock -f /dev/rtc1', year);
class AST2x00MachineMMC(LinuxKernelTest):
ASSET_RAINIER_EMMC = Asset(

View File

@ -37,11 +37,6 @@ class BananaPiMachine(LinuxKernelTest):
'5b41b4e11423e562c6011640f9a7cd3bdd0a3d42b83430f7caa70a432e6cd82c')
def test_arm_bpim2u(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:bpim2u
:avocado: tags=accel:tcg
"""
self.set_machine('bpim2u')
deb_path = self.ASSET_DEB.fetch()
kernel_path = self.extract_from_deb(deb_path,
@ -64,11 +59,6 @@ class BananaPiMachine(LinuxKernelTest):
os.remove(dtb_path)
def test_arm_bpim2u_initrd(self):
"""
:avocado: tags=arch:arm
:avocado: tags=accel:tcg
:avocado: tags=machine:bpim2u
"""
self.set_machine('bpim2u')
deb_path = self.ASSET_DEB.fetch()
kernel_path = self.extract_from_deb(deb_path,
@ -105,11 +95,6 @@ class BananaPiMachine(LinuxKernelTest):
os.remove(initrd_path)
def test_arm_bpim2u_gmac(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:bpim2u
:avocado: tags=device:sd
"""
self.set_machine('bpim2u')
self.require_netdev('user')
@ -160,11 +145,6 @@ class BananaPiMachine(LinuxKernelTest):
@skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 'storage limited')
def test_arm_bpim2u_openwrt_22_03_3(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:bpim2u
:avocado: tags=device:sd
"""
self.set_machine('bpim2u')
# This test download a 8.9 MiB compressed image and expand it
# to 127 MiB.

View File

@ -49,11 +49,6 @@ class BananaPiMachine(LinuxKernelTest):
'20d3e07dc057e15c12452620e90ecab2047f0f7940d9cba8182ebc795927177f')
def test_arm_orangepi(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:orangepi-pc
:avocado: tags=accel:tcg
"""
self.set_machine('orangepi-pc')
deb_path = self.ASSET_DEB.fetch()
kernel_path = self.extract_from_deb(deb_path,
@ -75,11 +70,6 @@ class BananaPiMachine(LinuxKernelTest):
os.remove(dtb_path)
def test_arm_orangepi_initrd(self):
"""
:avocado: tags=arch:arm
:avocado: tags=accel:tcg
:avocado: tags=machine:orangepi-pc
"""
self.set_machine('orangepi-pc')
deb_path = self.ASSET_DEB.fetch()
kernel_path = self.extract_from_deb(deb_path,
@ -115,12 +105,6 @@ class BananaPiMachine(LinuxKernelTest):
os.remove(initrd_path)
def test_arm_orangepi_sd(self):
"""
:avocado: tags=arch:arm
:avocado: tags=accel:tcg
:avocado: tags=machine:orangepi-pc
:avocado: tags=device:sd
"""
self.set_machine('orangepi-pc')
self.require_netdev('user')
deb_path = self.ASSET_DEB.fetch()
@ -167,11 +151,6 @@ class BananaPiMachine(LinuxKernelTest):
@skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 'storage limited')
def test_arm_orangepi_armbian(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:orangepi-pc
:avocado: tags=device:sd
"""
self.set_machine('orangepi-pc')
# This test download a 275 MiB compressed image and expand it
# to 1036 MiB, but the underlying filesystem is 1552 MiB...
@ -208,12 +187,6 @@ class BananaPiMachine(LinuxKernelTest):
@skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 'storage limited')
def test_arm_orangepi_uboot_netbsd9(self):
"""
:avocado: tags=arch:arm
:avocado: tags=machine:orangepi-pc
:avocado: tags=device:sd
:avocado: tags=os:netbsd
"""
self.set_machine('orangepi-pc')
# This test download a 304MB compressed image and expand it to 2GB
deb_path = self.ASSET_UBOOT.fetch()

View File

@ -37,8 +37,7 @@ class NextCubeMachine(QemuSystemTest):
self.vm.launch()
self.log.info('VM launched, waiting for display')
# TODO: Use avocado.utils.wait.wait_for to catch the
# 'displaysurface_create 1120x832' trace-event.
# TODO: wait for the 'displaysurface_create 1120x832' trace-event.
time.sleep(2)
self.vm.cmd('human-monitor-command',

View File

@ -129,7 +129,7 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
screendump_path = os.path.join(self.workdir, 'screendump.pbm')
kernel_path_gz = self.ASSET_KERNEL_4_7_0.fetch()
kernel_path = self.workdir + "vmlinux"
kernel_path = self.workdir + "/vmlinux"
gzip_uncompress(kernel_path_gz, kernel_path)
tuxlogo_path = self.ASSET_TUXLOGO.fetch()
@ -159,7 +159,7 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
loc = np.where(result >= match_threshold)
tuxlogo_count = 0
h, w = tuxlogo_bgr.shape[:2]
debug_png = os.getenv('AVOCADO_CV2_SCREENDUMP_PNG_PATH')
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)
cv2.rectangle(screendump_bgr, pt,

View File

@ -80,9 +80,8 @@ class VirtioGPUx86(QemuSystemTest):
self.wait_for_console_pattern("as init process")
exec_command_and_wait_for_pattern(
self, "/usr/sbin/modprobe virtio_gpu", ""
self, "/usr/sbin/modprobe virtio_gpu", "features: +virgl +edid"
)
self.wait_for_console_pattern("features: +virgl +edid")
def test_vhost_user_vga_virgl(self):
# FIXME: should check presence of vhost-user-gpu, virgl, memfd etc