[PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits

Ani Sinha posted 10 patches 1 year, 6 months ago
Failed in applying to current master (apply log)
There is a newer version of this series
MAINTAINERS                                   |    6 +
docs/devel/acpi-bits.rst                      |  148 +
tests/avocado/acpi-bits.py                    |  389 +++
.../acpi-bits/bits-config/bits-cfg.txt        |   18 +
tests/avocado/acpi-bits/bits-tests/smbios.py2 | 2434 +++++++++++++++++
.../acpi-bits/bits-tests/smilatency.py2       |  107 +
.../avocado/acpi-bits/bits-tests/testacpi.py2 |  287 ++
.../acpi-bits/bits-tests/testcpuid.py2        |   87 +
8 files changed, 3476 insertions(+)
create mode 100644 docs/devel/acpi-bits.rst
create mode 100644 tests/avocado/acpi-bits.py
create mode 100644 tests/avocado/acpi-bits/bits-config/bits-cfg.txt
create mode 100644 tests/avocado/acpi-bits/bits-tests/smbios.py2
create mode 100644 tests/avocado/acpi-bits/bits-tests/smilatency.py2
create mode 100644 tests/avocado/acpi-bits/bits-tests/testacpi.py2
create mode 100644 tests/avocado/acpi-bits/bits-tests/testcpuid.py2
[PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
Please see the rst doc file in patch 9 for more details.
Sample runs are as follows:

Passed tests:

$ ./tests/venv/bin/avocado run -t acpi tests/avocado
Fetching asset from tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
JOB ID     : e95c7413e996bfb59389839e5ca5105464ef098f
JOB LOG    : /home/anisinha/avocado/job-results/job-2022-10-14T19.15-e95c741/job.log
 (1/1) tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits: PASS (33.08 s)
RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
JOB TIME   : 39.18 s


$ ./tests/venv/bin/avocado run ./tests/avocado/acpi-bits.py 
Fetching asset from ./tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
JOB ID     : c6e588594bceb2c5fdbdf45095559c58e4030f9c
JOB LOG    : /home/anisinha/avocado/job-results/job-2022-10-14T19.13-c6e5885/job.log
 (1/1) ./tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits: PASS (32.29 s)
RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
JOB TIME   : 39.27 s

When PSS tests are enabled:

$ git diff
diff --git a/tests/avocado/acpi-bits/bits-tests/testacpi.py2 b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
index f818a9cce6..18dc818d62 100644
--- a/tests/avocado/acpi-bits/bits-tests/testacpi.py2
+++ b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
@@ -40,8 +40,8 @@ import time
 
 def register_tests():
     testsuite.add_test("ACPI _MAT (Multiple APIC Table Entry) under Processor objects", test_mat, submenu="ACPI Tests")
-#    testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests")
-#    testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests")
+    testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests")
+    testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests")
     testsuite.add_test("ACPI DSDT (Differentiated System Description Table)", test_dsdt, submenu="ACPI Tests")
     testsuite.add_test("ACPI FACP (Fixed ACPI Description Table)", test_facp, submenu="ACPI Tests")
     testsuite.add_test("ACPI HPET (High Precision Event Timer Table)", test_hpet, submenu="ACPI Tests")

$ ./tests/venv/bin/avocado run -t acpi tests/avocado
Fetching asset from tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
JOB ID     : 16a8b8c7f8dc87c4b84f8a2f95135bb63464a71e
JOB LOG    : /home/anisinha/avocado/job-results/job-2022-10-14T22.43-16a8b8c/job.log
 (1/1) tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits: FAIL: '1' != '0'\n- 1\n+ 0\n : Some bits tests seems to have failed. Please check the test logs for more info. (33.01 s)
RESULTS    : PASS 0 | ERROR 0 | FAIL 1 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
JOB TIME   : 39.17 s


Changelog:
v6:
  - skip test when dependencies (xorriso for example) are not installed.
  - skip test when run on a platform other than x86_64.
  - move README as an rst file under docs/devel.
  - updated tags.
v5:
  - fixed bits so that grub-mkrescue is built as a static binary.
  - updated the test so that it points to the new bits artifact.
  - V=1 now spits out more meaningful information on failure.
  - added a check to see if xorriso is installed. If not, the test skips with
    a meaningful message instructing the user to install it.
  - fixed README by removing references to stale instructions and adding
    updated instructions.
  - tags updated.
v4:
  - renamed the bits test files as .py2.
  - fixed a bug with missing log file parsing. dump bits logs automatically
    for test failures (no need to re-run with V=1).
  - fixed issues with README file and enhanced it.
  - cosmetic comment updates.
v3:
  - converted the existing test to avocado tests as per the popular
    recommendation. Added appropriate tags.
  - artifact download URL modified based on gitlab-CI URL.

  For biosbits repo:
  - moved to a gitlab repo with me being the maintainer.
  - added .gitlab-ci.yml file to generate the artifacts.
v2:
 - a new class of python based tests introduced that is separate from avocado
   tests or qtests. Can be run by using "make check-pytest".
 - acpi biosbits tests are the first tests to use pytest environment.
 - bios bits tests now download the bits binary archives from a remote
   repository if they are not found locally. The test skips if download
   fails.
 - A new environment variable is introduced that can be passed by the tester
   to specify the location of the bits archives locally. test skips if the
   bits binaries are not found in that location.
 - if pip install of python module fails for whatever reaoson, the test skips.
 - misc code fixes including spell check of the README doc. README has been
   updated as well.
 - addition of SPDX license headers to bits test files.
 - update MAINTAINERS to reflect the new pytest test class.

For biosbits repo:
 - added Dockerfile and build script. Made bios bits build on gcc 11.
   https://github.com/ani-sinha/bits/blob/bits-qemu-logging/Dockerfile
   https://github.com/ani-sinha/bits/blob/bits-qemu-logging/build-artifacts.sh
   The build script generates the zip archive and tarball used by the test.

v1: initial patchset. uses qtest to implement the bios bits tests.

Cc: Qemu Devel <qemu-devel@nongnu.org>
Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>

Ani Sinha (10):
  acpi/tests/avocado/bits: initial commit of test scripts that are run
    by biosbits
  acpi/tests/avocado/bits: add SPDX license identifiers for bios bits
    tests
  acpi/tests/avocado/bits: disable acpi PSS tests that are failing in
    biosbits
  acpi/tests/avocado/bits: add smilatency test suite from bits in order
    to disable it
  acpi/tests/avocado/bits: add SPDX license identifiers for bios bits
    smilatency tests
  acpi/tests/avocado/bits: disable smilatency test since it does not
    pass everytime
  acpi/tests/avocado/bits: add biosbits config file for running bios
    tests
  acpi/tests/avocado/bits: add acpi and smbios avocado tests that uses
    biosbits
  acpi/tests/avocado/bits/doc: add a doc file to describe the acpi bits
    test
  MAINTAINERS: add myself as the maintainer for acpi biosbits avocado
    tests

 MAINTAINERS                                   |    6 +
 docs/devel/acpi-bits.rst                      |  148 +
 tests/avocado/acpi-bits.py                    |  389 +++
 .../acpi-bits/bits-config/bits-cfg.txt        |   18 +
 tests/avocado/acpi-bits/bits-tests/smbios.py2 | 2434 +++++++++++++++++
 .../acpi-bits/bits-tests/smilatency.py2       |  107 +
 .../avocado/acpi-bits/bits-tests/testacpi.py2 |  287 ++
 .../acpi-bits/bits-tests/testcpuid.py2        |   87 +
 8 files changed, 3476 insertions(+)
 create mode 100644 docs/devel/acpi-bits.rst
 create mode 100644 tests/avocado/acpi-bits.py
 create mode 100644 tests/avocado/acpi-bits/bits-config/bits-cfg.txt
 create mode 100644 tests/avocado/acpi-bits/bits-tests/smbios.py2
 create mode 100644 tests/avocado/acpi-bits/bits-tests/smilatency.py2
 create mode 100644 tests/avocado/acpi-bits/bits-tests/testacpi.py2
 create mode 100644 tests/avocado/acpi-bits/bits-tests/testcpuid.py2

-- 
2.34.1


Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
> Please see the rst doc file in patch 9 for more details.
> Sample runs are as follows:
> 
> Passed tests:
> 
> $ ./tests/venv/bin/avocado run -t acpi tests/avocado
> Fetching asset from tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
> JOB ID     : e95c7413e996bfb59389839e5ca5105464ef098f
> JOB LOG    : /home/anisinha/avocado/job-results/job-2022-10-14T19.15-e95c741/job.log
>  (1/1) tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits: PASS (33.08 s)
> RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
> JOB TIME   : 39.18 s
> 
> 
> $ ./tests/venv/bin/avocado run ./tests/avocado/acpi-bits.py 
> Fetching asset from ./tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
> JOB ID     : c6e588594bceb2c5fdbdf45095559c58e4030f9c
> JOB LOG    : /home/anisinha/avocado/job-results/job-2022-10-14T19.13-c6e5885/job.log
>  (1/1) ./tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits: PASS (32.29 s)
> RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
> JOB TIME   : 39.27 s
> 
> When PSS tests are enabled:
> 
> $ git diff
> diff --git a/tests/avocado/acpi-bits/bits-tests/testacpi.py2 b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
> index f818a9cce6..18dc818d62 100644
> --- a/tests/avocado/acpi-bits/bits-tests/testacpi.py2
> +++ b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
> @@ -40,8 +40,8 @@ import time
>  
>  def register_tests():
>      testsuite.add_test("ACPI _MAT (Multiple APIC Table Entry) under Processor objects", test_mat, submenu="ACPI Tests")
> -#    testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests")
> -#    testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests")
> +    testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests")
> +    testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests")
>      testsuite.add_test("ACPI DSDT (Differentiated System Description Table)", test_dsdt, submenu="ACPI Tests")
>      testsuite.add_test("ACPI FACP (Fixed ACPI Description Table)", test_facp, submenu="ACPI Tests")
>      testsuite.add_test("ACPI HPET (High Precision Event Timer Table)", test_hpet, submenu="ACPI Tests")
> 
> $ ./tests/venv/bin/avocado run -t acpi tests/avocado
> Fetching asset from tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
> JOB ID     : 16a8b8c7f8dc87c4b84f8a2f95135bb63464a71e
> JOB LOG    : /home/anisinha/avocado/job-results/job-2022-10-14T22.43-16a8b8c/job.log
>  (1/1) tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits: FAIL: '1' != '0'\n- 1\n+ 0\n : Some bits tests seems to have failed. Please check the test logs for more info. (33.01 s)
> RESULTS    : PASS 0 | ERROR 0 | FAIL 1 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
> JOB TIME   : 39.17 s
> 
> 
> Changelog:
> v6:
>   - skip test when dependencies (xorriso for example) are not installed.
>   - skip test when run on a platform other than x86_64.

Hmm why is that btw?

>   - move README as an rst file under docs/devel.
>   - updated tags.
> v5:
>   - fixed bits so that grub-mkrescue is built as a static binary.
>   - updated the test so that it points to the new bits artifact.
>   - V=1 now spits out more meaningful information on failure.
>   - added a check to see if xorriso is installed. If not, the test skips with
>     a meaningful message instructing the user to install it.
>   - fixed README by removing references to stale instructions and adding
>     updated instructions.
>   - tags updated.
> v4:
>   - renamed the bits test files as .py2.
>   - fixed a bug with missing log file parsing. dump bits logs automatically
>     for test failures (no need to re-run with V=1).
>   - fixed issues with README file and enhanced it.
>   - cosmetic comment updates.
> v3:
>   - converted the existing test to avocado tests as per the popular
>     recommendation. Added appropriate tags.
>   - artifact download URL modified based on gitlab-CI URL.
> 
>   For biosbits repo:
>   - moved to a gitlab repo with me being the maintainer.
>   - added .gitlab-ci.yml file to generate the artifacts.
> v2:
>  - a new class of python based tests introduced that is separate from avocado
>    tests or qtests. Can be run by using "make check-pytest".
>  - acpi biosbits tests are the first tests to use pytest environment.
>  - bios bits tests now download the bits binary archives from a remote
>    repository if they are not found locally. The test skips if download
>    fails.
>  - A new environment variable is introduced that can be passed by the tester
>    to specify the location of the bits archives locally. test skips if the
>    bits binaries are not found in that location.
>  - if pip install of python module fails for whatever reaoson, the test skips.
>  - misc code fixes including spell check of the README doc. README has been
>    updated as well.
>  - addition of SPDX license headers to bits test files.
>  - update MAINTAINERS to reflect the new pytest test class.
> 
> For biosbits repo:
>  - added Dockerfile and build script. Made bios bits build on gcc 11.
>    https://github.com/ani-sinha/bits/blob/bits-qemu-logging/Dockerfile
>    https://github.com/ani-sinha/bits/blob/bits-qemu-logging/build-artifacts.sh
>    The build script generates the zip archive and tarball used by the test.
> 
> v1: initial patchset. uses qtest to implement the bios bits tests.
> 
> Cc: Qemu Devel <qemu-devel@nongnu.org>
> Cc: Daniel P. Berrangé <berrange@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Maydell Peter <peter.maydell@linaro.org>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Thomas Huth <thuth@redhat.com>
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Michael Tsirkin <mst@redhat.com>
> 
> Ani Sinha (10):
>   acpi/tests/avocado/bits: initial commit of test scripts that are run
>     by biosbits
>   acpi/tests/avocado/bits: add SPDX license identifiers for bios bits
>     tests
>   acpi/tests/avocado/bits: disable acpi PSS tests that are failing in
>     biosbits
>   acpi/tests/avocado/bits: add smilatency test suite from bits in order
>     to disable it
>   acpi/tests/avocado/bits: add SPDX license identifiers for bios bits
>     smilatency tests
>   acpi/tests/avocado/bits: disable smilatency test since it does not
>     pass everytime
>   acpi/tests/avocado/bits: add biosbits config file for running bios
>     tests
>   acpi/tests/avocado/bits: add acpi and smbios avocado tests that uses
>     biosbits
>   acpi/tests/avocado/bits/doc: add a doc file to describe the acpi bits
>     test
>   MAINTAINERS: add myself as the maintainer for acpi biosbits avocado
>     tests
> 
>  MAINTAINERS                                   |    6 +
>  docs/devel/acpi-bits.rst                      |  148 +
>  tests/avocado/acpi-bits.py                    |  389 +++
>  .../acpi-bits/bits-config/bits-cfg.txt        |   18 +
>  tests/avocado/acpi-bits/bits-tests/smbios.py2 | 2434 +++++++++++++++++
>  .../acpi-bits/bits-tests/smilatency.py2       |  107 +
>  .../avocado/acpi-bits/bits-tests/testacpi.py2 |  287 ++
>  .../acpi-bits/bits-tests/testcpuid.py2        |   87 +
>  8 files changed, 3476 insertions(+)
>  create mode 100644 docs/devel/acpi-bits.rst
>  create mode 100644 tests/avocado/acpi-bits.py
>  create mode 100644 tests/avocado/acpi-bits/bits-config/bits-cfg.txt
>  create mode 100644 tests/avocado/acpi-bits/bits-tests/smbios.py2
>  create mode 100644 tests/avocado/acpi-bits/bits-tests/smilatency.py2
>  create mode 100644 tests/avocado/acpi-bits/bits-tests/testacpi.py2
>  create mode 100644 tests/avocado/acpi-bits/bits-tests/testcpuid.py2
> 
> -- 
> 2.34.1
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
> >
> >
> > Changelog:
> > v6:
> >   - skip test when dependencies (xorriso for example) are not installed.
> >   - skip test when run on a platform other than x86_64.
>
> Hmm why is that btw?

The bits binaries that generate the iso (grub-mkrescue etc) are built
for and are known to work only on x86_64 platform. They might also
work on amd64 but I do not have one at my disposal at the moment to
check.
On other platforms, for example 32 bit x86 and non-x86, those binaries
will likely not work. The test will fail.
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Thu, Oct 20, 2022 at 06:12:10PM +0530, Ani Sinha wrote:
> On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
> > >
> > >
> > > Changelog:
> > > v6:
> > >   - skip test when dependencies (xorriso for example) are not installed.
> > >   - skip test when run on a platform other than x86_64.
> >
> > Hmm why is that btw?
> 
> The bits binaries that generate the iso (grub-mkrescue etc) are built
> for and are known to work only on x86_64 platform. They might also
> work on amd64 but I do not have one at my disposal at the moment to
> check.
> On other platforms, for example 32 bit x86 and non-x86, those binaries
> will likely not work. The test will fail.

confused. I thought we are distributing the iso?

-- 
MST
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Thu, Oct 20, 2022 at 6:15 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Thu, Oct 20, 2022 at 06:12:10PM +0530, Ani Sinha wrote:
> > On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> > >
> > > On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
> > > >
> > > >
> > > > Changelog:
> > > > v6:
> > > >   - skip test when dependencies (xorriso for example) are not installed.
> > > >   - skip test when run on a platform other than x86_64.
> > >
> > > Hmm why is that btw?
> >
> > The bits binaries that generate the iso (grub-mkrescue etc) are built
> > for and are known to work only on x86_64 platform. They might also
> > work on amd64 but I do not have one at my disposal at the moment to
> > check.
> > On other platforms, for example 32 bit x86 and non-x86, those binaries
> > will likely not work. The test will fail.
>
> confused. I thought we are distributing the iso?

No, the test builds the iso after adding the modified test scripts and
then spawns the vm with it. It is all part of the test itself.
We need to do that so that the iso contains the newly added tests etc.
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Thu, Oct 20, 2022 at 06:20:20PM +0530, Ani Sinha wrote:
> On Thu, Oct 20, 2022 at 6:15 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > On Thu, Oct 20, 2022 at 06:12:10PM +0530, Ani Sinha wrote:
> > > On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> > > >
> > > > On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
> > > > >
> > > > >
> > > > > Changelog:
> > > > > v6:
> > > > >   - skip test when dependencies (xorriso for example) are not installed.
> > > > >   - skip test when run on a platform other than x86_64.
> > > >
> > > > Hmm why is that btw?
> > >
> > > The bits binaries that generate the iso (grub-mkrescue etc) are built
> > > for and are known to work only on x86_64 platform. They might also
> > > work on amd64 but I do not have one at my disposal at the moment to
> > > check.
> > > On other platforms, for example 32 bit x86 and non-x86, those binaries
> > > will likely not work. The test will fail.
> >
> > confused. I thought we are distributing the iso?
> 
> No, the test builds the iso after adding the modified test scripts and
> then spawns the vm with it. It is all part of the test itself.
> We need to do that so that the iso contains the newly added tests etc.

It's good to have for people developing tests, but for most qemu
developers please just have a ready iso and have avocado fetch it.
It's important to make tests run on all platforms.

We can think about moving iso generation into a VM too
but as a first step I guess we can live with a container.

-- 
MST
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, Oct 21, 2022 at 12:43 AM Michael S. Tsirkin <mst@redhat.com> wrote:

> On Thu, Oct 20, 2022 at 06:20:20PM +0530, Ani Sinha wrote:
> > On Thu, Oct 20, 2022 at 6:15 PM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> > >
> > > On Thu, Oct 20, 2022 at 06:12:10PM +0530, Ani Sinha wrote:
> > > > On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> > > > >
> > > > > On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
> > > > > >
> > > > > >
> > > > > > Changelog:
> > > > > > v6:
> > > > > >   - skip test when dependencies (xorriso for example) are not
> installed.
> > > > > >   - skip test when run on a platform other than x86_64.
> > > > >
> > > > > Hmm why is that btw?
> > > >
> > > > The bits binaries that generate the iso (grub-mkrescue etc) are built
> > > > for and are known to work only on x86_64 platform. They might also
> > > > work on amd64 but I do not have one at my disposal at the moment to
> > > > check.
> > > > On other platforms, for example 32 bit x86 and non-x86, those
> binaries
> > > > will likely not work. The test will fail.
> > >
> > > confused. I thought we are distributing the iso?
> >
> > No, the test builds the iso after adding the modified test scripts and
> > then spawns the vm with it. It is all part of the test itself.
> > We need to do that so that the iso contains the newly added tests etc.
>
> It's good to have for people developing tests, but for most qemu
> developers please just have a ready iso and have avocado fetch it.
> It's important to make tests run on all platforms.


This changes things a lot and goes down the path of where do we check in
test code changes? Do we deal with multiple repos? Where do we keep iso?
Etc. having a static iso limits us also.

If we can think through and come up with a consensus, I can write a second
test. Else let's just go with this first. If we are really keen on running
tests on multiple platforms, we can have binaries built for those.


>
> We can think about moving iso generation into a VM too
> but as a first step I guess we can live with a container.
>
> --
> MST
>
>
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Fri, Oct 21, 2022 at 05:10:43AM +0530, Ani Sinha wrote:
> 
> 
> On Fri, Oct 21, 2022 at 12:43 AM Michael S. Tsirkin <mst@redhat.com> wrote:
> 
>     On Thu, Oct 20, 2022 at 06:20:20PM +0530, Ani Sinha wrote:
>     > On Thu, Oct 20, 2022 at 6:15 PM Michael S. Tsirkin <mst@redhat.com>
>     wrote:
>     > >
>     > > On Thu, Oct 20, 2022 at 06:12:10PM +0530, Ani Sinha wrote:
>     > > > On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <mst@redhat.com>
>     wrote:
>     > > > >
>     > > > > On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
>     > > > > >
>     > > > > >
>     > > > > > Changelog:
>     > > > > > v6:
>     > > > > >   - skip test when dependencies (xorriso for example) are not
>     installed.
>     > > > > >   - skip test when run on a platform other than x86_64.
>     > > > >
>     > > > > Hmm why is that btw?
>     > > >
>     > > > The bits binaries that generate the iso (grub-mkrescue etc) are built
>     > > > for and are known to work only on x86_64 platform. They might also
>     > > > work on amd64 but I do not have one at my disposal at the moment to
>     > > > check.
>     > > > On other platforms, for example 32 bit x86 and non-x86, those
>     binaries
>     > > > will likely not work. The test will fail.
>     > >
>     > > confused. I thought we are distributing the iso?
>     >
>     > No, the test builds the iso after adding the modified test scripts and
>     > then spawns the vm with it. It is all part of the test itself.
>     > We need to do that so that the iso contains the newly added tests etc.
> 
>     It's good to have for people developing tests, but for most qemu
>     developers please just have a ready iso and have avocado fetch it.
>     It's important to make tests run on all platforms.
> 
> 
> This changes things a lot and goes down the path of where do we check in test
> code changes? Do we deal with multiple repos? Where do we keep iso? Etc. having
> a static iso limits us also. 

It's the same as any firmware really. I don't see much of a difference.

> If we can think through and come up with a consensus, I can write a second
> test. Else let's just go with this first.

We can go ahead for now.

> If we are really keen on running
> tests on multiple platforms, we can have binaries built for those. 
> 

Oh my.  Not dealing with this is *exactly* what people use
virtualization for.

> 
> 
>     We can think about moving iso generation into a VM too
>     but as a first step I guess we can live with a container.
> 
>     --
>     MST
> 
> 
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, Oct 21, 2022 at 13:50 Michael S. Tsirkin <mst@redhat.com> wrote:

> On Fri, Oct 21, 2022 at 05:10:43AM +0530, Ani Sinha wrote:
> >
> >
> > On Fri, Oct 21, 2022 at 12:43 AM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> >
> >     On Thu, Oct 20, 2022 at 06:20:20PM +0530, Ani Sinha wrote:
> >     > On Thu, Oct 20, 2022 at 6:15 PM Michael S. Tsirkin <mst@redhat.com
> >
> >     wrote:
> >     > >
> >     > > On Thu, Oct 20, 2022 at 06:12:10PM +0530, Ani Sinha wrote:
> >     > > > On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <
> mst@redhat.com>
> >     wrote:
> >     > > > >
> >     > > > > On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
> >     > > > > >
> >     > > > > >
> >     > > > > > Changelog:
> >     > > > > > v6:
> >     > > > > >   - skip test when dependencies (xorriso for example) are
> not
> >     installed.
> >     > > > > >   - skip test when run on a platform other than x86_64.
> >     > > > >
> >     > > > > Hmm why is that btw?
> >     > > >
> >     > > > The bits binaries that generate the iso (grub-mkrescue etc)
> are built
> >     > > > for and are known to work only on x86_64 platform. They might
> also
> >     > > > work on amd64 but I do not have one at my disposal at the
> moment to
> >     > > > check.
> >     > > > On other platforms, for example 32 bit x86 and non-x86, those
> >     binaries
> >     > > > will likely not work. The test will fail.
> >     > >
> >     > > confused. I thought we are distributing the iso?
> >     >
> >     > No, the test builds the iso after adding the modified test scripts
> and
> >     > then spawns the vm with it. It is all part of the test itself.
> >     > We need to do that so that the iso contains the newly added tests
> etc.
> >
> >     It's good to have for people developing tests, but for most qemu
> >     developers please just have a ready iso and have avocado fetch it.
> >     It's important to make tests run on all platforms.
> >
> >
> > This changes things a lot and goes down the path of where do we check in
> test
> > code changes? Do we deal with multiple repos? Where do we keep iso? Etc.
> having
> > a static iso limits us also.
>
> It's the same as any firmware really. I don't see much of a difference.


Except that the iso is much larger than the current edk2 binaries and there
are serious objections to keeping them along with other bios binary blobs
in qemu repo.
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Fri, Oct 21, 2022 at 05:12:07PM +0530, Ani Sinha wrote:
> 
> 
> On Fri, Oct 21, 2022 at 13:50 Michael S. Tsirkin <mst@redhat.com> wrote:
> 
>     On Fri, Oct 21, 2022 at 05:10:43AM +0530, Ani Sinha wrote:
>     >
>     >
>     > On Fri, Oct 21, 2022 at 12:43 AM Michael S. Tsirkin <mst@redhat.com>
>     wrote:
>     >
>     >     On Thu, Oct 20, 2022 at 06:20:20PM +0530, Ani Sinha wrote:
>     >     > On Thu, Oct 20, 2022 at 6:15 PM Michael S. Tsirkin <mst@redhat.com>
>     >     wrote:
>     >     > >
>     >     > > On Thu, Oct 20, 2022 at 06:12:10PM +0530, Ani Sinha wrote:
>     >     > > > On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <
>     mst@redhat.com>
>     >     wrote:
>     >     > > > >
>     >     > > > > On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
>     >     > > > > >
>     >     > > > > >
>     >     > > > > > Changelog:
>     >     > > > > > v6:
>     >     > > > > >   - skip test when dependencies (xorriso for example) are
>     not
>     >     installed.
>     >     > > > > >   - skip test when run on a platform other than x86_64.
>     >     > > > >
>     >     > > > > Hmm why is that btw?
>     >     > > >
>     >     > > > The bits binaries that generate the iso (grub-mkrescue etc) are
>     built
>     >     > > > for and are known to work only on x86_64 platform. They might
>     also
>     >     > > > work on amd64 but I do not have one at my disposal at the
>     moment to
>     >     > > > check.
>     >     > > > On other platforms, for example 32 bit x86 and non-x86, those
>     >     binaries
>     >     > > > will likely not work. The test will fail.
>     >     > >
>     >     > > confused. I thought we are distributing the iso?
>     >     >
>     >     > No, the test builds the iso after adding the modified test scripts
>     and
>     >     > then spawns the vm with it. It is all part of the test itself.
>     >     > We need to do that so that the iso contains the newly added tests
>     etc.
>     >
>     >     It's good to have for people developing tests, but for most qemu
>     >     developers please just have a ready iso and have avocado fetch it.
>     >     It's important to make tests run on all platforms.
>     >
>     >
>     > This changes things a lot and goes down the path of where do we check in
>     test
>     > code changes? Do we deal with multiple repos? Where do we keep iso? Etc.
>     having
>     > a static iso limits us also. 
> 
>     It's the same as any firmware really. I don't see much of a difference.
> 
> 
> Except that the iso is much larger than the current edk2 binaries and there are
> serious objections to keeping them along with other bios binary blobs in qemu
> repo.
> 

Right, I get that. So avocado was supposed to know how to download them
automatically, no?

-- 
MST
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Sat, Oct 22, 2022 at 22:11 Michael S. Tsirkin <mst@redhat.com> wrote:

> On Fri, Oct 21, 2022 at 05:12:07PM +0530, Ani Sinha wrote:
> >
> >
> > On Fri, Oct 21, 2022 at 13:50 Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> >     On Fri, Oct 21, 2022 at 05:10:43AM +0530, Ani Sinha wrote:
> >     >
> >     >
> >     > On Fri, Oct 21, 2022 at 12:43 AM Michael S. Tsirkin <
> mst@redhat.com>
> >     wrote:
> >     >
> >     >     On Thu, Oct 20, 2022 at 06:20:20PM +0530, Ani Sinha wrote:
> >     >     > On Thu, Oct 20, 2022 at 6:15 PM Michael S. Tsirkin <
> mst@redhat.com>
> >     >     wrote:
> >     >     > >
> >     >     > > On Thu, Oct 20, 2022 at 06:12:10PM +0530, Ani Sinha wrote:
> >     >     > > > On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <
> >     mst@redhat.com>
> >     >     wrote:
> >     >     > > > >
> >     >     > > > > On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha
> wrote:
> >     >     > > > > >
> >     >     > > > > >
> >     >     > > > > > Changelog:
> >     >     > > > > > v6:
> >     >     > > > > >   - skip test when dependencies (xorriso for
> example) are
> >     not
> >     >     installed.
> >     >     > > > > >   - skip test when run on a platform other than
> x86_64.
> >     >     > > > >
> >     >     > > > > Hmm why is that btw?
> >     >     > > >
> >     >     > > > The bits binaries that generate the iso (grub-mkrescue
> etc) are
> >     built
> >     >     > > > for and are known to work only on x86_64 platform. They
> might
> >     also
> >     >     > > > work on amd64 but I do not have one at my disposal at the
> >     moment to
> >     >     > > > check.
> >     >     > > > On other platforms, for example 32 bit x86 and non-x86,
> those
> >     >     binaries
> >     >     > > > will likely not work. The test will fail.
> >     >     > >
> >     >     > > confused. I thought we are distributing the iso?
> >     >     >
> >     >     > No, the test builds the iso after adding the modified test
> scripts
> >     and
> >     >     > then spawns the vm with it. It is all part of the test
> itself.
> >     >     > We need to do that so that the iso contains the newly added
> tests
> >     etc.
> >     >
> >     >     It's good to have for people developing tests, but for most
> qemu
> >     >     developers please just have a ready iso and have avocado fetch
> it.
> >     >     It's important to make tests run on all platforms.
> >     >
> >     >
> >     > This changes things a lot and goes down the path of where do we
> check in
> >     test
> >     > code changes? Do we deal with multiple repos? Where do we keep
> iso? Etc.
> >     having
> >     > a static iso limits us also.
> >
> >     It's the same as any firmware really. I don't see much of a
> difference.
> >
> >
> > Except that the iso is much larger than the current edk2 binaries and
> there are
> > serious objections to keeping them along with other bios binary blobs in
> qemu
> > repo.
> >
>
> Right, I get that. So avocado was supposed to know how to download them
> automatically, no?


Yea that’s the reason why we are using CI artifacts and telling avocado to
download them from a specific URL.


>
> --
> MST
>
>
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, Oct 21, 2022 at 5:10 AM Ani Sinha <ani@anisinha.ca> wrote:

>
>
> On Fri, Oct 21, 2022 at 12:43 AM Michael S. Tsirkin <mst@redhat.com>
> wrote:
>
>> On Thu, Oct 20, 2022 at 06:20:20PM +0530, Ani Sinha wrote:
>> > On Thu, Oct 20, 2022 at 6:15 PM Michael S. Tsirkin <mst@redhat.com>
>> wrote:
>> > >
>> > > On Thu, Oct 20, 2022 at 06:12:10PM +0530, Ani Sinha wrote:
>> > > > On Thu, Oct 20, 2022 at 6:08 PM Michael S. Tsirkin <mst@redhat.com>
>> wrote:
>> > > > >
>> > > > > On Thu, Oct 20, 2022 at 06:04:56PM +0530, Ani Sinha wrote:
>> > > > > >
>> > > > > >
>> > > > > > Changelog:
>> > > > > > v6:
>> > > > > >   - skip test when dependencies (xorriso for example) are not
>> installed.
>> > > > > >   - skip test when run on a platform other than x86_64.
>> > > > >
>> > > > > Hmm why is that btw?
>> > > >
>> > > > The bits binaries that generate the iso (grub-mkrescue etc) are
>> built
>> > > > for and are known to work only on x86_64 platform. They might also
>> > > > work on amd64 but I do not have one at my disposal at the moment to
>> > > > check.
>> > > > On other platforms, for example 32 bit x86 and non-x86, those
>> binaries
>> > > > will likely not work. The test will fail.
>> > >
>> > > confused. I thought we are distributing the iso?
>> >
>> > No, the test builds the iso after adding the modified test scripts and
>> > then spawns the vm with it. It is all part of the test itself.
>> > We need to do that so that the iso contains the newly added tests etc.
>>
>> It's good to have for people developing tests, but for most qemu
>> developers please just have a ready iso and have avocado fetch it.
>> It's important to make tests run on all platforms.
>
>
> This changes things a lot and goes down the path of where do we check in
> test code changes? Do we deal with multiple repos? Where do we keep iso?
> Etc. having a static iso limits us also.
>
> If we can think through and come up with a consensus, I can write a second
> test. Else let's just go with this first. If we are really keen on running
> tests on multiple platforms, we can have binaries built for those.
>

And have multiple platform specific branches in bits that have fixes for
those platforms so that bits can run there. Plus the existing test can be
enhanced to pull in binaries from those branches based on the platform on
which it is being run.
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
> And have multiple platform specific branches in bits that have fixes for those
> platforms so that bits can run there. Plus the existing test can be enhanced to
> pull in binaries from those branches based on the platform on which it is being
> run.
> 

What a mess.
Who is going to be testing all these million platforms?
All this does nothing at all to help developers avoid
bugs and when they do trigger debug the issue. Which is
after all why we have testing.
Yes once in a very long while we are going to tweak
something in the tests, and for that rare occurence
it makes sense to periodically rebuild everything,
otherwise code bitrots.

But the test is supposed to run within a VM anyway, let's
have an image and be done with it.

-- 
MST
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
> > And have multiple platform specific branches in bits that have fixes for those
> > platforms so that bits can run there. Plus the existing test can be enhanced to
> > pull in binaries from those branches based on the platform on which it is being
> > run.
> >
>
> What a mess.
> Who is going to be testing all these million platforms?

I am not talking about branches in QEMU but branches in bits.
If you are going to test multiple platforms, you do need to build bits
binaries for them. There is no way around it.
bits is not all platform independent python. It does have binary executables.

Currently bits is built only for the x86 platform. Other platforms are
not tested. I doubt if anyone even tried building bits for arm or
mips.
It makes sense to try things incrementally once we have something going.

Lets discuss this on a separate thread.

> All this does nothing at all to help developers avoid
> bugs and when they do trigger debug the issue. Which is
> after all why we have testing.
> Yes once in a very long while we are going to tweak
> something in the tests, and for that rare occurence
> it makes sense to periodically rebuild everything,
> otherwise code bitrots.
>
> But the test is supposed to run within a VM anyway, let's
> have an image and be done with it.
>
> --
> MST
>
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>>
>> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
>> > And have multiple platform specific branches in bits that have fixes for those
>> > platforms so that bits can run there. Plus the existing test can be enhanced to
>> > pull in binaries from those branches based on the platform on which it is being
>> > run.
>> >
>>
>> What a mess.
>> Who is going to be testing all these million platforms?
>
> I am not talking about branches in QEMU but branches in bits.
> If you are going to test multiple platforms, you do need to build bits
> binaries for them. There is no way around it.
> bits is not all platform independent python. It does have binary executables.
>
> Currently bits is built only for the x86 platform. Other platforms are
> not tested. I doubt if anyone even tried building bits for arm or
> mips.

I'm not worried about test bits on other targets, but we do run x86
targets on a number of hosts. The current reliance on a special patched
host build tool for only one architecture is the problem. If  we just
download the iso that problem goes away.

> It makes sense to try things incrementally once we have something going.
>
> Lets discuss this on a separate thread.
>
>> All this does nothing at all to help developers avoid
>> bugs and when they do trigger debug the issue. Which is
>> after all why we have testing.
>> Yes once in a very long while we are going to tweak
>> something in the tests, and for that rare occurence
>> it makes sense to periodically rebuild everything,
>> otherwise code bitrots.
>>
>> But the test is supposed to run within a VM anyway, let's
>> have an image and be done with it.
>>
>> --
>> MST
>>


-- 
Alex Bennée
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
> 
> Ani Sinha <ani@anisinha.ca> writes:
> 
> > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >>
> >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
> >> > And have multiple platform specific branches in bits that have fixes for those
> >> > platforms so that bits can run there. Plus the existing test can be enhanced to
> >> > pull in binaries from those branches based on the platform on which it is being
> >> > run.
> >> >
> >>
> >> What a mess.
> >> Who is going to be testing all these million platforms?
> >
> > I am not talking about branches in QEMU but branches in bits.
> > If you are going to test multiple platforms, you do need to build bits
> > binaries for them. There is no way around it.
> > bits is not all platform independent python. It does have binary executables.
> >
> > Currently bits is built only for the x86 platform. Other platforms are
> > not tested. I doubt if anyone even tried building bits for arm or
> > mips.
> 
> I'm not worried about test bits on other targets, but we do run x86
> targets on a number of hosts. The current reliance on a special patched
> host build tool for only one architecture is the problem. If  we just
> download the iso that problem goes away.

👍what he said.

> > It makes sense to try things incrementally once we have something going.
> >
> > Lets discuss this on a separate thread.
> >
> >> All this does nothing at all to help developers avoid
> >> bugs and when they do trigger debug the issue. Which is
> >> after all why we have testing.
> >> Yes once in a very long while we are going to tweak
> >> something in the tests, and for that rare occurence
> >> it makes sense to periodically rebuild everything,
> >> otherwise code bitrots.
> >>
> >> But the test is supposed to run within a VM anyway, let's
> >> have an image and be done with it.
> >>
> >> --
> >> MST
> >>
> 
> 
> -- 
> Alex Bennée


Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
> >
> > Ani Sinha <ani@anisinha.ca> writes:
> >
> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> > >>
> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
> > >> > And have multiple platform specific branches in bits that have fixes for those
> > >> > platforms so that bits can run there. Plus the existing test can be enhanced to
> > >> > pull in binaries from those branches based on the platform on which it is being
> > >> > run.
> > >> >
> > >>
> > >> What a mess.
> > >> Who is going to be testing all these million platforms?
> > >
> > > I am not talking about branches in QEMU but branches in bits.
> > > If you are going to test multiple platforms, you do need to build bits
> > > binaries for them. There is no way around it.
> > > bits is not all platform independent python. It does have binary executables.
> > >
> > > Currently bits is built only for the x86 platform. Other platforms are
> > > not tested. I doubt if anyone even tried building bits for arm or
> > > mips.
> >
> > I'm not worried about test bits on other targets, but we do run x86
> > targets on a number of hosts. The current reliance on a special patched
> > host build tool for only one architecture is the problem. If  we just
> > download the iso that problem goes away.
>
> 👍what he said.

Yes, in that case the problem is that upstream bits does not pass all
the test out of the box. Hence we are taking this approach of keeping
some test scripts in QEMU repo and modifying them. Then generating the
iso with the modified scripts. It also helps developers who want to
write new tests or make enhancements to existing tests.
If modifications need to be made to tests, they need to be versioned.
We have gone through the route of not using submodules and I am not
going to open that can of worms again.
We also have no consensus on where to keep the one time built iso that
we can download for this test you are proposing.

So let's figure out the above first. Programmatically downloading an
iso and running tests within a VM would be a much simpler test than
the one I wrote. We can add a subtest or a brand new test anytime if
we can figure out the above logistics.

>
> > > It makes sense to try things incrementally once we have something going.
> > >
> > > Lets discuss this on a separate thread.
> > >
> > >> All this does nothing at all to help developers avoid
> > >> bugs and when they do trigger debug the issue. Which is
> > >> after all why we have testing.
> > >> Yes once in a very long while we are going to tweak
> > >> something in the tests, and for that rare occurence
> > >> it makes sense to periodically rebuild everything,
> > >> otherwise code bitrots.
> > >>
> > >> But the test is supposed to run within a VM anyway, let's
> > >> have an image and be done with it.
> > >>
> > >> --
> > >> MST
> > >>
> >
> >
> > --
> > Alex Bennée
>
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>>
>> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
>> >
>> > Ani Sinha <ani@anisinha.ca> writes:
>> >
>> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>> > >>
>> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
>> > >> > And have multiple platform specific branches in bits that have fixes for those
>> > >> > platforms so that bits can run there. Plus the existing test can be enhanced to
>> > >> > pull in binaries from those branches based on the platform on which it is being
>> > >> > run.
>> > >> >
>> > >>
>> > >> What a mess.
>> > >> Who is going to be testing all these million platforms?
>> > >
>> > > I am not talking about branches in QEMU but branches in bits.
>> > > If you are going to test multiple platforms, you do need to build bits
>> > > binaries for them. There is no way around it.
>> > > bits is not all platform independent python. It does have binary executables.
>> > >
>> > > Currently bits is built only for the x86 platform. Other platforms are
>> > > not tested. I doubt if anyone even tried building bits for arm or
>> > > mips.
>> >
>> > I'm not worried about test bits on other targets, but we do run x86
>> > targets on a number of hosts. The current reliance on a special patched
>> > host build tool for only one architecture is the problem. If  we just
>> > download the iso that problem goes away.
>>
>> 👍what he said.
>
> Yes, in that case the problem is that upstream bits does not pass all
> the test out of the box. Hence we are taking this approach of keeping
> some test scripts in QEMU repo and modifying them. Then generating the
> iso with the modified scripts. It also helps developers who want to
> write new tests or make enhancements to existing tests.
> If modifications need to be made to tests, they need to be versioned.
> We have gone through the route of not using submodules and I am not
> going to open that can of worms again.

We have added a mirror of biosbits to the QEMU project so there is no
reason why we can't track changes and modifications there (we do this
for TestFloat which is forked from the upstream SoftFloat code).
Maintaining and occasionally re-based "vendor" branch shouldn't be too
hard and would track the changes we've made for QEMU's purposes.

> We also have no consensus on where to keep the one time built iso that
> we can download for this test you are proposing.

How big is the eventual ISO? If it's small we could just enable some CI
steps and serve the ISOs directly as tagged build artefacts from GitLab.

> So let's figure out the above first. Programmatically downloading an
> iso and running tests within a VM would be a much simpler test than
> the one I wrote. We can add a subtest or a brand new test anytime if
> we can figure out the above logistics.
>
>>
>> > > It makes sense to try things incrementally once we have something going.
>> > >
>> > > Lets discuss this on a separate thread.
>> > >
>> > >> All this does nothing at all to help developers avoid
>> > >> bugs and when they do trigger debug the issue. Which is
>> > >> after all why we have testing.
>> > >> Yes once in a very long while we are going to tweak
>> > >> something in the tests, and for that rare occurence
>> > >> it makes sense to periodically rebuild everything,
>> > >> otherwise code bitrots.
>> > >>
>> > >> But the test is supposed to run within a VM anyway, let's
>> > >> have an image and be done with it.
>> > >>
>> > >> --
>> > >> MST
>> > >>
>> >
>> >
>> > --
>> > Alex Bennée
>>


-- 
Alex Bennée
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, 21 Oct, 2022, 5:26 pm Alex Bennée, <alex.bennee@linaro.org> wrote:

>
> Ani Sinha <ani@anisinha.ca> writes:
>
> > On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> >>
> >> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
> >> >
> >> > Ani Sinha <ani@anisinha.ca> writes:
> >> >
> >> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> >> > >>
> >> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
> >> > >> > And have multiple platform specific branches in bits that have
> fixes for those
> >> > >> > platforms so that bits can run there. Plus the existing test can
> be enhanced to
> >> > >> > pull in binaries from those branches based on the platform on
> which it is being
> >> > >> > run.
> >> > >> >
> >> > >>
> >> > >> What a mess.
> >> > >> Who is going to be testing all these million platforms?
> >> > >
> >> > > I am not talking about branches in QEMU but branches in bits.
> >> > > If you are going to test multiple platforms, you do need to build
> bits
> >> > > binaries for them. There is no way around it.
> >> > > bits is not all platform independent python. It does have binary
> executables.
> >> > >
> >> > > Currently bits is built only for the x86 platform. Other platforms
> are
> >> > > not tested. I doubt if anyone even tried building bits for arm or
> >> > > mips.
> >> >
> >> > I'm not worried about test bits on other targets, but we do run x86
> >> > targets on a number of hosts. The current reliance on a special
> patched
> >> > host build tool for only one architecture is the problem. If  we just
> >> > download the iso that problem goes away.
> >>
> >> 👍what he said.
> >
> > Yes, in that case the problem is that upstream bits does not pass all
> > the test out of the box. Hence we are taking this approach of keeping
> > some test scripts in QEMU repo and modifying them. Then generating the
> > iso with the modified scripts. It also helps developers who want to
> > write new tests or make enhancements to existing tests.
> > If modifications need to be made to tests, they need to be versioned.
> > We have gone through the route of not using submodules and I am not
> > going to open that can of worms again.
>
> We have added a mirror of biosbits to the QEMU project so there is no
> reason why we can't track changes and modifications there (we do this
> for TestFloat which is forked from the upstream SoftFloat code).
>

The whole idea was that say an acpi developer added support for a new table
in QEMU, he should write a corresponding test for bits so that the same
table is exercised during run time. Making those changes from a single repo
(either directly or through a submodule)  makes things lit simpler and also
keeps things in sync with each other. If we use separate repos for acpi
bits test, it will be another mess when comes to developers adding changes
and keeping things in sync.

Anyways these things should have been brought up earlier. I'm out of the
debate.

I've sent v7 , incremental work over the last 6 months in my spare time
without getting any pay. So take it or scrap it.

😊

> Maintaining and occasionally re-based "vendor" branch shouldn't be too
> hard and would track the changes we've made for QEMU's purposes.
>
> > We also have no consensus on where to keep the one time built iso that
> > we can download for this test you are proposing.
>
> How big is the eventual ISO? If it's small we could just enable some CI
> steps and serve the ISOs directly as tagged build artefacts from GitLab.
>
> > So let's figure out the above first. Programmatically downloading an
> > iso and running tests within a VM would be a much simpler test than
> > the one I wrote. We can add a subtest or a brand new test anytime if
> > we can figure out the above logistics.
> >
> >>
> >> > > It makes sense to try things incrementally once we have something
> going.
> >> > >
> >> > > Lets discuss this on a separate thread.
> >> > >
> >> > >> All this does nothing at all to help developers avoid
> >> > >> bugs and when they do trigger debug the issue. Which is
> >> > >> after all why we have testing.
> >> > >> Yes once in a very long while we are going to tweak
> >> > >> something in the tests, and for that rare occurence
> >> > >> it makes sense to periodically rebuild everything,
> >> > >> otherwise code bitrots.
> >> > >>
> >> > >> But the test is supposed to run within a VM anyway, let's
> >> > >> have an image and be done with it.
> >> > >>
> >> > >> --
> >> > >> MST
> >> > >>
> >> >
> >> >
> >> > --
> >> > Alex Bennée
> >>
>
>
> --
> Alex Bennée
>
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

<snip>
>
>  We have added a mirror of biosbits to the QEMU project so there is no
>  reason why we can't track changes and modifications there (we do this
>  for TestFloat which is forked from the upstream SoftFloat code).
>
> The whole idea was that say an acpi developer added support for a new table in QEMU, he should write a corresponding
> test for bits so that the same table is exercised during run time. Making those changes from a single repo (either directly
> or through a submodule)  makes things lit simpler and also keeps things in sync with each other. If we use separate
> repos for acpi bits test, it will be another mess when comes to developers adding changes and keeping things in sync. 
>
> Anyways these things should have been brought up earlier. I'm out of the debate. 
>
> I've sent v7 , incremental work over the last 6 months in my spare time without getting any pay. So take it or scrap it. 
>
> 😊

I'm sorry you feel that way but you asked for people to spend their time
reviewing your code and giving feedback. If you don't have time to take
it forward then fine but I'm afraid a "take it or leave it" attitude
will just result in it not getting merged.

Hopefully someone else who has the time to look into it will be able to
pick it up later.

-- 
Alex Bennée
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, Oct 21, 2022 at 21:36 Alex Bennée <alex.bennee@linaro.org> wrote:

>
> Ani Sinha <ani@anisinha.ca> writes:
>
> <snip>
> >
> >  We have added a mirror of biosbits to the QEMU project so there is no
> >  reason why we can't track changes and modifications there (we do this
> >  for TestFloat which is forked from the upstream SoftFloat code).
> >
> > The whole idea was that say an acpi developer added support for a new
> table in QEMU, he should write a corresponding
> > test for bits so that the same table is exercised during run time.
> Making those changes from a single repo (either directly
> > or through a submodule)  makes things lit simpler and also keeps things
> in sync with each other. If we use separate
> > repos for acpi bits test, it will be another mess when comes to
> developers adding changes and keeping things in sync.
> >
> > Anyways these things should have been brought up earlier. I'm out of the
> debate.
> >
> > I've sent v7 , incremental work over the last 6 months in my spare time
> without getting any pay. So take it or scrap it.
> >
> > 😊
>
> I'm sorry you feel that way but you asked for people to spend their time
> reviewing your code and giving feedback.



I’m sorry but you don’t understand. Giving feedback is one thing. Asking
people to make major changes to their design late in the game is completely
not acceptable imho and outright rude. . I’ve been sending out the patch
series with cc to anyone who should remotely care about this stuff. So if
major rework is needed it should be pointed out earlier and not later. I’ve
begged people on irc even to take look at this stuff including Igor and
others. What else do you expect me to do?

If you don't have time to take
> it forward then fine


I’m extremely discouraged by this and have lost all motivation. It’s not
that I have no time. I squeeze all my spare time to work on this beyond my
paid responsibilities. Please be respectful of that.


but I'm afraid a "take it or leave it" attitude
> will just result in it not getting merged.
>
> Hopefully someone else who has the time to look into it will be able to
> pick it up later.
>
> --
> Alex Bennée
>
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Fri, Oct 21, 2022 at 09:47:04PM +0530, Ani Sinha wrote:
> 
> 
> On Fri, Oct 21, 2022 at 21:36 Alex Bennée <alex.bennee@linaro.org> wrote:
> 
> 
>     Ani Sinha <ani@anisinha.ca> writes:
> 
>     <snip>
>     >
>     >  We have added a mirror of biosbits to the QEMU project so there is no
>     >  reason why we can't track changes and modifications there (we do this
>     >  for TestFloat which is forked from the upstream SoftFloat code).
>     >
>     > The whole idea was that say an acpi developer added support for a new
>     table in QEMU, he should write a corresponding
>     > test for bits so that the same table is exercised during run time. Making
>     those changes from a single repo (either directly
>     > or through a submodule)  makes things lit simpler and also keeps things
>     in sync with each other. If we use separate
>     > repos for acpi bits test, it will be another mess when comes to
>     developers adding changes and keeping things in sync.
>     >
>     > Anyways these things should have been brought up earlier. I'm out of the
>     debate.
>     >
>     > I've sent v7 , incremental work over the last 6 months in my spare time
>     without getting any pay. So take it or scrap it.
>     >
>     > 😊
> 
>     I'm sorry you feel that way but you asked for people to spend their time
>     reviewing your code and giving feedback.
> 
> 
> 
> I’m sorry but you don’t understand. Giving feedback is one thing. Asking people
> to make major changes to their design late in the game is completely not
> acceptable imho and outright rude. . I’ve been sending out the patch series
> with cc to anyone who should remotely care about this stuff. So if major rework
> is needed it should be pointed out earlier and not later. I’ve begged people on
> irc even to take look at this stuff including Igor and others. What else do you
> expect me to do? 
> 
> 
>     If you don't have time to take
>     it forward then fine
> 
> 
> I’m extremely discouraged by this and have lost all motivation. It’s not that I
> have no time. I squeeze all my spare time to work on this beyond my paid
> responsibilities. Please be respectful of that.
> 


Woa I hope you'll get the motivation back.

I feel more testing for acpi can only help, even if it is
limited to specific hosts at the moment.

Let's start small, and build out.

So IMHO major changes aren't strictly necessary to get this merged.
Alex sent a bunch of code review comments - do you think you can
address them?
The limitations and TODO should just IMHO be mentioned in the
cover letter and probably in comments in the code.

Thanks!


> 
>     but I'm afraid a "take it or leave it" attitude
>     will just result in it not getting merged.
> 
>     Hopefully someone else who has the time to look into it will be able to
>     pick it up later.
> 
>     --
>     Alex Bennée
> 


Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Sat, Oct 22, 2022 at 22:15 Michael S. Tsirkin <mst@redhat.com> wrote:

> On Fri, Oct 21, 2022 at 09:47:04PM +0530, Ani Sinha wrote:
> >
> >
> > On Fri, Oct 21, 2022 at 21:36 Alex Bennée <alex.bennee@linaro.org>
> wrote:
> >
> >
> >     Ani Sinha <ani@anisinha.ca> writes:
> >
> >     <snip>
> >     >
> >     >  We have added a mirror of biosbits to the QEMU project so there
> is no
> >     >  reason why we can't track changes and modifications there (we do
> this
> >     >  for TestFloat which is forked from the upstream SoftFloat code).
> >     >
> >     > The whole idea was that say an acpi developer added support for a
> new
> >     table in QEMU, he should write a corresponding
> >     > test for bits so that the same table is exercised during run time.
> Making
> >     those changes from a single repo (either directly
> >     > or through a submodule)  makes things lit simpler and also keeps
> things
> >     in sync with each other. If we use separate
> >     > repos for acpi bits test, it will be another mess when comes to
> >     developers adding changes and keeping things in sync.
> >     >
> >     > Anyways these things should have been brought up earlier. I'm out
> of the
> >     debate.
> >     >
> >     > I've sent v7 , incremental work over the last 6 months in my spare
> time
> >     without getting any pay. So take it or scrap it.
> >     >
> >     > 😊
> >
> >     I'm sorry you feel that way but you asked for people to spend their
> time
> >     reviewing your code and giving feedback.
> >
> >
> >
> > I’m sorry but you don’t understand. Giving feedback is one thing. Asking
> people
> > to make major changes to their design late in the game is completely not
> > acceptable imho and outright rude. . I’ve been sending out the patch
> series
> > with cc to anyone who should remotely care about this stuff. So if major
> rework
> > is needed it should be pointed out earlier and not later. I’ve begged
> people on
> > irc even to take look at this stuff including Igor and others. What else
> do you
> > expect me to do?
> >
> >
> >     If you don't have time to take
> >     it forward then fine
> >
> >
> > I’m extremely discouraged by this and have lost all motivation. It’s not
> that I
> > have no time. I squeeze all my spare time to work on this beyond my paid
> > responsibilities. Please be respectful of that.
> >
>
>
> Woa I hope you'll get the motivation back.
>
> I feel more testing for acpi can only help, even if it is
> limited to specific hosts at the moment.
>
> Let's start small, and build out.
>
> So IMHO major changes aren't strictly necessary to get this merged.
> Alex sent a bunch of code review comments - do you think you can
> address them?


I’ve addressed them in v7.


> The limitations and TODO should just IMHO be mentioned in the
> cover letter and probably in comments in the code.
>
> Thanks!
>
>
> >
> >     but I'm afraid a "take it or leave it" attitude
> >     will just result in it not getting merged.
> >
> >     Hopefully someone else who has the time to look into it will be able
> to
> >     pick it up later.
> >
> >     --
> >     Alex Bennée
> >
>
>
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, 21 Oct, 2022, 5:52 pm Ani Sinha, <ani@anisinha.ca> wrote:

>
>
> On Fri, 21 Oct, 2022, 5:26 pm Alex Bennée, <alex.bennee@linaro.org> wrote:
>
>>
>> Ani Sinha <ani@anisinha.ca> writes:
>>
>> > On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <mst@redhat.com>
>> wrote:
>> >>
>> >> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
>> >> >
>> >> > Ani Sinha <ani@anisinha.ca> writes:
>> >> >
>> >> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <mst@redhat.com>
>> wrote:
>> >> > >>
>> >> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
>> >> > >> > And have multiple platform specific branches in bits that have
>> fixes for those
>> >> > >> > platforms so that bits can run there. Plus the existing test
>> can be enhanced to
>> >> > >> > pull in binaries from those branches based on the platform on
>> which it is being
>> >> > >> > run.
>> >> > >> >
>> >> > >>
>> >> > >> What a mess.
>> >> > >> Who is going to be testing all these million platforms?
>> >> > >
>> >> > > I am not talking about branches in QEMU but branches in bits.
>> >> > > If you are going to test multiple platforms, you do need to build
>> bits
>> >> > > binaries for them. There is no way around it.
>> >> > > bits is not all platform independent python. It does have binary
>> executables.
>> >> > >
>> >> > > Currently bits is built only for the x86 platform. Other platforms
>> are
>> >> > > not tested. I doubt if anyone even tried building bits for arm or
>> >> > > mips.
>> >> >
>> >> > I'm not worried about test bits on other targets, but we do run x86
>> >> > targets on a number of hosts. The current reliance on a special
>> patched
>> >> > host build tool for only one architecture is the problem. If  we just
>> >> > download the iso that problem goes away.
>> >>
>> >> 👍what he said.
>> >
>> > Yes, in that case the problem is that upstream bits does not pass all
>> > the test out of the box. Hence we are taking this approach of keeping
>> > some test scripts in QEMU repo and modifying them. Then generating the
>> > iso with the modified scripts. It also helps developers who want to
>> > write new tests or make enhancements to existing tests.
>> > If modifications need to be made to tests, they need to be versioned.
>> > We have gone through the route of not using submodules and I am not
>> > going to open that can of worms again.
>>
>> We have added a mirror of biosbits to the QEMU project so there is no
>> reason why we can't track changes and modifications there (we do this
>> for TestFloat which is forked from the upstream SoftFloat code).
>>
>
> The whole idea was that say an acpi developer added support for a new
> table in QEMU, he should write a corresponding test for bits so that the
> same table is exercised during run time. Making those changes from a single
> repo (either directly or through a submodule)  makes things lit simpler and
> also keeps things in sync with each other. If we use separate repos for
> acpi bits test, it will be another mess when comes to developers adding
> changes and keeping things in sync.
>

Not only this. let's look at the developers workflow.

(A) check out bits repo.
(B) write new test.
(C) build the bits iso.
(D) get back to QEMU repo.
(E) point the test to the new iso so that the test gets executed.
(F) oops something failed. So let's rinse and repeat.
(G) once ready, send a PR for bits repo. update tags and figure out how
gitlab ci works so that the QEMU test can point to it. To do that figure
out the artefact  hash and other parameters.
(H) send a patch for QEMU repo to update the test to point to new iso.


How complicated is that? How complicated will it be for the reviewer? Right
now the developer can simply make changes from a single repo and run a
avocado test and check logs for failures. Once test is fixed, they can run
the test again to make sure everything passes. Once done, commit the test
in QEMU repo. If the test exercises a new table we make sure that the
commits adding the new table is already present before the test that
exercises it is committed. Send a patch for review. The reviewer applies
the patch and simply runs the avocado test from QEMU repo. Everything is in
one place. No back and forth between two repos. A lot like "make check".
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> On Fri, 21 Oct, 2022, 5:52 pm Ani Sinha, <ani@anisinha.ca> wrote:
>
>  On Fri, 21 Oct, 2022, 5:26 pm Alex Bennée, <alex.bennee@linaro.org> wrote:
>
>  Ani Sinha <ani@anisinha.ca> writes:
>
>  > On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>  >>
>  >> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
>  >> >
>  >> > Ani Sinha <ani@anisinha.ca> writes:
>  >> >
>  >> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>  >> > >>
>  >> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
>  >> > >> > And have multiple platform specific branches in bits that have fixes for those
>  >> > >> > platforms so that bits can run there. Plus the existing test can be enhanced to
>  >> > >> > pull in binaries from those branches based on the platform on which it is being
>  >> > >> > run.
>  >> > >> >
>  >> > >>
>  >> > >> What a mess.
>  >> > >> Who is going to be testing all these million platforms?
>  >> > >
>  >> > > I am not talking about branches in QEMU but branches in bits.
>  >> > > If you are going to test multiple platforms, you do need to build bits
>  >> > > binaries for them. There is no way around it.
>  >> > > bits is not all platform independent python. It does have binary executables.
>  >> > >
>  >> > > Currently bits is built only for the x86 platform. Other platforms are
>  >> > > not tested. I doubt if anyone even tried building bits for arm or
>  >> > > mips.
>  >> >
>  >> > I'm not worried about test bits on other targets, but we do run x86
>  >> > targets on a number of hosts. The current reliance on a special patched
>  >> > host build tool for only one architecture is the problem. If  we just
>  >> > download the iso that problem goes away.
>  >>
>  >> 👍what he said.
>  >
>  > Yes, in that case the problem is that upstream bits does not pass all
>  > the test out of the box. Hence we are taking this approach of keeping
>  > some test scripts in QEMU repo and modifying them. Then generating the
>  > iso with the modified scripts. It also helps developers who want to
>  > write new tests or make enhancements to existing tests.
>  > If modifications need to be made to tests, they need to be versioned.
>  > We have gone through the route of not using submodules and I am not
>  > going to open that can of worms again.
>
>  We have added a mirror of biosbits to the QEMU project so there is no
>  reason why we can't track changes and modifications there (we do this
>  for TestFloat which is forked from the upstream SoftFloat code).
>
>  The whole idea was that say an acpi developer added support for a new table in QEMU, he should write a
>  corresponding test for bits so that the same table is exercised during run time. Making those changes from a single
>  repo (either directly or through a submodule)  makes things lit simpler and also keeps things in sync with each
>  other. If we use separate repos for acpi bits test, it will be another mess when comes to developers adding changes
>  and keeping things in sync.

For people that care about ACPI it shouldn't be that hard. Most QEMU
developers have separate repos of test cases that aren't directly
integrated into QEMU for various things (e.g. RISU, semihosting,
baremetal, kvm-unit-tests, LTP).

> Not only this. let's look at the developers workflow.
>
> (A) check out bits repo.
> (B) write new test.
> (C) build the bits iso.
> (D) get back to QEMU repo.
> (E) point the test to the new iso so that the test gets executed.

This seems like a long winded workflow. Usually you test your binaries
before integrating them into the acceptance tests. All you need is a
script to launch qemu (either system or point at a developer binary) and
run directly. Only once you are happy with the final ISO would you
upload and then integrate into check-acceptance.

> (F) oops something failed. So let's rinse and repeat.
> (G) once ready, send a PR for bits repo. update tags and figure out how gitlab ci works so that the QEMU test can point to
> it. To do that figure out the artefact  hash and other parameters.
> (H) send a patch for QEMU repo to update the test to point to new iso.
>
> How complicated is that? How complicated will it be for the reviewer? Right now the developer can simply make changes
> from a single repo and run a avocado test and check logs for failures. Once test is fixed, they can run the test again to
> make sure everything passes. Once done, commit the test in QEMU repo. If the test exercises a new table we make sure
> that the commits adding the new table is already present before the test that exercises it is committed. Send a patch for
> review. The reviewer applies the patch and simply runs the avocado test from QEMU repo. Everything is in one place. No
> back and forth between two repos. A lot like "make check".

We do indeed build tests for a lot of make check (unit, qtest, tcg) but
they build on all our host architectures and have configure machinery to
make them optional if host binaries are missing. For avocado tests we
typically are using other peoples binaries so this series is a departure
from that model.

-- 
Alex Bennée
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, Oct 21, 2022 at 9:32 PM Alex Bennée <alex.bennee@linaro.org> wrote:

>
> Ani Sinha <ani@anisinha.ca> writes:
>
> > On Fri, 21 Oct, 2022, 5:52 pm Ani Sinha, <ani@anisinha.ca> wrote:
> >
> >  On Fri, 21 Oct, 2022, 5:26 pm Alex Bennée, <alex.bennee@linaro.org>
> wrote:
> >
> >  Ani Sinha <ani@anisinha.ca> writes:
> >
> >  > On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> >  >>
> >  >> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
> >  >> >
> >  >> > Ani Sinha <ani@anisinha.ca> writes:
> >  >> >
> >  >> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <
> mst@redhat.com> wrote:
> >  >> > >>
> >  >> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
> >  >> > >> > And have multiple platform specific branches in bits that
> have fixes for those
> >  >> > >> > platforms so that bits can run there. Plus the existing test
> can be enhanced to
> >  >> > >> > pull in binaries from those branches based on the platform on
> which it is being
> >  >> > >> > run.
> >  >> > >> >
> >  >> > >>
> >  >> > >> What a mess.
> >  >> > >> Who is going to be testing all these million platforms?
> >  >> > >
> >  >> > > I am not talking about branches in QEMU but branches in bits.
> >  >> > > If you are going to test multiple platforms, you do need to
> build bits
> >  >> > > binaries for them. There is no way around it.
> >  >> > > bits is not all platform independent python. It does have binary
> executables.
> >  >> > >
> >  >> > > Currently bits is built only for the x86 platform. Other
> platforms are
> >  >> > > not tested. I doubt if anyone even tried building bits for arm or
> >  >> > > mips.
> >  >> >
> >  >> > I'm not worried about test bits on other targets, but we do run x86
> >  >> > targets on a number of hosts. The current reliance on a special
> patched
> >  >> > host build tool for only one architecture is the problem. If  we
> just
> >  >> > download the iso that problem goes away.
> >  >>
> >  >> 👍what he said.
> >  >
> >  > Yes, in that case the problem is that upstream bits does not pass all
> >  > the test out of the box. Hence we are taking this approach of keeping
> >  > some test scripts in QEMU repo and modifying them. Then generating the
> >  > iso with the modified scripts. It also helps developers who want to
> >  > write new tests or make enhancements to existing tests.
> >  > If modifications need to be made to tests, they need to be versioned.
> >  > We have gone through the route of not using submodules and I am not
> >  > going to open that can of worms again.
> >
> >  We have added a mirror of biosbits to the QEMU project so there is no
> >  reason why we can't track changes and modifications there (we do this
> >  for TestFloat which is forked from the upstream SoftFloat code).
> >
> >  The whole idea was that say an acpi developer added support for a new
> table in QEMU, he should write a
> >  corresponding test for bits so that the same table is exercised during
> run time. Making those changes from a single
> >  repo (either directly or through a submodule)  makes things lit simpler
> and also keeps things in sync with each
> >  other. If we use separate repos for acpi bits test, it will be another
> mess when comes to developers adding changes
> >  and keeping things in sync.
>
> For people that care about ACPI it shouldn't be that hard. Most QEMU
> developers have separate repos of test cases that aren't directly
> integrated into QEMU for various things (e.g. RISU, semihosting,
> baremetal, kvm-unit-tests, LTP).
>
> > Not only this. let's look at the developers workflow.
> >
> > (A) check out bits repo.
> > (B) write new test.
> > (C) build the bits iso.
> > (D) get back to QEMU repo.
> > (E) point the test to the new iso so that the test gets executed.
>
> This seems like a long winded workflow. Usually you test your binaries
> before integrating them into the acceptance tests. All you need is a
> script to launch qemu (either system or point at a developer binary) and
> run directly. Only once you are happy with the final ISO


And how would you know which iso is the final iso? You need several trial
runs with added test and building bits iso with it. Each time an iso is
generated, it must be launched with a qemu using the right command line
which the test automatically generates for the developer. Hence you either
need to examine what command line the test uses or use the test script
directly with the iso you generated and collect the logs. The test script
is in one repo, the bits is in one repo. Since bits is not a sub module,
the developer has to check out both repos separately and go back and forth.

And how are you supposed to explain all this to a guy who submitted a acpi
patch? You don't need to because you don't review acpi patches but I do.

My last 2 cents.


>
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, Oct 21, 2022 at 21:32 Alex Bennée <alex.bennee@linaro.org> wrote:

>
> Ani Sinha <ani@anisinha.ca> writes:
>
> > On Fri, 21 Oct, 2022, 5:52 pm Ani Sinha, <ani@anisinha.ca> wrote:
> >
> >  On Fri, 21 Oct, 2022, 5:26 pm Alex Bennée, <alex.bennee@linaro.org>
> wrote:
> >
> >  Ani Sinha <ani@anisinha.ca> writes:
> >
> >  > On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> >  >>
> >  >> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
> >  >> >
> >  >> > Ani Sinha <ani@anisinha.ca> writes:
> >  >> >
> >  >> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <
> mst@redhat.com> wrote:
> >  >> > >>
> >  >> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
> >  >> > >> > And have multiple platform specific branches in bits that
> have fixes for those
> >  >> > >> > platforms so that bits can run there. Plus the existing test
> can be enhanced to
> >  >> > >> > pull in binaries from those branches based on the platform on
> which it is being
> >  >> > >> > run.
> >  >> > >> >
> >  >> > >>
> >  >> > >> What a mess.
> >  >> > >> Who is going to be testing all these million platforms?
> >  >> > >
> >  >> > > I am not talking about branches in QEMU but branches in bits.
> >  >> > > If you are going to test multiple platforms, you do need to
> build bits
> >  >> > > binaries for them. There is no way around it.
> >  >> > > bits is not all platform independent python. It does have binary
> executables.
> >  >> > >
> >  >> > > Currently bits is built only for the x86 platform. Other
> platforms are
> >  >> > > not tested. I doubt if anyone even tried building bits for arm or
> >  >> > > mips.
> >  >> >
> >  >> > I'm not worried about test bits on other targets, but we do run x86
> >  >> > targets on a number of hosts. The current reliance on a special
> patched
> >  >> > host build tool for only one architecture is the problem. If  we
> just
> >  >> > download the iso that problem goes away.
> >  >>
> >  >> 👍what he said.
> >  >
> >  > Yes, in that case the problem is that upstream bits does not pass all
> >  > the test out of the box. Hence we are taking this approach of keeping
> >  > some test scripts in QEMU repo and modifying them. Then generating the
> >  > iso with the modified scripts. It also helps developers who want to
> >  > write new tests or make enhancements to existing tests.
> >  > If modifications need to be made to tests, they need to be versioned.
> >  > We have gone through the route of not using submodules and I am not
> >  > going to open that can of worms again.
> >
> >  We have added a mirror of biosbits to the QEMU project so there is no
> >  reason why we can't track changes and modifications there (we do this
> >  for TestFloat which is forked from the upstream SoftFloat code).


One last option. Commit this patch set but also double commit patch 3 to
the bits repo so that we can build an iso that would successfully run all
tests for a separate platform independent test to be written later.

Then we will have two tests:

- this one for developers writing new test.
- platform independent one for a basic sanity.

I’m just documenting the fact that I have proposed ideas that can work
where all can be happy. It’s up to others to take it or keep objecting and
killing motivations for freelance contributors.



> >
> >
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Sat, Oct 22, 2022 at 06:28:32AM +0530, Ani Sinha wrote:
> 
> 
> On Fri, Oct 21, 2022 at 21:32 Alex Bennée <alex.bennee@linaro.org> wrote:
> 
> 
>     Ani Sinha <ani@anisinha.ca> writes:
> 
>     > On Fri, 21 Oct, 2022, 5:52 pm Ani Sinha, <ani@anisinha.ca> wrote:
>     >
>     >  On Fri, 21 Oct, 2022, 5:26 pm Alex Bennée, <alex.bennee@linaro.org>
>     wrote:
>     >
>     >  Ani Sinha <ani@anisinha.ca> writes:
>     >
>     >  > On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <mst@redhat.com>
>     wrote:
>     >  >>
>     >  >> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
>     >  >> >
>     >  >> > Ani Sinha <ani@anisinha.ca> writes:
>     >  >> >
>     >  >> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <
>     mst@redhat.com> wrote:
>     >  >> > >>
>     >  >> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
>     >  >> > >> > And have multiple platform specific branches in bits that have
>     fixes for those
>     >  >> > >> > platforms so that bits can run there. Plus the existing test
>     can be enhanced to
>     >  >> > >> > pull in binaries from those branches based on the platform on
>     which it is being
>     >  >> > >> > run.
>     >  >> > >> >
>     >  >> > >>
>     >  >> > >> What a mess.
>     >  >> > >> Who is going to be testing all these million platforms?
>     >  >> > >
>     >  >> > > I am not talking about branches in QEMU but branches in bits.
>     >  >> > > If you are going to test multiple platforms, you do need to build
>     bits
>     >  >> > > binaries for them. There is no way around it.
>     >  >> > > bits is not all platform independent python. It does have binary
>     executables.
>     >  >> > >
>     >  >> > > Currently bits is built only for the x86 platform. Other
>     platforms are
>     >  >> > > not tested. I doubt if anyone even tried building bits for arm or
>     >  >> > > mips.
>     >  >> >
>     >  >> > I'm not worried about test bits on other targets, but we do run x86
>     >  >> > targets on a number of hosts. The current reliance on a special
>     patched
>     >  >> > host build tool for only one architecture is the problem. If  we
>     just
>     >  >> > download the iso that problem goes away.
>     >  >>
>     >  >> 👍what he said.
>     >  >
>     >  > Yes, in that case the problem is that upstream bits does not pass all
>     >  > the test out of the box. Hence we are taking this approach of keeping
>     >  > some test scripts in QEMU repo and modifying them. Then generating the
>     >  > iso with the modified scripts. It also helps developers who want to
>     >  > write new tests or make enhancements to existing tests.
>     >  > If modifications need to be made to tests, they need to be versioned.
>     >  > We have gone through the route of not using submodules and I am not
>     >  > going to open that can of worms again.
>     >
>     >  We have added a mirror of biosbits to the QEMU project so there is no
>     >  reason why we can't track changes and modifications there (we do this
>     >  for TestFloat which is forked from the upstream SoftFloat code).
> 
> 
> One last option. Commit this patch set but also double commit patch 3 to the
> bits repo so that we can build an iso that would successfully run all tests for
> a separate platform independent test to be written later.
> 
> Then we will have two tests:
> 
> - this one for developers writing new test.
> - platform independent one for a basic sanity.
> 
> I’m just documenting the fact that I have proposed ideas that can work where
> all can be happy. It’s up to others to take it or keep objecting and killing
> motivations for freelance contributors. 

I think it's ok to apply this as is for starters.
Anyone has objections?

Down the road I think things should be refactored slightly to work as follows:
- test developers can check out biosbits repo to create the iso
- everyone else gets iso downloaded

Objections to this plan?


> 
> 
> 
>     >
>     > 
> 


Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Sat, Oct 22, 2022 at 22:05 Michael S. Tsirkin <mst@redhat.com> wrote:

> On Sat, Oct 22, 2022 at 06:28:32AM +0530, Ani Sinha wrote:
> >
> >
> > On Fri, Oct 21, 2022 at 21:32 Alex Bennée <alex.bennee@linaro.org>
> wrote:
> >
> >
> >     Ani Sinha <ani@anisinha.ca> writes:
> >
> >     > On Fri, 21 Oct, 2022, 5:52 pm Ani Sinha, <ani@anisinha.ca> wrote:
> >     >
> >     >  On Fri, 21 Oct, 2022, 5:26 pm Alex Bennée, <
> alex.bennee@linaro.org>
> >     wrote:
> >     >
> >     >  Ani Sinha <ani@anisinha.ca> writes:
> >     >
> >     >  > On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <
> mst@redhat.com>
> >     wrote:
> >     >  >>
> >     >  >> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
> >     >  >> >
> >     >  >> > Ani Sinha <ani@anisinha.ca> writes:
> >     >  >> >
> >     >  >> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <
> >     mst@redhat.com> wrote:
> >     >  >> > >>
> >     >  >> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
> >     >  >> > >> > And have multiple platform specific branches in bits
> that have
> >     fixes for those
> >     >  >> > >> > platforms so that bits can run there. Plus the existing
> test
> >     can be enhanced to
> >     >  >> > >> > pull in binaries from those branches based on the
> platform on
> >     which it is being
> >     >  >> > >> > run.
> >     >  >> > >> >
> >     >  >> > >>
> >     >  >> > >> What a mess.
> >     >  >> > >> Who is going to be testing all these million platforms?
> >     >  >> > >
> >     >  >> > > I am not talking about branches in QEMU but branches in
> bits.
> >     >  >> > > If you are going to test multiple platforms, you do need
> to build
> >     bits
> >     >  >> > > binaries for them. There is no way around it.
> >     >  >> > > bits is not all platform independent python. It does have
> binary
> >     executables.
> >     >  >> > >
> >     >  >> > > Currently bits is built only for the x86 platform. Other
> >     platforms are
> >     >  >> > > not tested. I doubt if anyone even tried building bits for
> arm or
> >     >  >> > > mips.
> >     >  >> >
> >     >  >> > I'm not worried about test bits on other targets, but we do
> run x86
> >     >  >> > targets on a number of hosts. The current reliance on a
> special
> >     patched
> >     >  >> > host build tool for only one architecture is the problem.
> If  we
> >     just
> >     >  >> > download the iso that problem goes away.
> >     >  >>
> >     >  >> 👍what he said.
> >     >  >
> >     >  > Yes, in that case the problem is that upstream bits does not
> pass all
> >     >  > the test out of the box. Hence we are taking this approach of
> keeping
> >     >  > some test scripts in QEMU repo and modifying them. Then
> generating the
> >     >  > iso with the modified scripts. It also helps developers who
> want to
> >     >  > write new tests or make enhancements to existing tests.
> >     >  > If modifications need to be made to tests, they need to be
> versioned.
> >     >  > We have gone through the route of not using submodules and I am
> not
> >     >  > going to open that can of worms again.
> >     >
> >     >  We have added a mirror of biosbits to the QEMU project so there
> is no
> >     >  reason why we can't track changes and modifications there (we do
> this
> >     >  for TestFloat which is forked from the upstream SoftFloat code).
> >
> >
> > One last option. Commit this patch set but also double commit patch 3 to
> the
> > bits repo so that we can build an iso that would successfully run all
> tests for
> > a separate platform independent test to be written later.
> >
> > Then we will have two tests:
> >
> > - this one for developers writing new test.
> > - platform independent one for a basic sanity.
> >
> > I’m just documenting the fact that I have proposed ideas that can work
> where
> > all can be happy. It’s up to others to take it or keep objecting and
> killing
> > motivations for freelance contributors.
>
> I think it's ok to apply this as is for starters.
> Anyone has objections?
>
> Down the road I think things should be refactored slightly to work as
> follows:
> - test developers can check out biosbits repo to create the iso
> - everyone else gets iso downloaded


It will be difficult to convince test developers to check out another repo
and go back and forth between two repos. If the bits repo was a sub module
that’s another story.

Test developers should use the test scripts from qemu repo. Someone then
later can incrementally commit these new tests into bits repo and generate
newer iso at some periodic intervals. Since I am the maintainer of the bits
repo I can do the second part.



>
> Objections to this plan?
>
>
> >
> >
> >
> >     >
> >     >
> >
>
>
Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Michael S. Tsirkin 1 year, 6 months ago
On Sat, Oct 22, 2022 at 10:13:13PM +0530, Ani Sinha wrote:
> 
> 
> On Sat, Oct 22, 2022 at 22:05 Michael S. Tsirkin <mst@redhat.com> wrote:
> 
>     On Sat, Oct 22, 2022 at 06:28:32AM +0530, Ani Sinha wrote:
>     >
>     >
>     > On Fri, Oct 21, 2022 at 21:32 Alex Bennée <alex.bennee@linaro.org> wrote:
>     >
>     >
>     >     Ani Sinha <ani@anisinha.ca> writes:
>     >
>     >     > On Fri, 21 Oct, 2022, 5:52 pm Ani Sinha, <ani@anisinha.ca> wrote:
>     >     >
>     >     >  On Fri, 21 Oct, 2022, 5:26 pm Alex Bennée, <alex.bennee@linaro.org
>     >
>     >     wrote:
>     >     >
>     >     >  Ani Sinha <ani@anisinha.ca> writes:
>     >     >
>     >     >  > On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <
>     mst@redhat.com>
>     >     wrote:
>     >     >  >>
>     >     >  >> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
>     >     >  >> >
>     >     >  >> > Ani Sinha <ani@anisinha.ca> writes:
>     >     >  >> >
>     >     >  >> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <
>     >     mst@redhat.com> wrote:
>     >     >  >> > >>
>     >     >  >> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
>     >     >  >> > >> > And have multiple platform specific branches in bits
>     that have
>     >     fixes for those
>     >     >  >> > >> > platforms so that bits can run there. Plus the existing
>     test
>     >     can be enhanced to
>     >     >  >> > >> > pull in binaries from those branches based on the
>     platform on
>     >     which it is being
>     >     >  >> > >> > run.
>     >     >  >> > >> >
>     >     >  >> > >>
>     >     >  >> > >> What a mess.
>     >     >  >> > >> Who is going to be testing all these million platforms?
>     >     >  >> > >
>     >     >  >> > > I am not talking about branches in QEMU but branches in
>     bits.
>     >     >  >> > > If you are going to test multiple platforms, you do need to
>     build
>     >     bits
>     >     >  >> > > binaries for them. There is no way around it.
>     >     >  >> > > bits is not all platform independent python. It does have
>     binary
>     >     executables.
>     >     >  >> > >
>     >     >  >> > > Currently bits is built only for the x86 platform. Other
>     >     platforms are
>     >     >  >> > > not tested. I doubt if anyone even tried building bits for
>     arm or
>     >     >  >> > > mips.
>     >     >  >> >
>     >     >  >> > I'm not worried about test bits on other targets, but we do
>     run x86
>     >     >  >> > targets on a number of hosts. The current reliance on a
>     special
>     >     patched
>     >     >  >> > host build tool for only one architecture is the problem. If 
>     we
>     >     just
>     >     >  >> > download the iso that problem goes away.
>     >     >  >>
>     >     >  >> 👍what he said.
>     >     >  >
>     >     >  > Yes, in that case the problem is that upstream bits does not
>     pass all
>     >     >  > the test out of the box. Hence we are taking this approach of
>     keeping
>     >     >  > some test scripts in QEMU repo and modifying them. Then
>     generating the
>     >     >  > iso with the modified scripts. It also helps developers who want
>     to
>     >     >  > write new tests or make enhancements to existing tests.
>     >     >  > If modifications need to be made to tests, they need to be
>     versioned.
>     >     >  > We have gone through the route of not using submodules and I am
>     not
>     >     >  > going to open that can of worms again.
>     >     >
>     >     >  We have added a mirror of biosbits to the QEMU project so there is
>     no
>     >     >  reason why we can't track changes and modifications there (we do
>     this
>     >     >  for TestFloat which is forked from the upstream SoftFloat code).
>     >
>     >
>     > One last option. Commit this patch set but also double commit patch 3 to
>     the
>     > bits repo so that we can build an iso that would successfully run all
>     tests for
>     > a separate platform independent test to be written later.
>     >
>     > Then we will have two tests:
>     >
>     > - this one for developers writing new test.
>     > - platform independent one for a basic sanity.
>     >
>     > I’m just documenting the fact that I have proposed ideas that can work
>     where
>     > all can be happy. It’s up to others to take it or keep objecting and
>     killing
>     > motivations for freelance contributors. 
> 
>     I think it's ok to apply this as is for starters.
>     Anyone has objections?
> 
>     Down the road I think things should be refactored slightly to work as
>     follows:
>     - test developers can check out biosbits repo to create the iso
>     - everyone else gets iso downloaded
> 
> 
> It will be difficult to convince test developers to check out another repo and
> go back and forth between two repos. If the bits repo was a sub module that’s
> another story.
> 
> Test developers should use the test scripts from qemu repo. Someone then later
> can incrementally commit these new tests into bits repo and generate newer iso
> at some periodic intervals. Since I am the maintainer of the bits repo I can do
> the second part.

Sounds like a plan. Anyway, I think we can worry about that down the road
after something is merged.


> 
> 
> 
> 
>     Objections to this plan?
> 
> 
>     >
>     >
>     >
>     >     >
>     >     > 
>     >
> 
> 


Re: [PATCH v6 00/10] Introduce new acpi/smbios avocado tests using biosbits
Posted by Ani Sinha 1 year, 6 months ago
On Fri, Oct 21, 2022 at 21:32 Alex Bennée <alex.bennee@linaro.org> wrote:

>
> Ani Sinha <ani@anisinha.ca> writes:
>
> > On Fri, 21 Oct, 2022, 5:52 pm Ani Sinha, <ani@anisinha.ca> wrote:
> >
> >  On Fri, 21 Oct, 2022, 5:26 pm Alex Bennée, <alex.bennee@linaro.org>
> wrote:
> >
> >  Ani Sinha <ani@anisinha.ca> writes:
> >
> >  > On Fri, Oct 21, 2022 at 3:10 PM Michael S. Tsirkin <mst@redhat.com>
> wrote:
> >  >>
> >  >> On Fri, Oct 21, 2022 at 10:30:09AM +0100, Alex Bennée wrote:
> >  >> >
> >  >> > Ani Sinha <ani@anisinha.ca> writes:
> >  >> >
> >  >> > > On Fri, Oct 21, 2022 at 2:02 PM Michael S. Tsirkin <
> mst@redhat.com> wrote:
> >  >> > >>
> >  >> > >> On Fri, Oct 21, 2022 at 05:45:15AM +0530, Ani Sinha wrote:
> >  >> > >> > And have multiple platform specific branches in bits that
> have fixes for those
> >  >> > >> > platforms so that bits can run there. Plus the existing test
> can be enhanced to
> >  >> > >> > pull in binaries from those branches based on the platform on
> which it is being
> >  >> > >> > run.
> >  >> > >> >
> >  >> > >>
> >  >> > >> What a mess.
> >  >> > >> Who is going to be testing all these million platforms?
> >  >> > >
> >  >> > > I am not talking about branches in QEMU but branches in bits.
> >  >> > > If you are going to test multiple platforms, you do need to
> build bits
> >  >> > > binaries for them. There is no way around it.
> >  >> > > bits is not all platform independent python. It does have binary
> executables.
> >  >> > >
> >  >> > > Currently bits is built only for the x86 platform. Other
> platforms are
> >  >> > > not tested. I doubt if anyone even tried building bits for arm or
> >  >> > > mips.
> >  >> >
> >  >> > I'm not worried about test bits on other targets, but we do run x86
> >  >> > targets on a number of hosts. The current reliance on a special
> patched
> >  >> > host build tool for only one architecture is the problem. If  we
> just
> >  >> > download the iso that problem goes away.
> >  >>
> >  >> 👍what he said.
> >  >
> >  > Yes, in that case the problem is that upstream bits does not pass all
> >  > the test out of the box. Hence we are taking this approach of keeping
> >  > some test scripts in QEMU repo and modifying them. Then generating the
> >  > iso with the modified scripts. It also helps developers who want to
> >  > write new tests or make enhancements to existing tests.
> >  > If modifications need to be made to tests, they need to be versioned.
> >  > We have gone through the route of not using submodules and I am not
> >  > going to open that can of worms again.
> >
> >  We have added a mirror of biosbits to the QEMU project so there is no
> >  reason why we can't track changes and modifications there (we do this
> >  for TestFloat which is forked from the upstream SoftFloat code).
> >
> >  The whole idea was that say an acpi developer added support for a new
> table in QEMU, he should write a
> >  corresponding test for bits so that the same table is exercised during
> run time. Making those changes from a single
> >  repo (either directly or through a submodule)  makes things lit simpler
> and also keeps things in sync with each
> >  other. If we use separate repos for acpi bits test, it will be another
> mess when comes to developers adding changes
> >  and keeping things in sync.
>
> For people that care about ACPI it shouldn't be that hard.


People who submit patches for acpi come from all over the place and they
mostly care about the qemu source tree and not any other repos.

Most QEMU
> developers have separate repos of test cases that aren't directly
> integrated into QEMU for various things (e.g. RISU, semihosting,
> baremetal, kvm-unit-tests, LTP).
>
> > Not only this. let's look at the developers workflow.
> >
> > (A) check out bits repo.
> > (B) write new test.
> > (C) build the bits iso.
> > (D) get back to QEMU repo.
> > (E) point the test to the new iso so that the test gets executed.
>
> This seems like a long winded workflow. Usually you test your binaries
> before integrating them into the acceptance tests. All you need is a
> script to launch qemu (either system or point at a developer binary) and
> run directly. Only once you are happy with the final ISO would you
> upload and then integrate into check-acceptance.
>
> > (F) oops something failed. So let's rinse and repeat.
> > (G) once ready, send a PR for bits repo. update tags and figure out how
> gitlab ci works so that the QEMU test can point to
> > it. To do that figure out the artefact  hash and other parameters.
> > (H) send a patch for QEMU repo to update the test to point to new iso.
> >
> > How complicated is that? How complicated will it be for the reviewer?
> Right now the developer can simply make changes
> > from a single repo and run a avocado test and check logs for failures.
> Once test is fixed, they can run the test again to
> > make sure everything passes. Once done, commit the test in QEMU repo. If
> the test exercises a new table we make sure
> > that the commits adding the new table is already present before the test
> that exercises it is committed. Send a patch for
> > review. The reviewer applies the patch and simply runs the avocado test
> from QEMU repo. Everything is in one place. No
> > back and forth between two repos. A lot like "make check".
>
> We do indeed build tests for a lot of make check (unit, qtest, tcg) but
> they build on all our host architectures and have configure machinery to
> make them optional if host binaries are missing. For avocado tests we
> typically are using other peoples binaries so this series is a departure
> from that model.


Yea so if you are using other peoples binaries you should not assume that
they will work on all host architectures.
[PATCH v6 01/10] acpi/tests/avocado/bits: initial commit of test scripts that are run by biosbits
Posted by Ani Sinha 1 year, 6 months ago
This is initial commit of cpuid, acpi and smbios python test scripts for
biosbits to execute. No change has been made to them from the original code
written by the biosbits author Josh Triplett. They are required to be installed
into the bits iso file and then run from within the virtual machine booted off
with biosbits iso.

The test scripts have a ".py2" extension in order to prevent avocado from
loading them. They are written in python 2.7 and are run from within bios bits.
There is no need for avocado to try to load them and call out errors on python3
specific syntaxes.

The original location of these tests are here:
https://github.com/biosbits/bits/blob/master/python/testacpi.py
https://github.com/biosbits/bits/blob/master/python/smbios.py
https://github.com/biosbits/bits/blob/master/python/testcpuid.py

For QEMU, we maintain a fork of the above repo here with numerious fixes:
https://gitlab.com/qemu-project/biosbits-bits

The acpi test for example is maintained here in the fork:
https://gitlab.com/qemu-project/biosbits-bits/-/raw/master/python/testacpi.py

Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
---
 tests/avocado/acpi-bits/bits-tests/smbios.py2 | 2430 +++++++++++++++++
 .../avocado/acpi-bits/bits-tests/testacpi.py2 |  283 ++
 .../acpi-bits/bits-tests/testcpuid.py2        |   83 +
 3 files changed, 2796 insertions(+)
 create mode 100644 tests/avocado/acpi-bits/bits-tests/smbios.py2
 create mode 100644 tests/avocado/acpi-bits/bits-tests/testacpi.py2
 create mode 100644 tests/avocado/acpi-bits/bits-tests/testcpuid.py2

diff --git a/tests/avocado/acpi-bits/bits-tests/smbios.py2 b/tests/avocado/acpi-bits/bits-tests/smbios.py2
new file mode 100644
index 0000000000..9667d0542c
--- /dev/null
+++ b/tests/avocado/acpi-bits/bits-tests/smbios.py2
@@ -0,0 +1,2430 @@
+# Copyright (c) 2015, Intel Corporation
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#     * Redistributions of source code must retain the above copyright notice,
+#       this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright notice,
+#       this list of conditions and the following disclaimer in the documentation
+#       and/or other materials provided with the distribution.
+#     * Neither the name of Intel Corporation nor the names of its contributors
+#       may be used to endorse or promote products derived from this software
+#       without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""SMBIOS/DMI module."""
+
+import bits
+import bitfields
+import ctypes
+import redirect
+import struct
+import uuid
+import unpack
+import ttypager
+import sys
+
+class SMBIOS(unpack.Struct):
+    def __new__(cls):
+        if sys.platform == "BITS-EFI":
+            import efi
+            sm_ptr = efi.system_table.ConfigurationTableDict.get(efi.SMBIOS_TABLE_GUID)
+        else:
+            address = 0xF0000
+            mem = bits.memory(0xF0000, 0x10000)
+            for offset in range(0, len(mem), 16):
+                signature = (ctypes.c_char * 4).from_address(address + offset).value
+                if signature == "_SM_":
+                    entry_point_length = ctypes.c_ubyte.from_address(address + offset + 5).value
+                    csum = sum(map(ord, mem[offset:offset + entry_point_length])) & 0xff
+                    if csum == 0:
+                        sm_ptr = address + offset
+                        break
+            else:
+                return None
+
+        if not sm_ptr:
+            return None
+
+        sm = super(SMBIOS, cls).__new__(cls)
+        sm._header_memory = bits.memory(sm_ptr, 0x1f)
+        return sm
+
+    def __init__(self):
+        super(SMBIOS, self).__init__()
+        u = unpack.Unpackable(self._header_memory)
+        self.add_field('header', Header(u))
+        self._structure_memory = bits.memory(self.header.structure_table_address, self.header.structure_table_length)
+        u = unpack.Unpackable(self._structure_memory)
+        self.add_field('structures', unpack.unpack_all(u, _smbios_structures, self), unpack.format_each("\n\n{!r}"))
+
+    def structure_type(self, num):
+        '''Dumps structure of given Type if present'''
+        try:
+            types_present = [self.structures[x].smbios_structure_type for x in range(len(self.structures))]
+            matrix = dict()
+            for index in range(len(types_present)):
+                if types_present.count(types_present[index]) == 1:
+                    matrix[types_present[index]] = self.structures[index]
+                else: # if multiple structures of the same type, return a list of structures for the type number
+                    if matrix.has_key(types_present[index]):
+                        matrix[types_present[index]].append(self.structures[index])
+                    else:
+                        matrix[types_present[index]] = [self.structures[index]]
+            return matrix[num]
+        except:
+            print "Failure: Type {} - not found".format(num)
+
+class Header(unpack.Struct):
+    def __new__(cls, u):
+        return super(Header, cls).__new__(cls)
+
+    def __init__(self, u):
+        super(Header, self).__init__()
+        self.raw_data = u.unpack_rest()
+        u = unpack.Unpackable(self.raw_data)
+        self.add_field('anchor_string', u.unpack_one("4s"))
+        self.add_field('checksum', u.unpack_one("B"))
+        self.add_field('length', u.unpack_one("B"))
+        self.add_field('major_version', u.unpack_one("B"))
+        self.add_field('minor_version', u.unpack_one("B"))
+        self.add_field('max_structure_size', u.unpack_one("<H"))
+        self.add_field('entry_point_revision', u.unpack_one("B"))
+        self.add_field('formatted_area', u.unpack_one("5s"))
+        self.add_field('intermediate_anchor_string', u.unpack_one("5s"))
+        self.add_field('intermediate_checksum', u.unpack_one("B"))
+        self.add_field('structure_table_length', u.unpack_one("<H"))
+        self.add_field('structure_table_address', u.unpack_one("<I"))
+        self.add_field('number_structures', u.unpack_one("<H"))
+        self.add_field('bcd_revision', u.unpack_one("B"))
+        if not u.at_end():
+            self.add_field('data', u.unpack_rest())
+
+class SmbiosBaseStructure(unpack.Struct):
+    def __new__(cls, u, sm):
+        t = u.unpack_peek_one("B")
+        if cls.smbios_structure_type is not None and t != cls.smbios_structure_type:
+            return None
+        return super(SmbiosBaseStructure, cls).__new__(cls)
+
+    def __init__(self, u, sm):
+        super(SmbiosBaseStructure, self).__init__()
+        self.start_offset = u.offset
+        length = u.unpack_peek_one("<xB")
+        self.raw_data = u.unpack_raw(length)
+        self.u = unpack.Unpackable(self.raw_data)
+
+        self.strings_offset = u.offset
+        def unpack_string():
+            return "".join(iter(lambda: u.unpack_one("c"), "\x00"))
+        strings = list(iter(unpack_string, ""))
+        if not strings:
+            u.skip(1)
+
+        self.strings_length = u.offset - self.strings_offset
+        self.raw_strings = str(bits.memory(sm.header.structure_table_address + self.strings_offset, self.strings_length))
+
+        if len(strings):
+            self.strings = strings
+
+        self.add_field('type', self.u.unpack_one("B"))
+        self.add_field('length', self.u.unpack_one("B"))
+        self.add_field('handle', self.u.unpack_one("<H"))
+
+    def fini(self):
+        if not self.u.at_end():
+            self.add_field('data', self.u.unpack_rest())
+        del self.u
+
+    def fmtstr(self, i):
+        """Format the specified index and the associated string"""
+        return "{} '{}'".format(i, self.getstr(i))
+
+    def getstr(self, i):
+        """Get the string associated with the given index"""
+        if i == 0:
+            return "(none)"
+        if not hasattr(self, "strings"):
+            return "(error: structure has no strings)"
+        if i > len(self.strings):
+            return "(error: string index out of range)"
+        return self.strings[i - 1]
+
+class BIOSInformation(SmbiosBaseStructure):
+    smbios_structure_type = 0
+
+    def __init__(self, u, sm):
+        super(BIOSInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('vendor', u.unpack_one("B"), self.fmtstr)
+            self.add_field('version', u.unpack_one("B"), self.fmtstr)
+            self.add_field('starting_address_segment', u.unpack_one("<H"))
+            self.add_field('release_date', u.unpack_one("B"), self.fmtstr)
+            self.add_field('rom_size', u.unpack_one("B"))
+            self.add_field('characteristics', u.unpack_one("<Q"))
+            minor_version_str = str(sm.header.minor_version) # 34 is .34, 4 is .4, 41 is .41; compare ASCIIbetically to compare initial digits rather than numeric value
+            if (sm.header.major_version, minor_version_str) >= (2,"4"):
+                characteristic_bytes = 2
+            else:
+                characteristic_bytes = self.length - 0x12
+            self.add_field('characteristics_extensions', [u.unpack_one("B") for b in range(characteristic_bytes)])
+            if (sm.header.major_version, minor_version_str) >= (2,"4"):
+                self.add_field('major_release', u.unpack_one("B"))
+                self.add_field('minor_release', u.unpack_one("B"))
+                self.add_field('ec_major_release', u.unpack_one("B"))
+                self.add_field('ec_minor_release', u.unpack_one("B"))
+        except:
+            self.decode_failure = True
+            print "Error parsing BIOSInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class SystemInformation(SmbiosBaseStructure):
+    smbios_structure_type = 1
+
+    def __init__(self, u, sm):
+        super(SystemInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
+            self.add_field('product_name', u.unpack_one("B"), self.fmtstr)
+            self.add_field('version', u.unpack_one("B"), self.fmtstr)
+            self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x8:
+                self.add_field('uuid', uuid.UUID(bytes_le=u.unpack_one("16s")))
+                wakeup_types = {
+                    0: 'Reserved',
+                    1: 'Other',
+                    2: 'Unknown',
+                    3: 'APM Timer',
+                    4: 'Modem Ring',
+                    5: 'LAN Remote',
+                    6: 'Power Switch',
+                    7: 'PCI PME#',
+                    8: 'AC Power Restored'
+                }
+                self.add_field('wakeup_type', u.unpack_one("B"), unpack.format_table("{}", wakeup_types))
+            if self.length > 0x19:
+                self.add_field('sku_number', u.unpack_one("B"), self.fmtstr)
+                self.add_field('family', u.unpack_one("B"), self.fmtstr)
+        except:
+            self.decode_failure = True
+            print "Error parsing SystemInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+_board_types = {
+    1: 'Unknown',
+    2: 'Other',
+    3: 'Server Blade',
+    4: 'Connectivity Switch',
+    5: 'System Management Module',
+    6: 'Processor Module',
+    7: 'I/O Module',
+    8: 'Memory Module',
+    9: 'Daughter Board',
+    0xA: 'Motherboard',
+    0xB: 'Processor/Memory Module',
+    0xC: 'Processor/IO Module',
+    0xD: 'Interconnect Board'
+}
+
+class BaseboardInformation(SmbiosBaseStructure):
+    smbios_structure_type = 2
+
+    def __init__(self, u, sm):
+        super(BaseboardInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
+            self.add_field('product', u.unpack_one("B"), self.fmtstr)
+            self.add_field('version', u.unpack_one("B"), self.fmtstr)
+            self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
+
+            if self.length > 0x8:
+                self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
+
+            if self.length > 0x9:
+                self.add_field('feature_flags', u.unpack_one("B"))
+                self.add_field('hosting_board', bool(bitfields.getbits(self.feature_flags, 0)), "feature_flags[0]={}")
+                self.add_field('requires_daughter_card', bool(bitfields.getbits(self.feature_flags, 1)), "feature_flags[1]={}")
+                self.add_field('removable', bool(bitfields.getbits(self.feature_flags, 2)), "feature_flags[2]={}")
+                self.add_field('replaceable', bool(bitfields.getbits(self.feature_flags, 3)), "feature_flags[3]={}")
+                self.add_field('hot_swappable', bool(bitfields.getbits(self.feature_flags, 4)), "feature_flags[4]={}")
+
+            if self.length > 0xA:
+                self.add_field('location', u.unpack_one("B"), self.fmtstr)
+
+            if self.length > 0xB:
+                self.add_field('chassis_handle', u.unpack_one("<H"))
+
+            if self.length > 0xD:
+                self.add_field('board_type', u.unpack_one("B"), unpack.format_table("{}", _board_types))
+
+            if self.length > 0xE:
+                self.add_field('handle_count', u.unpack_one("B"))
+                if self.handle_count > 0:
+                    self.add_field('contained_object_handles', tuple(u.unpack_one("<H") for i in range(self.handle_count)))
+        except:
+            self.decode_failure = True
+            print "Error parsing BaseboardInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class SystemEnclosure(SmbiosBaseStructure):
+    smbios_structure_type = 3
+
+    def __init__(self, u, sm):
+        super(SystemEnclosure, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
+            self.add_field('enumerated_type', u.unpack_one("B"))
+            self.add_field('chassis_lock_present', bool(bitfields.getbits(self.enumerated_type, 7)), "enumerated_type[7]={}")
+            board_types = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'Desktop',
+                0x04: 'Low Profile Desktop',
+                0x05: 'Pizza Box',
+                0x06: 'Mini Tower',
+                0x07: 'Tower',
+                0x08: 'Portable',
+                0x09: 'Laptop',
+                0x0A: 'Notebook',
+                0x0B: 'Hand Held',
+                0x0C: 'Docking Station',
+                0x0D: 'All in One',
+                0x0E: 'Sub Notebook',
+                0x0F: 'Space-saving',
+                0x10: 'Lunch Box',
+                0x11: 'Main Server Chassis',
+                0x12: 'Expansion Chassis',
+                0x13: 'SubChassis',
+                0x14: 'Bus Expansion Chassis',
+                0x15: 'Peripheral Chassis',
+                0x16: 'RAID Chassis',
+                0x17: 'Rack Mount Chassis',
+                0x18: 'Sealed-case PC',
+                0x19: 'Multi-system chassis W',
+                0x1A: 'Compact PCI',
+                0x1B: 'Advanced TCA',
+                0x1C: 'Blade',
+                0x1D: 'Blade Enclosure',
+            }
+            self.add_field('system_enclosure_type', bitfields.getbits(self.enumerated_type, 6, 0), unpack.format_table("enumerated_type[6:0]={}", board_types))
+            self.add_field('version', u.unpack_one("B"), self.fmtstr)
+            self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
+            self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
+            minor_version_str = str(sm.header.minor_version) # 34 is .34, 4 is .4, 41 is .41; compare ASCIIbetically to compare initial digits rather than numeric value
+            if self.length > 9:
+                chassis_states = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Safe',
+                    0x04: 'Warning',
+                    0x05: 'Critical',
+                    0x06: 'Non-recoverable',
+                }
+                self.add_field('bootup_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states))
+                self.add_field('power_supply_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states))
+                self.add_field('thermal_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states))
+                security_states = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'None',
+                    0x04: 'External interface locked out',
+                    0x05: 'External interface enabled',
+                }
+                self.add_field('security_status', u.unpack_one("B"), unpack.format_table("{}", security_states))
+            if self.length > 0xd:
+                self.add_field('oem_defined', u.unpack_one("<I"))
+            if self.length > 0x11:
+                self.add_field('height', u.unpack_one("B"))
+                self.add_field('num_power_cords', u.unpack_one("B"))
+                self.add_field('contained_element_count', u.unpack_one("B"))
+                self.add_field('contained_element_length', u.unpack_one("B"))
+            if getattr(self, 'contained_element_count', 0):
+                self.add_field('contained_elements', tuple(SystemEnclosureContainedElement(u, self.contained_element_length) for i in range(self.contained_element_count)))
+            if self.length > (0x15 + (getattr(self, 'contained_element_count', 0) * getattr(self, 'contained_element_length', 0))):
+                self.add_field('sku_number', u.unpack_one("B"), self.fmtstr)
+        except:
+            self.decode_failure = True
+            print "Error parsing SystemEnclosure"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class SystemEnclosureContainedElement(unpack.Struct):
+    def __init__(self, u, length):
+        super(SystemEnclosureContainedElement, self).__init__()
+        self.start_offset = u.offset
+        self.raw_data = u.unpack_raw(length)
+        self.u = unpack.Unpackable(self.raw_data)
+        u = self.u
+        self.add_field('contained_element_type', u.unpack_one("B"))
+        type_selections = {
+            0: 'SMBIOS baseboard type enumeration',
+            1: 'SMBIOS structure type enumeration',
+        }
+        self.add_field('type_select', bitfields.getbits(self.contained_element_type, 7), unpack.format_table("contained_element_type[7]={}", type_selections))
+        self.add_field('type', bitfields.getbits(self.contained_element_type, 6, 0))
+        if self.type_select == 0:
+            self.add_field('smbios_board_type', self.type, unpack.format_table("{}", _board_types))
+        else:
+            self.add_field('smbios_structure_type', self.type)
+        self.add_field('minimum', u.unpack_one("B"))
+        self.add_field('maximum', u.unpack_one("B"))
+        if not u.at_end():
+            self.add_field('data', u.unpack_rest())
+        del self.u
+
+class ProcessorInformation(SmbiosBaseStructure):
+    smbios_structure_type = 4
+
+    def __init__(self, u, sm):
+        super(ProcessorInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('socket_designation', u.unpack_one("B"), self.fmtstr)
+            processor_types = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'Central Processor',
+                0x04: 'Math Processor',
+                0x05: 'DSP Processor',
+                0x06: 'Video Processor',
+            }
+            self.add_field('processor_type', u.unpack_one("B"), unpack.format_table("{}", processor_types))
+            self.add_field('processor_family', u.unpack_one("B"))
+            self.add_field('processor_manufacturer', u.unpack_one("B"), self.fmtstr)
+            self.add_field('processor_id', u.unpack_one("<Q"))
+            self.add_field('processor_version', u.unpack_one("B"), self.fmtstr)
+            self.add_field('voltage', u.unpack_one("B"))
+            self.add_field('external_clock', u.unpack_one("<H"))
+            self.add_field('max_speed', u.unpack_one("<H"))
+            self.add_field('current_speed', u.unpack_one("<H"))
+            self.add_field('status', u.unpack_one("B"))
+            processor_upgrades = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'Daughter Board',
+                0x04: 'ZIF Socket',
+                0x05: 'Replaceable Piggy Back',
+                0x06: 'None',
+                0x07: 'LIF Socket',
+                0x08: 'Slot 1',
+                0x09: 'Slot 2',
+                0x0A: '370-pin socket',
+                0x0B: 'Slot A',
+                0x0C: 'Slot M',
+                0x0D: 'Socket 423',
+                0x0E: 'Socket A (Socket 462)',
+                0x0F: 'Socket 478',
+                0x10: 'Socket 754',
+                0x11: 'Socket 940',
+                0x12: 'Socket 939',
+                0x13: 'Socket mPGA604',
+                0x14: 'Socket LGA771',
+                0x15: 'Socket LGA775',
+                0x16: 'Socket S1',
+                0x17: 'Socket AM2',
+                0x18: 'Socket F (1207)',
+                0x19: 'Socket LGA1366',
+                0x1A: 'Socket G34',
+                0x1B: 'Socket AM3',
+                0x1C: 'Socket C32',
+                0x1D: 'Socket LGA1156',
+                0x1E: 'Socket LGA1567',
+                0x1F: 'Socket PGA988A',
+                0x20: 'Socket BGA1288',
+                0x21: 'Socket rPGA988B',
+                0x22: 'Socket BGA1023',
+                0x23: 'Socket BGA1224',
+                0x24: 'Socket BGA1155',
+                0x25: 'Socket LGA1356',
+                0x26: 'Socket LGA2011',
+                0x27: 'Socket FS1',
+                0x28: 'Socket FS2',
+                0x29: 'Socket FM1',
+                0x2A: 'Socket FM2',
+            }
+            self.add_field('processor_upgrade', u.unpack_one("B"), unpack.format_table("{}", processor_upgrades))
+            if self.length > 0x1A:
+                self.add_field('l1_cache_handle', u.unpack_one("<H"))
+                self.add_field('l2_cache_handle', u.unpack_one("<H"))
+                self.add_field('l3_cache_handle', u.unpack_one("<H"))
+            if self.length > 0x20:
+                self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
+                self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
+                self.add_field('part_number', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x24:
+                self.add_field('core_count', u.unpack_one("B"))
+                self.add_field('core_enabled', u.unpack_one("B"))
+                self.add_field('thread_count', u.unpack_one("B"))
+                self.add_field('processor_characteristics', u.unpack_one("<H"))
+            if self.length > 0x28:
+                self.add_field('processor_family_2', u.unpack_one("<H"))
+            if self.length > 0x2A:
+                self.add_field('core_count2', u.unpack_one("<H"))
+                self.add_field('core_enabled2', u.unpack_one("<H"))
+                self.add_field('thread_count2', u.unpack_one("<H"))
+        except:
+            self.decode_failure = True
+            print "Error parsing Processor Information"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class MemoryControllerInformation(SmbiosBaseStructure): #obsolete starting with v2.1
+    smbios_structure_type = 5
+
+    def __init__(self, u, sm):
+        super(MemoryControllerInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            _error_detecting_method = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'None',
+                0x04: '8-bit Parity',
+                0x05: '32-bit ECC',
+                0x06: '64-bit ECC',
+                0x07: '128-bit ECC',
+                0x08: 'CRC'
+                }
+            self.add_field('error_detecting_method', u.unpack_one("B"), unpack.format_table("{}", _error_detecting_method))
+            self.add_field('error_correcting_capability', u.unpack_one("B"))
+            _interleaves = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'One-Way Interleave',
+                0x04: 'Two-Way Interleave',
+                0x05: 'Four-Way Interleave',
+                0x06: 'Eight-Way Interleave',
+                0x07: 'Sixteen-Way Interleave'
+                }
+            self.add_field('supported_interleave', u.unpack_one("B"), unpack.format_table("{}", _interleaves))
+            self.add_field('current_interleave', u.unpack_one("B"), unpack.format_table("{}", _interleaves))
+            self.add_field('max_memory_module_size', u.unpack_one("B"), self.fmtstr)
+            self.add_field('supported_speeds', u.unpack_one("<H"))
+            self.add_field('supported_memory_types', u.unpack_one("<H"))
+            self.add_field('memory_module_voltage', u.unpack_one("B"))
+            self.add_field('req_voltage_b2', bitfields.getbits(self.memory_module_voltage, 2), "memory_module_voltage[2]={}")
+            self.add_field('req_voltage_b1', bitfields.getbits(self.memory_module_voltage, 1), "memory_module_voltage[1]={}")
+            self.add_field('req_voltage_b0', bitfields.getbits(self.memory_module_voltage, 0), "memory_module_voltage[0]={}")
+            self.add_field('num_associated_memory_slots', u.unpack_one("B"))
+            self.add_field('memory_module_configuration_handles', u.unpack_one("<(self.num_associated_memory_slots)H"))
+            self.add_field('enabled_error_correcting_capabilities', u.unpack_one("B"))
+        except:
+            self.decode_failure = True
+            print "Error parsing MemoryControllerInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class MemoryModuleInformation(SmbiosBaseStructure): #obsolete starting with v2.1
+    smbios_structure_type = 6
+
+    def __init__(self, u, sm):
+        super(MemoryModuleInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('socket_designation', u.unpack_one("B"), self.fmtstr)
+            self.add_field('bank_connections', u.unpack_one("B"))
+            self.add_field('current_speed', u.unpack_one("B"))
+            self.add_field('current_memory_type', u.unpack_one("<H"))
+            _mem_connection = {
+                0: 'single',
+                1: 'double-bank'
+                }
+            self.add_field('installed_mem', u.unpack_one("B"))
+            self.add_field('installed_size', bitfields.getbits(self.installed_mem, 6, 0), "installed_mem[6:0]={}")
+            self.add_field('installed_memory_module_connection', bitfields.getbits(self.installed_mem, 7), unpack.format_table("installed_mem[7]={}", _mem_connection))
+            self.add_field('enabled_mem', u.unpack_one("B"))
+            self.add_field('enabled_size', bitfields.getbits(self.installed_mem, 6, 0), "enabled_mem[6:0]={}")
+            self.add_field('enabled_memory_module_connection', bitfields.getbits(self.installed_mem, 7), unpack.format_table("enabled_mem[7]={}", _mem_connection))
+            self.add_field('error_status', u.unpack_one("B"))
+            self.add_field('error_status_info_obstained_from_event_log', bool(bitfields.getbits(self.error_status, 2)), unpack.format_table("error_status[2]={}", _mem_connection))
+            self.add_field('correctable_errors_received', bool(bitfields.getbits(self.error_status, 1)), unpack.format_table("error_status[1]={}", _mem_connection))
+            self.add_field('uncorrectable_errors_received', bool(bitfields.getbits(self.error_status, 0)), unpack.format_table("error_status[0]={}", _mem_connection))
+        except:
+            self.decode_failure = True
+            print "Error parsing MemoryModuleInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class CacheInformation(SmbiosBaseStructure):
+    smbios_structure_type = 7
+
+    def __init__(self, u, sm):
+        super(CacheInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('socket_designation', u.unpack_one("B"), self.fmtstr)
+            processor_types = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'Central Processor',
+                0x04: 'Math Processor',
+                0x05: 'DSP Processor',
+                0x06: 'Video Processor',
+            }
+            self.add_field('cache_configuration', u.unpack_one("<H"))
+            _operational_mode = {
+                0b00: 'Write Through',
+                0b01: 'Write Back',
+                0b10: 'Varies with Memory Address',
+                0b11: 'Unknown'
+                }
+            self.add_field('operational_mode', bitfields.getbits(self.cache_configuration, 9, 8), unpack.format_table("cache_configuration[9:8]={}", _operational_mode))
+            self.add_field('enabled_at_boot_time', bool(bitfields.getbits(self.cache_configuration, 7)), "cache_configuration[7]={}")
+            _location = {
+                0b00: 'Internal',
+                0b01: 'External',
+                0b10: 'Reserved',
+                0b11: 'Unknown'
+                }
+            self.add_field('location_relative_to_cpu_module', bitfields.getbits(self.cache_configuration, 6, 5), unpack.format_table("cache_configuration[6:5]={}", _location))
+            self.add_field('cache_socketed', bool(bitfields.getbits(self.cache_configuration, 3)), "cache_configuration[3]={}")
+            self.add_field('cache_level', bitfields.getbits(self.cache_configuration, 2, 0), "cache_configuration[2:0]={}")
+            self.add_field('max_cache_size', u.unpack_one("<H"))
+            _granularity = {
+                0: '1K granularity',
+                1: '64K granularity'
+                }
+            self.add_field('max_granularity', bitfields.getbits(self.cache_configuration, 15), unpack.format_table("max_cache_size[15]={}", _granularity))
+            self.add_field('max_size_in_granularity', bitfields.getbits(self.cache_configuration, 14, 0), "max_cache_size[14, 0]={}")
+            self.add_field('installed_size', u.unpack_one("<H"))
+            if self.installed_size != 0:
+                self.add_field('installed_granularity', bitfields.getbits(self.cache_configuration, 15), unpack.format_table("installed_size[15]={}", _granularity))
+                self.add_field('installed_size_in_granularity', bitfields.getbits(self.cache_configuration, 14, 0), "installed_size[14, 0]={}")
+            self.add_field('supported_sram_type', u.unpack_one("<H"))
+            self.add_field('current_sram_type', u.unpack_one("<H"))
+            if self.length > 0x0F:
+                self.add_field('cache_speed', u.unpack_one("B"))
+            if self.length > 0x10:
+                _error_correction = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'None',
+                    0x04: 'Parity',
+                    0x05: 'Single-bit ECC',
+                    0x06: 'Multi-bit ECC'
+                    }
+                self.add_field('error_correction', u.unpack_one("B"), unpack.format_table("{}", _error_correction))
+            if self.length > 0x10:
+                _system_cache_type = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Instruction',
+                    0x04: 'Data',
+                    0x05: 'Unified'
+                    }
+                self.add_field('system_cache_type', u.unpack_one("B"), unpack.format_table("{}", _system_cache_type))
+            if self.length > 0x12:
+                _associativity = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Direct Mapped',
+                    0x04: '2-way Set-Associative',
+                    0x05: '4-way Set-Associative',
+                    0x06: 'Fully Associative',
+                    0x07: '8-way Set-Associative',
+                    0x08: '16-way Set-Associative',
+                    0x09: '12-way Set-Associative',
+                    0x0A: '24-way Set-Associative',
+                    0x0B: '32-way Set-Associative',
+                    0x0C: '48-way Set-Associative',
+                    0x0D: '64-way Set-Associative',
+                    0x0E: '20-way Set-Associative'
+                    }
+                self.add_field('associativity', u.unpack_one("B"), unpack.format_table("{}", _associativity))
+
+        except:
+            self.decode_failure = True
+            print "Error parsing CacheInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class PortConnectorInfo(SmbiosBaseStructure):
+    smbios_structure_type = 8
+
+    def __init__(self, u, sm):
+        super(PortConnectorInfo, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('internal_reference_designator', u.unpack_one("B"), self.fmtstr)
+            connector_types = {
+                0x00: 'None',
+                0x01: 'Centronics',
+                0x02: 'Mini Centronics',
+                0x03: 'Proprietary',
+                0x04: 'DB-25 pin male',
+                0x05: 'DB-25 pin female',
+                0x06: 'DB-15 pin male',
+                0x07: 'DB-15 pin female',
+                0x08: 'DB-9 pin male',
+                0x09: 'DB-9 pin female',
+                0x0A: 'RJ-11',
+                0x0B: 'RJ-45',
+                0x0C: '50-pin MiniSCSI',
+                0x0D: 'Mini-DIN',
+                0x0E: 'Micro-DIN',
+                0x0F: 'PS/2',
+                0x10: 'Infrared',
+                0x11: 'HP-HIL',
+                0x12: 'Access Bus (USB)',
+                0x13: 'SSA SCSI',
+                0x14: 'Circular DIN-8 male',
+                0x15: 'Circular DIN-8 female',
+                0x16: 'On Board IDE',
+                0x17: 'On Board Floppy',
+                0x18: '9-pin Dual Inline (pin 10 cut)',
+                0x19: '25-pin Dual Inline (pin 26 cut)',
+                0x1A: '50-pin Dual Inline',
+                0x1B: '68-pin Dual Inline',
+                0x1C: 'On Board Sound Input from CD-ROM',
+                0x1D: 'Mini-Centronics Type-14',
+                0x1E: 'Mini-Centronics Type-26',
+                0x1F: 'Mini-jack (headphones)',
+                0x20: 'BNC',
+                0x21: '1394',
+                0x22: 'SAS/SATA Plug Receptacle',
+                0xA0: 'PC-98',
+                0xA1: 'PC-98Hireso',
+                0xA2: 'PC-H98',
+                0xA3: 'PC-98Note',
+                0xA4: 'PC-98Full',
+                0xFF: 'Other',
+            }
+            self.add_field('internal_connector_type', u.unpack_one("B"), unpack.format_table("{}", connector_types))
+            self.add_field('external_reference_designator', u.unpack_one("B"), self.fmtstr)
+            self.add_field('external_connector_type', u.unpack_one("B"), unpack.format_table("{}", connector_types))
+            port_types = {
+                0x00: 'None',
+                0x01: 'Parallel Port XT/AT Compatible',
+                0x02: 'Parallel Port PS/2',
+                0x03: 'Parallel Port ECP',
+                0x04: 'Parallel Port EPP',
+                0x05: 'Parallel Port ECP/EPP',
+                0x06: 'Serial Port XT/AT Compatible',
+                0x07: 'Serial Port 16450 Compatible',
+                0x08: 'Serial Port 16550 Compatible',
+                0x09: 'Serial Port 16550A Compatible',
+                0x0A: 'SCSI Port',
+                0x0B: 'MIDI Port',
+                0x0C: 'Joy Stick Port',
+                0x0D: 'Keyboard Port',
+                0x0E: 'Mouse Port',
+                0x0F: 'SSA SCSI',
+                0x10: 'USB',
+                0x11: 'FireWire (IEEE P1394)',
+                0x12: 'PCMCIA Type I2',
+                0x13: 'PCMCIA Type II',
+                0x14: 'PCMCIA Type III',
+                0x15: 'Cardbus',
+                0x16: 'Access Bus Port',
+                0x17: 'SCSI II',
+                0x18: 'SCSI Wide',
+                0x19: 'PC-98',
+                0x1A: 'PC-98-Hireso',
+                0x1B: 'PC-H98',
+                0x1C: 'Video Port',
+                0x1D: 'Audio Port',
+                0x1E: 'Modem Port',
+                0x1F: 'Network Port',
+                0x20: 'SATA',
+                0x21: 'SAS',
+                0xA0: '8251 Compatible',
+                0xA1: '8251 FIFO Compatible',
+                0xFF: 'Other',
+            }
+            self.add_field('port_type', u.unpack_one("B"), unpack.format_table("{}", port_types))
+        except:
+            self.decodeFailure = True
+            print "Error parsing PortConnectorInfo"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class SystemSlots(SmbiosBaseStructure):
+    smbios_structure_type = 9
+
+    def __init__(self, u, sm):
+        super(SystemSlots, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('designation', u.unpack_one("B"), self.fmtstr)
+            _slot_types = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'ISA',
+                0x04: 'MCA',
+                0x05: 'EISA',
+                0x06: 'PCI',
+                0x07: 'PC Card (PCMCIA)',
+                0x08: 'VL-VESA',
+                0x09: 'Proprietary',
+                0x0A: 'Processor Card Slot',
+                0x0B: 'Proprietary Memory Card Slot',
+                0x0C: 'I/O Riser Card Slot',
+                0x0D: 'NuBus',
+                0x0E: 'PCI 66MHz Capable',
+                0x0F: 'AGP',
+                0x10: 'AGP 2X',
+                0x11: 'AGP 4X',
+                0x12: 'PCI-X',
+                0x13: 'AGP 8X',
+                0xA0: 'PC-98/C20',
+                0xA1: 'PC-98/C24',
+                0xA2: 'PC-98/E',
+                0xA3: 'PC-98/Local Bus',
+                0xA4: 'PC-98/Card',
+                0xA5: 'PCI Express',
+                0xA6: 'PCI Express x1',
+                0xA7: 'PCI Express x2',
+                0xA8: 'PCI Express x4',
+                0xA9: 'PCI Express x8',
+                0xAA: 'PCI Express x16',
+                0xAB: 'PCI Express Gen 2',
+                0xAC: 'PCI Express Gen 2 x1',
+                0xAD: 'PCI Express Gen 2 x2',
+                0xAE: 'PCI Express Gen 2 x4',
+                0xAF: 'PCI Express Gen 2 x8',
+                0xB0: 'PCI Express Gen 2 x16',
+                0xB1: 'PCI Express Gen 3',
+                0xB2: 'PCI Express Gen 3 x1',
+                0xB3: 'PCI Express Gen 3 x2',
+                0xB4: 'PCI Express Gen 3 x4',
+                0xB5: 'PCI Express Gen 3 x8',
+                0xB6: 'PCI Express Gen 3 x16',
+            }
+            self.add_field('slot_type', u.unpack_one("B"), unpack.format_table("{}", _slot_types))
+            _slot_data_bus_widths = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: '8 bit',
+                0x04: '16 bit',
+                0x05: '32 bit',
+                0x06: '64 bit',
+                0x07: '128 bit',
+                0x08: '1x or x1',
+                0x09: '2x or x2',
+                0x0A: '4x or x4',
+                0x0B: '8x or x8',
+                0x0C: '12x or x12',
+                0x0D: '16x or x16',
+                0x0E: '32x or x32',
+            }
+            self.add_field('slot_data_bus_width', u.unpack_one('B'), unpack.format_table("{}", _slot_data_bus_widths))
+            _current_usages = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'Available',
+                0x04: 'In use',
+            }
+            self.add_field('current_usage', u.unpack_one('B'), unpack.format_table("{}", _current_usages))
+            _slot_lengths = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'Short Length',
+                0x04: 'Long Length',
+            }
+            self.add_field('slot_length', u.unpack_one('B'), unpack.format_table("{}", _slot_lengths))
+            self.add_field('slot_id', u.unpack_one('<H'))
+            self.add_field('characteristics1', u.unpack_one('B'))
+            self.add_field('characteristics_unknown', bool(bitfields.getbits(self.characteristics1, 0)), "characteristics1[0]={}")
+            self.add_field('provides_5_0_volts', bool(bitfields.getbits(self.characteristics1, 1)), "characteristics1[1]={}")
+            self.add_field('provides_3_3_volts', bool(bitfields.getbits(self.characteristics1, 2)), "characteristics1[2]={}")
+            self.add_field('shared_slot', bool(bitfields.getbits(self.characteristics1, 3)), "characteristics1[3]={}")
+            self.add_field('supports_pc_card_16', bool(bitfields.getbits(self.characteristics1, 4)), "characteristics1[4]={}")
+            self.add_field('supports_cardbus', bool(bitfields.getbits(self.characteristics1, 5)), "characteristics1[5]={}")
+            self.add_field('supports_zoom_video', bool(bitfields.getbits(self.characteristics1, 6)), "characteristics1[6]={}")
+            self.add_field('supports_modem_ring_resume', bool(bitfields.getbits(self.characteristics1, 7)), "characteristics1[7]={}")
+            if self.length > 0x0C:
+                self.add_field('characteristics2', u.unpack_one('B'))
+                self.add_field('supports_PME', bool(bitfields.getbits(self.characteristics2, 0)), "characteristics2[0]={}")
+                self.add_field('supports_hot_plug', bool(bitfields.getbits(self.characteristics2, 1)), "characteristics2[1]={}")
+                self.add_field('supports_smbus', bool(bitfields.getbits(self.characteristics2, 2)), "characteristics2[2]={}")
+            if self.length > 0x0D:
+                self.add_field('segment_group_number', u.unpack_one('<H'))
+                self.add_field('bus_number', u.unpack_one('B'))
+                self.add_field('device_function_number', u.unpack_one('B'))
+                self.add_field('device_number', bitfields.getbits(self.device_function_number, 7, 3), "device_function_number[7:3]={}")
+                self.add_field('function_number', bitfields.getbits(self.device_function_number, 2, 0), "device_function_number[2:0]={}")
+        except:
+            self.decodeFailure = True
+            print "Error parsing SystemSlots"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class OnBoardDevicesInformation(SmbiosBaseStructure):
+    smbios_structure_type = 10
+
+    def __init__(self, u, sm):
+        super(OnBoardDevicesInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('device_type', u.unpack_one("B"))
+            self.add_field('device_enabled', bool(bitfields.getbits(self.device_type, 7)), "device_type[7]={}")
+            _device_types = {
+                0x01: 'Other',
+                0x02: 'Unknown',
+                0x03: 'Video',
+                0x04: 'SCSI Controller',
+                0x05: 'Ethernet',
+                0x06: 'Token Ring',
+                0x07: 'Sound',
+                0x08: 'PATA Controller',
+                0x09: 'SATA Controller',
+                0x0A: 'SAS Controller'
+            }
+            self.add_field('type_of_device', bitfields.getbits(self.device_type, 6, 0), unpack.format_table("device_type[6:0]={}", _device_types))
+            self.add_field('description_string', u.unpack_one("B"), self.fmtstr)
+        except:
+            self.decodeFailure = True
+            print "Error parsing OnBoardDevicesInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class OEMStrings(SmbiosBaseStructure):
+    smbios_structure_type = 11
+
+    def __init__(self, u, sm):
+        super(OEMStrings, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('count', u.unpack_one("B"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing OEMStrings"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class SystemConfigOptions(SmbiosBaseStructure):
+    smbios_structure_type = 12
+
+    def __init__(self, u, sm):
+        super(SystemConfigOptions, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('count', u.unpack_one("B"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing SystemConfigOptions"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class BIOSLanguageInformation(SmbiosBaseStructure):
+    smbios_structure_type = 13
+
+    def __init__(self, u, sm):
+        super(BIOSLanguageInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('installable_languages', u.unpack_one("B"))
+            if self.length > 0x05:
+                self.add_field('flags', u.unpack_one('B'))
+                self.add_field('abbreviated_format', bool(bitfields.getbits(self.flags, 0)), "flags[0]={}")
+            if self.length > 0x6:
+                u.skip(15)
+                self.add_field('current_language', u.unpack_one('B'), self.fmtstr)
+        except:
+            self.decodeFailure = True
+            print "Error parsing BIOSLanguageInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class GroupAssociations(SmbiosBaseStructure):
+    smbios_structure_type = 14
+
+    def __init__(self, u, sm):
+        super(GroupAssociations, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('group_name', u.unpack_one("B"), self.fmtstr)
+            self.add_field('item_type', u.unpack_one('B'))
+            self.add_field('item_handle', u.unpack_one('<H'))
+        except:
+            self.decodeFailure = True
+            print "Error parsing GroupAssociations"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class SystemEventLog(SmbiosBaseStructure):
+    smbios_structure_type = 15
+
+    def __init__(self, u, sm):
+        super(SystemEventLog, self).__init__(u, sm)
+        u = self.u
+        try:
+            self.add_field('log_area_length', u.unpack_one("<H"))
+            self.add_field('log_header_start_offset', u.unpack_one('<H'))
+            self.add_field('log_data_start_offset', u.unpack_one('<H'))
+            _access_method = {
+                0x00: 'Indexed I/O: 1 8-bit index port, 1 8-bit data port',
+                0x01: 'Indexed I/O: 2 8-bit index ports, 1 8-bit data port',
+                0x02: 'Indexed I/O: 1 16-bit index port, 1 8-bit data port',
+                0x03: 'Memory-mapped physical 32-bit address',
+                0x04: 'Available through General-Purpose NonVolatile Data functions',
+                xrange(0x05, 0x07F): 'Available for future assignment',
+                xrange(0x80, 0xFF): 'BIOS Vendor/OEM-specific'
+                }
+            self.add_field('access_method', u.unpack_one('B'), unpack.format_table("{}", _access_method))
+            self.add_field('log_status', u.unpack_one('B'))
+            self.add_field('log_area_full', bool(bitfields.getbits(self.log_status, 1)), "log_status[1]={}")
+            self.add_field('log_area_valid', bool(bitfields.getbits(self.log_status, 0)), "log_status[0]={}")
+            self.add_field('log_change_token', u.unpack_one('<I'))
+            self.add_field('access_method_address', u.unpack_one('<I'))
+            if self.length > 0x14:
+                _log_header_formats = {
+                    0: 'No header',
+                    1: 'Type 1 log header',
+                    xrange(2, 0x7f): 'Available for future assignment',
+                    xrange(0x80, 0xff): 'BIOS vendor or OEM-specific format'
+                    }
+                self.add_field('log_header_format', u.unpack_one("B"), unpack.format_table("{}", _log_header_formats))
+            if self.length > 0x15:
+                self.add_field('num_supported_log_type_descriptors', u.unpack_one('B'))
+            if self.length > 0x16:
+                self.add_field('length_log_type_descriptor', u.unpack_one('B'))
+            if self.length != (0x17 + (self.num_supported_log_type_descriptors * self.length_log_type_descriptor)):
+                print "Error: structure length ({}) != 0x17 + (num_supported_log_type_descriptors ({}) * length_log_type_descriptor({}))".format(self.length, self.num_supported_log_type_descriptors, self.length_log_type_descriptor)
+                print "structure length = {}".format(self.length)
+                print "num_supported_log_type_descriptors = {}".format(self.num_supported_log_type_descriptors)
+                print "length_log_type_descriptor = {}".format(self.length_log_type_descriptor)
+                self.decodeFailure = True
+            self.add_field('descriptors', tuple(EventLogDescriptor.unpack(u) for i in range(self.num_supported_log_type_descriptors)), unpack.format_each("\n{!r}"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing SystemEventLog"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class EventLogDescriptor(unpack.Struct):
+    @staticmethod
+    def _unpack(u):
+        _event_log_type_descriptors = {
+            0x00: 'Reserved',
+            0x01: 'Single-bit ECC memory error',
+            0x02: 'Multi-bit ECC memory error',
+            0x03: 'Parity memory error',
+            0x04: 'Bus time-out',
+            0x05: 'I/O Channel Check',
+            0x06: 'Software NMI',
+            0x07: 'POST Memory Resize',
+            0x08: 'POST Error',
+            0x09: 'PCI Parity Error',
+            0x0A: 'PCI System Error',
+            0x0B: 'CPU Failure',
+            0x0C: 'EISA FailSafe Timer time-out',
+            0x0D: 'Correctable memory log disabled',
+            0x0E: 'Logging disabled for a specific Event Type - too many errors of the same type received in a short amount of time',
+            0x0F: 'Reserved',
+            0x10: 'System Limit Exceeded',
+            0x11: 'Asynchronous hardware timer expired and issued a system reset',
+            0x12: 'System configuration information',
+            0x13: 'Hard-disk information',
+            0x14: 'System reconfigured',
+            0x15: 'Uncorrectable CPU-complex error',
+            0x16: 'Log Area Reset/Cleared',
+            0x17: 'System boot',
+            xrange(0x18, 0x7F): 'Unused, available for assignment',
+            xrange(0x80, 0xFE): 'Availalbe for system- and OEM-specific assignments',
+            0xFF: 'End of log'
+        }
+        yield 'log_type', u.unpack_one('B'), unpack.format_table("{}", _event_log_type_descriptors)
+        _event_log_format = {
+            0x00: 'None',
+            0x01: 'Handle',
+            0x02: 'Multiple-Event',
+            0x03: 'Multiple-Event Handle',
+            0x04: 'POST Results Bitmap',
+            0x05: 'System Management Type',
+            0x06: 'Multiple-Event System Management Type',
+            xrange(0x80, 0xFF): 'OEM assigned'
+        }
+        yield 'variable_data_format_type', u.unpack_one('B'), unpack.format_table("{}", _event_log_format)
+
+class PhysicalMemoryArray(SmbiosBaseStructure):
+    smbios_structure_type = 16
+
+    def __init__(self, u, sm):
+        super(PhysicalMemoryArray, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                _location_field = {
+                    0x01: "Other",
+                    0x02: "Unknown",
+                    0x03: "System board or motherboard",
+                    0x04: "ISA add-on card",
+                    0x05: "EISA add-on card",
+                    0x06: "PCI add-on card",
+                    0x07: "MCA add-on card",
+                    0x08: "PCMCIA add-on card",
+                    0x09: "Proprietary add-on card",
+                    0x0A: "NuBus",
+                    0xA0: "PC-98/C20 add-on card",
+                    0xA1: "PC-98/C24 add-on card",
+                    0xA2: "PC-98/E add-on card",
+                    0xA3: "PC-98/Local bus add-on card"
+                    }
+                self.add_field('location', u.unpack_one("B"), unpack.format_table("{}", _location_field))
+            if self.length > 0x05:
+                _use = {
+                    0x01: "Other",
+                    0x02: "Unknown",
+                    0x03: "System memory",
+                    0x04: "Video memory",
+                    0x05: "Flash memory",
+                    0x06: "Non-volatile RAM",
+                    0x07: "Cache memory"
+                    }
+                self.add_field('use', u.unpack_one('B'), unpack.format_table("{}", _use))
+            if self.length > 0x06:
+                _error_correction = {
+                    0x01: "Other",
+                    0x02: "Unknown",
+                    0x03: "None",
+                    0x04: "Parity",
+                    0x05: "Single-bit ECC",
+                    0x06: "Multi-bit ECC",
+                    0x07: "CRC"
+                    }
+                self.add_field('memory_error_correction', u.unpack_one('B'), unpack.format_table("{}", _error_correction))
+            if self.length > 0x07:
+                self.add_field('maximum_capacity', u.unpack_one('<I'))
+            if self.length > 0x0B:
+                self.add_field('memory_error_information_handle', u.unpack_one('<H'))
+            if self.length > 0x0D:
+                self.add_field('num_memory_devices', u.unpack_one('<H'))
+            if self.length > 0x0F:
+                self.add_field('extended_maximum_capacity', u.unpack_one('<Q'))
+        except:
+            self.decodeFailure = True
+            print "Error parsing PhysicalMemoryArray"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class MemoryDevice(SmbiosBaseStructure):
+    smbios_structure_type = 17
+
+    def __init__(self, u, sm):
+        super(MemoryDevice, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('physical_memory_array_handle', u.unpack_one("<H"))
+            if self.length > 0x6:
+                self.add_field('memory_error_information_handle', u.unpack_one("<H"))
+            if self.length > 0x8:
+                self.add_field('total_width', u.unpack_one("<H"))
+            if self.length > 0xA:
+                self.add_field('data_width', u.unpack_one("<H"))
+            if self.length > 0xC:
+                self.add_field('size', u.unpack_one("<H"))
+            if self.length > 0xE:
+                _form_factors = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'SIMM',
+                    0x04: 'SIP',
+                    0x05: 'Chip',
+                    0x06: 'DIP',
+                    0x07: 'ZIP',
+                    0x08: 'Proprietary Card',
+                    0x09: 'DIMM',
+                    0x0A: 'TSOP',
+                    0x0B: 'Row of chips',
+                    0x0C: 'RIMM',
+                    0x0D: 'SODIMM',
+                    0x0E: 'SRIMM',
+                    0x0F: 'FB-DIMM'
+                    }
+                self.add_field('form_factor', u.unpack_one("B"), unpack.format_table("{}", _form_factors))
+            if self.length > 0xF:
+                self.add_field('device_set', u.unpack_one("B"))
+            if self.length > 0x10:
+                self.add_field('device_locator', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x11:
+                self.add_field('bank_locator', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x12:
+                _memory_types = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'DRAM',
+                    0x04: 'EDRAM',
+                    0x05: 'VRAM',
+                    0x06: 'SRAM',
+                    0x07: 'RAM',
+                    0x08: 'ROM',
+                    0x09: 'FLASH',
+                    0x0A: 'EEPROM',
+                    0x0B: 'FEPROM',
+                    0x0C: 'EPROM',
+                    0x0D: 'CDRAM',
+                    0x0E: '3DRAM',
+                    0x0F: 'SDRAM',
+                    0x10: 'SGRAM',
+                    0x11: 'RDRAM',
+                    0x12: 'DDR',
+                    0x13: 'DDR2',
+                    0x14: 'DDR2 FB-DIMM',
+                    xrange(0x15, 0x17): 'Reserved',
+                    0x18: 'DDR3',
+                    0x19: 'FBD2'
+                    }
+                self.add_field('memory_type', u.unpack_one("B"), unpack.format_table("{}", _memory_types))
+            if self.length > 0x13:
+                self.add_field('type_detail', u.unpack_one('<H'))
+            if self.length > 0x15:
+                self.add_field('speed', u.unpack_one("<H"))
+            if self.length > 0x17:
+                self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x18:
+                self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x19:
+                self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x1A:
+                self.add_field('part_number', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x1B:
+                self.add_field('attributes', u.unpack_one("B"))
+                self.add_field('rank', bitfields.getbits(self.attributes, 3, 0), "attributes[3:0]={}")
+            if self.length > 0x1C:
+                if self.size == 0x7FFF:
+                    self.add_field('extended_size', u.unpack_one('<I'))
+                    self.add_field('mem_size', bitfields.getbits(self.type_detail, 30, 0), "type_detail[30:0]={}")
+                else:
+                    u.skip(4)
+            if self.length > 0x20:
+                self.add_field('configured_memory_clock_speed', u.unpack_one("<H"))
+            if self.length > 0x22:
+                self.add_field('minimum_voltage', u.unpack_one("<H"))
+            if self.length > 0x24:
+                self.add_field('maximum_voltage', u.unpack_one("<H"))
+            if self.length > 0x26:
+                self.add_field('configured_voltage', u.unpack_one("<H"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing MemoryDevice"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class MemoryErrorInfo32Bit(SmbiosBaseStructure):
+    smbios_structure_type = 18
+
+    def __init__(self, u, sm):
+        super(MemoryErrorInfo32Bit, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                _error_types = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'OK',
+                    0x04: 'Bad read',
+                    0x05: 'Parity error',
+                    0x06: 'Single-bit error',
+                    0x07: 'Double-bit error',
+                    0x08: 'Multi-bit error',
+                    0x09: 'Nibble error',
+                    0x0A: 'Checksum error',
+                    0x0B: 'CRC error',
+                    0x0C: 'Corrected single-bit error',
+                    0x0D: 'Corrected error',
+                    0x0E: 'Uncorrectable error'
+                    }
+                self.add_field('error_type', u.unpack_one("B"), unpack.format_table("{}", _error_types))
+            if self.length > 0x5:
+                 _error_granularity_field = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Device level',
+                    0x04: 'Memory partition level'
+                    }
+                 self.add_field('error_granularity', u.unpack_one("B"), unpack.format_table("{}", _error_granularity_field))
+            if self.length > 0x6:
+                _error_operation_field = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Read',
+                    0x04: 'Write',
+                    0x05: 'Partial write'
+                    }
+                self.add_field('error_operation', u.unpack_one("B"), unpack.format_table("{}", _error_operation_field))
+            if self.length > 0x7:
+                self.add_field('vendor_syndrome', u.unpack_one("<I"))
+            if self.length > 0xB:
+                self.add_field('memory_array_error_address', u.unpack_one("<I"))
+            if self.length > 0xF:
+                self.add_field('device_error_address', u.unpack_one("<I"))
+            if self.length > 0x13:
+                self.add_field('error_resolution', u.unpack_one("<I"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing MemoryErrorInfo32Bit"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class MemoryArrayMappedAddress(SmbiosBaseStructure):
+    smbios_structure_type = 19
+
+    def __init__(self, u, sm):
+        super(MemoryArrayMappedAddress, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('starting_address', u.unpack_one("<I"))
+                # if FFFF FFFF: address stored in Extended Starting Address
+            if self.length > 0x8:
+                self.add_field('ending_address', u.unpack_one("<I"))
+            if self.length > 0xC:
+                self.add_field('memory_array_handle', u.unpack_one("<H"))
+            if self.length > 0xE:
+                self.add_field('partition_width', u.unpack_one("B"))
+            if self.length > 0xF:
+                # valid if starting_address = FFFF FFFF
+                if self.starting_address == 0xFFFFFFFF:
+                    self.add_field('extended_starting_address', u.unpack_one("<Q"))
+                    if self.length > 0x17:
+                        self.add_field('extended_ending_address', u.unpack_one("<Q"))
+                else:
+                    u.skip(16)
+
+        except:
+            self.decodeFailure = True
+            print "Error parsing MemoryArrayMappedAddress"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class MemoryDeviceMappedAddress(SmbiosBaseStructure):
+    smbios_structure_type = 20
+
+    def __init__(self, u, sm):
+        super(MemoryDeviceMappedAddress, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('starting_address', u.unpack_one("<I"))
+                # if FFFF FFFF: address stored in Extended Starting Address
+            if self.length > 0x8:
+                self.add_field('ending_address', u.unpack_one("<I"))
+            if self.length > 0xC:
+                self.add_field('memory_device_handle', u.unpack_one("<H"))
+            if self.length > 0xE:
+                self.add_field('memory_array_mapped_address_handle', u.unpack_one("<H"))
+            if self.length > 0x10:
+                self.add_field('partition_row_position', u.unpack_one("B"))
+            if self.length > 0x11:
+                self.add_field('interleave_position', u.unpack_one("B"))
+            if self.length > 0x12:
+                self.add_field('interleave_data_depth', u.unpack_one("B"))
+            if self.length > 0x13:
+                # valid if starting_address = FFFF FFFF
+                if self.starting_address == 0xFFFFFFFF:
+                    self.add_field('extended_starting_address', u.unpack_one("<Q"))
+                    if self.length > 0x1B:
+                        self.add_field('extended_ending_address', u.unpack_one("<Q"))
+                else:
+                    u.skip(16)
+        except:
+            self.decodeFailure = True
+            print "Error parsing MemoryDeviceMappedAddress"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class BuiltInPointingDevice(SmbiosBaseStructure):
+    smbios_structure_type = 21
+
+    def __init__(self, u, sm):
+        super(BuiltInPointingDevice, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                _pointing_device_types = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Mouse',
+                    0x04: 'Track Ball',
+                    0x05: 'Track Point',
+                    0x06: 'Glide Point',
+                    0x07: 'Touch Pad',
+                    0x08: 'Touch Screen',
+                    0x09: 'Optical Sensor'
+                    }
+                self.add_field('pointing_device_type', u.unpack_one("B"), unpack.format_table("{}", _pointing_device_types))
+            if self.length > 0x5:
+                _interfaces = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Serial',
+                    0x04: 'PS/2',
+                    0x05: 'Infared',
+                    0x06: 'HP-HIL',
+                    0x07: 'Bus mouse',
+                    0x08: 'ADB (Apple Desktop Bus)',
+                    0x09: 'Bus mouse DB-9',
+                    0x0A: 'Bus mouse micro-DIN',
+                    0x0B: 'USB'
+                    }
+                self.add_field('interface', u.unpack_one("B"), unpack.format_table("{}", _interfaces))
+            if self.length > 0x6:
+                self.add_field('num_buttons', u.unpack_one("B"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing BuiltInPointingDevice"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class PortableBattery(SmbiosBaseStructure):
+    smbios_structure_type = 22
+
+    def __init__(self, u, sm):
+        super(PortableBattery, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('location', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x5:
+                self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x6:
+                self.add_field('manufacturer_date', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x7:
+                self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x8:
+                self.add_field('device_name', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x9:
+                _device_chemistry = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Lead Acid',
+                    0x04: 'Nickel Cadmium',
+                    0x05: 'Nickel metal hydride',
+                    0x06: 'Lithium-ion',
+                    0x07: 'Zinc air',
+                    0x08: 'Lithium Polymer'
+                    }
+                self.add_field('device_chemistry', u.unpack_one("B"), unpack.format_table("{}", _device_chemistry))
+            if self.length > 0xA:
+                self.add_field('design_capacity', u.unpack_one("<H"))
+            if self.length > 0xC:
+                self.add_field('design_voltage', u.unpack_one("<H"))
+            if self.length > 0xE:
+                self.add_field('sbds_version_number', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0xF:
+                self.add_field('max_error_battery_data', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x10:
+                if self.serial_number == 0:
+                    self.add_field('sbds_serial_number', u.unpack_one("<H"))
+                else:
+                    u.skip(2)
+            if self.length > 0x12:
+                if self.manufacturer_date == 0:
+                    self.add_field('sbds_manufacture_date', u.unpack_one("<H"))
+                    self.add_field('year_biased_by_1980', bitfields.getbits(self.sbds_manufacture_date, 15, 9), "sbds_manufacture_date[15:9]={}")
+                    self.add_field('month', bitfields.getbits(self.sbds_manufacture_date, 8, 5), "sbds_manufacture_date[8:5]={}")
+                    self.add_field('date', bitfields.getbits(self.sbds_manufacture_date, 4, 0), "sbds_manufacture_date[4:0]={}")
+                else:
+                    u.skip(2)
+            if self.length > 0x14:
+                if self.device_chemistry == 0x02:
+                    self.add_field('sbds_device_chemistry', u.unpack_one("B"), self.fmtstr)
+                else:
+                    u.skip(1)
+            if self.length > 0x15:
+                self.add_field('design_capacity_multiplier', u.unpack_one("B"))
+            if self.length > 0x16:
+                self.add_field('oem_specific', u.unpack_one("<I"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing PortableBattery"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class SystemReset(SmbiosBaseStructure):
+    smbios_structure_type = 23
+
+    def __init__(self, u, sm):
+        super(SystemReset, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('capabilities', u.unpack_one("B"))
+                self.add_field('contains_watchdog_timer', bool(bitfields.getbits(self.capabilities, 5)), "capabilities[5]={}")
+                _boot_option = {
+                    0b00: 'Reserved, do not use',
+                    0b01: 'Operating System',
+                    0b10: 'System utilities',
+                    0b11: 'Do not reboot'
+                    }
+                self.add_field('boot_option_on_limit', bitfields.getbits(self.capabilities, 4, 3), unpack.format_table("capabilities[4:3]={}", _boot_option))
+                self.add_field('boot_option_after_watchdog_reset', bitfields.getbits(self.capabilities, 2, 1), unpack.format_table("capabilities[2:1]={}", _boot_option))
+                self.add_field('system_reset_enabled_by_user', bool(bitfields.getbits(self.capabilities, 0)), "capabilities[0]={}")
+            if self.length > 0x5:
+                self.add_field('reset_count', u.unpack_one("<H"))
+            if self.length > 0x5:
+                self.add_field('reset_limit', u.unpack_one("<H"))
+            if self.length > 0x9:
+                self.add_field('timer_interval', u.unpack_one("<H"))
+            if self.length > 0xB:
+                self.add_field('timeout', u.unpack_one("<H"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing SystemReset"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class HardwareSecurity(SmbiosBaseStructure):
+    smbios_structure_type = 24
+
+    def __init__(self, u, sm):
+        super(HardwareSecurity, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('hardware_security_settings', u.unpack_one("B"))
+                _status = {
+                    0x00: 'Disabled',
+                    0x01: 'Enabled',
+                    0x02: 'Not Implemented',
+                    0x03: 'Unknown'
+                    }
+                self.add_field('power_on_password_status', bitfields.getbits(self.hardware_security_settings, 7, 6), unpack.format_table("hardware_security_settings[7:6]={}", _status))
+                self.add_field('keyboard_password_status', bitfields.getbits(self.hardware_security_settings, 5, 4), unpack.format_table("hardware_security_settings[5:4]={}", _status))
+                self.add_field('admin_password_status', bitfields.getbits(self.hardware_security_settings, 3, 2), unpack.format_table("hardware_security_settings0[3:2]={}", _status))
+                self.add_field('front_panel_reset_status', bitfields.getbits(self.hardware_security_settings, 1, 0), unpack.format_table("hardware_security_settings[1:0]={}", _status))
+        except:
+            self.decodeFailure = True
+            print "Error parsing HardwareSecurity"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class SystemPowerControls(SmbiosBaseStructure):
+    smbios_structure_type = 25
+
+    def __init__(self, u, sm):
+        super(SystemPowerControls, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('next_scheduled_poweron_month', u.unpack_one("B"))
+                self.add_field('next_scheduled_poweron_day_of_month', u.unpack_one("B"))
+                self.add_field('next_scheduled_poweron_hour', u.unpack_one("B"))
+                self.add_field('next_scheduled_poweron_minute', u.unpack_one("B"))
+                self.add_field('next_scheduled_poweron_second', u.unpack_one("B"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing SystemPowerControls"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class VoltageProbe(SmbiosBaseStructure):
+    smbios_structure_type = 26
+
+    def __init__(self, u, sm):
+        super(VoltageProbe, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('description', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x5:
+                self.add_field('location_and_status', u.unpack_one("B"))
+                _status = {
+                    0b001: 'Other',
+                    0b010: 'Unknown',
+                    0b011: 'OK',
+                    0b100: 'Non-critical',
+                    0b101: 'Critical',
+                    0b110: 'Non-recoverable'
+                    }
+                _location = {
+                    0b00001: 'Other',
+                    0b00010: 'Unknown',
+                    0b00011: 'Processor',
+                    0b00100: 'Disk',
+                    0b00101: 'Peripheral Bay',
+                    0b00110: 'System Management Module',
+                    0b00111: 'Motherboard',
+                    0b01000: 'Memory Module',
+                    0b01001: 'Processor Module',
+                    0b01010: 'Power Unit',
+                    0b01011: 'Add-in Card'
+                    }
+                self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status))
+                self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location))
+            if self.length > 0x6:
+                self.add_field('max_value', u.unpack_one("<H"))
+            if self.length > 0x8:
+                self.add_field('min_value', u.unpack_one("<H"))
+            if self.length > 0xA:
+                self.add_field('resolution', u.unpack_one("<H"))
+            if self.length > 0xC:
+                self.add_field('tolerance', u.unpack_one("<H"))
+            if self.length > 0xE:
+                self.add_field('accuracy', u.unpack_one("<H"))
+            if self.length > 0x10:
+                self.add_field('oem_defined', u.unpack_one("<I"))
+            if self.length > 0x14:
+                self.add_field('nominal_value', u.unpack_one("<H"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing VoltageProbe"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class CoolingDevice(SmbiosBaseStructure):
+    smbios_structure_type = 27
+
+    def __init__(self, u, sm):
+        super(CoolingDevice, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('temperature_probe_handle', u.unpack_one("<H"))
+            if self.length > 0x6:
+                self.add_field('device_type_and_status', u.unpack_one("B"))
+                _status = {
+                    0b001: 'Other',
+                    0b010: 'Unknown',
+                    0b011: 'OK',
+                    0b100: 'Non-critical',
+                    0b101: 'Critical',
+                    0b110: 'Non-recoverable'
+                    }
+                _type = {
+                    0b00001: 'Other',
+                    0b00010: 'Unknown',
+                    0b00011: 'Fan',
+                    0b00100: 'Centrifugal Blower',
+                    0b00101: 'Chip Fan',
+                    0b00110: 'Cabinet Fan',
+                    0b00111: 'Power Supply Fan',
+                    0b01000: 'Heat Pipe',
+                    0b01001: 'Integrated Refrigeration',
+                    0b10000: 'Active Cooling',
+                    0b10001: 'Passive Cooling'
+                    }
+                self.add_field('status', bitfields.getbits(self.device_type_and_status, 7, 5), unpack.format_table("device_type_and_status[7:5]={}", _status))
+                self.add_field('device_type', bitfields.getbits(self.device_type_and_status, 4, 0), unpack.format_table("device_type_and_status[4:0]={}", _type))
+            if self.length > 0x7:
+                self.add_field('cooling_unit_group', u.unpack_one("B"))
+            if self.length > 0x8:
+                self.add_field('OEM_defined', u.unpack_one("<I"))
+            if self.length > 0xC:
+                self.add_field('nominal_speed', u.unpack_one("<H"))
+            if self.length > 0xE:
+               self.add_field('description', u.unpack_one("B"), self.fmtstr)
+        except:
+            self.decodeFailure = True
+            print "Error parsing CoolingDevice"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class TemperatureProbe(SmbiosBaseStructure):
+    smbios_structure_type = 28
+
+    def __init__(self, u, sm):
+        super(TemperatureProbe, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('description', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x5:
+                self.add_field('location_and_status', u.unpack_one("B"))
+                _status = {
+                    0b001: 'Other',
+                    0b010: 'Unknown',
+                    0b011: 'OK',
+                    0b100: 'Non-critical',
+                    0b101: 'Critical',
+                    0b110: 'Non-recoverable'
+                    }
+                _location = {
+                    0b00001: 'Other',
+                    0b00010: 'Unknown',
+                    0b00011: 'Processor',
+                    0b00100: 'Disk',
+                    0b00101: 'Peripheral Bay',
+                    0b00110: 'System Management Module',
+                    0b00111: 'Motherboard',
+                    0b01000: 'Memory Module',
+                    0b01001: 'Processor Module',
+                    0b01010: 'Power Unit',
+                    0b01011: 'Add-in Card',
+                    0b01100: 'Front Panel Board',
+                    0b01101: 'Back Panel Board',
+                    0b01110: 'Power System Board',
+                    0b01111: 'Drive Back Plane'
+                    }
+                self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status))
+                self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location))
+            if self.length > 0x6:
+                self.add_field('maximum_value', u.unpack_one("<H"))
+            if self.length > 0x8:
+                self.add_field('minimum_value', u.unpack_one("<H"))
+            if self.length > 0xA:
+                self.add_field('resolution', u.unpack_one("<H"))
+            if self.length > 0xC:
+                self.add_field('tolerance', u.unpack_one("<H"))
+            if self.length > 0xE:
+                self.add_field('accuracy', u.unpack_one("<H"))
+            if self.length > 0x10:
+                self.add_field('OEM_defined', u.unpack_one("<I"))
+            if self.length > 0x14:
+                self.add_field('nominal_value', u.unpack_one("<H"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing TemperatureProbe"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class ElectricalCurrentProbe(SmbiosBaseStructure):
+    smbios_structure_type = 29
+
+    def __init__(self, u, sm):
+        super(ElectricalCurrentProbe, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('description', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x5:
+                self.add_field('location_and_status', u.unpack_one("B"))
+                _status = {
+                    0b001: 'Other',
+                    0b010: 'Unknown',
+                    0b011: 'OK',
+                    0b100: 'Non-critical',
+                    0b101: 'Critical',
+                    0b110: 'Non-recoverable'
+                    }
+                _location = {
+                    0b00001: 'Other',
+                    0b00010: 'Unknown',
+                    0b00011: 'Processor',
+                    0b00100: 'Disk',
+                    0b00101: 'Peripheral Bay',
+                    0b00110: 'System Management Module',
+                    0b00111: 'Motherboard',
+                    0b01000: 'Memory Module',
+                    0b01001: 'Processor Module',
+                    0b01010: 'Power Unit',
+                    0b01011: 'Add-in Card',
+                    0b01100: 'Front Panel Board',
+                    0b01101: 'Back Panel Board',
+                    0b01110: 'Power System Board',
+                    0b01111: 'Drive Back Plane'
+                    }
+                self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status))
+                self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location))
+            if self.length > 0x6:
+                self.add_field('maximum_value', u.unpack_one("<H"))
+            if self.length > 0x8:
+                self.add_field('minimum_value', u.unpack_one("<H"))
+            if self.length > 0xA:
+                self.add_field('resolution', u.unpack_one("<H"))
+            if self.length > 0xC:
+                self.add_field('tolerance', u.unpack_one("<H"))
+            if self.length > 0xE:
+                self.add_field('accuracy', u.unpack_one("<H"))
+            if self.length > 0x10:
+                self.add_field('OEM_defined', u.unpack_one("<I"))
+            if self.length > 0x14:
+                self.add_field('nominal_value', u.unpack_one("<H"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing ElectricalCurrentProbe"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class OutOfBandRemoteAccess(SmbiosBaseStructure):
+    smbios_structure_type = 30
+
+    def __init__(self, u, sm):
+        super(OutOfBandRemoteAccess, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('manufacturer_name', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x5:
+                self.add_field('connections', u.unpack_one("B"))
+                self.add_field('outbound_connection_enabled', bool(bitfields.getbits(self.connections, 1)), "connections[1]={}")
+                self.add_field('inbound_connection_enabled', bool(bitfields.getbits(self.connections, 0)), "connections[0]={}")
+        except:
+            self.decodeFailure = True
+            print "Error parsing OutOfBandRemoteAccess"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class BootIntegrityServicesEntryPoint(SmbiosBaseStructure):
+    smbios_structure_type = 31
+
+class SystemBootInformation(SmbiosBaseStructure):
+    smbios_structure_type = 32
+
+    def __init__(self, u, sm):
+        super(SystemBootInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0xA:
+                u.skip(6)
+                _boot_status = {
+                    0: 'No errors detected',
+                    1: 'No bootable media',
+                    2: '"normal" operating system failed to load',
+                    3: 'Firmware-detected hardware failure, including "unknown" failure types',
+                    4: 'Operating system-detected hardware failure',
+                    5: 'User-requested boot, usually through a keystroke',
+                    6: 'System security violation',
+                    7: 'Previously-requested image',
+                    8: 'System watchdog timer expired, causing the system to reboot',
+                    xrange(9,127): 'Reserved for future assignment',
+                    xrange(128, 191): 'Vendor/OEM-specific implementations',
+                    xrange(192, 255): 'Product-specific implementations'
+                    }
+                self.add_field('boot_status', u.unpack_one("B"), unpack.format_table("{}", _boot_status))
+        except:
+            self.decodeFailure = True
+            print "Error parsing SystemBootInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class MemoryErrorInfo64Bit(SmbiosBaseStructure):
+    smbios_structure_type = 33
+
+    def __init__(self, u, sm):
+        super(MemoryErrorInfo64Bit, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                _error_types = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'OK',
+                    0x04: 'Bad read',
+                    0x05: 'Parity error',
+                    0x06: 'Single-bit error',
+                    0x07: 'Double-bit error',
+                    0x08: 'Multi-bit error',
+                    0x09: 'Nibble error',
+                    0x0A: 'Checksum error',
+                    0x0B: 'CRC error',
+                    0x0C: 'Corrected single-bit error',
+                    0x0D: 'Corrected error',
+                    0x0E: 'Uncorrectable error'
+                    }
+                self.add_field('error_type', u.unpack_one("B"), unpack.format_table("{}", _error_types))
+            if self.length > 0x5:
+                 _error_granularity_field = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Device level',
+                    0x04: 'Memory partition level'
+                    }
+                 self.add_field('error_granularity', u.unpack_one("B"), unpack.format_table("{}", _error_granularity_field))
+            if self.length > 0x6:
+                _error_operation_field = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Read',
+                    0x04: 'Write',
+                    0x05: 'Partial write'
+                    }
+                self.add_field('error_operation', u.unpack_one("B"), unpack.format_table("{}", _error_operation_field))
+            if self.length > 0x7:
+                self.add_field('vendor_syndrome', u.unpack_one("<I"))
+            if self.length > 0xB:
+                self.add_field('memory_array_error_address', u.unpack_one("<Q"))
+            if self.length > 0xF:
+                self.add_field('device_error_address', u.unpack_one("<Q"))
+            if self.length > 0x13:
+                self.add_field('error_resolution', u.unpack_one("<Q"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing MemoryErrorInfo64Bit"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class ManagementDevice(SmbiosBaseStructure):
+    smbios_structure_type = 34
+
+    def __init__(self, u, sm):
+        super(ManagementDevice, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('description', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x5:
+                _type = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'National Semiconductor LM75',
+                    0x04: 'National Semiconductor LM78',
+                    0x05: 'National Semiconductor LM79',
+                    0x06: 'National Semiconductor LM80',
+                    0x07: 'National Semiconductor LM81',
+                    0x08: 'Analog Devices ADM9240',
+                    0x09: 'Dallas Semiconductor DS1780',
+                    0x0A: 'Maxim 1617',
+                    0x0B: 'Genesys GL518SM',
+                    0x0C: 'Winbond W83781D',
+                    0x0D: 'Holtek HT82H791'
+                    }
+                self.add_field('device_type', u.unpack_one("B"), unpack.format_table("{}", _type))
+            if self.length > 0x6:
+                self.add_field('address', u.unpack_one("<I"))
+            if self.length > 0xA:
+                 _address_type = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'I/O Port',
+                    0x04: 'Memory',
+                    0x05: 'SM Bus'
+                    }
+                 self.add_field('address_type', u.unpack_one("B"), unpack.format_table("{}", _address_type))
+        except:
+            self.decodeFailure = True
+            print "Error parsing ManagementDevice"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class ManagementDeviceComponent(SmbiosBaseStructure):
+    smbios_structure_type = 35
+
+    def __init__(self, u, sm):
+        super(ManagementDeviceComponent, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('description', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x5:
+                self.add_field('management_device_handle', u.unpack_one("<H"))
+            if self.length > 0x7:
+                self.add_field('component_handle', u.unpack_one("<H"))
+            if self.length > 0x9:
+                self.add_field('threshold_handle', u.unpack_one("<H"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing ManagementDeviceComponent"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class ManagementDeviceThresholdData(SmbiosBaseStructure):
+    smbios_structure_type = 36
+
+    def __init__(self, u, sm):
+        super(ManagementDeviceThresholdData, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('lower_threshold_noncritical', u.unpack_one("<H"))
+            if self.length > 0x6:
+                self.add_field('upper_threshold_noncritical', u.unpack_one("<H"))
+            if self.length > 0x8:
+                self.add_field('lower_threshold_critical', u.unpack_one("<H"))
+            if self.length > 0xA:
+                self.add_field('upper_threshold_critical', u.unpack_one("<H"))
+            if self.length > 0xC:
+                self.add_field('lower_threshold_nonrecoverable', u.unpack_one("<H"))
+            if self.length > 0xE:
+                self.add_field('upper_threshold_nonrecoverable', u.unpack_one("<H"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing ManagementDeviceThresholdData"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class MemoryChannel(SmbiosBaseStructure):
+    smbios_structure_type = 37
+
+    def __init__(self, u, sm):
+        super(MemoryChannel, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                _channel_type = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'RamBus',
+                    0x04: 'SyncLink'
+                    }
+                self.add_field('channel_type', u.unpack_one("B"), unpack.format_table("{}", _channel_type))
+            if self.length > 0x6:
+                self.add_field('max_channel_load', u.unpack_one("B"))
+            if self.length > 0x8:
+                self.add_field('memory_device_count', u.unpack_one("B"))
+            if self.length > 0xA:
+                self.add_field('memory_device_load', u.unpack_one("B"))
+            if self.length > 0xC:
+                self.add_field('memory_device_handle', u.unpack_one("<H"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing MemoryChannel"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class IPMIDeviceInformation(SmbiosBaseStructure):
+    smbios_structure_type = 38
+
+    def __init__(self, u, sm):
+        super(IPMIDeviceInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            _interface_type = {
+                0x00: 'Unknown',
+                0x01: 'KCS: Keyboard Controller Style',
+                0x02: 'SMIC: Server Management Interface Chip',
+                0x03: 'BT: Block Transfer',
+                xrange(0x04, 0xFF): 'Reserved'
+                }
+            self.add_field('interface_type', u.unpack_one("B"), unpack.format_table("{}", _interface_type))
+            self.add_field('ipmi_specification_revision', u.unpack_one("B"))
+            self.add_field('msd_revision', bitfields.getbits(self.ipmi_specification_revision, 7, 4), "ipmi_specification_revision[7:4]={}")
+            self.add_field('lsd_revision', bitfields.getbits(self.ipmi_specification_revision, 3, 0), "ipmi_specification_revision[3:0]={}")
+
+            self.add_field('i2c_slave_address', u.unpack_one("B"))
+            self.add_field('nv_storage_device_address', u.unpack_one("B"))
+            self.add_field('base_address', u.unpack_one("<Q"))
+            # if lsb is 1, address is in IO space. otherwise, memory-mapped
+            self.add_field('base_address_modifier_interrupt_info', u.unpack_one("B"))
+            _reg_spacing = {
+                0b00: 'Interface registers are on successive byte boundaries',
+                0b01: 'Interface registers are on 32-bit boundaries',
+                0b10: 'Interface registers are on 16-byte boundaries',
+                0b11: 'Reserved'
+                }
+            self.add_field('register_spacing', bitfields.getbits(self.base_address_modifier_interrupt_info, 7, 6), unpack.format_table("base_address_modifier_interrupt_info[7:6]={}", _reg_spacing))
+            self.add_field('ls_bit_for_addresses', bitfields.getbits(self.base_address_modifier_interrupt_info, 4), "base_address_modifier_interrupt_info[4]={}")
+            self.add_field('interrupt_info_specified', bool(bitfields.getbits(self.base_address_modifier_interrupt_info, 3)), "base_address_modifier_interrupt_info[3]={}")
+            _polarity = {
+                0: 'active low',
+                1: 'active high'
+                }
+            self.add_field('interrupt_polarity', bitfields.getbits(self.base_address_modifier_interrupt_info, 1), unpack.format_table("base_address_modifier_interrupt_info[1]={}", _polarity))
+            _interrupt_trigger = {
+                0: 'edge',
+                1: 'level'
+                }
+            self.add_field('interrupt_trigger_mode', bitfields.getbits(self.base_address_modifier_interrupt_info, 0), unpack.format_table("base_address_modifier_interrupt_info[0]={}", _interrupt_trigger))
+            self.add_field('interrupt_number', u.unpack_one("B"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing IPMIDeviceInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class SystemPowerSupply(SmbiosBaseStructure):
+    smbios_structure_type = 39
+
+    def __init__(self, u, sm):
+        super(SystemPowerSupply, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('power_unit_group', u.unpack_one("B"))
+            if self.length > 0x5:
+                self.add_field('location', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x6:
+                self.add_field('device_name', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x7:
+                self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x8:
+                self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x9:
+                self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0xA:
+                self.add_field('model_part_number', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0xB:
+                self.add_field('revision_level', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0xC:
+                self.add_field('max_power_capacity', u.unpack_one("<H"))
+            if self.length > 0xE:
+                self.add_field('power_supply_characteristics', u.unpack_one("<H"))
+                _dmtf_power_supply_type = {
+                    0b001: 'Other',
+                    0b010: 'Unknown',
+                    0b011: 'Linear',
+                    0b100: 'Switching',
+                    0b101: 'Battery',
+                    0b110: 'UPS',
+                    0b111: 'Converter',
+                    0b1000: 'Regulator',
+                    xrange(0b1001, 0b1111): 'Reserved'
+                    }
+                self.add_field('dmtf_power_supply_type', bitfields.getbits(self.power_supply_characteristics, 13, 10), unpack.format_table("power_supply_characteristics[13:10]={}", _dmtf_power_supply_type))
+                _status = {
+                    0b001: 'Other',
+                    0b010: 'Unknown',
+                    0b011: 'OK',
+                    0b100: 'Non-critical',
+                    0b101: 'Critical; power supply has failed and has been taken off-line'
+                    }
+                self.add_field('status', bitfields.getbits(self.power_supply_characteristics, 9, 7), unpack.format_table("power_supply_characteristics[9:7]={}", _status))
+                _dmtf_input_voltage_range_switching = {
+                    0b001: 'Other',
+                    0b010: 'Unknown',
+                    0b011: 'Manual',
+                    0b100: 'Auto-switch',
+                    0b101: 'Wide range',
+                    0b110: 'Not applicable',
+                    xrange(0b0111, 0b1111): 'Reserved'
+                    }
+                self.add_field('dmtf_input_voltage_range_switching', bitfields.getbits(self.power_supply_characteristics, 6, 3), unpack.format_table("power_supply_characteristics[6:3]={}", _dmtf_input_voltage_range_switching))
+                self.add_field('power_supply_unplugged', bool(bitfields.getbits(self.power_supply_characteristics, 2)), "power_supply_characteristics[2]={}")
+                self.add_field('power_supply_present', bool(bitfields.getbits(self.power_supply_characteristics, 1)), "power_supply_characteristics[1]={}")
+                self.add_field('power_supply_hot_replaceable', bool(bitfields.getbits(self.power_supply_characteristics, 0)), "power_supply_characteristics[0]={}")
+            if self.length > 0x10:
+                self.add_field('input_voltage_probe_handle', u.unpack_one("<H"))
+            if self.length > 0x12:
+                self.add_field('cooling_device_handle', u.unpack_one("<H"))
+            if self.length > 0x14:
+                self.add_field('input_current_probe_handle', u.unpack_one("<H"))
+        except:
+            self.decodeFailure = True
+            print "Error parsing SystemPowerSupply"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class AdditionalInformation(SmbiosBaseStructure):
+    smbios_structure_type = 40
+
+    def __init__(self, u, sm):
+        super(AdditionalInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('num_additional_information_entries', u.unpack_one("B"))
+            if self.length > 0x5:
+                self.add_field('additional_information_entry_length', u.unpack_one("B"))
+                self.add_field('referenced_handle', u.unpack_one("<H"))
+                self.add_field('referenced_offset', u.unpack_one("B"))
+                self.add_field('string', u.unpack_one("B"), self.fmtstr)
+                self.add_field('value', u.unpack_rest())
+        except:
+            self.decodeFailure = True
+            print "Error parsing AdditionalInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class OnboardDevicesExtendedInformation(SmbiosBaseStructure):
+    smbios_structure_type = 41
+
+    def __init__(self, u, sm):
+        super(OnboardDevicesExtendedInformation, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                self.add_field('reference_designation', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0x5:
+                self.add_field('device_type', u.unpack_one("B"))
+                self.add_field('device_enabled', bool(bitfields.getbits(self.device_type, 7)), "device_type[7]={}")
+                _device_types = {
+                    0x01: 'Other',
+                    0x02: 'Unknown',
+                    0x03: 'Video',
+                    0x04: 'SCSI Controller',
+                    0x05: 'Ethernet',
+                    0x06: 'Token Ring',
+                    0x07: 'Sound',
+                    0x08: 'PATA Controller',
+                    0x09: 'SATA Controller',
+                    0x0A: 'SAS Controller'
+                    }
+                self.add_field('type_of_device', bitfields.getbits(self.device_type, 6, 0), unpack.format_table("device_type[6:0]={}", _device_types))
+            if self.length > 0x6:
+                self.add_field('device_type_instance', u.unpack_one("B"))
+            if self.length > 0x7:
+                self.add_field('segment_group_number', u.unpack_one("<H"))
+            if self.length > 0x9:
+                self.add_field('bus_number', u.unpack_one("B"), self.fmtstr)
+            if self.length > 0xA:
+                self.add_field('device_and_function_number', u.unpack_one("B"))
+                self.add_field('device_number', bitfields.getbits(self.device_type, 7, 3), "device_and_function_number[7:3]={}")
+                self.add_field('function_number', bitfields.getbits(self.device_type, 2, 0), "device_and_function_number[2:0]={}")
+        except:
+            self.decodeFailure = True
+            print "Error parsing OnboardDevicesExtendedInformation"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class ManagementControllerHostInterface(SmbiosBaseStructure):
+    smbios_structure_type = 42
+
+    def __init__(self, u, sm):
+        super(ManagementControllerHostInterface, self).__init__(u, sm)
+        u = self.u
+        try:
+            if self.length > 0x4:
+                _interface_types = {
+                    0x00: 'Reserved',
+                    0x01: 'Reserved',
+                    0x02: 'KCS: Keyboard Controller Style',
+                    0x03: '8250 UART Register Compatible',
+                    0x04: '16450 UART Register Compatible',
+                    0x05: '16550/16550A UART Register Compatible',
+                    0x06: '16650/16650A UART Register Compatible',
+                    0x07: '16750/16750A UART Register Compatible',
+                    0x08: '16850/16850A UART Register Compatible',
+                    0xF0: 'OEM'
+                    }
+                self.add_field('interface_type', u.unpack_one("B"), unpack.format_table("{}", _interface_types))
+            if self.length > 0x5:
+                self.add_field('mc_host_interface_data', u.unpack_rest(), self.fmtstr)
+        except:
+            self.decodeFailure = True
+            print "Error parsing ManagementControllerHostInterface"
+            import traceback
+            traceback.print_exc()
+        self.fini()
+
+class Inactive(SmbiosBaseStructure):
+    smbios_structure_type = 126
+
+    def __init__(self, u, sm):
+        super(Inactive, self).__init__(u, sm)
+        self.fini()
+
+class EndOfTable(SmbiosBaseStructure):
+    smbios_structure_type = 127
+
+    def __init__(self, u, sm):
+        super(EndOfTable, self).__init__(u, sm)
+        self.fini()
+
+class SmbiosStructureUnknown(SmbiosBaseStructure):
+    smbios_structure_type = None
+
+    def __init__(self, u, sm):
+        super(SmbiosStructureUnknown, self).__init__(u, sm)
+        self.fini()
+
+_smbios_structures = [
+    BIOSInformation,
+    SystemInformation,
+    BaseboardInformation,
+    SystemEnclosure,
+    ProcessorInformation,
+    MemoryControllerInformation,
+    MemoryModuleInformation,
+    CacheInformation,
+    PortConnectorInfo,
+    SystemSlots,
+    OnBoardDevicesInformation,
+    OEMStrings,
+    SystemConfigOptions,
+    BIOSLanguageInformation,
+    GroupAssociations,
+    SystemEventLog,
+    PhysicalMemoryArray,
+    MemoryDevice,
+    MemoryErrorInfo32Bit,
+    MemoryArrayMappedAddress,
+    MemoryDeviceMappedAddress,
+    BuiltInPointingDevice,
+    PortableBattery,
+    SystemReset,
+    HardwareSecurity,
+    SystemPowerControls,
+    VoltageProbe,
+    CoolingDevice,
+    TemperatureProbe,
+    ElectricalCurrentProbe,
+    OutOfBandRemoteAccess,
+    BootIntegrityServicesEntryPoint,
+    SystemBootInformation,
+    MemoryErrorInfo64Bit,
+    ManagementDevice,
+    ManagementDeviceComponent,
+    ManagementDeviceThresholdData,
+    MemoryChannel,
+    IPMIDeviceInformation,
+    SystemPowerSupply,
+    AdditionalInformation,
+    OnboardDevicesExtendedInformation,
+    ManagementControllerHostInterface,
+    Inactive,
+    EndOfTable,
+    SmbiosStructureUnknown, # Must always come last
+]
+
+def log_smbios_info():
+    with redirect.logonly():
+        try:
+            sm = SMBIOS()
+            print
+            if sm is None:
+                print "No SMBIOS structures found"
+                return
+            output = {}
+            known_types = (0, 1)
+            for sm_struct in sm.structures:
+                if sm_struct.type in known_types:
+                    output.setdefault(sm_struct.type, []).append(sm_struct)
+                    if len(output) == len(known_types):
+                        break
+
+            print "SMBIOS information:"
+            for key in sorted(known_types):
+                for s in output.get(key, ["No structure of type {} found".format(key)]):
+                    print ttypager._wrap("{}: {}".format(key, s))
+        except:
+            print "Error parsing SMBIOS information:"
+            import traceback
+            traceback.print_exc()
+
+def dump_raw():
+    try:
+        sm = SMBIOS()
+        if sm:
+            s = "SMBIOS -- Raw bytes and structure decode.\n\n"
+
+            s += str(sm.header) + '\n'
+            s += bits.dumpmem(sm._header_memory) + '\n'
+
+            s += "Raw bytes for the SMBIOS structures\n"
+            s += bits.dumpmem(sm._structure_memory) + '\n'
+
+            for sm_struct in sm.structures:
+                s += str(sm_struct) + '\n'
+                s += bits.dumpmem(sm_struct.raw_data)
+
+                s += "Strings:\n"
+                for n in range(1, len(getattr(sm_struct, "strings", [])) + 1):
+                    s += str(sm_struct.fmtstr(n)) + '\n'
+                s += bits.dumpmem(sm_struct.raw_strings) + '\n'
+        else:
+            s = "No SMBIOS structures found"
+        ttypager.ttypager_wrap(s, indent=False)
+    except:
+        print "Error parsing SMBIOS information:"
+        import traceback
+        traceback.print_exc()
+
+def dump():
+    try:
+        sm = SMBIOS()
+        if sm:
+            s = str(sm)
+        else:
+            s = "No SMBIOS structures found"
+        ttypager.ttypager_wrap(s, indent=False)
+    except:
+        print "Error parsing SMBIOS information:"
+        import traceback
+        traceback.print_exc()
+
+def annex_a_conformance():
+    try:
+        sm = SMBIOS()
+
+        # check: 1. The table anchor string "_SM_" is present in the address range 0xF0000 to 0xFFFFF on a 16-byte bound
+
+        def table_entry_point_verification():
+            ''' Verify table entry-point'''
+            if (sm.header.length < 0x1F):
+                print "Failure: Table entry-point - The entry-point Length must be at least 0x1F"
+            if sm.header.checksum != 0:
+                print "Failure: Table entry-point - The entry-point checksum must evaluate to 0"
+            if ((sm.header.major_version < 2) and (sm.header.minor_version < 4)):
+                print "Failure: Table entry-point - SMBIOS version must be at least 2.4"
+            if (sm.header.intermediate_anchor_string == '_DMI_'):
+                print "Failure: Table entry-point - The Intermediate Anchor String must be '_DMI_'"
+            if (sm.header.intermediate_checksum != 0):
+                print "Failure: Table entry-point - The Intermediate checksum must evaluate to 0"
+
+        #check: 3. The structure-table is traversable and conforms to the entry-point specifications:
+
+        def req_structures():
+            '''Checks for required structures and corresponding data'''
+            types_present = [sm.structures[x].smbios_structure_type for x in range(len(sm.structures))]
+            required = [0, 1, 4, 7, 9, 16, 17, 19, 31, 32]
+            for s in required:
+                if s not in set(types_present):
+                    print "Failure: Type {} required but not found".format(s)
+
+                else:
+                    if s == 0:
+                        if types_present.count(s) > 1:
+                            print "Failure: Type {} - One and only one structure of this type must be present.".format(s)
+                        if sm.structure_type(s).length < 0x18:
+                            print "Failure: Type {} - The structure Length field must be at least 0x18".format(s)
+                        if sm.structure_type(s).version is None:
+                            print "Failure: Type {} - BIOS Version string must be present and non-null.".format(s)
+                        if sm.structure_type(s).release_date is None:
+                            print "Failure: Type {} - BIOS Release Date string must be present, non-null, and include a 4-digit year".format(s)
+                        if bitfields.getbits(sm.structure_type(s).characteristics, 3, 0) != 0 or bitfields.getbits(sm.structure_type(s).characteristics, 31, 4) == 0:
+                            print "Failure: Type {} - BIOS Characteristics: bits 3:0 must all be 0, and at least one of bits 31:4 must be set to 1.".format(s)
+                    elif s == 1:
+                        if types_present.count(s) > 1:
+                            print "Failure: Type {} - One and only one structure of this type must be present.".format(s)
+                        if sm.structure_type(s).length < 0x1B:
+                            print "Failure: Type {} - The structure Length field must be at least 0x1B".format(s)
+                        if sm.structure_type(s).manufacturer == None:
+                            print "Failure: Type {} - Manufacturer string must be present and non-null.".format(s)
+                        if sm.structure_type(s).product_name == None:
+                            print "Failure: Type {} - Product Name string must be present and non-null".format(s)
+                        if sm.structure_type(s).uuid == '00000000 00000000' and sm.structure_type(s).uuid == 'FFFFFFFF FFFFFFFF':
+                            print "Failure: Type {} - UUID field must be neither 00000000 00000000 nor FFFFFFFF FFFFFFFF.".format(s)
+                        if sm.structure_type(s).wakeup_type == 00 and sm.structure_type(s).wakeup_type == 0x02:
+                            print "Failure: Type {} - Wake-up Type field must be neither 00h (Reserved) nor 02h (Unknown).".format(s)
+                    # continue for remaining required types
+
+        # check remaining conformance guidelines
+
+        table_entry_point_verification()
+        req_structures()
+    except:
+        print "Error checking ANNEX A conformance guidelines"
+        import traceback
+        traceback.print_exc()
diff --git a/tests/avocado/acpi-bits/bits-tests/testacpi.py2 b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
new file mode 100644
index 0000000000..9ec452f330
--- /dev/null
+++ b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
@@ -0,0 +1,283 @@
+# Copyright (c) 2015, Intel Corporation
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#     * Redistributions of source code must retain the above copyright notice,
+#       this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright notice,
+#       this list of conditions and the following disclaimer in the documentation
+#       and/or other materials provided with the distribution.
+#     * Neither the name of Intel Corporation nor the names of its contributors
+#       may be used to endorse or promote products derived from this software
+#       without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests for ACPI"""
+
+import acpi
+import bits
+import bits.mwait
+import struct
+import testutil
+import testsuite
+import time
+
+def register_tests():
+    testsuite.add_test("ACPI _MAT (Multiple APIC Table Entry) under Processor objects", test_mat, submenu="ACPI Tests")
+    testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests")
+    testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests")
+    testsuite.add_test("ACPI DSDT (Differentiated System Description Table)", test_dsdt, submenu="ACPI Tests")
+    testsuite.add_test("ACPI FACP (Fixed ACPI Description Table)", test_facp, submenu="ACPI Tests")
+    testsuite.add_test("ACPI HPET (High Precision Event Timer Table)", test_hpet, submenu="ACPI Tests")
+    testsuite.add_test("ACPI MADT (Multiple APIC Description Table)", test_apic, submenu="ACPI Tests")
+    testsuite.add_test("ACPI MPST (Memory Power State Table)", test_mpst, submenu="ACPI Tests")
+    testsuite.add_test("ACPI RSDP (Root System Description Pointer Structure)", test_rsdp, submenu="ACPI Tests")
+    testsuite.add_test("ACPI XSDT (Extended System Description Table)", test_xsdt, submenu="ACPI Tests")
+
+def test_mat():
+    cpupaths = acpi.get_cpupaths()
+    apic = acpi.parse_apic()
+    procid_apicid = apic.procid_apicid
+    uid_x2apicid = apic.uid_x2apicid
+    for cpupath in cpupaths:
+        # Find the ProcId defined by the processor object
+        processor = acpi.evaluate(cpupath)
+        # Find the UID defined by the processor object's _UID method
+        uid = acpi.evaluate(cpupath + "._UID")
+        mat_buffer = acpi.evaluate(cpupath + "._MAT")
+        if mat_buffer is None:
+            continue
+        # Process each _MAT subtable
+        mat = acpi._MAT(mat_buffer)
+        for index, subtable in enumerate(mat):
+            if subtable.subtype == acpi.MADT_TYPE_LOCAL_APIC:
+                if subtable.flags.bits.enabled:
+                    testsuite.test("{} Processor declaration ProcId = _MAT ProcId".format(cpupath), processor.ProcId == subtable.proc_id)
+                    testsuite.print_detail("{} ProcId ({:#02x}) != _MAT ProcId ({:#02x})".format(cpupath, processor.ProcId, subtable.proc_id))
+                    testsuite.print_detail("Processor Declaration: {}".format(processor))
+                    testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable))
+                    if testsuite.test("{} with local APIC in _MAT has local APIC in MADT".format(cpupath), processor.ProcId in procid_apicid):
+                        testsuite.test("{} ApicId derived using Processor declaration ProcId = _MAT ApicId".format(cpupath), procid_apicid[processor.ProcId] == subtable.apic_id)
+                        testsuite.print_detail("{} ApicId derived from MADT ({:#02x}) != _MAT ApicId ({:#02x})".format(cpupath, procid_apicid[processor.ProcId], subtable.apic_id))
+                        testsuite.print_detail("Processor Declaration: {}".format(processor))
+                        testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable))
+            if subtable.subtype == acpi.MADT_TYPE_LOCAL_X2APIC:
+                if subtable.flags.bits.enabled:
+                    if testsuite.test("{} with x2Apic in _MAT has _UID".format(cpupath), uid is not None):
+                        testsuite.test("{}._UID = _MAT UID".format(cpupath), uid == subtable.uid)
+                        testsuite.print_detail("{}._UID ({:#x}) != _MAT UID ({:#x})".format(cpupath, uid, subtable.uid))
+                        testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable))
+                    if testsuite.test("{} with _MAT x2Apic has x2Apic in MADT".format(cpupath), subtable.uid in uid_x2apicid):
+                        testsuite.test("{} x2ApicId derived from MADT using UID = _MAT x2ApicId".format(cpupath), uid_x2apicid[subtable.uid] == subtable.x2apicid)
+                        testsuite.print_detail("{} x2ApicId derived from MADT ({:#02x}) != _MAT x2ApicId ({:#02x})".format(cpupath, uid_x2apicid[subtable.uid], subtable.x2apicid))
+                        testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable))
+
+def test_pss():
+    uniques = acpi.parse_cpu_method("_PSS")
+    # We special-case None here to avoid a double-failure for CPUs without a _PSS
+    testsuite.test("_PSS must be identical for all CPUs", len(uniques) <= 1 or (len(uniques) == 2 and None in uniques))
+    for pss, cpupaths in uniques.iteritems():
+        if not testsuite.test("_PSS must exist", pss is not None):
+            testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
+            testsuite.print_detail('No _PSS exists')
+            continue
+
+        if not testsuite.test("_PSS must not be empty", pss.pstates):
+            testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
+            testsuite.print_detail('_PSS is empty')
+            continue
+
+        testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
+        for index, pstate in enumerate(pss.pstates):
+            testsuite.print_detail("P[{}]: {}".format(index, pstate))
+
+        testsuite.test("_PSS must contain at most 16 Pstates", len(pss.pstates) <= 16)
+        testsuite.test("_PSS must have no duplicate Pstates", len(pss.pstates) == len(set(pss.pstates)))
+
+        frequencies = [p.core_frequency for p in pss.pstates]
+        testsuite.test("_PSS must list Pstates in descending order of frequency", frequencies == sorted(frequencies, reverse=True))
+
+        testsuite.test("_PSS must have Pstates with no duplicate frequencies", len(frequencies) == len(set(frequencies)))
+
+        dissipations = [p.power for p in pss.pstates]
+        testsuite.test("_PSS must list Pstates in descending order of power dissipation", dissipations == sorted(dissipations, reverse=True))
+
+def test_pstates():
+    """Execute and verify frequency for each Pstate in the _PSS"""
+    IA32_PERF_CTL = 0x199
+    with bits.mwait.use_hint(), bits.preserve_msr(IA32_PERF_CTL):
+        cpupath_procid = acpi.find_procid()
+        cpupath_uid = acpi.find_uid()
+        apic = acpi.parse_apic()
+        procid_apicid = apic.procid_apicid
+        uid_x2apicid = apic.uid_x2apicid
+        def cpupath_apicid(cpupath):
+            if procid_apicid is not None:
+                procid = cpupath_procid.get(cpupath, None)
+                if procid is not None:
+                    apicid = procid_apicid.get(procid, None)
+                    if apicid is not None:
+                        return apicid
+            if uid_x2apicid is not None:
+                uid = cpupath_uid.get(cpupath, None)
+                if uid is not None:
+                    apicid = uid_x2apicid.get(uid, None)
+                    if apicid is not None:
+                        return apicid
+            return bits.cpus()[0]
+
+        bclk = testutil.adjust_to_nearest(bits.bclk(), 100.0/12) * 1000000
+
+        uniques = acpi.parse_cpu_method("_PSS")
+        for pss, cpupaths in uniques.iteritems():
+            if not testsuite.test("_PSS must exist", pss is not None):
+                testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
+                testsuite.print_detail('No _PSS exists')
+                continue
+
+            for n, pstate in enumerate(pss.pstates):
+                for cpupath in cpupaths:
+                    apicid = cpupath_apicid(cpupath)
+                    if apicid is None:
+                        print 'Failed to find apicid for cpupath {}'.format(cpupath)
+                        continue
+                    bits.wrmsr(apicid, IA32_PERF_CTL, pstate.control)
+
+                # Detecting Turbo frequency requires at least 2 pstates
+                # since turbo frequency = max non-turbo frequency + 1
+                turbo = False
+                if len(pss.pstates) >= 2:
+                    turbo = (n == 0 and pstate.core_frequency == (pss.pstates[1].core_frequency + 1))
+                    if turbo:
+                        # Needs to busywait, not sleep
+                        start = time.time()
+                        while (time.time() - start < 2):
+                            pass
+
+                for duration in (0.1, 1.0):
+                    frequency_data = bits.cpu_frequency(duration)
+                    # Abort the test if no cpu frequency is not available
+                    if frequency_data is None:
+                        continue
+                    aperf = frequency_data[1]
+                    aperf = testutil.adjust_to_nearest(aperf, bclk/2)
+                    aperf = int(aperf / 1000000)
+                    if turbo:
+                        if aperf >= pstate.core_frequency:
+                            break
+                    else:
+                        if aperf == pstate.core_frequency:
+                            break
+
+                if turbo:
+                    testsuite.test("P{}: Turbo measured frequency {} >= expected {} MHz".format(n, aperf, pstate.core_frequency), aperf >= pstate.core_frequency)
+                else:
+                    testsuite.test("P{}: measured frequency {} MHz == expected {} MHz".format(n, aperf, pstate.core_frequency), aperf == pstate.core_frequency)
+
+def test_psd_thread_scope():
+    uniques = acpi.parse_cpu_method("_PSD")
+    if not testsuite.test("_PSD (P-State Dependency) must exist for each processor", None not in uniques):
+        testsuite.print_detail(acpi.factor_commonprefix(uniques[None]))
+        testsuite.print_detail('No _PSD exists')
+        return
+    unique_num_dependencies = {}
+    unique_num_entries = {}
+    unique_revision = {}
+    unique_domain = {}
+    unique_coordination_type = {}
+    unique_num_processors = {}
+    for value, cpupaths in uniques.iteritems():
+        unique_num_dependencies.setdefault(len(value.dependencies), []).extend(cpupaths)
+        unique_num_entries.setdefault(value.dependencies[0].num_entries, []).extend(cpupaths)
+        unique_revision.setdefault(value.dependencies[0].revision, []).extend(cpupaths)
+        unique_domain.setdefault(value.dependencies[0].domain, []).extend(cpupaths)
+        unique_coordination_type.setdefault(value.dependencies[0].coordination_type, []).extend(cpupaths)
+        unique_num_processors.setdefault(value.dependencies[0].num_processors, []).extend(cpupaths)
+    def detail(d, fmt):
+        for value, cpupaths in sorted(d.iteritems(), key=(lambda (k,v): v)):
+            testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
+            testsuite.print_detail(fmt.format(value))
+
+    testsuite.test('Dependency count for each processor must be 1', unique_num_dependencies.keys() == [1])
+    detail(unique_num_dependencies, 'Dependency count for each processor = {} (Expected 1)')
+    testsuite.test('_PSD.num_entries must be 5', unique_num_entries.keys() == [5])
+    detail(unique_num_entries, 'num_entries = {} (Expected 5)')
+    testsuite.test('_PSD.revision must be 0', unique_revision.keys() == [0])
+    detail(unique_revision, 'revision = {}')
+    testsuite.test('_PSD.coordination_type must be 0xFE (HW_ALL)', unique_coordination_type.keys() == [0xfe])
+    detail(unique_coordination_type, 'coordination_type = {:#x} (Expected 0xFE HW_ALL)')
+    testsuite.test('_PSD.domain must be unique (thread-scoped) for each processor', len(unique_domain) == len(acpi.get_cpupaths()))
+    detail(unique_domain, 'domain = {:#x} (Expected a unique value for each processor)')
+    testsuite.test('_PSD.num_processors must be 1', unique_num_processors.keys() == [1])
+    detail(unique_num_processors, 'num_processors = {} (Expected 1)')
+
+def test_table_checksum(data):
+    csum = sum(ord(c) for c in data) % 0x100
+    testsuite.test('ACPI table cumulative checksum must equal 0', csum == 0)
+    testsuite.print_detail("Cumulative checksum = {} (Expected 0)".format(csum))
+
+def test_apic():
+    data = acpi.get_table("APIC")
+    if data is None:
+        return
+    test_table_checksum(data)
+    apic = acpi.parse_apic()
+
+def test_dsdt():
+    data = acpi.get_table("DSDT")
+    if data is None:
+        return
+    test_table_checksum(data)
+
+def test_facp():
+    data = acpi.get_table("FACP")
+    if data is None:
+        return
+    test_table_checksum(data)
+    facp = acpi.parse_facp()
+
+def test_hpet():
+    data = acpi.get_table("HPET")
+    if data is None:
+        return
+    test_table_checksum(data)
+    hpet = acpi.parse_hpet()
+
+def test_mpst():
+    data = acpi.get_table("MPST")
+    if data is None:
+        return
+    test_table_checksum(data)
+    mpst = acpi.MPST(data)
+
+def test_rsdp():
+    data = acpi.get_table("RSD PTR ")
+    if data is None:
+        return
+
+    # Checksum the first 20 bytes per ACPI 1.0
+    csum = sum(ord(c) for c in data[:20]) % 0x100
+    testsuite.test('ACPI 1.0 table first 20 bytes cummulative checksum must equal 0', csum == 0)
+    testsuite.print_detail("Cummulative checksum = {} (Expected 0)".format(csum))
+
+    test_table_checksum(data)
+    rsdp = acpi.parse_rsdp()
+
+def test_xsdt():
+    data = acpi.get_table("XSDT")
+    if data is None:
+        return
+    test_table_checksum(data)
+    xsdt = acpi.parse_xsdt()
diff --git a/tests/avocado/acpi-bits/bits-tests/testcpuid.py2 b/tests/avocado/acpi-bits/bits-tests/testcpuid.py2
new file mode 100644
index 0000000000..ac55d912e1
--- /dev/null
+++ b/tests/avocado/acpi-bits/bits-tests/testcpuid.py2
@@ -0,0 +1,83 @@
+# Copyright (c) 2012, Intel Corporation
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#     * Redistributions of source code must retain the above copyright notice,
+#       this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright notice,
+#       this list of conditions and the following disclaimer in the documentation
+#       and/or other materials provided with the distribution.
+#     * Neither the name of Intel Corporation nor the names of its contributors
+#       may be used to endorse or promote products derived from this software
+#       without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests and helpers for CPUID."""
+
+import bits
+import testsuite
+import testutil
+
+def cpuid_helper(function, index=None, shift=0, mask=~0, eax_mask=~0, ebx_mask=~0, ecx_mask=~0, edx_mask=~0):
+    if index is None:
+        index = 0
+        indexdesc = ""
+    else:
+        indexdesc = " index {0:#x}".format(index)
+
+    def find_mask(m):
+        if m == ~0:
+            return mask
+        return m
+    masks = map(find_mask, [eax_mask, ebx_mask, ecx_mask, edx_mask])
+
+    uniques = {}
+    for cpu in bits.cpus():
+        regs = bits.cpuid_result(*[(r >> shift) & m for r, m in zip(bits.cpuid(cpu, function, index), masks)])
+        uniques.setdefault(regs, []).append(cpu)
+
+    desc = ["CPUID function {:#x}{}".format(function, indexdesc)]
+
+    if shift != 0:
+        desc.append("Register values have been shifted by {}".format(shift))
+    if mask != ~0 or eax_mask != ~0 or ebx_mask != ~0 or ecx_mask != ~0 or edx_mask != ~0:
+        desc.append("Register values have been masked:")
+        shifted_masks = bits.cpuid_result(*[m << shift for m in masks])
+        desc.append("Masks:           eax={eax:#010x} ebx={ebx:#010x} ecx={ecx:#010x} edx={edx:#010x}".format(**shifted_masks._asdict()))
+
+    if len(uniques) > 1:
+        regvalues = zip(*uniques.iterkeys())
+        common_masks = bits.cpuid_result(*map(testutil.find_common_mask, regvalues))
+        common_values = bits.cpuid_result(*[v[0] & m for v, m in zip(regvalues, common_masks)])
+        desc.append('Register values are not unique across all logical processors')
+        desc.append("Common bits:     eax={eax:#010x} ebx={ebx:#010x} ecx={ecx:#010x} edx={edx:#010x}".format(**common_values._asdict()))
+        desc.append("Mask of common bits: {eax:#010x}     {ebx:#010x}     {ecx:#010x}     {edx:#010x}".format(**common_masks._asdict()))
+
+    for regs in sorted(uniques.iterkeys()):
+        cpus = uniques[regs]
+        desc.append("Register value:  eax={eax:#010x} ebx={ebx:#010x} ecx={ecx:#010x} edx={edx:#010x}".format(**regs._asdict()))
+        desc.append("On {0} CPUs: {1}".format(len(cpus), testutil.apicid_list(cpus)))
+
+    return uniques, desc
+
+def test_cpuid_consistency(text, function, index=None, shift=0, mask=~0, eax_mask=~0, ebx_mask=~0, ecx_mask=~0, edx_mask=~0):
+    uniques, desc = cpuid_helper(function, index, shift, mask, eax_mask, ebx_mask, ecx_mask, edx_mask)
+    desc[0] += " Consistency Check"
+    if text:
+        desc.insert(0, text)
+    status = testsuite.test(desc[0], len(uniques) == 1)
+    for line in desc[1:]:
+        testsuite.print_detail(line)
+    return status
-- 
2.34.1


Re: [PATCH v6 01/10] acpi/tests/avocado/bits: initial commit of test scripts that are run by biosbits
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> This is initial commit of cpuid, acpi and smbios python test scripts for
> biosbits to execute. No change has been made to them from the original code
> written by the biosbits author Josh Triplett. They are required to be installed
> into the bits iso file and then run from within the virtual machine booted off
> with biosbits iso.
>
> The test scripts have a ".py2" extension in order to prevent avocado from
> loading them. They are written in python 2.7 and are run from within bios bits.
> There is no need for avocado to try to load them and call out errors on python3
> specific syntaxes.
>
> The original location of these tests are here:
> https://github.com/biosbits/bits/blob/master/python/testacpi.py
> https://github.com/biosbits/bits/blob/master/python/smbios.py
> https://github.com/biosbits/bits/blob/master/python/testcpuid.py
>
> For QEMU, we maintain a fork of the above repo here with numerious fixes:
> https://gitlab.com/qemu-project/biosbits-bits
>
> The acpi test for example is maintained here in the fork:
> https://gitlab.com/qemu-project/biosbits-bits/-/raw/master/python/testacpi.py
>
> Cc: Daniel P. Berrangé <berrange@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Maydell Peter <peter.maydell@linaro.org>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Thomas Huth <thuth@redhat.com>
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Michael Tsirkin <mst@redhat.com>
> Signed-off-by: Ani Sinha <ani@anisinha.ca>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
[PATCH v6 02/10] acpi/tests/avocado/bits: add SPDX license identifiers for bios bits tests
Posted by Ani Sinha 1 year, 6 months ago
Added the SPDX license identifiers for biosbits tests.
Also added a comment on each of the test scripts to indicate that they run
from within the biosbits environment and hence are not subjected to the regular
maintanance acivities for QEMU and is excluded from the dependency management
challenges in the host testing environment.

Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 tests/avocado/acpi-bits/bits-tests/smbios.py2    | 4 ++++
 tests/avocado/acpi-bits/bits-tests/testacpi.py2  | 4 ++++
 tests/avocado/acpi-bits/bits-tests/testcpuid.py2 | 4 ++++
 3 files changed, 12 insertions(+)

diff --git a/tests/avocado/acpi-bits/bits-tests/smbios.py2 b/tests/avocado/acpi-bits/bits-tests/smbios.py2
index 9667d0542c..fc623de072 100644
--- a/tests/avocado/acpi-bits/bits-tests/smbios.py2
+++ b/tests/avocado/acpi-bits/bits-tests/smbios.py2
@@ -1,6 +1,8 @@
 # Copyright (c) 2015, Intel Corporation
 # All rights reserved.
 #
+# SPDX-License-Identifier: BSD-3-Clause
+#
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
 #
@@ -24,6 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# This script runs only from the biosbits VM.
+
 """SMBIOS/DMI module."""
 
 import bits
diff --git a/tests/avocado/acpi-bits/bits-tests/testacpi.py2 b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
index 9ec452f330..18dc818d62 100644
--- a/tests/avocado/acpi-bits/bits-tests/testacpi.py2
+++ b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
@@ -1,6 +1,8 @@
 # Copyright (c) 2015, Intel Corporation
 # All rights reserved.
 #
+# SPDX-License-Identifier: BSD-3-Clause
+#
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
 #
@@ -24,6 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# This script runs only from the biosbits VM.
+
 """Tests for ACPI"""
 
 import acpi
diff --git a/tests/avocado/acpi-bits/bits-tests/testcpuid.py2 b/tests/avocado/acpi-bits/bits-tests/testcpuid.py2
index ac55d912e1..7adefbe355 100644
--- a/tests/avocado/acpi-bits/bits-tests/testcpuid.py2
+++ b/tests/avocado/acpi-bits/bits-tests/testcpuid.py2
@@ -1,6 +1,8 @@
 # Copyright (c) 2012, Intel Corporation
 # All rights reserved.
 #
+# SPDX-License-Identifier: BSD-3-Clause
+#
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
 #
@@ -24,6 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# This script runs only from the biosbits VM.
+
 """Tests and helpers for CPUID."""
 
 import bits
-- 
2.34.1


[PATCH v6 03/10] acpi/tests/avocado/bits: disable acpi PSS tests that are failing in biosbits
Posted by Ani Sinha 1 year, 6 months ago
PSS tests in acpi test suite seems to be failing in biosbits. This is because
the test is unable to find PSS support in QEMU bios. Let us disable
them for now so that make check does not fail. We can fix the tests and
re-enable them later.

Example failure:

---- ACPI _PSS (Pstate) table conformance tests ----
[assert] _PSS must exist FAIL
  \_SB_.CPUS.C000
  No _PSS exists
Summary: 1 passed, 1 failed
---- ACPI _PSS (Pstate) runtime tests ----
[assert] _PSS must exist FAIL
  \_SB_.CPUS.C000
  No _PSS exists
Summary: 0 passed, 1 failed

Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
---
 tests/avocado/acpi-bits/bits-tests/testacpi.py2 | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/avocado/acpi-bits/bits-tests/testacpi.py2 b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
index 18dc818d62..f818a9cce6 100644
--- a/tests/avocado/acpi-bits/bits-tests/testacpi.py2
+++ b/tests/avocado/acpi-bits/bits-tests/testacpi.py2
@@ -40,8 +40,8 @@ import time
 
 def register_tests():
     testsuite.add_test("ACPI _MAT (Multiple APIC Table Entry) under Processor objects", test_mat, submenu="ACPI Tests")
-    testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests")
-    testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests")
+#    testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests")
+#    testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests")
     testsuite.add_test("ACPI DSDT (Differentiated System Description Table)", test_dsdt, submenu="ACPI Tests")
     testsuite.add_test("ACPI FACP (Fixed ACPI Description Table)", test_facp, submenu="ACPI Tests")
     testsuite.add_test("ACPI HPET (High Precision Event Timer Table)", test_hpet, submenu="ACPI Tests")
-- 
2.34.1


Re: [PATCH v6 03/10] acpi/tests/avocado/bits: disable acpi PSS tests that are failing in biosbits
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> PSS tests in acpi test suite seems to be failing in biosbits. This is because
> the test is unable to find PSS support in QEMU bios. Let us disable
> them for now so that make check does not fail. We can fix the tests and
> re-enable them later.
>
> Example failure:
>
> ---- ACPI _PSS (Pstate) table conformance tests ----
> [assert] _PSS must exist FAIL
>   \_SB_.CPUS.C000
>   No _PSS exists
> Summary: 1 passed, 1 failed
> ---- ACPI _PSS (Pstate) runtime tests ----
> [assert] _PSS must exist FAIL
>   \_SB_.CPUS.C000
>   No _PSS exists
> Summary: 0 passed, 1 failed
>
> Cc: Daniel P. Berrangé <berrange@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Maydell Peter <peter.maydell@linaro.org>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Thomas Huth <thuth@redhat.com>
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Michael Tsirkin <mst@redhat.com>
> Signed-off-by: Ani Sinha <ani@anisinha.ca>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
[PATCH v6 04/10] acpi/tests/avocado/bits: add smilatency test suite from bits in order to disable it
Posted by Ani Sinha 1 year, 6 months ago
smilatency tests does not reliably pass every time it is run from QEMU. This
change adds the test file unchanged from bits so that the next change can
disable the test.

The test has an extension .py2 just like other tests so that they are excluded
from loading by avocado framework.

Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
---
 .../acpi-bits/bits-tests/smilatency.py2       | 102 ++++++++++++++++++
 1 file changed, 102 insertions(+)
 create mode 100644 tests/avocado/acpi-bits/bits-tests/smilatency.py2

diff --git a/tests/avocado/acpi-bits/bits-tests/smilatency.py2 b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
new file mode 100644
index 0000000000..fb1b7228e3
--- /dev/null
+++ b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
@@ -0,0 +1,102 @@
+# Copyright (c) 2015, Intel Corporation
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#     * Redistributions of source code must retain the above copyright notice,
+#       this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright notice,
+#       this list of conditions and the following disclaimer in the documentation
+#       and/or other materials provided with the distribution.
+#     * Neither the name of Intel Corporation nor the names of its contributors
+#       may be used to endorse or promote products derived from this software
+#       without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""SMI latency test."""
+
+import bits
+from collections import namedtuple
+import testsuite
+import time
+import usb
+
+def register_tests():
+    testsuite.add_test("SMI latency test", smi_latency);
+    testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False);
+
+def smi_latency():
+    MSR_SMI_COUNT = 0x34
+
+    print "Warning: touching the keyboard can affect the results of this test."
+
+    tsc_per_sec = bits.tsc_per_sec()
+    tsc_per_usec = tsc_per_sec / (1000 * 1000)
+    bins = [long(tsc_per_usec * 10**i) for i in range(9)]
+    bin_descs = [
+        "0     < t <=   1us",
+        "1us   < t <=  10us",
+        "10us  < t <= 100us",
+        "100us < t <=   1ms",
+        "1ms   < t <=  10ms",
+        "10ms  < t <= 100ms",
+        "100ms < t <=   1s ",
+        "1s    < t <=  10s ",
+        "10s   < t <= 100s ",
+        "100s  < t         ",
+    ]
+
+    print "Starting test. Wait here, I will be back in 15 seconds."
+    (max_latency, smi_count_delta, bins) = bits.smi_latency(long(15 * tsc_per_sec), bins)
+    BinType = namedtuple('BinType', ("max", "total", "count", "times"))
+    bins = [BinType(*b) for b in bins]
+
+    testsuite.test("SMI latency < 150us to minimize risk of OS timeouts", max_latency / tsc_per_usec <= 150)
+    if not testsuite.show_detail():
+        return
+
+    for bin, desc in zip(bins, bin_descs):
+        if bin.count == 0:
+            continue
+        testsuite.print_detail("{}; average = {}; count = {}".format(desc, bits.format_tsc(bin.total/bin.count), bin.count))
+        deltas = (bits.format_tsc(t2 - t1) for t1,t2 in zip(bin.times, bin.times[1:]))
+        testsuite.print_detail(" Times between first few observations: {}".format(" ".join("{:>6}".format(delta) for delta in deltas)))
+
+    if smi_count_delta is not None:
+        testsuite.print_detail("{} SMI detected using MSR_SMI_COUNT (MSR {:#x})".format(smi_count_delta, MSR_SMI_COUNT))
+
+    testsuite.print_detail("Summary of impact: observed maximum latency = {}".format(bits.format_tsc(max_latency)))
+
+def test_with_usb_disabled():
+    if usb.handoff_to_os():
+        smi_latency()
+
+def average_io_smi(port, value, count):
+    def f():
+        tsc_start = bits.rdtsc()
+        bits.outb(port, value)
+        return bits.rdtsc() - tsc_start
+    counts = [f() for i in range(count)]
+    return sum(counts)/len(counts)
+
+def time_io_smi(port=0xb2, value=0, count=1000):
+    count_for_estimate = 10
+    start = time.time()
+    average_io_smi(port, value, count_for_estimate)
+    avg10 = time.time() - start
+    estimate = avg10 * count/count_for_estimate
+    if estimate > 1:
+        print "Running test, estimated time: {}s".format(int(estimate))
+    average = average_io_smi(port, value, count)
+    print "Average of {} SMIs (via outb, port={:#x}, value={:#x}): {}".format(count, port, value, bits.format_tsc(average))
-- 
2.34.1


[PATCH v6 05/10] acpi/tests/avocado/bits: add SPDX license identifiers for bios bits smilatency tests
Posted by Ani Sinha 1 year, 6 months ago
Added the SPDX license identifier for smilatency tests.
Also added a comment indicating that smilatency test is run from within the
biosbits environment/VM and hence is not subjected to QEMU build/test
environment dependency fulfilments or QEMU maintanance activities.

Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
---
 tests/avocado/acpi-bits/bits-tests/smilatency.py2 | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tests/avocado/acpi-bits/bits-tests/smilatency.py2 b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
index fb1b7228e3..d616970b31 100644
--- a/tests/avocado/acpi-bits/bits-tests/smilatency.py2
+++ b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
@@ -1,6 +1,8 @@
 # Copyright (c) 2015, Intel Corporation
 # All rights reserved.
 #
+# SPDX-License-Identifier: BSD-3-Clause
+#
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
 #
@@ -24,6 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# This script runs only from the biosbits VM.
+
 """SMI latency test."""
 
 import bits
-- 
2.34.1


Re: [PATCH v6 05/10] acpi/tests/avocado/bits: add SPDX license identifiers for bios bits smilatency tests
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> Added the SPDX license identifier for smilatency tests.
> Also added a comment indicating that smilatency test is run from within the
> biosbits environment/VM and hence is not subjected to QEMU build/test
> environment dependency fulfilments or QEMU maintanance activities.
>
> Cc: Daniel P. Berrangé <berrange@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Maydell Peter <peter.maydell@linaro.org>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Thomas Huth <thuth@redhat.com>
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Michael Tsirkin <mst@redhat.com>
> Signed-off-by: Ani Sinha <ani@anisinha.ca>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée
[PATCH v6 06/10] acpi/tests/avocado/bits: disable smilatency test since it does not pass everytime
Posted by Ani Sinha 1 year, 6 months ago
smilatency test is latency sensitive and does not pass deterministically when
run in QEMU environment under biosbits. Disable the test suite for now.

Example failure:

==== SMI latency test ====
Warning: touching the keyboard can affect the results of this test.
Starting test. Wait here, I will be back in 15 seconds.
[assert] SMI latency < 150us to minimize risk of OS timeouts FAIL
  1us   < t <=  10us; average = 1372ns; count = 10912449
   Times between first few observations:  176us 1646ns 1441ns 1450ns 1462ns
  10us  < t <= 100us; average = 16us; count = 1187
   Times between first few observations:   15ms 3148us 5856us   49ms   33ms
  100us < t <=   1ms; average = 259us; count = 8
   Times between first few observations:  111ms 2227ms 1779ms  999ms  219ms
  0 SMI detected using MSR_SMI_COUNT (MSR 0x34)
  Summary of impact: observed maximum latency = 298us
Summary: 0 passed, 1 failed

Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
---
 tests/avocado/acpi-bits/bits-tests/smilatency.py2 | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tests/avocado/acpi-bits/bits-tests/smilatency.py2 b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
index d616970b31..e907c55cc2 100644
--- a/tests/avocado/acpi-bits/bits-tests/smilatency.py2
+++ b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
@@ -37,8 +37,9 @@ import time
 import usb
 
 def register_tests():
-    testsuite.add_test("SMI latency test", smi_latency);
-    testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False);
+    pass
+    # testsuite.add_test("SMI latency test", smi_latency);
+    # testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False);
 
 def smi_latency():
     MSR_SMI_COUNT = 0x34
-- 
2.34.1


Re: [PATCH v6 06/10] acpi/tests/avocado/bits: disable smilatency test since it does not pass everytime
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> smilatency test is latency sensitive and does not pass deterministically when
> run in QEMU environment under biosbits. Disable the test suite for now.
>
> Example failure:
>
> ==== SMI latency test ====
> Warning: touching the keyboard can affect the results of this test.
> Starting test. Wait here, I will be back in 15 seconds.
> [assert] SMI latency < 150us to minimize risk of OS timeouts FAIL
>   1us   < t <=  10us; average = 1372ns; count = 10912449
>    Times between first few observations:  176us 1646ns 1441ns 1450ns 1462ns
>   10us  < t <= 100us; average = 16us; count = 1187
>    Times between first few observations:   15ms 3148us 5856us   49ms   33ms
>   100us < t <=   1ms; average = 259us; count = 8
>    Times between first few observations:  111ms 2227ms 1779ms  999ms  219ms
>   0 SMI detected using MSR_SMI_COUNT (MSR 0x34)
>   Summary of impact: observed maximum latency = 298us
> Summary: 0 passed, 1 failed

Is this because of TCG slowness? You might try running under icount for
a more consistent elapsed time for the guest.

>
> Cc: Daniel P. Berrangé <berrange@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Maydell Peter <peter.maydell@linaro.org>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Thomas Huth <thuth@redhat.com>
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Michael Tsirkin <mst@redhat.com>
> Signed-off-by: Ani Sinha <ani@anisinha.ca>
> ---
>  tests/avocado/acpi-bits/bits-tests/smilatency.py2 | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/tests/avocado/acpi-bits/bits-tests/smilatency.py2 b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
> index d616970b31..e907c55cc2 100644
> --- a/tests/avocado/acpi-bits/bits-tests/smilatency.py2
> +++ b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
> @@ -37,8 +37,9 @@ import time
>  import usb
>  
>  def register_tests():
> -    testsuite.add_test("SMI latency test", smi_latency);
> -    testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False);
> +    pass
> +    # testsuite.add_test("SMI latency test", smi_latency);
> +    # testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False);
>  
>  def smi_latency():
>      MSR_SMI_COUNT = 0x34


-- 
Alex Bennée
Re: [PATCH v6 06/10] acpi/tests/avocado/bits: disable smilatency test since it does not pass everytime
Posted by Ani Sinha 1 year, 6 months ago
On Thu, Oct 20, 2022 at 11:17 PM Alex Bennée <alex.bennee@linaro.org> wrote:
>
>
> Ani Sinha <ani@anisinha.ca> writes:
>
> > smilatency test is latency sensitive and does not pass deterministically when
> > run in QEMU environment under biosbits. Disable the test suite for now.
> >
> > Example failure:
> >
> > ==== SMI latency test ====
> > Warning: touching the keyboard can affect the results of this test.
> > Starting test. Wait here, I will be back in 15 seconds.
> > [assert] SMI latency < 150us to minimize risk of OS timeouts FAIL
> >   1us   < t <=  10us; average = 1372ns; count = 10912449
> >    Times between first few observations:  176us 1646ns 1441ns 1450ns 1462ns
> >   10us  < t <= 100us; average = 16us; count = 1187
> >    Times between first few observations:   15ms 3148us 5856us   49ms   33ms
> >   100us < t <=   1ms; average = 259us; count = 8
> >    Times between first few observations:  111ms 2227ms 1779ms  999ms  219ms
> >   0 SMI detected using MSR_SMI_COUNT (MSR 0x34)
> >   Summary of impact: observed maximum latency = 298us
> > Summary: 0 passed, 1 failed
>
> Is this because of TCG slowness? You might try running under icount for
> a more consistent elapsed time for the guest.

bang on! It does indeed pass consistently with "-icount auto" set. I
have tried 10 iterations on baremetal and on a VM environment.
I will remove smilatency test stuff from the patchset for now and add
that additional command line in v7.

>
> >
> > Cc: Daniel P. Berrangé <berrange@redhat.com>
> > Cc: Paolo Bonzini <pbonzini@redhat.com>
> > Cc: Maydell Peter <peter.maydell@linaro.org>
> > Cc: John Snow <jsnow@redhat.com>
> > Cc: Thomas Huth <thuth@redhat.com>
> > Cc: Alex Bennée <alex.bennee@linaro.org>
> > Cc: Igor Mammedov <imammedo@redhat.com>
> > Cc: Michael Tsirkin <mst@redhat.com>
> > Signed-off-by: Ani Sinha <ani@anisinha.ca>
> > ---
> >  tests/avocado/acpi-bits/bits-tests/smilatency.py2 | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/tests/avocado/acpi-bits/bits-tests/smilatency.py2 b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
> > index d616970b31..e907c55cc2 100644
> > --- a/tests/avocado/acpi-bits/bits-tests/smilatency.py2
> > +++ b/tests/avocado/acpi-bits/bits-tests/smilatency.py2
> > @@ -37,8 +37,9 @@ import time
> >  import usb
> >
> >  def register_tests():
> > -    testsuite.add_test("SMI latency test", smi_latency);
> > -    testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False);
> > +    pass
> > +    # testsuite.add_test("SMI latency test", smi_latency);
> > +    # testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False);
> >
> >  def smi_latency():
> >      MSR_SMI_COUNT = 0x34
>
>
> --
> Alex Bennée
[PATCH v6 07/10] acpi/tests/avocado/bits: add biosbits config file for running bios tests
Posted by Ani Sinha 1 year, 6 months ago
This change adds initial biosbits config file that instructs biosbits to run
bios test suits in batch mode. Additionally acpi and smbios structures are also
dumped.

Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
---
 .../avocado/acpi-bits/bits-config/bits-cfg.txt | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 tests/avocado/acpi-bits/bits-config/bits-cfg.txt

diff --git a/tests/avocado/acpi-bits/bits-config/bits-cfg.txt b/tests/avocado/acpi-bits/bits-config/bits-cfg.txt
new file mode 100644
index 0000000000..8010804453
--- /dev/null
+++ b/tests/avocado/acpi-bits/bits-config/bits-cfg.txt
@@ -0,0 +1,18 @@
+# BITS configuration file
+[bits]
+
+# To run BITS in batch mode, set batch to a list of one or more of the
+# following keywords; BITS will then run all of the requested operations, then
+# save the log file to disk.
+#
+# test: Run the full BITS testsuite.
+# acpi: Dump all ACPI structures.
+# smbios: Dump all SMBIOS structures.
+#
+# Leave batch set to an empty string to disable batch mode.
+# batch =
+
+# Uncomment the following to run all available batch operations
+# please take a look at boot/python/init.py in bits zip file
+# to see how these options are parsed and used.
+batch = test acpi smbios
-- 
2.34.1


Re: [PATCH v6 07/10] acpi/tests/avocado/bits: add biosbits config file for running bios tests
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> This change adds initial biosbits config file that instructs biosbits to run
> bios test suits in batch mode. Additionally acpi and smbios structures are also
> dumped.

Is it possible to split this into different avocado tests or would it
require building multiple isos?

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>


>
> Cc: Daniel P. Berrangé <berrange@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Maydell Peter <peter.maydell@linaro.org>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Thomas Huth <thuth@redhat.com>
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Michael Tsirkin <mst@redhat.com>
> Signed-off-by: Ani Sinha <ani@anisinha.ca>
> ---
>  .../avocado/acpi-bits/bits-config/bits-cfg.txt | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>  create mode 100644 tests/avocado/acpi-bits/bits-config/bits-cfg.txt
>
> diff --git a/tests/avocado/acpi-bits/bits-config/bits-cfg.txt
> b/tests/avocado/acpi-bits/bits-config/bits-cfg.txt
> new file mode 100644
> index 0000000000..8010804453
> --- /dev/null
> +++ b/tests/avocado/acpi-bits/bits-config/bits-cfg.txt
> @@ -0,0 +1,18 @@
> +# BITS configuration file
> +[bits]
> +
> +# To run BITS in batch mode, set batch to a list of one or more of the
> +# following keywords; BITS will then run all of the requested operations, then
> +# save the log file to disk.
> +#
> +# test: Run the full BITS testsuite.
> +# acpi: Dump all ACPI structures.
> +# smbios: Dump all SMBIOS structures.
> +#
> +# Leave batch set to an empty string to disable batch mode.
> +# batch =
> +
> +# Uncomment the following to run all available batch operations
> +# please take a look at boot/python/init.py in bits zip file
> +# to see how these options are parsed and used.
> +batch = test acpi smbios


-- 
Alex Bennée
Re: [PATCH v6 07/10] acpi/tests/avocado/bits: add biosbits config file for running bios tests
Posted by Ani Sinha 1 year, 6 months ago
On Thu, Oct 20, 2022 at 11:18 PM Alex Bennée <alex.bennee@linaro.org> wrote:
>
>
> Ani Sinha <ani@anisinha.ca> writes:
>
> > This change adds initial biosbits config file that instructs biosbits to run
> > bios test suits in batch mode. Additionally acpi and smbios structures are also
> > dumped.
>
> Is it possible to split this into different avocado tests or would it
> require building multiple isos?

Bits takes this configuration to decide which tests it should run.
Currently, this config is not modified from the original bits config
file upstream.
It might be possible to use different config files for different bits
tests as you suggested and generate a separate iso for each of the
tests with their corresponding config file (and then use that iso for
the corresponding test).
However, I would like to leave this as a future exercise. Currently,
it's simple enough in my opinion to have just one config file and run
all the tests in batch mode. I do not see a compelling reason to add
the extra complication of generating an iso for every sub-test yet.

>
> Otherwise:
>
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
>
>
> >
> > Cc: Daniel P. Berrangé <berrange@redhat.com>
> > Cc: Paolo Bonzini <pbonzini@redhat.com>
> > Cc: Maydell Peter <peter.maydell@linaro.org>
> > Cc: John Snow <jsnow@redhat.com>
> > Cc: Thomas Huth <thuth@redhat.com>
> > Cc: Alex Bennée <alex.bennee@linaro.org>
> > Cc: Igor Mammedov <imammedo@redhat.com>
> > Cc: Michael Tsirkin <mst@redhat.com>
> > Signed-off-by: Ani Sinha <ani@anisinha.ca>
> > ---
> >  .../avocado/acpi-bits/bits-config/bits-cfg.txt | 18 ++++++++++++++++++
> >  1 file changed, 18 insertions(+)
> >  create mode 100644 tests/avocado/acpi-bits/bits-config/bits-cfg.txt
> >
> > diff --git a/tests/avocado/acpi-bits/bits-config/bits-cfg.txt
> > b/tests/avocado/acpi-bits/bits-config/bits-cfg.txt
> > new file mode 100644
> > index 0000000000..8010804453
> > --- /dev/null
> > +++ b/tests/avocado/acpi-bits/bits-config/bits-cfg.txt
> > @@ -0,0 +1,18 @@
> > +# BITS configuration file
> > +[bits]
> > +
> > +# To run BITS in batch mode, set batch to a list of one or more of the
> > +# following keywords; BITS will then run all of the requested operations, then
> > +# save the log file to disk.
> > +#
> > +# test: Run the full BITS testsuite.
> > +# acpi: Dump all ACPI structures.
> > +# smbios: Dump all SMBIOS structures.
> > +#
> > +# Leave batch set to an empty string to disable batch mode.
> > +# batch =
> > +
> > +# Uncomment the following to run all available batch operations
> > +# please take a look at boot/python/init.py in bits zip file
> > +# to see how these options are parsed and used.
> > +batch = test acpi smbios
>
>
> --
> Alex Bennée
[PATCH v6 08/10] acpi/tests/avocado/bits: add acpi and smbios avocado tests that uses biosbits
Posted by Ani Sinha 1 year, 6 months ago
This introduces QEMU acpi/smbios biosbits avocado test which is run
from within the python virtual environment. When the bits tests are run, bits
binaries are downloaded from an external repo/location, bios bits iso is
regenerated containing the acpi/smbios bits tests that are maintained as a part
of the QEMU source under tests/avocado/acpi-bits/bits-test . When the VM is
spawned with the iso, it runs the tests in batch mode and the results are pushed
out from the VM to the test machine where they are analyzed by this script and
pass/fail results are reported.

Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
---
 tests/avocado/acpi-bits.py | 389 +++++++++++++++++++++++++++++++++++++
 1 file changed, 389 insertions(+)
 create mode 100644 tests/avocado/acpi-bits.py

diff --git a/tests/avocado/acpi-bits.py b/tests/avocado/acpi-bits.py
new file mode 100644
index 0000000000..14d453e3ad
--- /dev/null
+++ b/tests/avocado/acpi-bits.py
@@ -0,0 +1,389 @@
+#!/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/>.
+#
+#
+# Author:
+#  Ani Sinha <ani@anisinha.ca>
+
+# pylint: disable=invalid-name
+# pylint: disable=consider-using-f-string
+
+"""
+This is QEMU ACPI/SMBIOS avocado tests using biosbits.
+Biosbits is available originally at https://biosbits.org/.
+This test uses a fork of the upstream bits and has numerous fixes
+including an upgraded acpica. The fork is located here:
+https://gitlab.com/qemu-project/biosbits-bits .
+"""
+
+import logging
+import os
+import platform
+import re
+import shutil
+import subprocess
+import tarfile
+import tempfile
+import time
+import zipfile
+from typing import (
+    List,
+    Optional,
+    Sequence,
+)
+from qemu.machine import QEMUMachine
+from avocado import skipIf
+from avocado_qemu import QemuBaseTest
+
+deps = ["xorriso"] # dependent tools needed in the test setup/box.
+supported_platforms = ['x86_64'] # supported test platforms.
+
+def _print_log(log):
+    print('\nlogs from biosbits follows:')
+    print('==========================================\n')
+    print(log)
+    print('==========================================\n')
+
+def which(tool):
+    """ looks up the full path for @tool, returns None if not found
+        or if @tool does not have executable permissions.
+    """
+    paths=os.getenv('PATH')
+    for p in paths.split(os.path.pathsep):
+        p = os.path.join(p, tool)
+        if os.path.exists(p) and os.access(p, os.X_OK):
+            return p
+    return None
+
+def missing_deps():
+    """ returns True if any of the test dependent tools are absent.
+    """
+    for dep in deps:
+        if which(dep) is None:
+            return True
+    return False
+
+def supported_platform():
+    """ checks if the test is running on a supported platform.
+    """
+    return platform.machine() in supported_platforms
+
+class QEMUBitsMachine(QEMUMachine): # pylint: disable=too-few-public-methods
+    """
+    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
+
+@skipIf(not supported_platform() or missing_deps() or os.getenv('GITLAB_CI'),
+        'incorrect platform or dependencies (%s) not installed ' \
+        'or running on GitLab' % ','.join(deps))
+class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
+    """
+    ACPI and SMBIOS tests using biosbits.
+
+    :avocado: tags=arch:x86_64
+    :avocado: tags=acpi
+
+    """
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self._vm = None
+        self._workDir = None
+        self._baseDir = None
+
+        # following are some standard configuration constants
+        self._bitsInternalVer = 2020
+        self._bitsCommitHash = 'b48b88ff' # commit hash must match
+                                          # the artifact tag below
+        self._bitsTag = "qemu-bits-10182022" # this is the latest bits
+                                             # release as of today.
+        self._bitsArtSHA1Hash = 'b04790ac9b99b5662d0416392c73b97580641fe5'
+        self._bitsArtURL = ("https://gitlab.com/qemu-project/"
+                            "biosbits-bits/-/jobs/artifacts/%s/"
+                            "download?job=qemu-bits-build" %self._bitsTag)
+        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'
+        bits_config_dir = os.path.join(self._baseDir, 'acpi-bits',
+                                       'bits-config')
+        target_config_dir = os.path.join(self._workDir,
+                                         'bits-%d' %self._bitsInternalVer,
+                                         'boot')
+        self.assertTrue(os.path.exists(bits_config_dir))
+        self.assertTrue(os.path.exists(target_config_dir))
+        self.assertTrue(os.access(os.path.join(bits_config_dir,
+                                               config_file), os.R_OK))
+        shutil.copy2(os.path.join(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. """
+
+        bits_test_dir = os.path.join(self._baseDir, 'acpi-bits',
+                                     'bits-tests')
+        target_test_dir = os.path.join(self._workDir,
+                                       'bits-%d' %self._bitsInternalVer,
+                                       'boot', 'python')
+
+        self.assertTrue(os.path.exists(bits_test_dir))
+        self.assertTrue(os.path.exists(target_test_dir))
+
+        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.
+                newfilename = os.path.splitext(filename)[0] + '.py'
+                shutil.copy2(os.path.join(bits_test_dir, filename),
+                             os.path.join(target_test_dir, newfilename))
+                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', encoding='utf-8') 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', encoding='utf-8') 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._bitsInternalVer)
+        iso_file = os.path.join(self._workDir,
+                                'bits-%d.iso' %self._bitsInternalVer)
+        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], stderr=subprocess.STDOUT)
+            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): # pylint: disable=arguments-differ
+        super().setUp('qemu-system-')
+
+        self._baseDir = os.getenv('AVOCADO_TEST_BASEDIR')
+
+        # 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')
+        logging.info('working dir: %s', self._workDir)
+
+        prebuiltDir = os.path.join(self._workDir, 'prebuilt')
+        if not os.path.isdir(prebuiltDir):
+            os.mkdir(prebuiltDir, mode=0o775)
+
+        bits_zip_file = os.path.join(prebuiltDir, 'bits-%d-%s.zip'
+                                     %(self._bitsInternalVer,
+                                       self._bitsCommitHash))
+        grub_tar_file = os.path.join(prebuiltDir,
+                                     'bits-%d-%s-grub.tar.gz'
+                                     %(self._bitsInternalVer,
+                                       self._bitsCommitHash))
+
+        bitsLocalArtLoc = self.fetch_asset(self._bitsArtURL,
+                                           asset_hash=self._bitsArtSHA1Hash)
+        logging.info("downloaded bits artifacts to %s", bitsLocalArtLoc)
+
+        # extract the bits artifact in the temp working directory
+        with zipfile.ZipFile(bitsLocalArtLoc, 'r') as zref:
+            zref.extractall(prebuiltDir)
+
+        # extract the bits software in the temp working directory
+        with zipfile.ZipFile(bits_zip_file, 'r') as zref:
+            zref.extractall(self._workDir)
+
+        with tarfile.open(grub_tar_file, 'r', encoding='utf-8') as tarball:
+            tarball.extractall(self._workDir)
+
+        self.copy_test_scripts()
+        self.copy_bits_config()
+        self.generate_bits_iso()
+
+    def parse_log(self):
+        """parse the log generated by running bits tests and
+           check for failures.
+        """
+        debugconf = os.path.join(self._workDir, self._debugcon_log)
+        log = ""
+        with open(debugconf, 'r', encoding='utf-8') as filehandle:
+            log = filehandle.read()
+
+        matchiter = re.finditer(r'(.*Summary: )(\d+ passed), (\d+ failed).*',
+                                log)
+        for match in matchiter:
+            # verify that no test cases failed.
+            try:
+                self.assertEqual(match.group(3).split()[0], '0',
+                                 'Some bits tests seems to have failed. ' \
+                                 'Please check the test logs for more info.')
+            except AssertionError as e:
+                _print_log(log)
+                raise e
+            else:
+                if os.getenv('V'):
+                    _print_log(log)
+
+    def tearDown(self):
+        """
+           Lets do some cleanups.
+        """
+        if self._vm:
+            self.assertFalse(not self._vm.is_running)
+        logging.info('removing the work directory %s', self._workDir)
+        shutil.rmtree(self._workDir)
+        super().tearDown()
+
+    def test_acpi_smbios_bits(self):
+        """The main test case implementaion."""
+
+        iso_file = os.path.join(self._workDir,
+                                'bits-%d.iso' %self._bitsInternalVer)
+
+        self.assertTrue(os.access(iso_file, os.R_OK))
+
+        self._vm = QEMUBitsMachine(binary=self.qemu_bin,
+                                   base_temp_dir=self._workDir,
+                                   debugcon_log=self._debugcon_log,
+                                   debugcon_addr=self._debugcon_addr)
+
+        self._vm.add_args('-cdrom', '%s' %iso_file)
+
+        args = " ".join(str(arg) for arg in self._vm.base_args()) + \
+            " " + " ".join(str(arg) for arg in self._vm.args)
+
+        logging.info("launching QEMU vm with the following arguments: %s",
+                     args)
+
+        self._vm.launch()
+        # biosbits has been configured to run all the specified test suites
+        # in batch mode and then automatically initiate a vm shutdown.
+        # sleep for maximum of one minute
+        max_sleep_time = time.monotonic() + 60
+        while self._vm.is_running() and time.monotonic() < max_sleep_time:
+            time.sleep(1)
+
+        self.assertFalse(time.monotonic() > max_sleep_time,
+                         'The VM seems to have failed to shutdown in time')
+
+        self.parse_log()
-- 
2.34.1


Re: [PATCH v6 08/10] acpi/tests/avocado/bits: add acpi and smbios avocado tests that uses biosbits
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> This introduces QEMU acpi/smbios biosbits avocado test which is run
> from within the python virtual environment. When the bits tests are run, bits
> binaries are downloaded from an external repo/location, bios bits iso is
> regenerated containing the acpi/smbios bits tests that are maintained as a part
> of the QEMU source under tests/avocado/acpi-bits/bits-test . When the VM is
> spawned with the iso, it runs the tests in batch mode and the results are pushed
> out from the VM to the test machine where they are analyzed by this script and
> pass/fail results are reported.
>
> Cc: Daniel P. Berrangé <berrange@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Maydell Peter <peter.maydell@linaro.org>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Thomas Huth <thuth@redhat.com>
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Michael Tsirkin <mst@redhat.com>
> Signed-off-by: Ani Sinha <ani@anisinha.ca>
> ---
>  tests/avocado/acpi-bits.py | 389 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 389 insertions(+)
>  create mode 100644 tests/avocado/acpi-bits.py
>
> diff --git a/tests/avocado/acpi-bits.py b/tests/avocado/acpi-bits.py
> new file mode 100644
> index 0000000000..14d453e3ad
> --- /dev/null
> +++ b/tests/avocado/acpi-bits.py
> @@ -0,0 +1,389 @@
> +#!/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/>.
> +#
> +#
> +# Author:
> +#  Ani Sinha <ani@anisinha.ca>
> +
> +# pylint: disable=invalid-name
> +# pylint: disable=consider-using-f-string
> +
> +"""
> +This is QEMU ACPI/SMBIOS avocado tests using biosbits.
> +Biosbits is available originally at https://biosbits.org/.
> +This test uses a fork of the upstream bits and has numerous fixes
> +including an upgraded acpica. The fork is located here:
> +https://gitlab.com/qemu-project/biosbits-bits .
> +"""
> +
> +import logging
> +import os
> +import platform
> +import re
> +import shutil
> +import subprocess
> +import tarfile
> +import tempfile
> +import time
> +import zipfile
> +from typing import (
> +    List,
> +    Optional,
> +    Sequence,
> +)
> +from qemu.machine import QEMUMachine
> +from avocado import skipIf
> +from avocado_qemu import QemuBaseTest
> +
> +deps = ["xorriso"] # dependent tools needed in the test setup/box.
> +supported_platforms = ['x86_64'] # supported test platforms.
> +
> +def _print_log(log):
> +    print('\nlogs from biosbits follows:')
> +    print('==========================================\n')
> +    print(log)
> +    print('==========================================\n')

Please log to avocado itself using the logger() functions otherwise this
ends up polluting stdout rather than going into the test log.

> +
> +def which(tool):
> +    """ looks up the full path for @tool, returns None if not found
> +        or if @tool does not have executable permissions.
> +    """
> +    paths=os.getenv('PATH')
> +    for p in paths.split(os.path.pathsep):
> +        p = os.path.join(p, tool)
> +        if os.path.exists(p) and os.access(p, os.X_OK):
> +            return p
> +    return None
> +
> +def missing_deps():
> +    """ returns True if any of the test dependent tools are absent.
> +    """
> +    for dep in deps:
> +        if which(dep) is None:
> +            return True
> +    return False
> +
> +def supported_platform():
> +    """ checks if the test is running on a supported platform.
> +    """
> +    return platform.machine() in supported_platforms
> +
> +class QEMUBitsMachine(QEMUMachine): # pylint: disable=too-few-public-methods
> +    """
> +    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
> +
> +@skipIf(not supported_platform() or missing_deps() or os.getenv('GITLAB_CI'),
> +        'incorrect platform or dependencies (%s) not installed ' \
> +        'or running on GitLab' % ','.join(deps))
> +class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes
> +    """
> +    ACPI and SMBIOS tests using biosbits.
> +
> +    :avocado: tags=arch:x86_64
> +    :avocado: tags=acpi
> +
> +    """
> +    def __init__(self, *args, **kwargs):
> +        super().__init__(*args, **kwargs)
> +        self._vm = None
> +        self._workDir = None
> +        self._baseDir = None
> +
> +        # following are some standard configuration constants
> +        self._bitsInternalVer = 2020
> +        self._bitsCommitHash = 'b48b88ff' # commit hash must match
> +                                          # the artifact tag below
> +        self._bitsTag = "qemu-bits-10182022" # this is the latest bits
> +                                             # release as of today.
> +        self._bitsArtSHA1Hash = 'b04790ac9b99b5662d0416392c73b97580641fe5'
> +        self._bitsArtURL = ("https://gitlab.com/qemu-project/"
> +                            "biosbits-bits/-/jobs/artifacts/%s/"
> +                            "download?job=qemu-bits-build" %self._bitsTag)
> +        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'
> +        bits_config_dir = os.path.join(self._baseDir, 'acpi-bits',
> +                                       'bits-config')
> +        target_config_dir = os.path.join(self._workDir,
> +                                         'bits-%d' %self._bitsInternalVer,
> +                                         'boot')
> +        self.assertTrue(os.path.exists(bits_config_dir))
> +        self.assertTrue(os.path.exists(target_config_dir))
> +        self.assertTrue(os.access(os.path.join(bits_config_dir,
> +                                               config_file), os.R_OK))
> +        shutil.copy2(os.path.join(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. """
> +
> +        bits_test_dir = os.path.join(self._baseDir, 'acpi-bits',
> +                                     'bits-tests')
> +        target_test_dir = os.path.join(self._workDir,
> +                                       'bits-%d' %self._bitsInternalVer,
> +                                       'boot', 'python')
> +
> +        self.assertTrue(os.path.exists(bits_test_dir))
> +        self.assertTrue(os.path.exists(target_test_dir))
> +
> +        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.
> +                newfilename = os.path.splitext(filename)[0] + '.py'
> +                shutil.copy2(os.path.join(bits_test_dir, filename),
> +                             os.path.join(target_test_dir, newfilename))
> +                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', encoding='utf-8') 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', encoding='utf-8') 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._bitsInternalVer)
> +        iso_file = os.path.join(self._workDir,
> +                                'bits-%d.iso' %self._bitsInternalVer)
> +        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], stderr=subprocess.STDOUT)
> +            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): # pylint: disable=arguments-differ
> +        super().setUp('qemu-system-')
> +
> +        self._baseDir = os.getenv('AVOCADO_TEST_BASEDIR')
> +
> +        # 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')
> +        logging.info('working dir: %s', self._workDir)
> +
> +        prebuiltDir = os.path.join(self._workDir, 'prebuilt')
> +        if not os.path.isdir(prebuiltDir):
> +            os.mkdir(prebuiltDir, mode=0o775)
> +
> +        bits_zip_file = os.path.join(prebuiltDir, 'bits-%d-%s.zip'
> +                                     %(self._bitsInternalVer,
> +                                       self._bitsCommitHash))
> +        grub_tar_file = os.path.join(prebuiltDir,
> +                                     'bits-%d-%s-grub.tar.gz'
> +                                     %(self._bitsInternalVer,
> +                                       self._bitsCommitHash))
> +
> +        bitsLocalArtLoc = self.fetch_asset(self._bitsArtURL,
> +                                           asset_hash=self._bitsArtSHA1Hash)
> +        logging.info("downloaded bits artifacts to %s", bitsLocalArtLoc)
> +
> +        # extract the bits artifact in the temp working directory
> +        with zipfile.ZipFile(bitsLocalArtLoc, 'r') as zref:
> +            zref.extractall(prebuiltDir)
> +
> +        # extract the bits software in the temp working directory
> +        with zipfile.ZipFile(bits_zip_file, 'r') as zref:
> +            zref.extractall(self._workDir)
> +
> +        with tarfile.open(grub_tar_file, 'r', encoding='utf-8') as tarball:
> +            tarball.extractall(self._workDir)
> +
> +        self.copy_test_scripts()
> +        self.copy_bits_config()
> +        self.generate_bits_iso()
> +
> +    def parse_log(self):
> +        """parse the log generated by running bits tests and
> +           check for failures.
> +        """
> +        debugconf = os.path.join(self._workDir, self._debugcon_log)
> +        log = ""
> +        with open(debugconf, 'r', encoding='utf-8') as filehandle:
> +            log = filehandle.read()
> +
> +        matchiter = re.finditer(r'(.*Summary: )(\d+ passed), (\d+ failed).*',
> +                                log)
> +        for match in matchiter:
> +            # verify that no test cases failed.
> +            try:
> +                self.assertEqual(match.group(3).split()[0], '0',
> +                                 'Some bits tests seems to have failed. ' \
> +                                 'Please check the test logs for more info.')
> +            except AssertionError as e:
> +                _print_log(log)
> +                raise e
> +            else:
> +                if os.getenv('V'):
> +                    _print_log(log)

logging() and logging.debug can be used here.

> +
> +    def tearDown(self):
> +        """
> +           Lets do some cleanups.
> +        """
> +        if self._vm:
> +            self.assertFalse(not self._vm.is_running)
> +        logging.info('removing the work directory %s', self._workDir)
> +        shutil.rmtree(self._workDir)
> +        super().tearDown()
> +
> +    def test_acpi_smbios_bits(self):
> +        """The main test case implementaion."""
> +
> +        iso_file = os.path.join(self._workDir,
> +                                'bits-%d.iso' %self._bitsInternalVer)
> +
> +        self.assertTrue(os.access(iso_file, os.R_OK))
> +
> +        self._vm = QEMUBitsMachine(binary=self.qemu_bin,
> +                                   base_temp_dir=self._workDir,
> +                                   debugcon_log=self._debugcon_log,
> +                                   debugcon_addr=self._debugcon_addr)
> +
> +        self._vm.add_args('-cdrom', '%s' %iso_file)
> +
> +        args = " ".join(str(arg) for arg in self._vm.base_args()) + \
> +            " " + " ".join(str(arg) for arg in self._vm.args)
> +
> +        logging.info("launching QEMU vm with the following arguments: %s",
> +                     args)
> +
> +        self._vm.launch()
> +        # biosbits has been configured to run all the specified test suites
> +        # in batch mode and then automatically initiate a vm shutdown.
> +        # sleep for maximum of one minute
> +        max_sleep_time = time.monotonic() + 60
> +        while self._vm.is_running() and time.monotonic() < max_sleep_time:
> +            time.sleep(1)
> +
> +        self.assertFalse(time.monotonic() > max_sleep_time,
> +                         'The VM seems to have failed to shutdown in time')
> +
> +        self.parse_log()


-- 
Alex Bennée
[PATCH v6 09/10] acpi/tests/avocado/bits/doc: add a doc file to describe the acpi bits test
Posted by Ani Sinha 1 year, 6 months ago
A doc file is added under docs/devel that describes the purpose of the various
test files and gives guidance to developers on where and how to make changes.

Cc: Daniel P. Berrange" <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
---
 docs/devel/acpi-bits.rst | 148 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 148 insertions(+)
 create mode 100644 docs/devel/acpi-bits.rst

diff --git a/docs/devel/acpi-bits.rst b/docs/devel/acpi-bits.rst
new file mode 100644
index 0000000000..06d50b76d9
--- /dev/null
+++ b/docs/devel/acpi-bits.rst
@@ -0,0 +1,148 @@
+=============================================================================
+ACPI/SMBIOS AVOCADO TESTS USING BIOSBITS
+=============================================================================
+
+Biosbits is a software written by Josh Triplett that can be downloaded
+from https://biosbits.org/. The github codebase can be found here:
+https://github.com/biosbits/bits/tree/master. It is a software that executes
+the bios components such as acpi and smbios tables directly through acpica
+bios interpreter (a freely available C based library written by Intel,
+downloadable from https://acpica.org/ and is included with biosbits) without an
+operating system getting involved in between.
+There are several advantages to directly testing the bios in a real physical
+machine or VM as opposed to indirectly discovering bios issues through the
+operating system. For one thing, the OSes tend to hide bios problems from the
+end user. The other is that we have more control of what we wanted to test
+and how by directly using acpica interpreter on top of the bios on a running
+system. More details on the inspiration for developing biosbits and its real
+life uses can be found in (a) and (b).
+This directory contains tests written in python using avocado framework that
+exercizes the QEMU bios components using biosbits and reports test failures.
+For QEMU, we maintain a fork of bios bits in gitlab along with all the
+dependent submodules:
+https://gitlab.com/qemu-project/biosbits-bits
+This fork contains numerous fixes, a newer acpica and changes specific to
+running this avocado QEMU tests using bits. The author of this document
+is the sole maintainer of the QEMU fork of bios bits repo.
+
+Under the directory ``tests/avocado/``, ``acpi-bits.py`` is a QEMU avocado
+test that drives all this.
+
+A brief description of the various test files follows.
+
+Under ``tests/avocado/`` as the root we have:
+
+::
+
+   ├── acpi-bits
+   │ ├── bits-config
+   │ │ └── bits-cfg.txt
+   │ ├── bits-tests
+   │ │ ├── smbios.py2
+   │ │ ├── smilatency.py2
+   │ │ ├── testacpi.py2
+   │ │ └── testcpuid.py2
+   │ └── README
+   ├── acpi-bits.py
+
+* ``tests/avocado``:
+
+   ``acpi-bits.py``:
+   This is the main python avocado test script that generates a
+   biosbits iso. It then spawns a QEMU VM with it, collects the log and reports
+   test failures. This is the script one would be interested in if they wanted
+   to add or change some component of the log parsing, add a new command line
+   to alter how QEMU is spawned etc. Test writers typically would not need to
+   modify this script unless they wanted to enhance or change the log parsing
+   for their tests. Following environment variables are used in this test:
+
+   **V=1** : This enables verbose mode for the test. It dumps the entire log
+   from bios bits and also more details in case failure happens. It is
+   useful for debugging the test failures or tests themselves.
+
+   In order to run this test, please perform the following steps from the QEMU
+   build directory:
+   ::
+
+     $ make check-venv (needed only the first time to create the venv)
+     $ ./tests/venv/bin/avocado run -t acpi tests/avocado
+
+   The above will run all acpi avocado tests including this one.
+   In order to run the individual tests, perform the following:
+   ::
+
+     $ ./tests/venv/bin/avocado run tests/avocado/acpi-bits.py --tap -
+
+   The above will produce output in tap format. You can omit "--tap -" in the
+   end and it will produce output like the following:
+   ::
+
+      $ ./tests/venv/bin/avocado run tests/avocado/acpi-bits.py
+      Fetching asset from tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
+      JOB ID     : eab225724da7b64c012c65705dc2fa14ab1defef
+      JOB LOG    : /home/anisinha/avocado/job-results/job-2022-10-10T17.58-eab2257/job.log
+      (1/1) tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits: PASS (33.09 s)
+      RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
+      JOB TIME   : 39.22 s
+
+   You can inspect the log file for more information about the run or in order
+   to diagnoze issues. If you pass V=1 in the environment, more diagnostic logs
+   would be found in the test log.
+
+* ``tests/avocado/acpi-bits/bits-config``:
+
+   This location contains biosbits configuration files that determine how the
+   software runs the tests.
+
+   ``bits-config.txt``:
+   This is the biosbits config file that determines what tests
+   or actions are performed by bits. The description of the config options are
+   provided in the file itself.
+
+* ``tests/avocado/acpi-bits/bits-tests``:
+
+   This directory contains biosbits python based tests that are run from within
+   the biosbits environment in the spawned VM. New additions of test cases can
+   be made in the appropriate test file. For example, new acpi tests can go
+   into testacpi.py2 and one would call testsuite.add_test() to register the new
+   test so that it gets executed as a part of the ACPI tests.
+   It might be occasionally necessary to disable some subtests or add a new
+   test that belongs to a test suite not already present in this directory. To
+   do this, please clone the bits source from
+   https://gitlab.com/qemu-project/biosbits-bits/-/tree/qemu-bits.
+   Note that this is the "qemu-bits" branch and not the "bits" branch of the
+   repository. "qemu-bits" is the branch where we have made all the QEMU
+   specific enhancements and we must use the source from this branch only.
+   Copy the test suite/script that needs modification (addition of new tests
+   or disabling them) from python directory into this directory. For
+   example, in order to change cpuid related tests, copy the following
+   file into this directory and rename it with .py2 extension:
+   https://gitlab.com/qemu-project/biosbits-bits/-/blob/qemu-bits/python/testcpuid.py
+   Then make your additions and changes here. Therefore, the steps are:
+
+       (a) Copy unmodified test script to this directory from bits source.
+       (b) Add a SPDX license header.
+       (c) Perform modifications to the test.
+
+   Commits (a), (b) and (c) should go under separate commits so that the original
+   test script and the changes we have made are separated and clear.
+
+   The test framework will then use your modified test script to run the test.
+   No further changes would be needed. Please check the logs to make sure that
+   appropriate changes have taken effect.
+
+   The tests have an extension .py2 in order to indicate that:
+
+   (a) They are python2.7 based scripts and not python 3 scripts.
+   (b) They are run from within the bios bits VM and is not subjected to QEMU
+       build/test python script maintainance and dependency resolutions.
+   (c) They need not be loaded by avocado framework when running tests.
+
+
+Author: Ani Sinha <ani@anisinha.ca>
+
+References:
+-----------
+(a) https://blog.linuxplumbersconf.org/2011/ocw/system/presentations/867/original/bits.pdf
+(b) https://www.youtube.com/watch?v=36QIepyUuhg
+
-- 
2.34.1


Re: [PATCH v6 09/10] acpi/tests/avocado/bits/doc: add a doc file to describe the acpi bits test
Posted by Alex Bennée 1 year, 6 months ago
Ani Sinha <ani@anisinha.ca> writes:

> A doc file is added under docs/devel that describes the purpose of the various
> test files and gives guidance to developers on where and how to make changes.
>
> Cc: Daniel P. Berrange" <berrange@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Maydell Peter <peter.maydell@linaro.org>
> Cc: John Snow <jsnow@redhat.com>
> Cc: Thomas Huth <thuth@redhat.com>
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Michael Tsirkin <mst@redhat.com>
> Signed-off-by: Ani Sinha <ani@anisinha.ca>
> ---
>  docs/devel/acpi-bits.rst | 148 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 148 insertions(+)
>  create mode 100644 docs/devel/acpi-bits.rst

You will also need to add it to the index-build.rst:

    testing
+   acpi-bits
    qtest

Other wise the build will complains.

>
> diff --git a/docs/devel/acpi-bits.rst b/docs/devel/acpi-bits.rst
> new file mode 100644
> index 0000000000..06d50b76d9
> --- /dev/null
> +++ b/docs/devel/acpi-bits.rst
> @@ -0,0 +1,148 @@
> +=============================================================================
> +ACPI/SMBIOS AVOCADO TESTS USING BIOSBITS

No need to use all caps here.

> +=============================================================================
> +
> +Biosbits is a software written by Josh Triplett that can be downloaded
> +from https://biosbits.org/. The github codebase can be found here:
> +https://github.com/biosbits/bits/tree/master.

`here <https://github.com/biosbits/bits/tree/master>`__.


> It is a software that executes
> +the bios components such as acpi and smbios tables directly through acpica
> +bios interpreter (a freely available C based library written by Intel,
> +downloadable from https://acpica.org/ and is included with biosbits) without an
> +operating system getting involved in between.
> +There are several advantages to directly testing the bios in a real physical
> +machine or VM as opposed to indirectly discovering bios issues through the
> +operating system. For one thing, the OSes tend to hide bios problems from the
> +end user. The other is that we have more control of what we wanted to test
> +and how by directly using acpica interpreter on top of the bios on a running
> +system. More details on the inspiration for developing biosbits and its real
> +life uses can be found in (a) and (b).

[#a]_ and [#b]_ for proper footnotes

> +This directory contains tests written in python using avocado framework that
> +exercizes the QEMU bios components using biosbits and reports test
> failures.

exercises

> +For QEMU, we maintain a fork of bios bits in gitlab along with all the
> +dependent submodules:
> +https://gitlab.com/qemu-project/biosbits-bits
> +This fork contains numerous fixes, a newer acpica and changes specific to
> +running this avocado QEMU tests using bits. The author of this document
> +is the sole maintainer of the QEMU fork of bios bits repo.
> +
> +Under the directory ``tests/avocado/``, ``acpi-bits.py`` is a QEMU avocado
> +test that drives all this.
> +
> +A brief description of the various test files follows.
> +
> +Under ``tests/avocado/`` as the root we have:
> +
> +::
> +
> +   ├── acpi-bits
> +   │ ├── bits-config
> +   │ │ └── bits-cfg.txt
> +   │ ├── bits-tests
> +   │ │ ├── smbios.py2
> +   │ │ ├── smilatency.py2
> +   │ │ ├── testacpi.py2
> +   │ │ └── testcpuid.py2
> +   │ └── README
> +   ├── acpi-bits.py
> +
> +* ``tests/avocado``:
> +
> +   ``acpi-bits.py``:
> +   This is the main python avocado test script that generates a
> +   biosbits iso. It then spawns a QEMU VM with it, collects the log and reports
> +   test failures. This is the script one would be interested in if they wanted
> +   to add or change some component of the log parsing, add a new command line
> +   to alter how QEMU is spawned etc. Test writers typically would not need to
> +   modify this script unless they wanted to enhance or change the log parsing
> +   for their tests. Following environment variables are used in this test:
> +
> +   **V=1** : This enables verbose mode for the test. It dumps the entire log
> +   from bios bits and also more details in case failure happens. It is
> +   useful for debugging the test failures or tests themselves.

As there is only one environment variable you could just describe it
inline, e.g.:

   Test writers typically would not need to modify this script unless
   they wanted to enhance or change the log parsing for their tests. To
   enable debugging you can set the ``V=1`` environment variable. This
   will cause the test to dump the entire log from bios bits and also
   more details in case failure happens.

> +
> +   In order to run this test, please perform the following steps from the QEMU
> +   build directory:
> +   ::
> +
> +     $ make check-venv (needed only the first time to create the venv)
> +     $ ./tests/venv/bin/avocado run -t acpi tests/avocado
> +
> +   The above will run all acpi avocado tests including this one.
> +   In order to run the individual tests, perform the following:
> +   ::
> +
> +     $ ./tests/venv/bin/avocado run tests/avocado/acpi-bits.py --tap -
> +
> +   The above will produce output in tap format. You can omit "--tap -" in the
> +   end and it will produce output like the following:
> +   ::
> +
> +      $ ./tests/venv/bin/avocado run tests/avocado/acpi-bits.py
> +      Fetching asset from tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
> +      JOB ID     : eab225724da7b64c012c65705dc2fa14ab1defef
> +      JOB LOG    : /home/anisinha/avocado/job-results/job-2022-10-10T17.58-eab2257/job.log
> +      (1/1) tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits: PASS (33.09 s)
> +      RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
> +      JOB TIME   : 39.22 s
> +
> +   You can inspect the log file for more information about the run or in order
> +   to diagnoze issues. If you pass V=1 in the environment, more diagnostic logs
> +   would be found in the test log.
> +
> +* ``tests/avocado/acpi-bits/bits-config``:
> +
> +   This location contains biosbits configuration files that determine how the
> +   software runs the tests.
> +
> +   ``bits-config.txt``:
> +   This is the biosbits config file that determines what tests
> +   or actions are performed by bits. The description of the config options are
> +   provided in the file itself.
> +
> +* ``tests/avocado/acpi-bits/bits-tests``:
> +
> +   This directory contains biosbits python based tests that are run from within
> +   the biosbits environment in the spawned VM. New additions of test cases can
> +   be made in the appropriate test file. For example, new acpi tests can go
> +   into testacpi.py2 and one would call testsuite.add_test() to register the new
> +   test so that it gets executed as a part of the ACPI tests.
> +   It might be occasionally necessary to disable some subtests or add a new
> +   test that belongs to a test suite not already present in this directory. To
> +   do this, please clone the bits source from
> +   https://gitlab.com/qemu-project/biosbits-bits/-/tree/qemu-bits.
> +   Note that this is the "qemu-bits" branch and not the "bits" branch of the
> +   repository. "qemu-bits" is the branch where we have made all the QEMU
> +   specific enhancements and we must use the source from this branch only.
> +   Copy the test suite/script that needs modification (addition of new tests
> +   or disabling them) from python directory into this directory. For
> +   example, in order to change cpuid related tests, copy the following
> +   file into this directory and rename it with .py2 extension:
> +   https://gitlab.com/qemu-project/biosbits-bits/-/blob/qemu-bits/python/testcpuid.py
> +   Then make your additions and changes here. Therefore, the steps are:
> +
> +       (a) Copy unmodified test script to this directory from bits source.
> +       (b) Add a SPDX license header.
> +       (c) Perform modifications to the test.

Maybe unordered lists would be better here

> +
> +   Commits (a), (b) and (c) should go under separate commits so that the original
> +   test script and the changes we have made are separated and clear.
> +
> +   The test framework will then use your modified test script to run the test.
> +   No further changes would be needed. Please check the logs to make sure that
> +   appropriate changes have taken effect.
> +
> +   The tests have an extension .py2 in order to indicate that:
> +
> +   (a) They are python2.7 based scripts and not python 3 scripts.
> +   (b) They are run from within the bios bits VM and is not subjected to QEMU
> +       build/test python script maintainance and dependency resolutions.
> +   (c) They need not be loaded by avocado framework when running tests.
> +
> +
> +Author: Ani Sinha <ani@anisinha.ca>
> +
> +References:
> +-----------
> +(a) https://blog.linuxplumbersconf.org/2011/ocw/system/presentations/867/original/bits.pdf
> +(b) https://www.youtube.com/watch?v=36QIepyUuhg
> +

and then:

.. [#a] https://blog.linuxplumbersconf.org/2011/ocw/system/presentations/867/original/bits.pdf
.. [#b] https://www.youtube.com/watch?v=36QIepyUuhg


-- 
Alex Bennée
[PATCH v6 10/10] MAINTAINERS: add myself as the maintainer for acpi biosbits avocado tests
Posted by Ani Sinha 1 year, 6 months ago
I wrote the biosbits avocado tests for testing QEMU's ACPI/SMBIOS implementation
and all the related changes including fixes in biosbits software itself. Making
myself as the maintainer for QEMU's biosbits related files and test scripts.

Cc: Daniel P. Berrangé <berrange@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Maydell Peter <peter.maydell@linaro.org>
Cc: John Snow <jsnow@redhat.com>
Cc: Thomas Huth <thuth@redhat.com>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Michael Tsirkin <mst@redhat.com>
Signed-off-by: Ani Sinha <ani@anisinha.ca>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8ae2e43c83..30c7cd96ef 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1859,6 +1859,12 @@ S: Supported
 F: hw/acpi/viot.c
 F: hw/acpi/viot.h
 
+ACPI/AVOCADO/BIOSBITS
+M: Ani Sinha <ani@anisinha.ca>
+S: Supported
+F: tests/avocado/acpi-bits/*
+F: tests/avocado/acpi-bits.py
+
 ACPI/HEST/GHES
 R: Dongjiu Geng <gengdongjiu1@gmail.com>
 L: qemu-arm@nongnu.org
-- 
2.34.1