summary: Ensure that the kernel-module-load interface works.

details: |
    The kernel-module-load interface allows to statically control kernel module
    loading in a way that can be constrained via snap-declaration.

environment:
    SNAP_NAME: test-snapd-kernel-module-load

prepare: |
    "$TESTSTOOLS"/snaps-state install-local $SNAP_NAME

restore: |
    echo "Ensure snap is removed even if something goes wrong"
    snap remove "$SNAP_NAME"
    modprobe -r xcbc md4 wp512 || true

execute: |
    echo "When the interface is connected"
    snap connect "$SNAP_NAME:kernel-module-load"

    echo "Then the kernel modules are configured"
    MODPROBE_CONF="/etc/modprobe.d/snap.$SNAP_NAME.conf"
    MATCH "blacklist mymodule" < "$MODPROBE_CONF"
    MATCH "blacklist other_module" < "$MODPROBE_CONF"
    MATCH "options bfq slice_idle_us=20 strict_guarantees=1" < "$MODPROBE_CONF"
    NOMATCH "blacklist bfq" < "$MODPROBE_CONF"
    NOMATCH "pcspkr" < "$MODPROBE_CONF"
    MATCH "options md4 something=ok" < "$MODPROBE_CONF"
    # This has the "*" value for the options: no entry should be written:
    NOMATCH "wp512" < "$MODPROBE_CONF"

    echo "And modules are configured to be auto-loaded"
    MODULES_LOAD_CONF="/etc/modules-load.d/snap.$SNAP_NAME.conf"
    MATCH "bfq" < "$MODULES_LOAD_CONF"
    MATCH "arc4" < "$MODULES_LOAD_CONF"
    NOMATCH "mymodule" < "$MODULES_LOAD_CONF"
    NOMATCH "md4" < "$MODULES_LOAD_CONF"
    NOMATCH "wp512" < "$MODULES_LOAD_CONF"

    echo "Test dynamic loading of kernel modules"
    test-snapd-kernel-module-load.cmd snapctl kmod insert xcbc
    test-snapd-kernel-module-load.cmd snapctl kmod insert md4
    test-snapd-kernel-module-load.cmd snapctl kmod insert wp512
    MATCH "^xcbc " < /proc/modules
    MATCH "^md4 " < /proc/modules
    MATCH "^wp512 " < /proc/modules

    echo "Test unloading"
    test-snapd-kernel-module-load.cmd snapctl kmod remove xcbc
    test-snapd-kernel-module-load.cmd snapctl kmod remove md4
    test-snapd-kernel-module-load.cmd snapctl kmod remove wp512
    NOMATCH "^xcbc " < /proc/modules
    NOMATCH "^md4 " < /proc/modules
    NOMATCH "^wp512 " < /proc/modules

    echo "Test loading with options"
    if test-snapd-kernel-module-load.cmd snapctl kmod insert xcbc option=value; then
        echo "Should not be able to specify parameters for xcbc module!"
        exit 1
    fi
    # Even if the options match those from the interface, we don't allow them
    if test-snapd-kernel-module-load.cmd snapctl kmod insert md4 something=ok; then
        echo "Should not be able to specify parameters for md4 module!"
        exit 1
    fi
    test-snapd-kernel-module-load.cmd snapctl kmod insert wp512 opt1=v1 opt2=v2
    MATCH "^wp512 " < /proc/modules

    echo "Disconnect the interface"
    snap disconnect "$SNAP_NAME:kernel-module-load"

    echo "and verify that module configuration files are gone"
    test ! -f "$MODPROBE_CONF"
    test ! -f "$MODULES_LOAD_CONF"

    echo "Check that snapctl cannot be invoked with the disconnected interface"
    test-snapd-kernel-module-load.cmd snapctl kmod insert xcbc 2>&1 \
        | MATCH ".*cannot load module \"xcbc\": required interface not connected"

    # Now we want to verify that removing the snap does not leave any leftovers
    echo "Reconnect the interface"
    snap connect "$SNAP_NAME:kernel-module-load"

    echo "Configuration files have been recreated"
    test -f "$MODPROBE_CONF"
    test -f "$MODULES_LOAD_CONF"

    echo "Uninstall the snap"
    snap remove "$SNAP_NAME"

    echo "verify that module configuration files are gone"
    test ! -f "$MODPROBE_CONF"
    test ! -f "$MODULES_LOAD_CONF"
