diff options
| -rw-r--r-- | .github/workflows/run-tests.yml | 4 | ||||
| -rw-r--r-- | CMakeLists.txt | 11 | ||||
| -rw-r--r-- | cmake/install-kernel-module.cmake | 35 | ||||
| -rw-r--r-- | drivers/ipoe/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | drivers/ppposeq/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | drivers/vlan_mon/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | tests/README.md | 21 | ||||
| -rw-r--r-- | tests/kernel-module-install/Makefile | 18 | ||||
| -rw-r--r-- | tests/kernel-module-install/test.sh | 38 |
9 files changed, 141 insertions, 4 deletions
diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 9cd47a00..22f24bdd 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -379,6 +379,10 @@ jobs: -DKDIR=/usr/src/linux-headers-`uname -r` -DLUA=TRUE -DSHAPER=TRUE -DRADIUS=TRUE .. + - name: Test kernel module installation + working-directory: ./build + run: ctest --output-on-failure -R '^kernel-module-install$' + - name: make && make install working-directory: ./build run: make && sudo make install diff --git a/CMakeLists.txt b/CMakeLists.txt index 72b5eb83..4c856491 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,3 +101,14 @@ if (BUILD_VLAN_MON_DRIVER) endif () CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) + +include(CTest) + +if (BUILD_TESTING) + add_test( + NAME kernel-module-install + COMMAND sh + ${CMAKE_CURRENT_SOURCE_DIR}/tests/kernel-module-install/test.sh + ${CMAKE_COMMAND} + ) +endif () diff --git a/cmake/install-kernel-module.cmake b/cmake/install-kernel-module.cmake new file mode 100644 index 00000000..1350e7c9 --- /dev/null +++ b/cmake/install-kernel-module.cmake @@ -0,0 +1,35 @@ +if (NOT DEFINED KERNEL_BUILD_DIR OR KERNEL_BUILD_DIR STREQUAL "") + message(FATAL_ERROR "Kernel build directory is not set") +endif () + +if (NOT DEFINED KERNEL_MODULE_BUILD_DIR OR + KERNEL_MODULE_BUILD_DIR STREQUAL "") + message(FATAL_ERROR "Kernel module build directory is not set") +endif () + +set(_install_command + make -C "${KERNEL_BUILD_DIR}" + "M=${KERNEL_MODULE_BUILD_DIR}" + modules_install +) + +# DESTDIR is the conventional CMake staging root. The kernel build system +# uses INSTALL_MOD_PATH for the same purpose, so propagate it explicitly. +if (NOT "$ENV{DESTDIR}" STREQUAL "") + list(APPEND _install_command "INSTALL_MOD_PATH=$ENV{DESTDIR}") +endif () + +execute_process( + COMMAND ${_install_command} + RESULT_VARIABLE _install_result +) + +if (NOT "${_install_result}" STREQUAL "0") + message(FATAL_ERROR + "Failed to install kernel module from " + "${KERNEL_MODULE_BUILD_DIR} (exit status: ${_install_result})" + ) +endif () + +unset(_install_command) +unset(_install_result) diff --git a/drivers/ipoe/CMakeLists.txt b/drivers/ipoe/CMakeLists.txt index d0d6902c..5bbac4f6 100644 --- a/drivers/ipoe/CMakeLists.txt +++ b/drivers/ipoe/CMakeLists.txt @@ -41,5 +41,9 @@ ADD_CUSTOM_TARGET(ipoe_drv ALL ) IF (NOT DEFINED CPACK_TYPE) - INSTALL(CODE "EXECUTE_PROCESS(COMMAND make -C ${KDIR} M=${CMAKE_CURRENT_BINARY_DIR}/drivers/ipoe modules_install)") + INSTALL(CODE " + set(KERNEL_BUILD_DIR [==[${KDIR}]==]) + set(KERNEL_MODULE_BUILD_DIR [==[${CMAKE_CURRENT_BINARY_DIR}/driver]==]) + include([==[${CMAKE_SOURCE_DIR}/cmake/install-kernel-module.cmake]==]) + ") ENDIF() diff --git a/drivers/ppposeq/CMakeLists.txt b/drivers/ppposeq/CMakeLists.txt index 08c45c76..daeffb11 100644 --- a/drivers/ppposeq/CMakeLists.txt +++ b/drivers/ppposeq/CMakeLists.txt @@ -15,5 +15,9 @@ ADD_CUSTOM_TARGET(ppposeq_drv ALL ) IF (NOT DEFINED CPACK_TYPE) - INSTALL(CODE "EXECUTE_PROCESS(COMMAND make -C ${KDIR} M=${CMAKE_CURRENT_BINARY_DIR}/driver modules_install)") + INSTALL(CODE " + set(KERNEL_BUILD_DIR [==[${KDIR}]==]) + set(KERNEL_MODULE_BUILD_DIR [==[${CMAKE_CURRENT_BINARY_DIR}/driver]==]) + include([==[${CMAKE_SOURCE_DIR}/cmake/install-kernel-module.cmake]==]) + ") ENDIF() diff --git a/drivers/vlan_mon/CMakeLists.txt b/drivers/vlan_mon/CMakeLists.txt index b4c8e348..5269805d 100644 --- a/drivers/vlan_mon/CMakeLists.txt +++ b/drivers/vlan_mon/CMakeLists.txt @@ -16,5 +16,9 @@ ADD_CUSTOM_TARGET(vlan_mon_drv ALL ) if (NOT DEFINED CPACK_TYPE) - INSTALL(CODE "EXECUTE_PROCESS(COMMAND make -C ${KDIR} M=${CMAKE_CURRENT_BINARY_DIR}/drivers/vlan_mon modules_install)") + INSTALL(CODE " + set(KERNEL_BUILD_DIR [==[${KDIR}]==]) + set(KERNEL_MODULE_BUILD_DIR [==[${CMAKE_CURRENT_BINARY_DIR}/driver]==]) + include([==[${CMAKE_SOURCE_DIR}/cmake/install-kernel-module.cmake]==]) + ") endif () diff --git a/tests/README.md b/tests/README.md index 689a16d8..65afd254 100644 --- a/tests/README.md +++ b/tests/README.md @@ -2,6 +2,25 @@ These tests are done for Ubuntu and Debian distros. Please use latest stable Debian or Ubuntu to run the tests. +## Kernel module installation test + +The kernel module installation regression test is rootless and does not need +kernel headers. It uses a fake kernel build tree to verify that `ipoe`, +`vlan_mon`, and `ppposeq` are installed from their actual build directories, +honor `DESTDIR`, and make installation fail when `modules_install` fails. + +Run it through CTest after configuring the project: + +```bash +ctest --test-dir build --output-on-failure -R '^kernel-module-install$' +``` + +It can also be run directly from the repository root: + +```bash +sh tests/kernel-module-install/test.sh cmake +``` + ## Preparations Install pytest @@ -100,4 +119,4 @@ If you want to re-run tests 'from scratch', you may want to remove coverage data # from root dir (parent for this dir) sudo gcovr -d # build report and delete sudo gcovr -d # check that data is deleted (any coverage = 0%) -```
\ No newline at end of file +``` diff --git a/tests/kernel-module-install/Makefile b/tests/kernel-module-install/Makefile new file mode 100644 index 00000000..9b8bf2bc --- /dev/null +++ b/tests/kernel-module-install/Makefile @@ -0,0 +1,18 @@ +.PHONY: kernelrelease modules modules_install + +kernelrelease: + @printf '%s\n' test-kernel + +modules: + @module=$$(basename "$$(dirname "$(M)")"); \ + printf 'test module %s\n' "$$module" > "$(M)/$$module.ko" + +modules_install: + @test "$(M)" != "" + @test -d "$(M)" + @if test "$${FAIL_MODULES_INSTALL:-0}" = 1; then exit 42; fi + @module=$$(basename "$$(dirname "$(M)")"); \ + test -f "$(M)/$$module.ko"; \ + destination="$(INSTALL_MOD_PATH)/lib/modules/test-kernel/extra"; \ + mkdir -p "$$destination"; \ + cp "$(M)/$$module.ko" "$$destination/$$module.ko" diff --git a/tests/kernel-module-install/test.sh b/tests/kernel-module-install/test.sh new file mode 100644 index 00000000..1fbfd623 --- /dev/null +++ b/tests/kernel-module-install/test.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +set -eu + +cmake_command=${1:-cmake} +script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +source_dir=$(CDPATH= cd -- "${script_dir}/../.." && pwd) +work_dir=$(mktemp -d) +trap 'rm -rf "${work_dir}"' EXIT HUP INT TERM + +"${cmake_command}" \ + -S "${source_dir}" \ + -B "${work_dir}/build" \ + -DBUILD_TESTING=OFF \ + -DBUILD_DRIVER_ONLY=TRUE \ + -DBUILD_IPOE_DRIVER=TRUE \ + -DBUILD_VLAN_MON_DRIVER=TRUE \ + -DBUILD_PPPOSEQ_DRIVER=TRUE \ + -DIGNORE_GIT=TRUE \ + -DKDIR="${script_dir}" + +"${cmake_command}" --build "${work_dir}/build" --parallel 2 + +DESTDIR="${work_dir}/stage" \ + "${cmake_command}" --install "${work_dir}/build" + +test -f "${work_dir}/stage/lib/modules/test-kernel/extra/ipoe.ko" +test -f "${work_dir}/stage/lib/modules/test-kernel/extra/vlan_mon.ko" +test -f "${work_dir}/stage/lib/modules/test-kernel/extra/ppposeq.ko" + +if FAIL_MODULES_INSTALL=1 DESTDIR="${work_dir}/failed-stage" \ + "${cmake_command}" --install "${work_dir}/build" \ + >"${work_dir}/failed-install.log" 2>&1; then + printf '%s\n' 'kernel module installation unexpectedly succeeded' >&2 + exit 1 +fi + +grep -q 'Failed to install kernel module' "${work_dir}/failed-install.log" |
