From: "Daniel P. Berrangé" <berrange@redhat.com>
To: Ani Sinha <ani@anisinha.ca>
Cc: qemu-devel@nongnu.org, thuth@redhat.com,
peter.maydell@linaro.org, jsnow@redhat.com, pbonzini@redhat.com,
imammedo@redhat.com, mst@redhat.com
Subject: Re: [PATCH v2 07/11] acpi/tests/bits: add python test that exercizes QEMU bios tables using biosbits
Date: Thu, 14 Jul 2022 15:05:42 +0100 [thread overview]
Message-ID: <YtAitsVyHmsLRKEL@redhat.com> (raw)
In-Reply-To: <20220710170014.1673480-8-ani@anisinha.ca>
On Sun, Jul 10, 2022 at 10:30:10PM +0530, Ani Sinha wrote:
> This change adds python based test environment that can be used to run pytest
> from within a virtual environment. A bash script sets up a virtual environment
> and then runs the python based tests from within that environment.
> All dependent python packages are installed in the virtual environment using
> pip python module. QEMU python test modules are also available in the environment
> for spawning the QEMU based VMs.
>
> It also introduces QEMU acpi/smbios biosbits python test script which is run
> from within the python virtual environment. When the bios bits tests are run,
> bios bits binaries are downloaded from an external repo/location.
> Currently, the test points to an external private github repo where the bits
> archives are checked in.
>
> Signed-off-by: Ani Sinha <ani@anisinha.ca>
> ---
> tests/pytest/acpi-bits/acpi-bits-test-venv.sh | 59 +++
> tests/pytest/acpi-bits/acpi-bits-test.py | 382 ++++++++++++++++++
> tests/pytest/acpi-bits/meson.build | 33 ++
> tests/pytest/acpi-bits/requirements.txt | 1 +
> 4 files changed, 475 insertions(+)
> create mode 100644 tests/pytest/acpi-bits/acpi-bits-test-venv.sh
> create mode 100644 tests/pytest/acpi-bits/acpi-bits-test.py
> create mode 100644 tests/pytest/acpi-bits/meson.build
> create mode 100644 tests/pytest/acpi-bits/requirements.txt
>
> diff --git a/tests/pytest/acpi-bits/acpi-bits-test-venv.sh b/tests/pytest/acpi-bits/acpi-bits-test-venv.sh
> new file mode 100644
> index 0000000000..186395473b
> --- /dev/null
> +++ b/tests/pytest/acpi-bits/acpi-bits-test-venv.sh
> @@ -0,0 +1,59 @@
> +#!/usr/bin/env bash
> +# Generates a python virtual environment for the test to run.
> +# Then runs python test scripts from within that virtual environment.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +#
> +# Author: Ani Sinha <ani@anisinha.ca>
> +
> +set -e
> +
> +MYPATH=$(realpath ${BASH_SOURCE:-$0})
> +MYDIR=$(dirname $MYPATH)
> +
> +if [ -z "$PYTEST_SOURCE_ROOT" ]; then
> + echo -n "Please set QTEST_SOURCE_ROOT env pointing"
> + echo " to the root of the qemu source tree."
> + echo -n "This is required so that the test can find the "
> + echo "python modules that it needs for execution."
> + exit 1
> +fi
> +SRCDIR=$PYTEST_SOURCE_ROOT
> +TESTSCRIPTS=("acpi-bits-test.py")
> +PIPCMD="-m pip -q --disable-pip-version-check"
> +# we need to save the old value of PWD before we do a change-dir later
> +PYTEST_PWD=$PWD
> +
> +TESTS_PYTHON=/usr/bin/python3
> +TESTS_VENV_REQ=requirements.txt
> +
> +# sadly for pip -e and -t options do not work together.
> +# please see https://github.com/pypa/pip/issues/562
> +cd $MYDIR
> +
> +$TESTS_PYTHON -m venv .
> +$TESTS_PYTHON $PIPCMD install -e $SRCDIR/python/
> +[ -f $TESTS_VENV_REQ ] && \
> + $TESTS_PYTHON $PIPCMD install -r $TESTS_VENV_REQ || exit 0
> +
> +# venv is activated at this point.
> +
> +# run the test
> +for testscript in ${TESTSCRIPTS[@]} ; do
> + export PYTEST_PWD; python3 $testscript
> +done
> +
> +cd $PYTEST_PWD
> +
> +exit 0
> diff --git a/tests/pytest/acpi-bits/acpi-bits-test.py b/tests/pytest/acpi-bits/acpi-bits-test.py
> new file mode 100644
> index 0000000000..97e61eb709
> --- /dev/null
> +++ b/tests/pytest/acpi-bits/acpi-bits-test.py
> @@ -0,0 +1,382 @@
> +#!/usr/bin/env python3
> +# group: rw quick
> +# Exercize QEMU generated ACPI/SMBIOS tables using biosbits,
> +# https://biosbits.org/
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +#
> +# Some parts are slightly taken from qtest.py and iotests.py
> +#
> +# Authors:
> +# Ani Sinha <ani@anisinha.ca>
> +
> +# pylint: disable=invalid-name
> +
> +"""
> +QEMU bios tests using biosbits available at
> +https://biosbits.org/.
> +"""
> +
> +import logging
> +import os
> +import re
> +import shutil
> +import subprocess
> +import sys
> +import tarfile
> +import tempfile
> +import time
> +import unittest
> +from urllib import request
> +import zipfile
> +from typing import (
> + List,
> + Optional,
> + Sequence,
> +)
> +from tap import TAPTestRunner
> +from qemu.machine import QEMUMachine
> +
> +PYTESTQEMUBIN = os.getenv('PYTEST_QEMU_BINARY')
> +PYTEST_PWD = os.getenv('PYTEST_PWD')
> +
> +def get_arch():
> + """finds the arch from the qemu binary name"""
> + match = re.search('.*qemu-system-(.*)', PYTESTQEMUBIN)
> + if match:
> + return match.group(1)
> + return 'x86_64'
> +
> +ARCH = get_arch()
> +
> +class QEMUBitsMachine(QEMUMachine):
> + """
> + A QEMU VM, with isa-debugcon enabled and bits iso passed
> + using -cdrom to QEMU commandline.
> + """
> + def __init__(self,
> + binary: str,
> + args: Sequence[str] = (),
> + wrapper: Sequence[str] = (),
> + name: Optional[str] = None,
> + base_temp_dir: str = "/var/tmp",
> + debugcon_log: str = "debugcon-log.txt",
> + debugcon_addr: str = "0x403",
> + sock_dir: Optional[str] = None,
> + qmp_timer: Optional[float] = None):
> + # pylint: disable=too-many-arguments
> +
> + if name is None:
> + name = "qemu-bits-%d" % os.getpid()
> + if sock_dir is None:
> + sock_dir = base_temp_dir
> + super().__init__(binary, args, wrapper=wrapper, name=name,
> + base_temp_dir=base_temp_dir,
> + sock_dir=sock_dir, qmp_timer=qmp_timer)
> + self.debugcon_log = debugcon_log
> + self.debugcon_addr = debugcon_addr
> + self.base_temp_dir = base_temp_dir
> +
> + @property
> + def _base_args(self) -> List[str]:
> + args = super()._base_args
> + args.extend([
> + '-chardev',
> + 'file,path=%s,id=debugcon' %os.path.join(self.base_temp_dir,
> + self.debugcon_log),
> + '-device',
> + 'isa-debugcon,iobase=%s,chardev=debugcon' %self.debugcon_addr,
> + ])
> + return args
> +
> + def base_args(self):
> + """return the base argument to QEMU binary"""
> + return self._base_args
> +
> +class AcpiBitsTest(unittest.TestCase):
> + """ACPI and SMBIOS tests using biosbits."""
> + def __init__(self, *args, **kwargs):
> + super().__init__(*args, **kwargs)
> + self._vm = None
> + self._workDir = None
> + self._bitsVer = 2100
> + self._bitsLoc = "https://github.com/ani-sinha/bits/raw/bits-builds/"
This URL location gives a 404 - was it supposed to be poiinting to the
bits-builds branch ? eg to form a URL like:
https://github.com/ani-sinha/bits/blob/bits-builds/bits-2100.zip?raw=true
> + self._debugcon_addr = '0x403'
> + self._debugcon_log = 'debugcon-log.txt'
> + logging.basicConfig(level=logging.INFO)
> +
> + def copy_bits_config(self):
> + """ copies the bios bits config file into bits.
> + """
> + config_file = 'bits-cfg.txt'
> + qemu_bits_config_dir = os.path.join(os.getcwd(), 'bits-config')
> + target_config_dir = os.path.join(self._workDir,
> + 'bits-%d' %self._bitsVer, 'boot')
> + self.assertTrue(os.path.exists(qemu_bits_config_dir))
> + self.assertTrue(os.path.exists(target_config_dir))
> + self.assertTrue(os.access(os.path.join(qemu_bits_config_dir,
> + config_file), os.R_OK))
> + shutil.copy2(os.path.join(qemu_bits_config_dir, config_file),
> + target_config_dir)
> + logging.info('copied config file %s to %s',
> + config_file, target_config_dir)
> +
> + def copy_test_scripts(self):
> + """copies the python test scripts into bits. """
> + qemu_test_dir = os.path.join(os.getcwd(), 'bits-tests')
> + target_test_dir = os.path.join(self._workDir, 'bits-%d' %self._bitsVer,
> + 'boot', 'python')
> +
> + self.assertTrue(os.path.exists(qemu_test_dir))
> + self.assertTrue(os.path.exists(target_test_dir))
> +
> + for filename in os.listdir(qemu_test_dir):
> + if os.path.isfile(os.path.join(qemu_test_dir, filename)) and \
> + filename.endswith('.py'):
> + shutil.copy2(os.path.join(qemu_test_dir, filename),
> + target_test_dir)
> + logging.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.
> + testfile_pyc = os.path.splitext(filename)[0] + '.pyc'
> + if os.access(os.path.join(target_test_dir, testfile_pyc),
> + os.F_OK):
> + os.remove(os.path.join(target_test_dir, testfile_pyc))
> + logging.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
> + 'libdir'. They must be pointed to the right location so that the
> + iso can be generated appropriately. We point the two variables to
> + 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')
> +
> + self.assertTrue(os.path.exists(grub_x86_64_mods))
> + self.assertTrue(os.path.exists(grub_i386_mods))
> +
> + new_script = ""
> + with open(mkrescue, 'r') as filehandle:
> + orig_script = filehandle.read()
> + new_script = re.sub('(^prefix=)(.*)',
> + r'\1"%s"' %grub_x86_64_mods,
> + orig_script, flags=re.M)
> + new_script = re.sub('(^libdir=)(.*)', r'\1"%s/lib"' %grub_i386_mods,
> + new_script, flags=re.M)
> +
> + with open(mkrescue, 'w') as filehandle:
> + filehandle.write(new_script)
> +
> + def generate_bits_iso(self):
> + """ Uses grub-mkrescue to generate a fresh bits iso with the python
> + test scripts
> + """
> + bits_dir = os.path.join(self._workDir, 'bits-%d' %self._bitsVer)
> + iso_file = os.path.join(self._workDir, 'bits-%d.iso' %self._bitsVer)
> + mkrescue_script = os.path.join(self._workDir,
> + 'grub-inst-x86_64-efi', 'bin',
> + 'grub-mkrescue')
> +
> + self.assertTrue(os.access(mkrescue_script,
> + os.R_OK | os.W_OK | os.X_OK))
> +
> + self.fix_mkrescue(mkrescue_script)
> +
> + logging.info('calling grub-mkrescue to generate the biosbits iso ...')
> +
> + try:
> + if os.getenv('V'):
> + subprocess.check_call([mkrescue_script, '-o',
> + iso_file, bits_dir],
> + stdout=subprocess.DEVNULL)
> + else:
> + subprocess.check_call([mkrescue_script, '-o',
> + iso_file, bits_dir],
> + stderr=subprocess.DEVNULL,
> + stdout=subprocess.DEVNULL)
> + except Exception as e: # pylint: disable=broad-except
> + self.skipTest("Error while generating the bits iso. "
> + "Pass V=1 in the environment to get more details. "
> + + str(e))
> +
> + self.assertTrue(os.access(iso_file, os.R_OK))
> +
> + logging.info('iso file %s successfully generated.', iso_file)
> +
> + def setUp(self):
> + BITS_LOC = os.getenv("PYTEST_BITSLOC")
> + if BITS_LOC:
> + prefix = BITS_LOC
> + else:
> + prefix = os.path.join(os.getcwd(), 'prebuilt')
> + if not os.path.isdir(prefix):
> + os.mkdir(prefix, mode=0o775)
> +
> + bits_zip_file = os.path.join(prefix, 'bits-%d.zip'
> + %self._bitsVer)
> + grub_tar_file = os.path.join(prefix,
> + 'bits-%d-grub.tar.gz' %self._bitsVer)
> + # if the location of the bits binaries has been specified by the user
> + # and they are not found in that location, skip the test.
> + if BITS_LOC and not os.access(bits_zip_file, os.F_OK):
> + self.skipTest("test skipped since biosbits binaries " +
> + "could not be found in the specified location %s." \
> + %BITS_LOC)
> + if BITS_LOC and not os.access(grub_tar_file, os.F_OK):
> + self.skipTest("test skipped since biosbits binaries " +
> + "could not be found in the specified location %s." \
> + %BITS_LOC)
> +
> + self._workDir = tempfile.mkdtemp(prefix='acpi-bits-',
> + suffix='.tmp')
> + logging.info('working dir: %s', self._workDir)
> +
> + localArchive = "bits-%d.zip" % self._bitsVer
> + if not os.access(bits_zip_file, os.F_OK):
> + logging.info("archive %s not found in %s, downloading ...",
> + localArchive, bits_zip_file)
> + try:
> + req = request.urlopen(self._bitsLoc + localArchive)
> + with open(os.path.join(prefix, localArchive),
> + 'wb') as archivef:
> + archivef.write(req.read())
> + except Exception as e: # pylint: disable=broad-except
> + self.skipTest("test skipped since biosbits binaries " +
> + "could not be obtained." + str(e))
> + else:
> + logging.info('using locally found %s', localArchive)
so you skip downlaod if it already exists locally. IIUC it is looking
in the CWD, which is presumably the directory the QEMU build is
performed in ? So if dev cleans their build tree, the cache is lost ?
Avocado has a more persistent cache outside the build tree IIUC.
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
next prev parent reply other threads:[~2022-07-14 14:09 UTC|newest]
Thread overview: 90+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-10 17:00 [PATCH v2 00/11] Introduce new acpi/smbios python tests using biosbits Ani Sinha
2022-07-10 17:00 ` [PATCH v2 01/11] acpi/tests/bits: initial commit of test scripts that are run by biosbits Ani Sinha
2022-07-11 20:38 ` John Snow
2022-07-12 7:17 ` Ani Sinha
2022-07-12 15:23 ` John Snow
2022-07-12 15:38 ` Ani Sinha
2022-07-12 15:42 ` John Snow
2022-07-12 15:46 ` Ani Sinha
2022-07-10 17:00 ` [PATCH v2 02/11] acpi/tests/bits: add SPDX license identifiers for bios bits tests Ani Sinha
2022-07-14 13:56 ` Daniel P. Berrangé
2022-07-14 14:12 ` Ani Sinha
2022-07-10 17:00 ` [PATCH v2 03/11] acpi/tests/bits: disable acpi PSS tests that are failing in biosbits Ani Sinha
2022-07-10 17:00 ` [PATCH v2 04/11] acpi/tests/bits: add smilatency test suite from bits in order to disable it Ani Sinha
2022-07-10 17:00 ` [PATCH v2 05/11] acpi/tests/bits: add SPDX license identifiers for bios bits smilatency tests Ani Sinha
2022-07-10 17:00 ` [PATCH v2 06/11] acpi/tests/bits: disable smilatency test since it does not pass everytime Ani Sinha
2022-07-10 17:00 ` [PATCH v2 07/11] acpi/tests/bits: add python test that exercizes QEMU bios tables using biosbits Ani Sinha
2022-07-11 20:42 ` John Snow
2022-07-12 7:15 ` Ani Sinha
2022-09-06 13:05 ` Daniel P. Berrangé
2022-07-14 14:05 ` Daniel P. Berrangé [this message]
2022-07-14 14:19 ` Ani Sinha
2022-07-14 17:49 ` Ani Sinha
2022-07-14 20:43 ` Michael S. Tsirkin
2022-07-14 20:41 ` Michael S. Tsirkin
2022-07-15 4:17 ` Ani Sinha
2022-07-15 6:50 ` Michael S. Tsirkin
2022-07-16 6:36 ` Ani Sinha
2022-07-16 15:30 ` Michael S. Tsirkin
2022-07-25 18:02 ` Ani Sinha
2022-07-27 18:38 ` Ani Sinha
2022-09-16 16:00 ` Ani Sinha
2022-09-17 20:28 ` Michael S. Tsirkin
2022-09-27 8:13 ` Ani Sinha
2022-09-27 8:33 ` Daniel P. Berrangé
2022-09-27 10:07 ` Ani Sinha
2022-09-27 10:18 ` Daniel P. Berrangé
2022-09-27 10:24 ` Ani Sinha
2022-09-27 11:42 ` Ani Sinha
2022-09-27 14:05 ` Ani Sinha
2022-09-27 15:45 ` Daniel P. Berrangé
2022-09-27 21:21 ` Michael S. Tsirkin
2022-09-28 8:31 ` Thomas Huth
2022-09-28 8:35 ` Daniel P. Berrangé
2022-09-28 9:47 ` Michael S. Tsirkin
2022-09-28 9:35 ` Michael S. Tsirkin
2022-09-28 9:39 ` Thomas Huth
2022-09-28 9:56 ` Michael S. Tsirkin
2022-10-06 7:58 ` Ani Sinha
2022-10-06 8:11 ` Ani Sinha
2022-10-06 10:18 ` Ani Sinha
2022-09-27 21:19 ` Michael S. Tsirkin
2022-09-27 21:18 ` Michael S. Tsirkin
2022-09-28 3:08 ` Ani Sinha
2022-09-28 3:58 ` Michael S. Tsirkin
2022-09-28 6:06 ` Ani Sinha
2022-10-06 12:12 ` Michael S. Tsirkin
2022-09-28 6:58 ` Daniel P. Berrangé
2022-09-28 7:15 ` Ani Sinha
2022-09-28 7:26 ` Daniel P. Berrangé
2022-09-28 9:19 ` Michael S. Tsirkin
2022-09-27 21:44 ` Paolo Bonzini
2022-09-27 22:09 ` Michael S. Tsirkin
2022-09-27 23:10 ` Paolo Bonzini
2022-09-28 5:53 ` Michael S. Tsirkin
2022-09-28 7:06 ` Daniel P. Berrangé
2022-09-28 7:43 ` Thomas Huth
2022-10-09 5:21 ` Ani Sinha
2022-10-09 6:30 ` Ani Sinha
2022-10-09 16:06 ` Ani Sinha
2022-07-10 17:00 ` [PATCH v2 08/11] acpi/tests/bits: add biosbits config file for running bios tests Ani Sinha
2022-07-10 17:00 ` [PATCH v2 09/11] acpi/tests/bits: add a README file describing bits pytests Ani Sinha
2022-07-10 17:00 ` [PATCH v2 10/11] pytest: add pytest to the meson build system Ani Sinha
2022-07-11 20:46 ` John Snow
2022-07-12 6:52 ` Ani Sinha
2022-09-06 13:10 ` Daniel P. Berrangé
2022-09-27 21:26 ` Michael S. Tsirkin
2022-09-28 7:32 ` Thomas Huth
2022-09-28 9:23 ` Michael S. Tsirkin
2022-07-10 17:00 ` [PATCH v2 11/11] MAINTAINERS: add myself as the maintainer for acpi biosbits pytests Ani Sinha
2022-07-11 9:33 ` [PATCH v2 00/11] Introduce new acpi/smbios python tests using biosbits Michael S. Tsirkin
2022-07-14 13:24 ` Peter Maydell
2022-09-06 6:26 ` Ani Sinha
2022-09-06 8:19 ` Michael S. Tsirkin
2022-09-06 13:15 ` Daniel P. Berrangé
2022-09-06 13:28 ` Ani Sinha
2022-09-06 13:30 ` Daniel P. Berrangé
2022-09-09 12:53 ` Ani Sinha
2022-09-06 14:03 ` Michael S. Tsirkin
2022-09-06 14:10 ` Daniel P. Berrangé
2022-09-06 14:19 ` Michael S. Tsirkin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YtAitsVyHmsLRKEL@redhat.com \
--to=berrange@redhat.com \
--cc=ani@anisinha.ca \
--cc=imammedo@redhat.com \
--cc=jsnow@redhat.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).