test_image_expiry() {
    # shellcheck disable=2039,3043
    local INCUS2_DIR INCUS2_ADDR
    INCUS2_DIR=$(mktemp -d -p "${TEST_DIR}" XXX)
    chmod +x "${INCUS2_DIR}"
    spawn_incus "${INCUS2_DIR}" true
    INCUS2_ADDR=$(cat "${INCUS2_DIR}/incus.addr")

    ensure_import_testimage

    token="$(incus config trust add foo -q)"
    # shellcheck disable=2153
    incus_remote remote add l1 "${INCUS_ADDR}" --accept-certificate --token "${token}"

    token="$(INCUS_DIR=${INCUS2_DIR} incus config trust add foo -q)"
    incus_remote remote add l2 "${INCUS2_ADDR}" --accept-certificate --token "${token}"

    # Create containers from a remote image in two projects.
    incus_remote project create l2:p1 -c features.images=true -c features.profiles=false
    incus_remote init l1:testimage l2:c1 --project default
    incus_remote project switch l2:p1
    incus_remote init l1:testimage l2:c2
    incus_remote project switch l2:default

    fp="$(incus_remote image info testimage | awk '/^Fingerprint/ {print $2}')"

    # Confirm the image is cached
    [ -n "${fp}" ]
    fpbrief=$(echo "${fp}" | cut -c 1-12)
    incus_remote image list l2: | grep -q "${fpbrief}"

    # Test modification of image expiry date
    incus_remote image info "l2:${fp}" | grep -q "Expires.*never"
    incus_remote image show "l2:${fp}" | sed "s/expires_at.*/expires_at: 3000-01-01T00:00:00-00:00/" | incus_remote image edit "l2:${fp}"
    incus_remote image info "l2:${fp}" | grep -q "Expires.*3000"

    # Override the upload date for the image record in the default project.
    INCUS_DIR="$INCUS2_DIR" incus admin sql global "UPDATE images SET last_use_date='$(date --rfc-3339=seconds -u -d "2 days ago")' WHERE fingerprint='${fp}' AND project_id = 1" | grep -q "Rows affected: 1"

    # Trigger the expiry
    incus_remote config set l2: images.remote_cache_expiry 1

    for _ in $(seq 20); do
        sleep 1
        ! incus_remote image list l2: | grep -q "${fpbrief}" && break
    done

    ! incus_remote image list l2: | grep -q "${fpbrief}" || false

    # Check image is still in p1 project and has not been expired.
    incus_remote image list l2: --project p1 | grep -q "${fpbrief}"

    # Test instance can still be created in p1 project.
    incus_remote project switch l2:p1
    incus_remote init l1:testimage l2:c3
    incus_remote project switch l2:default

    # Override the upload date for the image record in the p1 project.
    INCUS_DIR="$INCUS2_DIR" incus admin sql global "UPDATE images SET last_use_date='$(date --rfc-3339=seconds -u -d "2 days ago")' WHERE fingerprint='${fp}' AND project_id > 1" | grep -q "Rows affected: 1"
    incus_remote project set l2:p1 images.remote_cache_expiry=1

    # Trigger the expiry in p1 project by changing global images.remote_cache_expiry.
    incus_remote config unset l2: images.remote_cache_expiry

    for _ in $(seq 20); do
        sleep 1
        ! incus_remote image list l2: --project p1 | grep -q "${fpbrief}" && break
    done

    ! incus_remote image list l2: --project p1 | grep -q "${fpbrief}" || false

    # Cleanup and reset
    incus_remote delete -f l2:c1
    incus_remote delete -f l2:c2 --project p1
    incus_remote delete -f l2:c3 --project p1
    incus_remote project delete l2:p1
    incus_remote remote remove l1
    incus_remote remote remove l2
    kill_incus "$INCUS2_DIR"
}

test_image_list_all_aliases() {
    ensure_import_testimage
    # shellcheck disable=2039,2034,2155,3043
    local sum="$(incus image info testimage | awk '/^Fingerprint/ {print $2}')"
    incus image alias create zzz "$sum"
    incus image list | grep -vq zzz
    # both aliases are listed if the "aliases" column is included in output
    incus image list -c L | grep -q testimage
    incus image list -c L | grep -q zzz

}

test_image_import_dir() {
    ensure_import_testimage
    incus image export testimage
    # shellcheck disable=2039,2034,2155,3043
    local image="$(ls -1 -- *.tar.xz)"
    mkdir -p unpacked
    tar -C unpacked -xf "$image"
    # shellcheck disable=2039,2034,2155,3043
    local fingerprint="$(incus image import unpacked | awk '{print $NF;}')"
    rm -rf "$image" unpacked

    incus image export "$fingerprint"
    # shellcheck disable=2039,2034,2155,3043
    local exported="${fingerprint}.tar.xz"

    tar tvf "$exported" | grep -Fq metadata.yaml
    rm "$exported"
}

test_image_import_existing_alias() {
    ensure_import_testimage
    incus init testimage c
    incus publish c --alias newimage --alias image2
    incus delete c
    incus image export testimage testimage.file
    incus image delete testimage
    # the image can be imported with an existing alias
    incus image import testimage.file --alias newimage
    incus image delete newimage image2
}

test_image_import_with_reuse() {
    ensure_import_testimage
    incus init testimage c
    testimage_fingerprint="$(incus image ls -c F -f csv testimage)"
    image1_fingerprint="$(incus publish c --alias image1 | awk '{print $NF;}')"
    incus delete c
    incus image export image1 image1.file
    incus image delete image1

    incus image import image1.file.tar.gz --alias testimage --reuse

    [ "$(incus image ls -c F -f csv testimage)" = "${image1_fingerprint}" ]
    [ "$(incus image ls -c F -f csv "${testimage_fingerprint}" | wc -l)" = "0" ]

    incus image delete testimage
}

test_image_refresh() {
    # shellcheck disable=2039,3043
    local INCUS2_DIR INCUS2_ADDR
    INCUS2_DIR=$(mktemp -d -p "${TEST_DIR}" XXX)
    chmod +x "${INCUS2_DIR}"
    spawn_incus "${INCUS2_DIR}" true
    INCUS2_ADDR=$(cat "${INCUS2_DIR}/incus.addr")

    ensure_import_testimage

    token="$(INCUS_DIR=${INCUS2_DIR} incus config trust add foo -q)"
    incus_remote remote add l2 "${INCUS2_ADDR}" --accept-certificate --token "${token}"

    poolDriver="$(incus storage show "$(incus profile device get default root pool)" | awk '/^driver:/ {print $2}')"

    # Publish image
    incus image copy testimage l2: --alias testimage --public
    fp="$(incus image info l2:testimage | awk '/Fingerprint: / {print $2}')"
    incus image rm testimage

    # Create container from published image
    incus init l2:testimage c1

    # Create an alias for the received image
    incus image alias create testimage "${fp}"

    # Change image and publish it
    incus init l2:testimage l2:c1
    echo test | incus file push - l2:c1/tmp/testfile
    incus publish l2:c1 l2: --alias testimage --reuse --public
    new_fp="$(incus image info l2:testimage | awk '/Fingerprint: / {print $2}')"

    # Ensure the images differ
    [ "${fp}" != "${new_fp}" ]

    # Check original image exists before refresh.
    incus image info "${fp}"

    if [ "${poolDriver}" != "dir" ]; then
        # Check old storage volume record exists and new one doesn't.
        incus admin sql global 'select name from storage_volumes' | grep "${fp}"
        ! incus admin sql global 'select name from storage_volumes' | grep "${new_fp}" || false
    fi

    # Refresh image
    incus image refresh testimage

    # Ensure the old image is gone.
    ! incus image info "${fp}" || false

    if [ "${poolDriver}" != "dir" ]; then
        # Check old storage volume record has been replaced with new one.
        ! incus admin sql global 'select name from storage_volumes' | grep "${fp}" || false
        incus admin sql global 'select name from storage_volumes' | grep "${new_fp}"
    fi

    # Cleanup
    incus rm l2:c1
    incus rm c1
    incus remote rm l2
    kill_incus "${INCUS2_DIR}"
}

test_image_split() {
    ensure_import_testimage
    incus init testimage c
    incus publish c --alias splitimage --format=split
    incus delete c
    incus image export splitimage splitimage.file
    incus image delete splitimage
    incus image import splitimage.file splitimage.file.root --alias splitimage
    incus init splitimage c
    incus delete c
    incus image delete splitimage
}
