qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [RFC PATCH 0/7] avocado: Add acceptance tests parsing t


From: Cleber Rosa
Subject: Re: [Qemu-devel] [RFC PATCH 0/7] avocado: Add acceptance tests parsing the Linux boot console
Date: Mon, 30 Apr 2018 18:49:51 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2


On 04/19/2018 12:46 PM, Philippe Mathieu-Daudé wrote:
> Hi,
> 
> While previously working on a Super I/O refactor, I encountered some problems
> at runtime, after building the codebase successfully and running qtests.
> I had to manually start to boot different guests and check the bootlog.
> 
> I wanted to give a try at Avocado which seems designed to simplify that kind
> of functional tests.
> 
> I applied Amador Pahim work following Cleber Rosa documentation from
> http://lists.nongnu.org/archive/html/qemu-devel/2018-01/msg03891.html,
> however I had to modify few things to parse the boot console.
> Since his work is not merged, I included it in this series.
> 
> The tests simply expect to find a string reported by Linux printk when a
> device is detected/initialized, such "ttyS0 at I/O 0x3f8 (irq = 4) is a 
> 16550A"
> and "i8042 KBD port at 0x60,0x64 irq 1" for the Super I/O chip, or such
> "registered as PCnet/PCI II 79C970A" to confirms the PCI subsystem and network
> device are correctly detected:
> 
> 
>     self.assertIn(u'ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A', bootlog)
>     self.assertIn(u'ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A', bootlog)
>     self.assertIn(u'i8042 KBD port at 0x60,0x64 irq 1', bootlog)
>     self.assertIn(u'i8042 AUX port at 0x60,0x64 irq 12', bootlog)
> 
> Example of the tests output:
> 
>     $ avocado run test_linux-boot-console.py -m 
> test_linux-boot-console.py.data/parameters.yaml 
>     JOB ID     : 695094c9bbe8f6011226da7c2031c2c53e949910
>     JOB LOG    : 
> /home/phil/avocado/job-results/job-2018-04-19T13.36-695094c/job.log
>      (1/6) 
> test_linux-boot-console.py:TestAlphaClipperBoot2_6.test_boot_console;alpha-2582:
>  PASS (4.76 s)
>      (2/6) 
> test_linux-boot-console.py:TestAlphaClipperBoot2_6.test_boot_console;mips-4a72:
>  PASS (0.00 s)
>      (3/6) 
> test_linux-boot-console.py:TestMips4kcMaltaBoot2_6.test_boot_console;alpha-2582:
>  PASS (0.00 s)
>      (4/6) 
> test_linux-boot-console.py:TestMips4kcMaltaBoot2_6.test_boot_console;mips-4a72:
>  PASS (3.92 s)
>      (5/6) 
> test_linux-boot-console.py:TestMips4kcMaltaBoot3_2.test_boot_console;alpha-2582:
>  PASS (0.00 s)
>      (6/6) 
> test_linux-boot-console.py:TestMips4kcMaltaBoot3_2.test_boot_console;mips-4a72:
>  PASS (4.08 s)
>     RESULTS    : PASS 6 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | 
> CANCEL 0
>     JOB TIME   : 13.31 s
> 
> Please apologize my ugly Python, this series is just a proof-of-concept :)
> I couldn't figure out how to use the @skipUnless(correct arch) decorator.
> 
> Regards,
> 
> Phil.
> 

Hi Philippe,

Thanks for this interesting RFC/PoC.  As someone who has spent more time
"on the other" side of this code, this perspective is invaluable.  I'll
respond to the major feature utilization points here, and then proceed
to review the individual patches.

One of the distinguishing features of Avocado is the ability to reuse
test code in different scenarios (thus reducing the amount of duplicated
code while still improving the overall coverage).  I noticed you grasped
the overall usage pattern of the "YAML to Mux" plugin, by means of the
"parameter.yaml".

This is an alternative proposal for the "parameter.yaml" file:

--- "parameter.yaml" STARTS HERE
architechture: !mux
   alpha:
      arch: alpha
      machine_type: clipper
      kernel_url:
http://archive.debian.org/debian/dists/lenny/main/installer-alpha/current/images/cdrom/vmlinuz
   mips:
     arch: mips
     machine_type: malta
     check_pci: True
     kernel_versions: !mux
        2_6:
           kernel_url:
http://people.debian.org/~aurel32/qemu/mips/vmlinux-2.6.32-5-4kc-malta
        3_2:
           kernel_url:
http://people.debian.org/~aurel32/qemu/mips/vmlinux-3.2.0-4-4kc-malta
--- "parameter.yaml" ENDS HERE

This file content produces the following tree (run it with "avocado -c
-t -m parameter.yaml"):

Multiplex tree representation:
 ┗━━ run
      ┗━━ architechture
           ╠══ alpha
           ║     → arch: alpha
           ║     → machine_type: clipper
           ║     → kernel_url:
http://archive.debian.org/debian/dists/lenny/main/installer-alpha/current/images/cdrom/vmlinuz
           ╚══ mips
                ┃   → check_pci: True
                ┃   → arch: mips
                ┃   → machine_type: malta
                ┗━━ kernel_versions
                     ╠══ 2_6
                     ║     → kernel_url:
http://people.debian.org/~aurel32/qemu/mips/vmlinux-2.6.32-5-4kc-malta
                     ╚══ 3_2
                           → kernel_url:
http://people.debian.org/~aurel32/qemu/mips/vmlinux-3.2.0-4-4kc-malta


And it generates the following variants (run it with "avocado -m
parameters.yaml"):

Multiplex variants (3):
Variant alpha-deaa:  /run/architechture/alpha
Variant 2_6-6f08:    /run/architechture/mips/kernel_versions/2_6
Variant 3_2-e556:    /run/architechture/mips/kernel_versions/3_2

With these variants, it's possible to have a single code test
implementation.  Here's my alternative implementation of your tests:

--- "test_linux-boot-console.py" STARTS HERE
import os
import tempfile
import gzip

from avocado_qemu import test
from avocado.utils import process


class TestBootCheckDevices(test.QemuTest):
    """
    :avocado: enable
    """
    def get_kernel_uncompressed(self):
        kernel = self.fetch_asset(self.params.get("kernel_url"))
        try:
            process.run("gzip -l %s" % kernel)
        except process.CmdError:
            # only deal with gzip compressed kernels here
            return kernel

        kernel_uncompressed_path = kernel + ".uncompressed"
        with gzip.open(kernel, 'rb') as kernel_gzip:
            with open(kernel_uncompressed_path, 'wb') as
kernel_uncompressed:
                kernel_uncompressed.write(kernel_gzip.read())
        return kernel_uncompressed_path

    def setUp(self):
        kernel_path = self.get_kernel_uncompressed()
        self.console_path = tempfile.mkstemp()[1]
        self.vm._args.extend(['-m', '64'])
        self.vm._args.extend(['-kernel', kernel_path])
        self.vm._args.extend(['-append', '"console=ttyS0 printk.time=0"'])
        self.vm._args.extend(['-chardev',
'socket,id=srm,server,nowait,path=' + self.console_path])
        self.vm._args.extend(['-serial', 'chardev:srm'])
        # This kernel crashes without VGA display
        self.vm._args.extend(['-vga', 'std'])
        self.vm.launch(self.console_path)
        console = self.vm.get_console(console_address=self.console_path,
login=False)
        # no filesystem provided on purpose, wait for the Kernel panic
        self.bootlog = console.read_until_any_line_matches(["Kernel
panic - not syncing: VFS: Unable to mount root fs"], timeout=30.0)[1]
        console.close()

    def test(self):
        # check Super I/O
        self.assertIn(u'ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A',
self.bootlog)
        self.assertIn(u'ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A',
self.bootlog)
        self.assertIn(u'i8042 KBD port at 0x60,0x64 irq 1', self.bootlog)
        self.assertIn(u'i8042 AUX port at 0x60,0x64 irq 12', self.bootlog)
        # check PCI
        if self.params.get('check_pci', default=False):
            self.assertIn(u'registered as PCnet/PCI II 79C970A',
self.bootlog)

    def tearDown(self):
        self.vm.shutdown()
        os.remove(self.console_path)
--- "test_linux-boot-console.py" ENDS HERE

A few points about this code:

1) get_kernel_uncompressed() is a prime candidate for a utility
function, even at the "avocado.utils.archive" level (a better version,
of course).  It's one of those things that arise from writing more
diverse code (again, thanks for this experiment).

2) setUp() still contains a lot of boiler plate code, and can certainly
have some of that moved to "avocado_qemu".  For instance, the
"avocado_qemu" code already knows how to deal with some parameters, such
as "arch" and "machine_type", so "memory", "kernel", etc could be
handled in a similar fashion.

3) It wasn't clear to me if manually creating a serial device and using
it as a console was a hard requirement of the test.  The
QEMUMachine._create_console() method on the "scripts/qemu.py" file
already has some code to create many console types.

Finally, running this code + parameters (by using "avocado run -m
test_linux-boot-console.py.data/parameters.yaml --
test_linux-boot-console.py") results in:

JOB ID     : bb7585de42035a062ddda539801743267aa4431a
JOB LOG    :
/home/cleber/avocado/job-results/job-2018-04-30T18.46-bb7585d/job.log
 (1/3) test_linux-boot-console.py:TestBootCheckDevices.test;alpha-deaa:
PASS (3.04 s)
 (2/3) test_linux-boot-console.py:TestBootCheckDevices.test;2_6-6f08:
PASS (2.83 s)
 (3/3) test_linux-boot-console.py:TestBootCheckDevices.test;3_2-e556:
PASS (2.86 s)
RESULTS    : PASS 3 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 |
CANCEL 0
JOB TIME   : 9.86 s
JOB HTML   :
/home/cleber/avocado/job-results/job-2018-04-30T18.46-bb7585d/results.html

The resulting "job.log" file can be seen at:

https://paste.fedoraproject.org/paste/G4X-z5PcmMdmmIVBDKVWVg/raw

Now, unto individual commits.
- Cleber.

> Amador Pahim (1):
>   AVOCADO_QEMU: Snapshot commit
> 
> Philippe Mathieu-Daudé (6):
>   avocado: Update python scripts to upstream codebase
>   qemu.py: Check console arch is supported before calling mktemp()
>   qemu.py: Avoid deprecated tempfile.mktemp()
>   avocado: Add an optional flag 'login' to get_console()
>   avocado: Add a test parsing Linux kernel booting console
>   avocado: Add tests booting the Malta machine
> 
>  scripts/qemu.py                               |  50 ++-
>  tests/avocado/README.rst                      | 132 ++++++
>  tests/avocado/avocado_qemu/__init__.py        |   0
>  tests/avocado/avocado_qemu/test.py            | 419 ++++++++++++++++++
>  tests/avocado/parameters.yaml                 |  19 +
>  tests/avocado/test_info_memdev_host_nodes.py  |  66 +++
>  tests/avocado/test_linux-boot-console.py      | 180 ++++++++
>  .../parameters.yaml                           |   5 +
>  tests/avocado/test_nec-usb-xhci.py            |  63 +++
>  .../test_nec-usb-xhci.py.data/parameters.yaml |   4 +
>  tests/avocado/test_numa_hotplug.py            | 120 +++++
>  tests/avocado/test_ovmf_with_240_vcpus.py     |  70 +++
>  .../parameters.yaml                           |   2 +
>  tests/avocado/variants.yaml                   |  62 +++
>  14 files changed, 1187 insertions(+), 5 deletions(-)
>  create mode 100644 tests/avocado/README.rst
>  create mode 100644 tests/avocado/avocado_qemu/__init__.py
>  create mode 100644 tests/avocado/avocado_qemu/test.py
>  create mode 100644 tests/avocado/parameters.yaml
>  create mode 100644 tests/avocado/test_info_memdev_host_nodes.py
>  create mode 100644 tests/avocado/test_linux-boot-console.py
>  create mode 100644 
> tests/avocado/test_linux-boot-console.py.data/parameters.yaml
>  create mode 100644 tests/avocado/test_nec-usb-xhci.py
>  create mode 100644 tests/avocado/test_nec-usb-xhci.py.data/parameters.yaml
>  create mode 100644 tests/avocado/test_numa_hotplug.py
>  create mode 100644 tests/avocado/test_ovmf_with_240_vcpus.py
>  create mode 100644 
> tests/avocado/test_ovmf_with_240_vcpus.py.data/parameters.yaml
>  create mode 100644 tests/avocado/variants.yaml
> 

-- 
Cleber Rosa
[ Sr Software Engineer - Virtualization Team - Red Hat ]
[ Avocado Test Framework - avocado-framework.github.io ]
[  7ABB 96EB 8B46 B94D 5E0F  E9BB 657E 8D33 A5F2 09F3  ]



reply via email to

[Prev in Thread] Current Thread [Next in Thread]