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