Blame SOURCES/kvm-Add-functional-acceptance-tests-infrastructure.patch

383d26
From b041318485f538aa5bc9a34a010a629d45bbc73d Mon Sep 17 00:00:00 2001
383d26
From: Yash Mankad <ymankad@redhat.com>
383d26
Date: Tue, 17 Jul 2018 23:38:04 +0200
383d26
Subject: [PATCH 47/89] Add functional/acceptance tests infrastructure
383d26
MIME-Version: 1.0
383d26
Content-Type: text/plain; charset=UTF-8
383d26
Content-Transfer-Encoding: 8bit
383d26
383d26
RH-Author: Yash Mankad <ymankad@redhat.com>
383d26
Message-id: <c3796e31f415a6b2f021d5d2aa01a75d276d662a.1531870629.git.ymankad@redhat.com>
383d26
Patchwork-id: 81382
383d26
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 1/5] Add functional/acceptance tests infrastructure
383d26
Bugzilla:
383d26
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
383d26
RH-Acked-by: John Snow <jsnow@redhat.com>
383d26
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
383d26
383d26
From: Cleber Rosa <crosa@redhat.com>
383d26
383d26
This patch adds the very minimum infrastructure necessary for writing
383d26
and running functional/acceptance tests, including:
383d26
383d26
 * Documentation
383d26
 * The avocado_qemu.Test base test class
383d26
 * One example tests (version.py)
383d26
383d26
Additional functionality is expected to be added along the tests that
383d26
require them.
383d26
383d26
Signed-off-by: Cleber Rosa <crosa@redhat.com>
383d26
Message-Id: <20180530184156.15634-2-crosa@redhat.com>
383d26
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
383d26
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
383d26
[ehabkost: fix typo on testing.rst]
383d26
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
383d26
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
383d26
(cherry picked from commit c3d7e8c90db208b1d876f8d6458c2dfca169137f)
383d26
Signed-off-by: Yash Mankad <ymankad@redhat.com>
383d26
383d26
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
383d26
---
383d26
 docs/devel/testing.rst                    | 192 ++++++++++++++++++++++++++++++
383d26
 tests/acceptance/README.rst               |  10 ++
383d26
 tests/acceptance/avocado_qemu/__init__.py |  54 +++++++++
383d26
 tests/acceptance/version.py               |  24 ++++
383d26
 4 files changed, 280 insertions(+)
383d26
 create mode 100644 tests/acceptance/README.rst
383d26
 create mode 100644 tests/acceptance/avocado_qemu/__init__.py
383d26
 create mode 100644 tests/acceptance/version.py
383d26
383d26
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
383d26
index 0ca1a2d..f33e5a8 100644
383d26
--- a/docs/devel/testing.rst
383d26
+++ b/docs/devel/testing.rst
383d26
@@ -484,3 +484,195 @@ supported. To start the fuzzer, run
383d26
 
383d26
 Alternatively, some command different from "qemu-img info" can be tested, by
383d26
 changing the ``-c`` option.
383d26
+
383d26
+Acceptance tests using the Avocado Framework
383d26
+============================================
383d26
+
383d26
+The ``tests/acceptance`` directory hosts functional tests, also known
383d26
+as acceptance level tests.  They're usually higher level tests, and
383d26
+may interact with external resources and with various guest operating
383d26
+systems.
383d26
+
383d26
+These tests are written using the Avocado Testing Framework (which must
383d26
+be installed separately) in conjunction with a the ``avocado_qemu.Test``
383d26
+class, implemented at ``tests/acceptance/avocado_qemu``.
383d26
+
383d26
+Tests based on ``avocado_qemu.Test`` can easily:
383d26
+
383d26
+ * Customize the command line arguments given to the convenience
383d26
+   ``self.vm`` attribute (a QEMUMachine instance)
383d26
+
383d26
+ * Interact with the QEMU monitor, send QMP commands and check
383d26
+   their results
383d26
+
383d26
+ * Interact with the guest OS, using the convenience console device
383d26
+   (which may be useful to assert the effectiveness and correctness of
383d26
+   command line arguments or QMP commands)
383d26
+
383d26
+ * Interact with external data files that accompany the test itself
383d26
+   (see ``self.get_data()``)
383d26
+
383d26
+ * Download (and cache) remote data files, such as firmware and kernel
383d26
+   images
383d26
+
383d26
+ * Have access to a library of guest OS images (by means of the
383d26
+   ``avocado.utils.vmimage`` library)
383d26
+
383d26
+ * Make use of various other test related utilities available at the
383d26
+   test class itself and at the utility library:
383d26
+
383d26
+   - http://avocado-framework.readthedocs.io/en/latest/api/test/avocado.html#avocado.Test
383d26
+   - http://avocado-framework.readthedocs.io/en/latest/api/utils/avocado.utils.html
383d26
+
383d26
+Installation
383d26
+------------
383d26
+
383d26
+To install Avocado and its dependencies, run:
383d26
+
383d26
+.. code::
383d26
+
383d26
+  pip install --user avocado-framework
383d26
+
383d26
+Alternatively, follow the instructions on this link:
383d26
+
383d26
+  http://avocado-framework.readthedocs.io/en/latest/GetStartedGuide.html#installing-avocado
383d26
+
383d26
+Overview
383d26
+--------
383d26
+
383d26
+This directory provides the ``avocado_qemu`` Python module, containing
383d26
+the ``avocado_qemu.Test`` class.  Here's a simple usage example:
383d26
+
383d26
+.. code::
383d26
+
383d26
+  from avocado_qemu import Test
383d26
+
383d26
+
383d26
+  class Version(Test):
383d26
+      """
383d26
+      :avocado: enable
383d26
+      :avocado: tags=quick
383d26
+      """
383d26
+      def test_qmp_human_info_version(self):
383d26
+          self.vm.launch()
383d26
+          res = self.vm.command('human-monitor-command',
383d26
+                                command_line='info version')
383d26
+          self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
383d26
+
383d26
+To execute your test, run:
383d26
+
383d26
+.. code::
383d26
+
383d26
+  avocado run version.py
383d26
+
383d26
+Tests may be classified according to a convention by using docstring
383d26
+directives such as ``:avocado: tags=TAG1,TAG2``.  To run all tests
383d26
+in the current directory, tagged as "quick", run:
383d26
+
383d26
+.. code::
383d26
+
383d26
+  avocado run -t quick .
383d26
+
383d26
+The ``avocado_qemu.Test`` base test class
383d26
+-----------------------------------------
383d26
+
383d26
+The ``avocado_qemu.Test`` class has a number of characteristics that
383d26
+are worth being mentioned right away.
383d26
+
383d26
+First of all, it attempts to give each test a ready to use QEMUMachine
383d26
+instance, available at ``self.vm``.  Because many tests will tweak the
383d26
+QEMU command line, launching the QEMUMachine (by using ``self.vm.launch()``)
383d26
+is left to the test writer.
383d26
+
383d26
+At test "tear down", ``avocado_qemu.Test`` handles the QEMUMachine
383d26
+shutdown.
383d26
+
383d26
+QEMUMachine
383d26
+~~~~~~~~~~~
383d26
+
383d26
+The QEMUMachine API is already widely used in the Python iotests,
383d26
+device-crash-test and other Python scripts.  It's a wrapper around the
383d26
+execution of a QEMU binary, giving its users:
383d26
+
383d26
+ * the ability to set command line arguments to be given to the QEMU
383d26
+   binary
383d26
+
383d26
+ * a ready to use QMP connection and interface, which can be used to
383d26
+   send commands and inspect its results, as well as asynchronous
383d26
+   events
383d26
+
383d26
+ * convenience methods to set commonly used command line arguments in
383d26
+   a more succinct and intuitive way
383d26
+
383d26
+QEMU binary selection
383d26
+~~~~~~~~~~~~~~~~~~~~~
383d26
+
383d26
+The QEMU binary used for the ``self.vm`` QEMUMachine instance will
383d26
+primarily depend on the value of the ``qemu_bin`` parameter.  If it's
383d26
+not explicitly set, its default value will be the result of a dynamic
383d26
+probe in the same source tree.  A suitable binary will be one that
383d26
+targets the architecture matching host machine.
383d26
+
383d26
+Based on this description, test writers will usually rely on one of
383d26
+the following approaches:
383d26
+
383d26
+1) Set ``qemu_bin``, and use the given binary
383d26
+
383d26
+2) Do not set ``qemu_bin``, and use a QEMU binary named like
383d26
+   "${arch}-softmmu/qemu-system-${arch}", either in the current
383d26
+   working directory, or in the current source tree.
383d26
+
383d26
+The resulting ``qemu_bin`` value will be preserved in the
383d26
+``avocado_qemu.Test`` as an attribute with the same name.
383d26
+
383d26
+Attribute reference
383d26
+-------------------
383d26
+
383d26
+Besides the attributes and methods that are part of the base
383d26
+``avocado.Test`` class, the following attributes are available on any
383d26
+``avocado_qemu.Test`` instance.
383d26
+
383d26
+vm
383d26
+~~
383d26
+
383d26
+A QEMUMachine instance, initially configured according to the given
383d26
+``qemu_bin`` parameter.
383d26
+
383d26
+qemu_bin
383d26
+~~~~~~~~
383d26
+
383d26
+The preserved value of the ``qemu_bin`` parameter or the result of the
383d26
+dynamic probe for a QEMU binary in the current working directory or
383d26
+source tree.
383d26
+
383d26
+Parameter reference
383d26
+-------------------
383d26
+
383d26
+To understand how Avocado parameters are accessed by tests, and how
383d26
+they can be passed to tests, please refer to::
383d26
+
383d26
+  http://avocado-framework.readthedocs.io/en/latest/WritingTests.html#accessing-test-parameters
383d26
+
383d26
+Parameter values can be easily seen in the log files, and will look
383d26
+like the following:
383d26
+
383d26
+.. code::
383d26
+
383d26
+  PARAMS (key=qemu_bin, path=*, default=x86_64-softmmu/qemu-system-x86_64) => 'x86_64-softmmu/qemu-system-x86_64
383d26
+
383d26
+qemu_bin
383d26
+~~~~~~~~
383d26
+
383d26
+The exact QEMU binary to be used on QEMUMachine.
383d26
+
383d26
+Uninstalling Avocado
383d26
+--------------------
383d26
+
383d26
+If you've followed the installation instructions above, you can easily
383d26
+uninstall Avocado.  Start by listing the packages you have installed::
383d26
+
383d26
+  pip list --user
383d26
+
383d26
+And remove any package you want with::
383d26
+
383d26
+  pip uninstall <package_name>
383d26
diff --git a/tests/acceptance/README.rst b/tests/acceptance/README.rst
383d26
new file mode 100644
383d26
index 0000000..89260fa
383d26
--- /dev/null
383d26
+++ b/tests/acceptance/README.rst
383d26
@@ -0,0 +1,10 @@
383d26
+============================================
383d26
+Acceptance tests using the Avocado Framework
383d26
+============================================
383d26
+
383d26
+This directory contains functional tests, also known as acceptance
383d26
+level tests.  They're usually higher level, and may interact with
383d26
+external resources and with various guest operating systems.
383d26
+
383d26
+For more information, please refer to ``docs/devel/testing.rst``,
383d26
+section "Acceptance tests using the Avocado Framework".
383d26
diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py
383d26
new file mode 100644
383d26
index 0000000..1e54fd5
383d26
--- /dev/null
383d26
+++ b/tests/acceptance/avocado_qemu/__init__.py
383d26
@@ -0,0 +1,54 @@
383d26
+# Test class and utilities for functional tests
383d26
+#
383d26
+# Copyright (c) 2018 Red Hat, Inc.
383d26
+#
383d26
+# Author:
383d26
+#  Cleber Rosa <crosa@redhat.com>
383d26
+#
383d26
+# This work is licensed under the terms of the GNU GPL, version 2 or
383d26
+# later.  See the COPYING file in the top-level directory.
383d26
+
383d26
+import os
383d26
+import sys
383d26
+
383d26
+import avocado
383d26
+
383d26
+SRC_ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
383d26
+SRC_ROOT_DIR = os.path.abspath(os.path.dirname(SRC_ROOT_DIR))
383d26
+sys.path.append(os.path.join(SRC_ROOT_DIR, 'scripts'))
383d26
+
383d26
+from qemu import QEMUMachine
383d26
+
383d26
+def is_readable_executable_file(path):
383d26
+    return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK)
383d26
+
383d26
+
383d26
+def pick_default_qemu_bin():
383d26
+    """
383d26
+    Picks the path of a QEMU binary, starting either in the current working
383d26
+    directory or in the source tree root directory.
383d26
+    """
383d26
+    arch = os.uname()[4]
383d26
+    qemu_bin_relative_path = os.path.join("%s-softmmu" % arch,
383d26
+                                          "qemu-system-%s" % arch)
383d26
+    if is_readable_executable_file(qemu_bin_relative_path):
383d26
+        return qemu_bin_relative_path
383d26
+
383d26
+    qemu_bin_from_src_dir_path = os.path.join(SRC_ROOT_DIR,
383d26
+                                              qemu_bin_relative_path)
383d26
+    if is_readable_executable_file(qemu_bin_from_src_dir_path):
383d26
+        return qemu_bin_from_src_dir_path
383d26
+
383d26
+
383d26
+class Test(avocado.Test):
383d26
+    def setUp(self):
383d26
+        self.vm = None
383d26
+        self.qemu_bin = self.params.get('qemu_bin',
383d26
+                                        default=pick_default_qemu_bin())
383d26
+        if self.qemu_bin is None:
383d26
+            self.cancel("No QEMU binary defined or found in the source tree")
383d26
+        self.vm = QEMUMachine(self.qemu_bin)
383d26
+
383d26
+    def tearDown(self):
383d26
+        if self.vm is not None:
383d26
+            self.vm.shutdown()
383d26
diff --git a/tests/acceptance/version.py b/tests/acceptance/version.py
383d26
new file mode 100644
383d26
index 0000000..13b0a74
383d26
--- /dev/null
383d26
+++ b/tests/acceptance/version.py
383d26
@@ -0,0 +1,24 @@
383d26
+# Version check example test
383d26
+#
383d26
+# Copyright (c) 2018 Red Hat, Inc.
383d26
+#
383d26
+# Author:
383d26
+#  Cleber Rosa <crosa@redhat.com>
383d26
+#
383d26
+# This work is licensed under the terms of the GNU GPL, version 2 or
383d26
+# later.  See the COPYING file in the top-level directory.
383d26
+
383d26
+
383d26
+from avocado_qemu import Test
383d26
+
383d26
+
383d26
+class Version(Test):
383d26
+    """
383d26
+    :avocado: enable
383d26
+    :avocado: tags=quick
383d26
+    """
383d26
+    def test_qmp_human_info_version(self):
383d26
+        self.vm.launch()
383d26
+        res = self.vm.command('human-monitor-command',
383d26
+                              command_line='info version')
383d26
+        self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
383d26
-- 
383d26
1.8.3.1
383d26