xref: /dpdk/doc/guides/tools/dts.rst (revision 3fbb93cff3be23a45fc1ec524f83d001a30df273)
1..  SPDX-License-Identifier: BSD-3-Clause
2    Copyright(c) 2022-2023 PANTHEON.tech s.r.o.
3    Copyright(c) 2024 Arm Limited
4
5DPDK Test Suite
6===============
7
8The DPDK Test Suite, abbreviated DTS, is a Python test framework with test suites
9implementing functional and performance tests used to test DPDK.
10
11
12DTS Terminology
13---------------
14
15DTS node
16   A generic description of any host/server DTS connects to.
17
18DTS runtime environment
19   An environment containing Python with packages needed to run DTS.
20
21DTS runtime environment node
22  A node where at least one DTS runtime environment is present.
23  This is the node where we run DTS and from which DTS connects to other nodes.
24
25System under test
26  An SUT is the combination of DPDK and the hardware we're testing
27  in conjunction with DPDK (NICs, crypto and other devices).
28
29System under test node
30  A node where at least one SUT is present.
31
32Traffic generator
33  A TG is either software or hardware capable of sending packets.
34
35Traffic generator node
36  A node where at least one TG is present.
37  In case of hardware traffic generators, the TG and the node are literally the same.
38
39
40In most cases, interchangeably referring to a runtime environment, SUT, TG or the node
41they're running on (e.g. using SUT and SUT node interchangeably) doesn't cause confusion.
42There could theoretically be more than of these running on the same node and in that case
43it's useful to have stricter definitions.
44An example would be two different traffic generators (such as Trex and Scapy)
45running on the same node.
46A different example would be a node containing both a DTS runtime environment
47and a traffic generator, in which case it's both a DTS runtime environment node and a TG node.
48
49
50DTS Environment
51---------------
52
53DTS is written entirely in Python using a variety of dependencies.
54DTS uses Poetry as its Python dependency management.
55Python build/development and runtime environments are the same and DTS development environment,
56DTS runtime environment or just plain DTS environment are used interchangeably.
57
58.. _dts_deps:
59
60Setting up DTS environment
61~~~~~~~~~~~~~~~~~~~~~~~~~~
62
63#. **Python Version**
64
65   The Python Version required by DTS is specified in ``dts/pyproject.toml`` in the
66   **[tool.poetry.dependencies]** section:
67
68   .. literalinclude:: ../../../dts/pyproject.toml
69      :language: cfg
70      :start-at: [tool.poetry.dependencies]
71      :end-at: python
72
73   The Python dependency manager DTS uses, Poetry, doesn't install Python, so you may need
74   to satisfy this requirement by other means if your Python is not up-to-date.
75   A tool such as `Pyenv <https://github.com/pyenv/pyenv>`_ is a good way to get Python,
76   though not the only one.
77
78#. **Poetry**
79
80   The typical style of python dependency management, pip with ``requirements.txt``,
81   has a few issues.
82   The advantages of Poetry include specifying what Python version is required and forcing you
83   to specify versions, enforced by a lockfile, both of which help prevent broken dependencies.
84   Another benefit is the usage of ``pyproject.toml``, which has become the standard config file
85   for python projects, improving project organization.
86   To install Poetry, visit their `doc pages <https://python-poetry.org/docs/>`_.
87   The recommended Poetry version is at least 1.8.2.
88
89#. **Getting a Poetry shell**
90
91   Once you have Poetry along with the proper Python version all set up, it's just a matter
92   of installing dependencies via Poetry and using the virtual environment Poetry provides:
93
94   .. code-block:: console
95
96      poetry install
97      poetry shell
98
99#. **SSH Connection**
100
101   DTS uses the Fabric Python library for SSH connections between DTS environment
102   and the other hosts.
103   The authentication method used is pubkey authentication.
104   Fabric tries to use a passed key/certificate,
105   then any key it can with through an SSH agent,
106   then any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in ``~/.ssh/``
107   (with any matching OpenSSH-style certificates).
108   DTS doesn't pass any keys, so Fabric tries to use the other two methods.
109
110
111Setting up System Under Test
112----------------------------
113
114There are two areas that need to be set up on a System Under Test:
115
116#. **DPDK dependencies**
117
118   DPDK will be built and run on the SUT.
119   Consult the Getting Started guides for the list of dependencies for each distribution.
120
121#. **Hardware dependencies**
122
123   Any hardware DPDK uses needs a proper driver
124   and most OS distributions provide those, but the version may not be satisfactory.
125   It's up to each user to install the driver they're interested in testing.
126   The hardware also may also need firmware upgrades, which is also left at user discretion.
127
128#. **Hugepages**
129
130   There are two ways to configure hugepages:
131
132   * DTS configuration
133
134     You may specify the optional hugepage configuration in the DTS config file.
135     If you do, DTS will take care of configuring hugepages,
136     overwriting your current SUT hugepage configuration.
137     Configuration of hugepages via DTS allows only for allocation of 2MB hugepages,
138     as doing so prevents accidental/over allocation of hugepage sizes
139     not recommended during runtime due to contiguous memory space requirements.
140     Thus, if you require hugepage sizes not equal to 2MB,
141     then this configuration must be done outside of the DTS framework.
142
143   * System under test configuration
144
145     It's possible to use the hugepage configuration already present on the SUT.
146     If you wish to do so, don't specify the hugepage configuration in the DTS config file.
147
148#. **User with administrator privileges**
149
150.. _sut_admin_user:
151
152   DTS needs administrator privileges to run DPDK applications (such as testpmd) on the SUT.
153   The SUT user must be able run commands in privileged mode without asking for password.
154   On most Linux distributions, it's a matter of setting up passwordless sudo:
155
156   #. Run ``sudo visudo`` and check that it contains ``%sudo	ALL=(ALL:ALL) NOPASSWD:ALL``.
157
158   #. Add the SUT user to the sudo group with:
159
160   .. code-block:: console
161
162      sudo usermod -aG sudo <sut_user>
163
164
165Setting up Traffic Generator Node
166---------------------------------
167
168These need to be set up on a Traffic Generator Node:
169
170#. **Traffic generator dependencies**
171
172   The traffic generator running on the traffic generator node must be installed beforehand.
173   For Scapy traffic generator, only a few Python libraries need to be installed:
174
175   .. code-block:: console
176
177      sudo apt install python3-pip
178      sudo pip install --upgrade pip
179      sudo pip install scapy==2.5.0
180
181#. **Hardware dependencies**
182
183   The traffic generators, like DPDK, need a proper driver and firmware.
184   The Scapy traffic generator doesn't have strict requirements - the drivers that come
185   with most OS distributions will be satisfactory.
186
187
188#. **User with administrator privileges**
189
190   Similarly to the System Under Test, traffic generators need administrator privileges
191   to be able to use the devices.
192   Refer to the `System Under Test section <sut_admin_user>` for details.
193
194
195Running DTS
196-----------
197
198DTS needs to know which nodes to connect to and what hardware to use on those nodes.
199Once that's configured, either a DPDK source code tarball or tree folder
200need to be supplied whether these are on your DTS host machine or the SUT node.
201DTS can accept a pre-compiled build placed in a subdirectory,
202or it will compile DPDK on the SUT node,
203and then run the tests with the newly built binaries.
204
205
206Configuring DTS
207~~~~~~~~~~~~~~~
208
209DTS configuration is split into nodes and test runs,
210and must respect the model definitions
211as documented in the DTS API docs under the ``config`` page.
212The root of the configuration is represented by the ``Configuration`` model.
213By default, DTS will try to use the ``dts/conf.yaml`` :ref:`config file <configuration_example>`,
214which is a template that illustrates what can be configured in DTS.
215
216The user must have :ref:`administrator privileges <sut_admin_user>`
217which don't require password authentication.
218
219
220DTS Execution
221~~~~~~~~~~~~~
222
223DTS is run with ``main.py`` located in the ``dts`` directory after entering Poetry shell:
224
225.. code-block:: console
226
227   (dts-py3.10) $ ./main.py --help
228   usage: main.py [-h] [--config-file FILE_PATH] [--output-dir DIR_PATH] [-t SECONDS] [-v] [--dpdk-tree DIR_PATH | --tarball FILE_PATH] [--remote-source]
229                  [--precompiled-build-dir DIR_NAME] [--compile-timeout SECONDS] [--test-suite TEST_SUITE [TEST_CASES ...]] [--re-run N_TIMES]
230                  [--random-seed NUMBER]
231
232   Run DPDK test suites. All options may be specified with the environment variables provided in brackets. Command line arguments have higher priority.
233
234   options:
235     -h, --help            show this help message and exit
236     --config-file FILE_PATH
237                           [DTS_CFG_FILE] The configuration file that describes the test cases, SUTs and DPDK build configs. (default: conf.yaml)
238     --output-dir DIR_PATH, --output DIR_PATH
239                           [DTS_OUTPUT_DIR] Output directory where DTS logs and results are saved. (default: output)
240     -t SECONDS, --timeout SECONDS
241                           [DTS_TIMEOUT] The default timeout for all DTS operations except for compiling DPDK. (default: 15)
242     -v, --verbose         [DTS_VERBOSE] Specify to enable verbose output, logging all messages to the console. (default: False)
243     --compile-timeout SECONDS
244                           [DTS_COMPILE_TIMEOUT] The timeout for compiling DPDK. (default: 1200)
245     --test-suite TEST_SUITE [TEST_CASES ...]
246                           [DTS_TEST_SUITES] A list containing a test suite with test cases. The first parameter is the test suite name, and the rest are
247                           test case names, which are optional. May be specified multiple times. To specify multiple test suites in the environment
248                           variable, join the lists with a comma. Examples: --test-suite suite case case --test-suite suite case ... |
249                           DTS_TEST_SUITES='suite case case, suite case, ...' | --test-suite suite --test-suite suite case ... | DTS_TEST_SUITES='suite,
250                           suite case, ...' (default: [])
251     --re-run N_TIMES, --re_run N_TIMES
252                           [DTS_RERUN] Re-run each test case the specified number of times if a test failure occurs. (default: 0)
253     --random-seed NUMBER  [DTS_RANDOM_SEED] The seed to use with the pseudo-random generator. If not specified, the configuration value is used instead.
254                           If that's also not specified, a random seed is generated. (default: None)
255
256   DPDK Build Options:
257     Arguments in this group (and subgroup) will be applied to a DPDKLocation when the DPDK tree, tarball or revision will be provided, other arguments
258     like remote source and build dir are optional. A DPDKLocation from settings are used instead of from config if construct successful.
259
260     --dpdk-tree DIR_PATH  [DTS_DPDK_TREE] The path to the DPDK source tree directory to test. Cannot be used in conjunction with --tarball. (default:
261                             None)
262     --tarball FILE_PATH, --snapshot FILE_PATH
263                           [DTS_DPDK_TARBALL] The path to the DPDK source tarball to test. DPDK must be contained in a folder with the same name as the
264                           tarball file. Cannot be used in conjunction with --dpdk-tree. (default: None)
265     --remote-source       [DTS_REMOTE_SOURCE] Set this option if either the DPDK source tree or tarball to be used are located on the SUT node. Can only
266                           be used with --dpdk-tree or --tarball. (default: False)
267     --precompiled-build-dir DIR_NAME
268                           [DTS_PRECOMPILED_BUILD_DIR] Define the subdirectory under the DPDK tree root directory where the pre-compiled binaries are
269                           located. If set, DTS will build DPDK under the `build` directory instead. Can only be used with --dpdk-tree or --tarball.
270                           (default: None)
271
272
273The brackets contain the names of environment variables that set the same thing.
274The minimum DTS needs is a config file and a pre-built DPDK
275or DPDK sources location which can be specified in said config file
276or on the command line or environment variables.
277
278
279DTS Results
280~~~~~~~~~~~
281
282Results are stored in the output dir by default
283which be changed with the ``--output-dir`` command line argument.
284The results contain basic statistics of passed/failed test cases and DPDK version.
285
286
287Contributing to DTS
288-------------------
289
290There are two areas of contribution: The DTS framework and DTS test suites.
291
292The framework contains the logic needed to run test cases, such as connecting to nodes,
293running DPDK applications and collecting results.
294
295The test cases call APIs from the framework to test their scenarios.
296Adding test cases may require adding code to the framework as well.
297
298
299Framework Coding Guidelines
300~~~~~~~~~~~~~~~~~~~~~~~~~~~
301
302When adding code to the DTS framework, pay attention to the rest of the code
303and try not to divert much from it.
304The :ref:`DTS developer tools <dts_dev_tools>` will issue warnings
305when some of the basics are not met.
306You should also build the :ref:`API documentation <building_api_docs>`
307to address any issues found during the build.
308
309The API documentation, which is a helpful reference when developing, may be accessed
310in the code directly or generated with the :ref:`API docs build steps <building_api_docs>`.
311When adding new files or modifying the directory structure,
312the corresponding changes must be made to DTS API doc sources in ``doc/api/dts``.
313
314Speaking of which, the code must be properly documented with docstrings.
315The style must conform to the `Google style
316<https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings>`_.
317See an example of the style `here
318<https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html>`_.
319For cases which are not covered by the Google style, refer to `PEP 257
320<https://peps.python.org/pep-0257/>`_.
321There are some cases which are not covered by the two style guides,
322where we deviate or where some additional clarification is helpful:
323
324   * The ``__init__()`` methods of classes are documented separately
325     from the docstring of the class itself.
326   * The docstrings of implemented abstract methods should refer to the superclass's definition
327     if there's no deviation.
328   * Instance variables/attributes should be documented in the docstring of the class
329     in the ``Attributes:`` section.
330   * The ``dataclass.dataclass`` decorator changes how the attributes are processed.
331     The dataclass attributes which result in instance variables/attributes
332     should also be recorded in the ``Attributes:`` section.
333   * Class variables/attributes and Pydantic model fields, on the other hand,
334     should be documented with ``#:`` above the type annotated line.
335     The description may be omitted if the meaning is obvious.
336   * The ``Enum`` and ``TypedDict`` also process the attributes in particular ways
337     and should be documented with ``#:`` as well.
338     This is mainly so that the autogenerated documentation contains the assigned value.
339   * When referencing a parameter of a function or a method in their docstring,
340     don't use any articles and put the parameter into single backticks.
341     This mimics the style of `Python's documentation <https://docs.python.org/3/index.html>`_.
342   * When specifying a value, use double backticks::
343
344        def foo(greet: bool) -> None:
345            """Demonstration of single and double backticks.
346
347            `greet` controls whether ``Hello World`` is printed.
348
349            Args:
350               greet: Whether to print the ``Hello World`` message.
351            """
352            if greet:
353               print(f"Hello World")
354
355   * The docstring maximum line length is the same as the code maximum line length.
356
357
358How To Write a Test Suite
359-------------------------
360
361All test suites inherit from ``TestSuite`` defined in ``dts/framework/test_suite.py``.
362There are four types of methods that comprise a test suite:
363
364#. **Test cases**
365
366   | Test cases are methods that start with a particular prefix.
367   | Functional test cases start with ``test_``, e.g. ``test_hello_world_single_core``.
368   | Performance test cases start with ``test_perf_``, e.g. ``test_perf_nic_single_core``.
369   | A test suite may have any number of functional and/or performance test cases.
370     However, these test cases must test the same feature,
371     following the rule of one feature = one test suite.
372     Test cases for one feature don't need to be grouped in just one test suite, though.
373     If the feature requires many testing scenarios to cover,
374     the test cases would be better off spread over multiple test suites
375     so that each test suite doesn't take too long to execute.
376
377#. **Setup and Teardown methods**
378
379   | There are setup and teardown methods for the whole test suite and each individual test case.
380   | Methods ``set_up_suite`` and ``tear_down_suite`` will be executed
381     before any and after all test cases have been executed, respectively.
382   | Methods ``set_up_test_case`` and ``tear_down_test_case`` will be executed
383     before and after each test case, respectively.
384   | These methods don't need to be implemented if there's no need for them in a test suite.
385     In that case, nothing will happen when they are executed.
386
387#. **Configuration, traffic and other logic**
388
389   The ``TestSuite`` class contains a variety of methods for anything that
390   a test suite setup, a teardown, or a test case may need to do.
391
392   The test suites also frequently use a DPDK app, such as testpmd, in interactive mode
393   and use the interactive shell instances directly.
394
395   These are the two main ways to call the framework logic in test suites.
396   If there's any functionality or logic missing from the framework,
397   it should be implemented so that the test suites can use one of these two ways.
398
399#. **Test case verification**
400
401   Test case verification should be done with the ``verify`` method, which records the result.
402   The method should be called at the end of each test case.
403
404#. **Other methods**
405
406   Of course, all test suite code should adhere to coding standards.
407   Only the above methods will be treated specially and any other methods may be defined
408   (which should be mostly private methods needed by each particular test suite).
409   Any specific features (such as NIC configuration) required by a test suite
410   should be implemented in the ``SutNode`` class (and the underlying classes that ``SutNode`` uses)
411   and used by the test suite via the ``sut_node`` field.
412
413
414.. _dts_dev_tools:
415
416DTS Developer Tools
417-------------------
418
419There are three tools used in DTS to help with code checking, style and formatting:
420
421* `isort <https://pycqa.github.io/isort/>`_
422
423  Alphabetically sorts python imports within blocks.
424
425* `black <https://github.com/psf/black>`_
426
427  Does most of the actual formatting (whitespaces, comments, line length etc.)
428  and works similarly to clang-format.
429
430* `pylama <https://github.com/klen/pylama>`_
431
432  Runs a collection of python linters and aggregates output.
433  It will run these tools over the repository:
434
435  .. literalinclude:: ../../../dts/pyproject.toml
436     :language: cfg
437     :start-after: [tool.pylama]
438     :end-at: linters
439
440* `mypy <https://github.com/python/mypy>`_
441
442  Enables static typing for Python, exploiting the type hints in the source code.
443
444These three tools are all used in ``devtools/dts-check-format.sh``,
445the DTS code check and format script.
446Refer to the script for usage: ``devtools/dts-check-format.sh -h``.
447
448
449.. _building_api_docs:
450
451Building DTS API docs
452---------------------
453
454The documentation is built using the standard DPDK build system.
455See :doc:`../linux_gsg/build_dpdk` for more details on compiling DPDK with meson.
456
457The :ref:`doc build dependencies <doc_dependencies>` may be installed with Poetry:
458
459.. code-block:: console
460
461   poetry install --only docs
462   poetry install --with docs  # an alternative that will also install DTS dependencies
463   poetry shell
464
465After executing the meson command, build the documentation with:
466
467.. code-block:: console
468
469   ninja -C build doc
470
471The output is generated in ``build/doc/api/dts/html``.
472
473.. note::
474
475   Make sure to fix any Sphinx warnings when adding or updating docstrings.
476
477.. _configuration_example:
478
479Configuration Example
480---------------------
481
482The following example (which can be found in ``dts/conf.yaml``) sets up two nodes:
483
484* ``SUT1`` which is already setup with the DPDK build requirements and any other
485  required for execution;
486* ``TG1`` which already has Scapy installed in the system.
487
488And they both have two network ports which are physically connected to each other.
489
490.. note::
491   This example assumes that you have setup SSH keys in both the system under test
492   and traffic generator nodes.
493
494.. literalinclude:: ../../../dts/conf.yaml
495   :language: yaml
496   :start-at: test_runs:
497