1.. _checkfunctional-ref: 2 3Functional testing with Python 4============================== 5 6The ``tests/functional`` directory hosts functional tests written in 7Python. They are usually higher level tests, and may interact with 8external resources and with various guest operating systems. 9The functional tests have initially evolved from the Avocado tests, so there 10is a lot of similarity to those tests here (see :ref:`checkavocado-ref` for 11details about the Avocado tests). 12 13The tests should be written in the style of the Python `unittest`_ framework, 14using stdio for the TAP protocol. The folder ``tests/functional/qemu_test`` 15provides classes (e.g. the ``QemuBaseTest``, ``QemuUserTest`` and the 16``QemuSystemTest`` classes) and utility functions that help to get your test 17into the right shape, e.g. by replacing the 'stdout' python object to redirect 18the normal output of your test to stderr instead. 19 20Note that if you don't use one of the QemuBaseTest based classes for your 21test, or if you spawn subprocesses from your test, you have to make sure 22that there is no TAP-incompatible output written to stdio, e.g. either by 23prefixing every line with a "# " to mark the output as a TAP comment, or 24e.g. by capturing the stdout output of subprocesses (redirecting it to 25stderr is OK). 26 27Tests based on ``qemu_test.QemuSystemTest`` can easily: 28 29 * Customize the command line arguments given to the convenience 30 ``self.vm`` attribute (a QEMUMachine instance) 31 32 * Interact with the QEMU monitor, send QMP commands and check 33 their results 34 35 * Interact with the guest OS, using the convenience console device 36 (which may be useful to assert the effectiveness and correctness of 37 command line arguments or QMP commands) 38 39 * Download (and cache) remote data files, such as firmware and kernel 40 images 41 42Running tests 43------------- 44 45You can run the functional tests simply by executing: 46 47.. code:: 48 49 make check-functional 50 51It is also possible to run tests for a certain target only, for example 52the following line will only run the tests for the x86_64 target: 53 54.. code:: 55 56 make check-functional-x86_64 57 58To run a single test file without the meson test runner, you can also 59execute the file directly by specifying two environment variables first, 60the PYTHONPATH that has to include the python folder and the tests/functional 61folder of the source tree, and QEMU_TEST_QEMU_BINARY that has to point 62to the QEMU binary that should be used for the test. The current working 63directory should be your build folder. For example:: 64 65 $ export PYTHONPATH=../python:../tests/functional 66 $ export QEMU_TEST_QEMU_BINARY=$PWD/qemu-system-x86_64 67 $ pyvenv/bin/python3 ../tests/functional/test_file.py 68 69The test framework will automatically purge any scratch files created during 70the tests. If needing to debug a failed test, it is possible to keep these 71files around on disk by setting ```QEMU_TEST_KEEP_SCRATCH=1``` as an env 72variable. Any preserved files will be deleted the next time the test is run 73without this variable set. 74 75Overview 76-------- 77 78The ``tests/functional/qemu_test`` directory provides the ``qemu_test`` 79Python module, containing the ``qemu_test.QemuSystemTest`` class. 80Here is a simple usage example: 81 82.. code:: 83 84 #!/usr/bin/env python3 85 86 from qemu_test import QemuSystemTest 87 88 class Version(QemuSystemTest): 89 90 def test_qmp_human_info_version(self): 91 self.vm.launch() 92 res = self.vm.cmd('human-monitor-command', 93 command_line='info version') 94 self.assertRegex(res, r'^(\d+\.\d+\.\d)') 95 96 if __name__ == '__main__': 97 QemuSystemTest.main() 98 99By providing the "hash bang" line at the beginning of the script, marking 100the file as executable and by calling into QemuSystemTest.main(), the test 101can also be run stand-alone, without a test runner. OTOH when run via a test 102runner, the QemuSystemTest.main() function takes care of running the test 103functions in the right fassion (e.g. with TAP output that is required by the 104meson test runner). 105 106The ``qemu_test.QemuSystemTest`` base test class 107^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 108 109The ``qemu_test.QemuSystemTest`` class has a number of characteristics 110that are worth being mentioned. 111 112First of all, it attempts to give each test a ready to use QEMUMachine 113instance, available at ``self.vm``. Because many tests will tweak the 114QEMU command line, launching the QEMUMachine (by using ``self.vm.launch()``) 115is left to the test writer. 116 117The base test class has also support for tests with more than one 118QEMUMachine. The way to get machines is through the ``self.get_vm()`` 119method which will return a QEMUMachine instance. The ``self.get_vm()`` 120method accepts arguments that will be passed to the QEMUMachine creation 121and also an optional ``name`` attribute so you can identify a specific 122machine and get it more than once through the tests methods. A simple 123and hypothetical example follows: 124 125.. code:: 126 127 from qemu_test import QemuSystemTest 128 129 class MultipleMachines(QemuSystemTest): 130 def test_multiple_machines(self): 131 first_machine = self.get_vm() 132 second_machine = self.get_vm() 133 self.get_vm(name='third_machine').launch() 134 135 first_machine.launch() 136 second_machine.launch() 137 138 first_res = first_machine.cmd( 139 'human-monitor-command', 140 command_line='info version') 141 142 second_res = second_machine.cmd( 143 'human-monitor-command', 144 command_line='info version') 145 146 third_res = self.get_vm(name='third_machine').cmd( 147 'human-monitor-command', 148 command_line='info version') 149 150 self.assertEqual(first_res, second_res, third_res) 151 152At test "tear down", ``qemu_test.QemuSystemTest`` handles all the QEMUMachines 153shutdown. 154 155QEMUMachine 156----------- 157 158The QEMUMachine API is already widely used in the Python iotests, 159device-crash-test and other Python scripts. It's a wrapper around the 160execution of a QEMU binary, giving its users: 161 162 * the ability to set command line arguments to be given to the QEMU 163 binary 164 165 * a ready to use QMP connection and interface, which can be used to 166 send commands and inspect its results, as well as asynchronous 167 events 168 169 * convenience methods to set commonly used command line arguments in 170 a more succinct and intuitive way 171 172QEMU binary selection 173^^^^^^^^^^^^^^^^^^^^^ 174 175The QEMU binary used for the ``self.vm`` QEMUMachine instance will 176primarily depend on the value of the ``qemu_bin`` class attribute. 177If it is not explicitly set by the test code, its default value will 178be the result the QEMU_TEST_QEMU_BINARY environment variable. 179 180Debugging hung QEMU 181^^^^^^^^^^^^^^^^^^^ 182 183When test cases go wrong it may be helpful to debug a stalled QEMU 184process. While the QEMUMachine class owns the primary QMP monitor 185socket, it is possible to request a second QMP monitor be created 186by setting the ``QEMU_TEST_QMP_BACKDOOR`` env variable to refer 187to a UNIX socket name. The ``qmp-shell`` command can then be 188attached to the stalled QEMU to examine its live state. 189 190Attribute reference 191------------------- 192 193QemuBaseTest 194^^^^^^^^^^^^ 195 196The following attributes are available on any ``qemu_test.QemuBaseTest`` 197instance. 198 199arch 200"""" 201 202The target architecture of the QEMU binary. 203 204Tests are also free to use this attribute value, for their own needs. 205A test may, for instance, use this value when selecting the architecture 206of a kernel or disk image to boot a VM with. 207 208qemu_bin 209"""""""" 210 211The preserved value of the ``QEMU_TEST_QEMU_BINARY`` environment 212variable. 213 214QemuUserTest 215^^^^^^^^^^^^ 216 217The QemuUserTest class can be used for running an executable via the 218usermode emulation binaries. 219 220QemuSystemTest 221^^^^^^^^^^^^^^ 222 223The QemuSystemTest class can be used for running tests via one of the 224qemu-system-* binaries. 225 226vm 227"" 228 229A QEMUMachine instance, initially configured according to the given 230``qemu_bin`` parameter. 231 232cpu 233""" 234 235The cpu model that will be set to all QEMUMachine instances created 236by the test. 237 238machine 239""""""" 240 241The machine type that will be set to all QEMUMachine instances created 242by the test. By using the set_machine() function of the QemuSystemTest 243class to set this attribute, you can automatically check whether the 244machine is available to skip the test in case it is not built into the 245QEMU binary. 246 247Asset handling 248-------------- 249 250Many functional tests download assets (e.g. Linux kernels, initrds, 251firmware images, etc.) from the internet to be able to run tests with 252them. This imposes additional challenges to the test framework. 253 254First there is the the problem that some people might not have an 255unconstrained internet connection, so such tests should not be run by 256default when running ``make check``. To accomplish this situation, 257the tests that download files should only be added to the "thorough" 258speed mode in the meson.build file, while the "quick" speed mode is 259fine for functional tests that can be run without downloading files. 260``make check`` then only runs the quick functional tests along with 261the other quick tests from the other test suites. If you choose to 262run only run ``make check-functional``, the "thorough" tests will be 263executed, too. And to run all functional tests along with the others, 264you can use something like:: 265 266 make -j$(nproc) check SPEED=thorough 267 268The second problem with downloading files from the internet are time 269constraints. The time for downloading files should not be taken into 270account when the test is running and the timeout of the test is ticking 271(since downloading can be very slow, depending on the network bandwidth). 272This problem is solved by downloading the assets ahead of time, before 273the tests are run. This pre-caching is done with the qemu_test.Asset 274class. To use it in your test, declare an asset in your test class with 275its URL and SHA256 checksum like this:: 276 277 ASSET_somename = ( 278 ('https://www.qemu.org/assets/images/qemu_head_200.png'), 279 '34b74cad46ea28a2966c1d04e102510daf1fd73e6582b6b74523940d5da029dd') 280 281In your test function, you can then get the file name of the cached 282asset like this:: 283 284 def test_function(self): 285 file_path = self.ASSET_somename.fetch() 286 287The pre-caching will be done automatically when running 288``make check-functional`` (but not when running e.g. 289``make check-functional-<target>``). In case you just want to download 290the assets without running the tests, you can do so by running:: 291 292 make precache-functional 293 294The cache is populated in the ``~/.cache/qemu/download`` directory by 295default, but the location can be changed by setting the 296``QEMU_TEST_CACHE_DIR`` environment variable. 297 298Skipping tests 299-------------- 300 301Since the test framework is based on the common Python unittest framework, 302you can use the usual Python decorators which allow for easily skipping 303tests running under certain conditions, for example, on the lack of a binary 304on the test system or when the running environment is a CI system. For further 305information about those decorators, please refer to: 306 307 https://docs.python.org/3/library/unittest.html#skipping-tests-and-expected-failures 308 309While the conditions for skipping tests are often specifics of each one, there 310are recurring scenarios identified by the QEMU developers and the use of 311environment variables became a kind of standard way to enable/disable tests. 312 313Here is a list of the most used variables: 314 315QEMU_TEST_ALLOW_LARGE_STORAGE 316^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 317Tests which are going to fetch or produce assets considered *large* are not 318going to run unless that ``QEMU_TEST_ALLOW_LARGE_STORAGE=1`` is exported on 319the environment. 320 321The definition of *large* is a bit arbitrary here, but it usually means an 322asset which occupies at least 1GB of size on disk when uncompressed. 323 324QEMU_TEST_ALLOW_UNTRUSTED_CODE 325^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 326There are tests which will boot a kernel image or firmware that can be 327considered not safe to run on the developer's workstation, thus they are 328skipped by default. The definition of *not safe* is also arbitrary but 329usually it means a blob which either its source or build process aren't 330public available. 331 332You should export ``QEMU_TEST_ALLOW_UNTRUSTED_CODE=1`` on the environment in 333order to allow tests which make use of those kind of assets. 334 335QEMU_TEST_FLAKY_TESTS 336^^^^^^^^^^^^^^^^^^^^^ 337Some tests are not working reliably and thus are disabled by default. 338This includes tests that don't run reliably on GitLab's CI which 339usually expose real issues that are rarely seen on developer machines 340due to the constraints of the CI environment. If you encounter a 341similar situation then raise a bug and then mark the test as shown on 342the code snippet below: 343 344.. code:: 345 346 # See https://gitlab.com/qemu-project/qemu/-/issues/nnnn 347 @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') 348 def test(self): 349 do_something() 350 351Tests should not live in this state forever and should either be fixed 352or eventually removed. 353 354 355.. _unittest: https://docs.python.org/3/library/unittest.html 356