summary: Verify custom kernel command line handling in UC20

details: |
    This test checks support for customized kernel command line arguments in UC20

systems: [ubuntu-2*]

environment:
    NESTED_BUILD_SNAPD_FROM_CURRENT: true
    NESTED_ENABLE_TPM: true
    NESTED_ENABLE_SECURE_BOOT: true

prepare: |
    KEY_NAME=$(tests.nested download snakeoil-key)
    SNAKEOIL_KEY="$PWD/$KEY_NAME.key"
    SNAKEOIL_CERT="$PWD/$KEY_NAME.pem"

    echo "Grab and prepare the gadget snap"
    VERSION="$(tests.nested show version)"
    snap download --basename=pc --channel="$VERSION/edge" pc
    unsquashfs -d pc-gadget pc.snap

    echo "Sign the shim binary"
    tests.nested secboot-sign gadget pc-gadget "$SNAKEOIL_KEY" "$SNAKEOIL_CERT"

    echo 'snapd.debug=1 hello from test' > pc-gadget/cmdline.extra
    snap pack pc-gadget/ "$(tests.nested get extra-snaps-path)"

    echo 'snapd.debug=1 updated hello from test' > pc-gadget/cmdline.extra
    snap pack pc-gadget --filename=pc-gadget-cmdline-extra-updated.snap

    rm pc-gadget/cmdline.extra
    # keep the console so that we get some logging
    cat <<'EOF' > pc-gadget/cmdline.full
    snapd.debug=1
    # keep the console
    console=ttyS0
    full hello from
    test
    EOF
    snap pack pc-gadget --filename=pc-gadget-cmdline-full.snap

    rm pc-gadget/cmdline.full
    snap pack pc-gadget --filename=pc-gadget-cmdline-none.snap

    tests.nested build-image core
    tests.nested create-vm core

    for f in pc-gadget-cmdline-extra-updated.snap pc-gadget-cmdline-full.snap pc-gadget-cmdline-none.snap; do
        remote.push "$f"
    done

debug: |
    cat system.cmdline.run || true
    cat system.cmdline.recover || true

execute: |
    boot_id="$(tests.nested boot-id)"

    echo "Make sure the system is encrypted"
    # in which case the boot chains must exist
    remote.exec sudo cat /var/lib/snapd/device/fde/boot-chains

    # system is in run mode
    echo "Make sure the system is in run mode"
    remote.exec 'sudo cat /proc/cmdline' > system.cmdline.run
    MATCH snapd_recovery_mode=run < system.cmdline.run

    echo "Verify kernel command line in run mode"
    MATCH 'snapd_recovery_mode=run .* hello from test$' < system.cmdline.run

    echo "Perform an update of the gadget"
    REMOTE_CHG_ID=$(remote.exec 'sudo snap install --dangerous --no-wait ./pc-gadget-cmdline-extra-updated.snap')

    echo "Wait for reboot"
    remote.wait-for reboot "${boot_id}"
    boot_id="$(tests.nested boot-id)"
    remote.exec 'sudo cat /proc/cmdline' | MATCH 'snapd_recovery_mode=run .* updated hello from test'
    # wait for previous change to finish before proceeding
    remote.exec sudo snap watch "$REMOTE_CHG_ID"

    echo "Update to gadget with no command line"
    REMOTE_CHG_ID=$(remote.exec 'sudo snap install --dangerous --no-wait ./pc-gadget-cmdline-none.snap')
    remote.wait-for reboot "${boot_id}"
    boot_id="$(tests.nested boot-id)"
    echo "Verify that custom command line elements are not present"
    remote.exec 'sudo cat /proc/cmdline' | NOMATCH 'hello from test'
    # wait for previous change to finish before proceeding
    remote.exec sudo snap watch "$REMOTE_CHG_ID"

    echo "Update to gadget with full command line"
    REMOTE_CHG_ID=$(remote.exec 'sudo snap install --dangerous --no-wait ./pc-gadget-cmdline-full.snap')
    remote.wait-for reboot "${boot_id}"
    boot_id="$(tests.nested boot-id)"
    remote.exec 'sudo cat /proc/cmdline' | MATCH 'snapd_recovery_mode=run snapd.debug=1 console=ttyS0 full hello from test'
    # wait for previous change to finish before proceeding
    remote.exec sudo snap watch "$REMOTE_CHG_ID"

    echo "Transition to recover mode to verify kernel command line"
    remote.exec 'sudo snap reboot --recover'
    remote.wait-for reboot "${boot_id}"

    echo "Check the vm is in recover mode"
    remote.exec 'sudo cat /proc/cmdline' > system.cmdline.recover
    MATCH snapd_recovery_mode=recover < system.cmdline.recover

    MATCH 'snapd_recovery_mode=recover snapd_recovery_system=.* .* hello from test$' < system.cmdline.recover
