]> Git Repo - qemu.git/blob - tests/acceptance/avocado_qemu/__init__.py
Acceptance tests: refactor wait_for_console_pattern
[qemu.git] / tests / acceptance / avocado_qemu / __init__.py
1 # Test class and utilities for functional tests
2 #
3 # Copyright (c) 2018 Red Hat, Inc.
4 #
5 # Author:
6 #  Cleber Rosa <[email protected]>
7 #
8 # This work is licensed under the terms of the GNU GPL, version 2 or
9 # later.  See the COPYING file in the top-level directory.
10
11 import logging
12 import os
13 import sys
14 import uuid
15 import tempfile
16
17 import avocado
18
19 SRC_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..', '..', '..')
20 sys.path.append(os.path.join(SRC_ROOT_DIR, 'python'))
21
22 from qemu.machine import QEMUMachine
23
24 def is_readable_executable_file(path):
25     return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK)
26
27
28 def pick_default_qemu_bin(arch=None):
29     """
30     Picks the path of a QEMU binary, starting either in the current working
31     directory or in the source tree root directory.
32
33     :param arch: the arch to use when looking for a QEMU binary (the target
34                  will match the arch given).  If None (the default), arch
35                  will be the current host system arch (as given by
36                  :func:`os.uname`).
37     :type arch: str
38     :returns: the path to the default QEMU binary or None if one could not
39               be found
40     :rtype: str or None
41     """
42     if arch is None:
43         arch = os.uname()[4]
44     # qemu binary path does not match arch for powerpc, handle it
45     if 'ppc64le' in arch:
46         arch = 'ppc64'
47     qemu_bin_relative_path = os.path.join("%s-softmmu" % arch,
48                                           "qemu-system-%s" % arch)
49     if is_readable_executable_file(qemu_bin_relative_path):
50         return qemu_bin_relative_path
51
52     qemu_bin_from_src_dir_path = os.path.join(SRC_ROOT_DIR,
53                                               qemu_bin_relative_path)
54     if is_readable_executable_file(qemu_bin_from_src_dir_path):
55         return qemu_bin_from_src_dir_path
56
57
58 def wait_for_console_pattern(test, success_message, failure_message=None):
59     """
60     Waits for messages to appear on the console, while logging the content
61
62     :param test: an Avocado test containing a VM that will have its console
63                  read and probed for a success or failure message
64     :type test: :class:`avocado_qemu.Test`
65     :param success_message: if this message appears, test succeeds
66     :param failure_message: if this message appears, test fails
67     """
68     console = test.vm.console_socket.makefile()
69     console_logger = logging.getLogger('console')
70     while True:
71         msg = console.readline().strip()
72         if not msg:
73             continue
74         console_logger.debug(msg)
75         if success_message in msg:
76             break
77         if failure_message and failure_message in msg:
78             fail = 'Failure message found in console: %s' % failure_message
79             test.fail(fail)
80
81
82 class Test(avocado.Test):
83     def setUp(self):
84         self._vms = {}
85         arches = self.tags.get('arch', [])
86         if len(arches) == 1:
87             arch = arches.pop()
88         else:
89             arch = None
90         self.arch = self.params.get('arch', default=arch)
91         default_qemu_bin = pick_default_qemu_bin(arch=self.arch)
92         self.qemu_bin = self.params.get('qemu_bin',
93                                         default=default_qemu_bin)
94         if self.qemu_bin is None:
95             self.cancel("No QEMU binary defined or found in the source tree")
96
97     def _new_vm(self, *args):
98         vm = QEMUMachine(self.qemu_bin, sock_dir=tempfile.mkdtemp())
99         if args:
100             vm.add_args(*args)
101         return vm
102
103     @property
104     def vm(self):
105         return self.get_vm(name='default')
106
107     def get_vm(self, *args, name=None):
108         if not name:
109             name = str(uuid.uuid4())
110         if self._vms.get(name) is None:
111             self._vms[name] = self._new_vm(*args)
112         return self._vms[name]
113
114     def tearDown(self):
115         for vm in self._vms.values():
116             vm.shutdown()
This page took 0.030568 seconds and 4 git commands to generate.