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