summary: Create ubuntu core image, install snapd and test hotplug feature

details: |
    Check that when a device is plugged the hotplug slot is present, and when it
    is unplugged, the slot is no longer present. Also validates a snap can be
    connected to the device and serial-port permissions of the snap are correct.

systems: [ubuntu-1*]

prepare: |
    snap pack "$TESTSLIB"/snaps/serial-port-hotplug
    remote.push serial-port-hotplug_1.0_all.snap

restore: |
    rm -f /tmp/serialport{0,1}

debug: |
    remote.exec "snap connections --all" || true
    remote.exec "snap list" || true
    remote.exec "dmesg" || true
    remote.exec 'sudo cat /var/lib/snapd/state.json' | gojq -r '.data["hotplug-slots"]' || true

execute: |
    #shellcheck source=tests/lib/nested.sh
    . "$TESTSLIB/nested.sh"
    #shellcheck source=tests/lib/hotplug.sh
    . "$TESTSLIB/hotplug.sh"

    if [ "$NESTED_BUILD_SNAPD_FROM_CURRENT" != "true" ] && [ "$NESTED_CORE_REFRESH_CHANNEL" != "$NESTED_CORE_CHANNEL" ]; then
        echo "Refresh core snap to desired channel"
        nested_refresh_to_new_core "$NESTED_CORE_REFRESH_CHANNEL"
    fi

    if remote.exec "udevadm info -e" | MATCH "ID_MODEL=QEMU_USB_SERIAL"; then
        echo "USB serial already registered, exiting..."
        exit 1
    fi

    echo "Enabling hotplug"
    remote.exec "sudo snap set core experimental.hotplug=true"

    echo "Plugging the device"
    hotplug_add_dev1

    # precondition checks to make sure qemu setup is correct
    remote.exec "retry --wait 1 -n 5 sh -c 'udevadm info -e | MATCH ID_MODEL=QEMU_USB_SERIAL'"

    remote.exec "ls /dev/tty*" | MATCH "ttyUSB0"

    echo "Checking that qemuusbserial hotplug slot is present"
    check_slot_present qemuusbserial
    check_slot_not_gone qemuusbserial
    check_slot_device_path qemuusbserial "/dev/ttyUSB0"

    echo "Unplugging the device with no connections on the slot"
    hotplug_del_dev1

    # precondition check to make sure qemu event was triggered correctly
    remote.exec "retry --wait 1 -n 5 sh -c 'udevadm info -e | NOMATCH ID_MODEL=QEMU_USB_SERIAL'"
    if remote.exec "udevadm info -e" | MATCH "ID_MODEL=QEMU_USB_SERIAL"; then
        echo "USB serial should not be registered anymore, exiting..."
        exit 1
    fi

    echo "Checking that hotplug slot is no longer present"
    check_slot_not_present qemuusbserial
    check_slot_not_present_in_state qemuusbserial

    echo "Plugging the device back"
    hotplug_add_dev1

    echo "Checking that qemuusbserial hotplug slot is present again"
    check_slot_present qemuusbserial

    echo "Installing test snap with serial port plug"
    remote.exec "sudo snap install --dangerous serial-port-hotplug_1.0_all.snap"

    echo "Connecting hotplug slot of the first device"
    remote.exec "sudo snap connect serial-port-hotplug:serial-port :qemuusbserial"
    check_slot_connected qemuusbserial

    echo "Verifying serial-port permissions of the snap"
    verify_apparmor_profile "/dev/ttyUSB0"

    echo "Unplugging the device"
    hotplug_del_dev1

    echo "Checking that qemuusbserial hotplug slot is no longer present, but is remembered"
    check_slot_not_present qemuusbserial
    check_slot_gone qemuusbserial

    echo "Plugging device back, checking that the slot and connection are restored"
    hotplug_add_dev1
    check_slot_connected qemuusbserial
    check_slot_not_gone qemuusbserial

    echo "Unplugging the device again"
    hotplug_del_dev1

    echo "Checking that qemuusbserial hotplug slot is not present, but is still remembered"
    check_slot_not_present qemuusbserial
    check_slot_gone qemuusbserial

    echo "Plugging second device creates a slot with new name and it's expected on /dev/ttyUSB0"
    hotplug_add_dev2
    check_slot_present qemuusbserial-1
    check_slot_not_gone qemuusbserial-1
    check_slot_device_path qemuusbserial-1 "/dev/ttyUSB0"

    echo "Plugging first device back while second device is present, checking that connection is restored"
    hotplug_add_dev1
    check_slot_connected qemuusbserial
    check_slot_not_gone qemuusbserial

    echo "Verifying serial-port permissions of the snap, the first device is now expected on ttyUSB1"
    check_slot_device_path qemuusbserial "/dev/ttyUSB1"
    verify_apparmor_profile "/dev/ttyUSB1"

    echo "Restarting snapd should restore both hotplug slots since devices are still present"
    remote.exec "sudo systemctl stop snapd.service snapd.socket"
    remote.exec "sudo systemctl start snapd.service snapd.socket"
    check_slot_connected qemuusbserial
    check_slot_not_gone qemuusbserial
    check_slot_present qemuusbserial-1

    echo "Unplugging first device while snapd is stopped and then starting snapd remembers the slot internally due to connection"
    remote.exec "sudo systemctl stop snapd.service snapd.socket"
    hotplug_del_dev1
    remote.exec "sudo systemctl start snapd.service snapd.socket"
    check_slot_not_present qemuusbserial
    check_slot_gone qemuusbserial

    echo "Plugging first device back restores the slot and connection"
    hotplug_add_dev1
    check_slot_connected qemuusbserial
    check_slot_not_gone qemuusbserial

    echo "Disconnecting first slot and then unplugging the device removes the slot completely"
    # manual snap disconnect doesn't implement retry and errors out if there are conflicting changes, so wait for hotplug changes to complete
    wait_for_all_changes
    remote.exec "sudo snap disconnect serial-port-hotplug:serial-port :qemuusbserial"
    check_slot_present qemuusbserial
    hotplug_del_dev1
    check_slot_not_present qemuusbserial
    check_slot_not_present_in_state qemuusbserial

    echo "Unplugging second device removes the slot completely"
    hotplug_del_dev2
    check_slot_not_present qemuusbserial-1
    check_slot_not_present_in_state qemuusbserial-1

    echo "Plugging device back creates the slot again"
    hotplug_add_dev1
    check_slot_present qemuusbserial
    check_slot_not_gone qemuusbserial
    check_slot_device_path qemuusbserial "/dev/ttyUSB0"

    echo "Connecting hotplug slot of the first device again"
    remote.exec "sudo snap connect serial-port-hotplug:serial-port :qemuusbserial"
    check_slot_connected qemuusbserial

    echo "Hotplug slot stays after removing the snap"
    remote.exec "sudo snap remove serial-port-hotplug"
    check_slot_present qemuusbserial
    check_slot_not_gone qemuusbserial
