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:`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``.