Tests ===== Efficient and thorough testing is key to ensure bpfilter is stable and reliable. As manual testing is time-consuming and error-prone, bpfilter relies on automated tests to validate its features. Different type of tests are implemented to cover all the components of the project: - Unit tests to test every function part of the public API of ``libbpfilter``. - Ent-to-end tests to validate ``bfcli``'s language, and the behaviour of the BPF programs generate by ``bpfilter``. - Integreation tests to ensure ``libbpfilter`` and the core module can be integrated into other projects without issues. - Check tests to validate code style and quality. bpfilter uses CMake and CTest to manage and run its tests, a test suite is defined for each type of test. You can run the tests using: .. code-block:: shell # Run all the tests make -C $BUILD_DIR test_bin test # Run a specific test suite ctest -C $BUILD_DIR -L $TEST_SUITE --output-on-failure # Run a single test ctest -C $BUILD_DIR -R $TEST_NAME --output-on-failure By default, CTest doesn't build the test binaries when running tests. You can build the test binaries using: ``make -C $BUILD_DIR test_bin``. Test coverage is disabled by default, to enable it, configure CMake with the ``-DWITH_COVERAGE=1`` flag. Then, you can generate a coverage report using: ``make -C $BUILD_DIR coverage doc``. Unit tests ---------- Unit tests are limited to the libbpfilter library. They are designed to validate the different components of the library in isolation, using mocks and fakes when necessary. We expect every public function of the library to be covered by at least one unit test. **Adding a new unit test** 1. Create a new source file to contain the unit test under ``tests/unit``. You can use existing unit tests as examples. Usually, a source file in ``tests/unit`` will contain tests for a single source file in ``libbpfilter``. 2. Add the new source file to the ``tests/unit/CMakeLists.txt`` file using the ``bf_add_c_test`` function. 3. Implement the unit tests using the ``cmocka`` testing library. You can use existing unit tests as examples. CMocka supports test fixtures to setup and teardown common test data. You can use them to avoid code duplication when multiple tests require the same setup. **Example** The example below is used to test the ``bf_version()`` function from ``libbpfilter``. All the tests source file must include the ``test.h`` header, define a main function, and register the tests to be run. .. code-block:: c /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ #include #include "test.h" static void get_version(void **state) { (void)state; assert_non_null(bf_version()); } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(get_version), }; return cmocka_run_group_tests(tests, NULL, NULL); } End-to-end tests ---------------- End-to-end tests are designed to validate bpfilter's behaviour as seen by the user. They cover the entire stack, from ``bfcli`` to the BPF programs generated by ``bpfilter``. End-to-end tests ensure that the filtering rules defined using ``bfcli`` are correctly translated into BPF programs, and that these programs behave as expected when executed. **Adding a new end-to-end test** 1. Create a new source file to contain the end-to-end test under ``tests/e2e``. 2. Call ``bf_add_e2e_test()`` in ``tests/e2e/CMakeLists.txt`` to add the new source file to the end-to-end test suite. 3. In your test, use the functions provided by ``e2e_test_util.sh`` to setup the test environment. Any shell command failure will stop the test immediately and return a failure. **Example** ``e2e_test_util.sh`` provides functions to create a sandboxed environment and start the ``bpfilter`` daemon. Here is an example of a simple end-to-end test that creates a sandbox and starts ``bpfilter``: .. code-block:: shell #!/usr/bin/env bash set -eux set -o pipefail . "$(dirname "$0")"/../e2e_test_util.sh make_sandbox start_bpfilter # Ping the sandbox's IPv4 address from the sandboxed namespace ${FROM_NS} ping -c 1 -W 0.1 ${NS_IP_ADDR} Integration tests ----------------- Integration tests are designed to ensure that ``libbpfilter`` and the core ``bpfilter`` module can be integrated into other projects without issues. They validate that the public API of ``libbpfilter`` is stable and behaves as expected when used in different contexts. Check tests ----------- Check tests leverage the ``clang-tidy`` and ``clang-format``` tools to ensure code quality and style consistency across the codebase. They help identify potential issues early in the development process. Any warning or error reported by these tools will cause the check tests to fail. Harness ------- The test harness is a set of convenience functions used to ease testing of bpfilter. Test ~~~~ .. doxygenfile:: test.h Mocks ~~~~~ .. doxygenfile:: mock.h Fake ~~~~ .. doxygenfile:: fake.h