mirror of https://gitee.com/openkylin/qemu.git
Python queue, 2018-06-15
* Add avocado_qemu: functional/acceptance test infrastructure -----BEGIN PGP SIGNATURE----- iQIbBAABCAAGBQJbJA+UAAoJECgHk2+YTcWmRTQP920aopf/h3C7zF/af87rs87F 1HrVPnASBPPKPabnohxFAa2MV5NwB4VJlx4kjpxOoCV6v+kb+mV4zYdQe+d2kHvO W9IsCJVTOUxXFK4Xkl76QFTCQklk87LRz227uPjnH6YU6tlbfO/gkfeqm/ua/cIe SSndLQSpSMiMaeryuYaTzpyvrO8l9xD5lbPD0YwKGfEmdjHE5aqg0Q12ecK6Id8H 5PPWE5VEBL3WP9A9vA5lGr352+w9p/es/8Cf88iQu5fAC6fyRiBTAbZuZzyC9ido MjDtNC0HtLrCuuCLKWy5E7zd5KDah8cfYWTf9vVqNUdfY1CzbfmX49u6iADZEc4s O7I4oSHWma+uwNErAWB7ahC9YRjRbM1cuVy76UTllczLn5sP/SNvcdPzjhb8P+Hx YtEk2JhKSCBDmrHrWx0tBkPFoKfKF7z4IyWBYQ4irF0rakfNvKjvkdbnCquoqu5V /nL+CIUx1TW+6E2BXeYNpfERRra/DlFV51TfsSyS0WqBhJyLBLOCsrbHRnQFzAWA a1tjTmPFGRb8fXLqx6gABsNrCAQo339xYswNGWMVP/Flvzw8FHAg4EGnURhu4Uqd bG1Ru1nsRnfVE3WYcTYeMv11ydnHV3ty9XVaTAr9PYF59PxImFH7AuCXC4naj+WX DSso149y3PACsnaaoA8= =hk5m -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/python-next-pull-request' into staging Python queue, 2018-06-15 * Add avocado_qemu: functional/acceptance test infrastructure # gpg: Signature made Fri 15 Jun 2018 20:12:20 BST # gpg: using RSA key 2807936F984DC5A6 # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/python-next-pull-request: configure: Enable out-of-tree acceptance tests Acceptance tests: add Linux kernel boot and console checking test scripts/qemu.py: introduce set_console() method Acceptance tests: add quick VNC tests scripts/qemu.py: allow adding to the list of extra arguments Add functional/acceptance tests infrastructure Remove COPYING.PYTHON Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c5ee5cd9db
270
COPYING.PYTHON
270
COPYING.PYTHON
|
@ -1,270 +0,0 @@
|
|||
A. HISTORY OF THE SOFTWARE
|
||||
==========================
|
||||
|
||||
Python was created in the early 1990s by Guido van Rossum at Stichting
|
||||
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
|
||||
as a successor of a language called ABC. Guido remains Python's
|
||||
principal author, although it includes many contributions from others.
|
||||
|
||||
In 1995, Guido continued his work on Python at the Corporation for
|
||||
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
|
||||
in Reston, Virginia where he released several versions of the
|
||||
software.
|
||||
|
||||
In May 2000, Guido and the Python core development team moved to
|
||||
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
|
||||
year, the PythonLabs team moved to Digital Creations (now Zope
|
||||
Corporation, see http://www.zope.com). In 2001, the Python Software
|
||||
Foundation (PSF, see http://www.python.org/psf/) was formed, a
|
||||
non-profit organization created specifically to own Python-related
|
||||
Intellectual Property. Zope Corporation is a sponsoring member of
|
||||
the PSF.
|
||||
|
||||
All Python releases are Open Source (see http://www.opensource.org for
|
||||
the Open Source Definition). Historically, most, but not all, Python
|
||||
releases have also been GPL-compatible; the table below summarizes
|
||||
the various releases.
|
||||
|
||||
Release Derived Year Owner GPL-
|
||||
from compatible? (1)
|
||||
|
||||
0.9.0 thru 1.2 1991-1995 CWI yes
|
||||
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
|
||||
1.6 1.5.2 2000 CNRI no
|
||||
2.0 1.6 2000 BeOpen.com no
|
||||
1.6.1 1.6 2001 CNRI yes (2)
|
||||
2.1 2.0+1.6.1 2001 PSF no
|
||||
2.0.1 2.0+1.6.1 2001 PSF yes
|
||||
2.1.1 2.1+2.0.1 2001 PSF yes
|
||||
2.2 2.1.1 2001 PSF yes
|
||||
2.1.2 2.1.1 2002 PSF yes
|
||||
2.1.3 2.1.2 2002 PSF yes
|
||||
2.2.1 2.2 2002 PSF yes
|
||||
2.2.2 2.2.1 2002 PSF yes
|
||||
2.2.3 2.2.2 2003 PSF yes
|
||||
2.3 2.2.2 2002-2003 PSF yes
|
||||
2.3.1 2.3 2002-2003 PSF yes
|
||||
2.3.2 2.3.1 2002-2003 PSF yes
|
||||
2.3.3 2.3.2 2002-2003 PSF yes
|
||||
2.3.4 2.3.3 2004 PSF yes
|
||||
2.3.5 2.3.4 2005 PSF yes
|
||||
2.4 2.3 2004 PSF yes
|
||||
2.4.1 2.4 2005 PSF yes
|
||||
2.4.2 2.4.1 2005 PSF yes
|
||||
2.4.3 2.4.2 2006 PSF yes
|
||||
2.5 2.4 2006 PSF yes
|
||||
2.7 2.6 2010 PSF yes
|
||||
|
||||
Footnotes:
|
||||
|
||||
(1) GPL-compatible doesn't mean that we're distributing Python under
|
||||
the GPL. All Python licenses, unlike the GPL, let you distribute
|
||||
a modified version without making your changes open source. The
|
||||
GPL-compatible licenses make it possible to combine Python with
|
||||
other software that is released under the GPL; the others don't.
|
||||
|
||||
(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
|
||||
because its license has a choice of law clause. According to
|
||||
CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
|
||||
is "not incompatible" with the GPL.
|
||||
|
||||
Thanks to the many outside volunteers who have worked under Guido's
|
||||
direction to make these releases possible.
|
||||
|
||||
|
||||
B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
|
||||
===============================================================
|
||||
|
||||
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||
--------------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||
otherwise using this software ("Python") in source or binary form and
|
||||
its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, PSF
|
||||
hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
||||
license to reproduce, analyze, test, perform and/or display publicly,
|
||||
prepare derivative works, distribute, and otherwise use Python
|
||||
alone or in any derivative version, provided, however, that PSF's
|
||||
License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
|
||||
2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights
|
||||
Reserved" are retained in Python alone or in any derivative version
|
||||
prepared by Licensee.
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python.
|
||||
|
||||
4. PSF is making Python available to Licensee on an "AS IS"
|
||||
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
7. Nothing in this License Agreement shall be deemed to create any
|
||||
relationship of agency, partnership, or joint venture between PSF and
|
||||
Licensee. This License Agreement does not grant permission to use PSF
|
||||
trademarks or trade name in a trademark sense to endorse or promote
|
||||
products or services of Licensee, or any third party.
|
||||
|
||||
8. By copying, installing or otherwise using Python, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
|
||||
-------------------------------------------
|
||||
|
||||
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
|
||||
|
||||
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
|
||||
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
|
||||
Individual or Organization ("Licensee") accessing and otherwise using
|
||||
this software in source or binary form and its associated
|
||||
documentation ("the Software").
|
||||
|
||||
2. Subject to the terms and conditions of this BeOpen Python License
|
||||
Agreement, BeOpen hereby grants Licensee a non-exclusive,
|
||||
royalty-free, world-wide license to reproduce, analyze, test, perform
|
||||
and/or display publicly, prepare derivative works, distribute, and
|
||||
otherwise use the Software alone or in any derivative version,
|
||||
provided, however, that the BeOpen Python License is retained in the
|
||||
Software, alone or in any derivative version prepared by Licensee.
|
||||
|
||||
3. BeOpen is making the Software available to Licensee on an "AS IS"
|
||||
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
|
||||
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
|
||||
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
|
||||
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
5. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
6. This License Agreement shall be governed by and interpreted in all
|
||||
respects by the law of the State of California, excluding conflict of
|
||||
law provisions. Nothing in this License Agreement shall be deemed to
|
||||
create any relationship of agency, partnership, or joint venture
|
||||
between BeOpen and Licensee. This License Agreement does not grant
|
||||
permission to use BeOpen trademarks or trade names in a trademark
|
||||
sense to endorse or promote products or services of Licensee, or any
|
||||
third party. As an exception, the "BeOpen Python" logos available at
|
||||
http://www.pythonlabs.com/logos.html may be used according to the
|
||||
permissions granted on that web page.
|
||||
|
||||
7. By copying, installing or otherwise using the software, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
|
||||
---------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Corporation for National
|
||||
Research Initiatives, having an office at 1895 Preston White Drive,
|
||||
Reston, VA 20191 ("CNRI"), and the Individual or Organization
|
||||
("Licensee") accessing and otherwise using Python 1.6.1 software in
|
||||
source or binary form and its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, CNRI
|
||||
hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
||||
license to reproduce, analyze, test, perform and/or display publicly,
|
||||
prepare derivative works, distribute, and otherwise use Python 1.6.1
|
||||
alone or in any derivative version, provided, however, that CNRI's
|
||||
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
|
||||
1995-2001 Corporation for National Research Initiatives; All Rights
|
||||
Reserved" are retained in Python 1.6.1 alone or in any derivative
|
||||
version prepared by Licensee. Alternately, in lieu of CNRI's License
|
||||
Agreement, Licensee may substitute the following text (omitting the
|
||||
quotes): "Python 1.6.1 is made available subject to the terms and
|
||||
conditions in CNRI's License Agreement. This Agreement together with
|
||||
Python 1.6.1 may be located on the Internet using the following
|
||||
unique, persistent identifier (known as a handle): 1895.22/1013. This
|
||||
Agreement may also be obtained from a proxy server on the Internet
|
||||
using the following URL: http://hdl.handle.net/1895.22/1013".
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python 1.6.1 or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python 1.6.1.
|
||||
|
||||
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
|
||||
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
7. This License Agreement shall be governed by the federal
|
||||
intellectual property law of the United States, including without
|
||||
limitation the federal copyright law, and, to the extent such
|
||||
U.S. federal law does not apply, by the law of the Commonwealth of
|
||||
Virginia, excluding Virginia's conflict of law provisions.
|
||||
Notwithstanding the foregoing, with regard to derivative works based
|
||||
on Python 1.6.1 that incorporate non-separable material that was
|
||||
previously distributed under the GNU General Public License (GPL), the
|
||||
law of the Commonwealth of Virginia shall govern this License
|
||||
Agreement only as to issues arising under or with respect to
|
||||
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
|
||||
License Agreement shall be deemed to create any relationship of
|
||||
agency, partnership, or joint venture between CNRI and Licensee. This
|
||||
License Agreement does not grant permission to use CNRI trademarks or
|
||||
trade name in a trademark sense to endorse or promote products or
|
||||
services of Licensee, or any third party.
|
||||
|
||||
8. By clicking on the "ACCEPT" button where indicated, or by copying,
|
||||
installing or otherwise using Python 1.6.1, Licensee agrees to be
|
||||
bound by the terms and conditions of this License Agreement.
|
||||
|
||||
ACCEPT
|
||||
|
||||
|
||||
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
|
||||
--------------------------------------------------
|
||||
|
||||
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
|
||||
The Netherlands. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Stichting Mathematisch
|
||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior
|
||||
permission.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
||||
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@ -7239,9 +7239,11 @@ for rom in seabios vgabios ; do
|
|||
done
|
||||
|
||||
# set up tests data directory
|
||||
if [ ! -e tests/data ]; then
|
||||
symlink "$source_path/tests/data" tests/data
|
||||
fi
|
||||
for tests_subdir in acceptance data; do
|
||||
if [ ! -e tests/$tests_subdir ]; then
|
||||
symlink "$source_path/tests/$tests_subdir" tests/$tests_subdir
|
||||
fi
|
||||
done
|
||||
|
||||
# set up qemu-iotests in this build directory
|
||||
iotests_common_env="tests/qemu-iotests/common.env"
|
||||
|
|
|
@ -484,3 +484,195 @@ supported. To start the fuzzer, run
|
|||
|
||||
Alternatively, some command different from "qemu-img info" can be tested, by
|
||||
changing the ``-c`` option.
|
||||
|
||||
Acceptance tests using the Avocado Framework
|
||||
============================================
|
||||
|
||||
The ``tests/acceptance`` directory hosts functional tests, also known
|
||||
as acceptance level tests. They're usually higher level tests, and
|
||||
may interact with external resources and with various guest operating
|
||||
systems.
|
||||
|
||||
These tests are written using the Avocado Testing Framework (which must
|
||||
be installed separately) in conjunction with a the ``avocado_qemu.Test``
|
||||
class, implemented at ``tests/acceptance/avocado_qemu``.
|
||||
|
||||
Tests based on ``avocado_qemu.Test`` can easily:
|
||||
|
||||
* Customize the command line arguments given to the convenience
|
||||
``self.vm`` attribute (a QEMUMachine instance)
|
||||
|
||||
* Interact with the QEMU monitor, send QMP commands and check
|
||||
their results
|
||||
|
||||
* Interact with the guest OS, using the convenience console device
|
||||
(which may be useful to assert the effectiveness and correctness of
|
||||
command line arguments or QMP commands)
|
||||
|
||||
* Interact with external data files that accompany the test itself
|
||||
(see ``self.get_data()``)
|
||||
|
||||
* Download (and cache) remote data files, such as firmware and kernel
|
||||
images
|
||||
|
||||
* Have access to a library of guest OS images (by means of the
|
||||
``avocado.utils.vmimage`` library)
|
||||
|
||||
* Make use of various other test related utilities available at the
|
||||
test class itself and at the utility library:
|
||||
|
||||
- http://avocado-framework.readthedocs.io/en/latest/api/test/avocado.html#avocado.Test
|
||||
- http://avocado-framework.readthedocs.io/en/latest/api/utils/avocado.utils.html
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
To install Avocado and its dependencies, run:
|
||||
|
||||
.. code::
|
||||
|
||||
pip install --user avocado-framework
|
||||
|
||||
Alternatively, follow the instructions on this link:
|
||||
|
||||
http://avocado-framework.readthedocs.io/en/latest/GetStartedGuide.html#installing-avocado
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
This directory provides the ``avocado_qemu`` Python module, containing
|
||||
the ``avocado_qemu.Test`` class. Here's a simple usage example:
|
||||
|
||||
.. code::
|
||||
|
||||
from avocado_qemu import Test
|
||||
|
||||
|
||||
class Version(Test):
|
||||
"""
|
||||
:avocado: enable
|
||||
:avocado: tags=quick
|
||||
"""
|
||||
def test_qmp_human_info_version(self):
|
||||
self.vm.launch()
|
||||
res = self.vm.command('human-monitor-command',
|
||||
command_line='info version')
|
||||
self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
|
||||
|
||||
To execute your test, run:
|
||||
|
||||
.. code::
|
||||
|
||||
avocado run version.py
|
||||
|
||||
Tests may be classified according to a convention by using docstring
|
||||
directives such as ``:avocado: tags=TAG1,TAG2``. To run all tests
|
||||
in the current directory, tagged as "quick", run:
|
||||
|
||||
.. code::
|
||||
|
||||
avocado run -t quick .
|
||||
|
||||
The ``avocado_qemu.Test`` base test class
|
||||
-----------------------------------------
|
||||
|
||||
The ``avocado_qemu.Test`` class has a number of characteristics that
|
||||
are worth being mentioned right away.
|
||||
|
||||
First of all, it attempts to give each test a ready to use QEMUMachine
|
||||
instance, available at ``self.vm``. Because many tests will tweak the
|
||||
QEMU command line, launching the QEMUMachine (by using ``self.vm.launch()``)
|
||||
is left to the test writer.
|
||||
|
||||
At test "tear down", ``avocado_qemu.Test`` handles the QEMUMachine
|
||||
shutdown.
|
||||
|
||||
QEMUMachine
|
||||
~~~~~~~~~~~
|
||||
|
||||
The QEMUMachine API is already widely used in the Python iotests,
|
||||
device-crash-test and other Python scripts. It's a wrapper around the
|
||||
execution of a QEMU binary, giving its users:
|
||||
|
||||
* the ability to set command line arguments to be given to the QEMU
|
||||
binary
|
||||
|
||||
* a ready to use QMP connection and interface, which can be used to
|
||||
send commands and inspect its results, as well as asynchronous
|
||||
events
|
||||
|
||||
* convenience methods to set commonly used command line arguments in
|
||||
a more succinct and intuitive way
|
||||
|
||||
QEMU binary selection
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The QEMU binary used for the ``self.vm`` QEMUMachine instance will
|
||||
primarily depend on the value of the ``qemu_bin`` parameter. If it's
|
||||
not explicitly set, its default value will be the result of a dynamic
|
||||
probe in the same source tree. A suitable binary will be one that
|
||||
targets the architecture matching host machine.
|
||||
|
||||
Based on this description, test writers will usually rely on one of
|
||||
the following approaches:
|
||||
|
||||
1) Set ``qemu_bin``, and use the given binary
|
||||
|
||||
2) Do not set ``qemu_bin``, and use a QEMU binary named like
|
||||
"${arch}-softmmu/qemu-system-${arch}", either in the current
|
||||
working directory, or in the current source tree.
|
||||
|
||||
The resulting ``qemu_bin`` value will be preserved in the
|
||||
``avocado_qemu.Test`` as an attribute with the same name.
|
||||
|
||||
Attribute reference
|
||||
-------------------
|
||||
|
||||
Besides the attributes and methods that are part of the base
|
||||
``avocado.Test`` class, the following attributes are available on any
|
||||
``avocado_qemu.Test`` instance.
|
||||
|
||||
vm
|
||||
~~
|
||||
|
||||
A QEMUMachine instance, initially configured according to the given
|
||||
``qemu_bin`` parameter.
|
||||
|
||||
qemu_bin
|
||||
~~~~~~~~
|
||||
|
||||
The preserved value of the ``qemu_bin`` parameter or the result of the
|
||||
dynamic probe for a QEMU binary in the current working directory or
|
||||
source tree.
|
||||
|
||||
Parameter reference
|
||||
-------------------
|
||||
|
||||
To understand how Avocado parameters are accessed by tests, and how
|
||||
they can be passed to tests, please refer to::
|
||||
|
||||
http://avocado-framework.readthedocs.io/en/latest/WritingTests.html#accessing-test-parameters
|
||||
|
||||
Parameter values can be easily seen in the log files, and will look
|
||||
like the following:
|
||||
|
||||
.. code::
|
||||
|
||||
PARAMS (key=qemu_bin, path=*, default=x86_64-softmmu/qemu-system-x86_64) => 'x86_64-softmmu/qemu-system-x86_64
|
||||
|
||||
qemu_bin
|
||||
~~~~~~~~
|
||||
|
||||
The exact QEMU binary to be used on QEMUMachine.
|
||||
|
||||
Uninstalling Avocado
|
||||
--------------------
|
||||
|
||||
If you've followed the installation instructions above, you can easily
|
||||
uninstall Avocado. Start by listing the packages you have installed::
|
||||
|
||||
pip list --user
|
||||
|
||||
And remove any package you want with::
|
||||
|
||||
pip uninstall <package_name>
|
||||
|
|
103
scripts/qemu.py
103
scripts/qemu.py
|
@ -17,19 +17,41 @@
|
|||
import os
|
||||
import subprocess
|
||||
import qmp.qmp
|
||||
import re
|
||||
import shutil
|
||||
import socket
|
||||
import tempfile
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
#: Maps machine types to the preferred console device types
|
||||
CONSOLE_DEV_TYPES = {
|
||||
r'^clipper$': 'isa-serial',
|
||||
r'^malta': 'isa-serial',
|
||||
r'^(pc.*|q35.*|isapc)$': 'isa-serial',
|
||||
r'^(40p|powernv|prep)$': 'isa-serial',
|
||||
r'^pseries.*': 'spapr-vty',
|
||||
r'^s390-ccw-virtio.*': 'sclpconsole',
|
||||
}
|
||||
|
||||
|
||||
class QEMUMachineError(Exception):
|
||||
"""
|
||||
Exception called when an error in QEMUMachine happens.
|
||||
"""
|
||||
|
||||
|
||||
class QEMUMachineAddDeviceError(QEMUMachineError):
|
||||
"""
|
||||
Exception raised when a request to add a device can not be fulfilled
|
||||
|
||||
The failures are caused by limitations, lack of information or conflicting
|
||||
requests on the QEMUMachine methods. This exception does not represent
|
||||
failures reported by the QEMU binary itself.
|
||||
"""
|
||||
|
||||
class MonitorResponseError(qmp.qmp.QMPError):
|
||||
'''
|
||||
Represents erroneous QMP monitor reply
|
||||
|
@ -91,6 +113,10 @@ def __init__(self, binary, args=None, wrapper=None, name=None,
|
|||
self._test_dir = test_dir
|
||||
self._temp_dir = None
|
||||
self._launched = False
|
||||
self._machine = None
|
||||
self._console_device_type = None
|
||||
self._console_address = None
|
||||
self._console_socket = None
|
||||
|
||||
# just in case logging wasn't configured by the main script:
|
||||
logging.basicConfig()
|
||||
|
@ -175,9 +201,19 @@ def _base_args(self):
|
|||
self._monitor_address[1])
|
||||
else:
|
||||
moncdev = 'socket,id=mon,path=%s' % self._vm_monitor
|
||||
return ['-chardev', moncdev,
|
||||
args = ['-chardev', moncdev,
|
||||
'-mon', 'chardev=mon,mode=control',
|
||||
'-display', 'none', '-vga', 'none']
|
||||
if self._machine is not None:
|
||||
args.extend(['-machine', self._machine])
|
||||
if self._console_device_type is not None:
|
||||
self._console_address = os.path.join(self._temp_dir,
|
||||
self._name + "-console.sock")
|
||||
chardev = ('socket,id=console,path=%s,server,nowait' %
|
||||
self._console_address)
|
||||
device = '%s,chardev=console' % self._console_device_type
|
||||
args.extend(['-chardev', chardev, '-device', device])
|
||||
return args
|
||||
|
||||
def _pre_launch(self):
|
||||
self._temp_dir = tempfile.mkdtemp(dir=self._test_dir)
|
||||
|
@ -202,6 +238,10 @@ def _post_shutdown(self):
|
|||
|
||||
self._qemu_log_path = None
|
||||
|
||||
if self._console_socket is not None:
|
||||
self._console_socket.close()
|
||||
self._console_socket = None
|
||||
|
||||
if self._temp_dir is not None:
|
||||
shutil.rmtree(self._temp_dir)
|
||||
self._temp_dir = None
|
||||
|
@ -359,3 +399,64 @@ def get_log(self):
|
|||
of the qemu process.
|
||||
'''
|
||||
return self._iolog
|
||||
|
||||
def add_args(self, *args):
|
||||
'''
|
||||
Adds to the list of extra arguments to be given to the QEMU binary
|
||||
'''
|
||||
self._args.extend(args)
|
||||
|
||||
def set_machine(self, machine_type):
|
||||
'''
|
||||
Sets the machine type
|
||||
|
||||
If set, the machine type will be added to the base arguments
|
||||
of the resulting QEMU command line.
|
||||
'''
|
||||
self._machine = machine_type
|
||||
|
||||
def set_console(self, device_type=None):
|
||||
'''
|
||||
Sets the device type for a console device
|
||||
|
||||
If set, the console device and a backing character device will
|
||||
be added to the base arguments of the resulting QEMU command
|
||||
line.
|
||||
|
||||
This is a convenience method that will either use the provided
|
||||
device type, of if not given, it will used the device type set
|
||||
on CONSOLE_DEV_TYPES.
|
||||
|
||||
The actual setting of command line arguments will be be done at
|
||||
machine launch time, as it depends on the temporary directory
|
||||
to be created.
|
||||
|
||||
@param device_type: the device type, such as "isa-serial"
|
||||
@raises: QEMUMachineAddDeviceError if the device type is not given
|
||||
and can not be determined.
|
||||
'''
|
||||
if device_type is None:
|
||||
if self._machine is None:
|
||||
raise QEMUMachineAddDeviceError("Can not add a console device:"
|
||||
" QEMU instance without a "
|
||||
"defined machine type")
|
||||
for regex, device in CONSOLE_DEV_TYPES.items():
|
||||
if re.match(regex, self._machine):
|
||||
device_type = device
|
||||
break
|
||||
if device_type is None:
|
||||
raise QEMUMachineAddDeviceError("Can not add a console device:"
|
||||
" no matching console device "
|
||||
"type definition")
|
||||
self._console_device_type = device_type
|
||||
|
||||
@property
|
||||
def console_socket(self):
|
||||
"""
|
||||
Returns a socket connected to the console
|
||||
"""
|
||||
if self._console_socket is None:
|
||||
self._console_socket = socket.socket(socket.AF_UNIX,
|
||||
socket.SOCK_STREAM)
|
||||
self._console_socket.connect(self._console_address)
|
||||
return self._console_socket
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
============================================
|
||||
Acceptance tests using the Avocado Framework
|
||||
============================================
|
||||
|
||||
This directory contains functional tests, also known as acceptance
|
||||
level tests. They're usually higher level, and may interact with
|
||||
external resources and with various guest operating systems.
|
||||
|
||||
For more information, please refer to ``docs/devel/testing.rst``,
|
||||
section "Acceptance tests using the Avocado Framework".
|
|
@ -0,0 +1,54 @@
|
|||
# Test class and utilities for functional tests
|
||||
#
|
||||
# Copyright (c) 2018 Red Hat, Inc.
|
||||
#
|
||||
# Author:
|
||||
# Cleber Rosa <crosa@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import avocado
|
||||
|
||||
SRC_ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
SRC_ROOT_DIR = os.path.abspath(os.path.dirname(SRC_ROOT_DIR))
|
||||
sys.path.append(os.path.join(SRC_ROOT_DIR, 'scripts'))
|
||||
|
||||
from qemu import QEMUMachine
|
||||
|
||||
def is_readable_executable_file(path):
|
||||
return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK)
|
||||
|
||||
|
||||
def pick_default_qemu_bin():
|
||||
"""
|
||||
Picks the path of a QEMU binary, starting either in the current working
|
||||
directory or in the source tree root directory.
|
||||
"""
|
||||
arch = os.uname()[4]
|
||||
qemu_bin_relative_path = os.path.join("%s-softmmu" % arch,
|
||||
"qemu-system-%s" % arch)
|
||||
if is_readable_executable_file(qemu_bin_relative_path):
|
||||
return qemu_bin_relative_path
|
||||
|
||||
qemu_bin_from_src_dir_path = os.path.join(SRC_ROOT_DIR,
|
||||
qemu_bin_relative_path)
|
||||
if is_readable_executable_file(qemu_bin_from_src_dir_path):
|
||||
return qemu_bin_from_src_dir_path
|
||||
|
||||
|
||||
class Test(avocado.Test):
|
||||
def setUp(self):
|
||||
self.vm = None
|
||||
self.qemu_bin = self.params.get('qemu_bin',
|
||||
default=pick_default_qemu_bin())
|
||||
if self.qemu_bin is None:
|
||||
self.cancel("No QEMU binary defined or found in the source tree")
|
||||
self.vm = QEMUMachine(self.qemu_bin)
|
||||
|
||||
def tearDown(self):
|
||||
if self.vm is not None:
|
||||
self.vm.shutdown()
|
|
@ -0,0 +1,47 @@
|
|||
# Functional test that boots a Linux kernel and checks the console
|
||||
#
|
||||
# Copyright (c) 2018 Red Hat, Inc.
|
||||
#
|
||||
# Author:
|
||||
# Cleber Rosa <crosa@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
import logging
|
||||
|
||||
from avocado_qemu import Test
|
||||
|
||||
|
||||
class BootLinuxConsole(Test):
|
||||
"""
|
||||
Boots a x86_64 Linux kernel and checks that the console is operational
|
||||
and the kernel command line is properly passed from QEMU to the kernel
|
||||
|
||||
:avocado: enable
|
||||
:avocado: tags=x86_64
|
||||
"""
|
||||
|
||||
timeout = 60
|
||||
|
||||
def test(self):
|
||||
kernel_url = ('https://mirrors.kernel.org/fedora/releases/28/'
|
||||
'Everything/x86_64/os/images/pxeboot/vmlinuz')
|
||||
kernel_hash = '238e083e114c48200f80d889f7e32eeb2793e02a'
|
||||
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
|
||||
|
||||
self.vm.set_machine('pc')
|
||||
self.vm.set_console()
|
||||
kernel_command_line = 'console=ttyS0'
|
||||
self.vm.add_args('-kernel', kernel_path,
|
||||
'-append', kernel_command_line)
|
||||
self.vm.launch()
|
||||
console = self.vm.console_socket.makefile()
|
||||
console_logger = logging.getLogger('console')
|
||||
while True:
|
||||
msg = console.readline()
|
||||
console_logger.debug(msg.strip())
|
||||
if 'Kernel command line: %s' % kernel_command_line in msg:
|
||||
break
|
||||
if 'Kernel panic - not syncing' in msg:
|
||||
self.fail("Kernel panic reached")
|
|
@ -0,0 +1,24 @@
|
|||
# Version check example test
|
||||
#
|
||||
# Copyright (c) 2018 Red Hat, Inc.
|
||||
#
|
||||
# Author:
|
||||
# Cleber Rosa <crosa@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
|
||||
from avocado_qemu import Test
|
||||
|
||||
|
||||
class Version(Test):
|
||||
"""
|
||||
:avocado: enable
|
||||
:avocado: tags=quick
|
||||
"""
|
||||
def test_qmp_human_info_version(self):
|
||||
self.vm.launch()
|
||||
res = self.vm.command('human-monitor-command',
|
||||
command_line='info version')
|
||||
self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
|
|
@ -0,0 +1,60 @@
|
|||
# Simple functional tests for VNC functionality
|
||||
#
|
||||
# Copyright (c) 2018 Red Hat, Inc.
|
||||
#
|
||||
# Author:
|
||||
# Cleber Rosa <crosa@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
# later. See the COPYING file in the top-level directory.
|
||||
|
||||
from avocado_qemu import Test
|
||||
|
||||
|
||||
class Vnc(Test):
|
||||
"""
|
||||
:avocado: enable
|
||||
:avocado: tags=vnc,quick
|
||||
"""
|
||||
def test_no_vnc(self):
|
||||
self.vm.add_args('-nodefaults', '-S')
|
||||
self.vm.launch()
|
||||
self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled'])
|
||||
|
||||
def test_no_vnc_change_password(self):
|
||||
self.vm.add_args('-nodefaults', '-S')
|
||||
self.vm.launch()
|
||||
self.assertFalse(self.vm.qmp('query-vnc')['return']['enabled'])
|
||||
set_password_response = self.vm.qmp('change',
|
||||
device='vnc',
|
||||
target='password',
|
||||
arg='new_password')
|
||||
self.assertIn('error', set_password_response)
|
||||
self.assertEqual(set_password_response['error']['class'],
|
||||
'GenericError')
|
||||
self.assertEqual(set_password_response['error']['desc'],
|
||||
'Could not set password')
|
||||
|
||||
def test_vnc_change_password_requires_a_password(self):
|
||||
self.vm.add_args('-nodefaults', '-S', '-vnc', ':0')
|
||||
self.vm.launch()
|
||||
self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled'])
|
||||
set_password_response = self.vm.qmp('change',
|
||||
device='vnc',
|
||||
target='password',
|
||||
arg='new_password')
|
||||
self.assertIn('error', set_password_response)
|
||||
self.assertEqual(set_password_response['error']['class'],
|
||||
'GenericError')
|
||||
self.assertEqual(set_password_response['error']['desc'],
|
||||
'Could not set password')
|
||||
|
||||
def test_vnc_change_password(self):
|
||||
self.vm.add_args('-nodefaults', '-S', '-vnc', ':0,password')
|
||||
self.vm.launch()
|
||||
self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled'])
|
||||
set_password_response = self.vm.qmp('change',
|
||||
device='vnc',
|
||||
target='password',
|
||||
arg='new_password')
|
||||
self.assertEqual(set_password_response['return'], {})
|
Loading…
Reference in New Issue