1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
Tests
=====
Test harness
------------
The test harness is a set of convenience functions used to ease testing of ``bpfilter``.
Test
~~~~
.. doxygenfile:: test.h
Mocks
~~~~~
.. doxygenfile:: mock.h
Process
~~~~~~~
.. doxygenfile:: process.h
Daemon
~~~~~~~
.. doxygenfile:: daemon.h
Filters
~~~~~~~
.. doxygenfile:: filters.h
Program
~~~~~~~
.. doxygenfile:: prog.h
Unit tests
----------
.. warning::
In progress.
End-to-end tests
----------------
.. note::
The end-to-end test suite is not yet part of the ``make test`` global tests target. If the Python Scapy module is available on your system, you can run it using ``make e2e``.
End-to-end tests are designed to validate the bytecode generated by ``bpfilter``, which unit and manual tests can't do efficiently. The end-to-end tests harness will start a fresh ``bpfilter`` daemon for every test, generate a new chain, and use ``BPF_PROG_TEST_RUN`` to validate the expected behaviour. The test packets fed to the tested BPF programs are generated by the Python Scapy module (see ``tests/e2e/genpkts.py``).
Each test is run for every available hook automatically, so the BPF bytecode generated for each flavour can be validated to ensure consistent behaviour.
Similarly to the benchmarks (``make benchmark``), ``sudo`` will be used automatically if the current user doesn't have ``root`` privileges.
**Adding a new end-to-end test**
End-to-end tests are defined in ``tests/e2e`` and use ``cmocka`` as the testing library. To add a new end-to-end test:
1. Add a new ``cmocka`` test in a source file under ``tests/e2e``.
2. Create a chain: use the primitives in :ref:`developers/tests:Filters` to easily create chains, rules, and matchers. :c:struct:`bf_test_chain_get` will automatically disable attachment of the chain and generate a custom name for the BPF program prefixed with ``bf_e2e_``.
3. Run the test using :c:func:`bft_e2e_test` with the chain, the expected return value, and the generated packet name.
**Example**
The example below will create an empty chain with a default ``ACCEPT`` policy.
.. note::
While the following example defines a chain for the XDP hook, it will be overridden by :c:func:`bft_e2e_test` to be tested for every hook.
.. code-block:: c
Test(policy, accept_no_rule)
{
_free_bf_chain_ struct bf_chain *chain = bf_test_chain_get(
BF_HOOK_XDP,
BF_VERDICT_ACCEPT,
NULL,
(struct bf_rule *[]) {
NULL,
}
);
bft_e2e_test(chain, BF_VERDICT_ACCEPT, pkt_local_ip6_tcp);
}
Integration tests
-----------------
``bpfilter``'s repository contains patches to add support for ``bpfilter`` to ``nftables`` and ``iptables``. You first need to install ``nftables``' and ``iptables``' build dependencies:
.. code-block:: shell
# Fedora 40+
sudo dnf install -y autoconf automake gmp-devel libtool libedit-devel libmnl-devel libnftnl-devel
# Ubuntu 24.04
sudo apt-get install -y autoconf bison flex libedit-dev libgmp-dev libmnl-dev libnftnl-dev libtool
Then, you can build both from ``bpfilter``'s build directory:
.. code-block:: shell
make -C $BUILD_DIRECTORY integration
Once this command succeeds, ``nft`` (``nftables``'s command-line tool) and ``iptables`` are available in ``$BUILD_DIRECTORY/tools/install``.
With either ``nft`` or ``iptables``, you can now communicate directly with the ``bpfilter`` daemon instead of the kernel by using the ``--bpf`` flag. This allows your filtering rules to be translated into BPF programs by ``bpfilter``.
|