#!/bin/dash

# Copyright (C) 2011  Loïc Minier <lool@dooz.org>

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
# USA.

# Let the function library know that it is called from the testsuite.
FK_TESTSUITE_RUNNING="yes"

. ./testlib

functions="${FK_CHECKOUT:-$FK_DIR}/functions"

test_syntax() {
    sh -n "$functions"
}
add_test test_syntax

test_mtdblock() {
    get_tempfile
    mock_proc_mtd="$last_tempfile"
    cat >"$mock_proc_mtd" <<EOF
dev:    size   erasesize  name
mtd0: 00580000 00020000 "root"
mtd1: 00100000 00020000 "kernel"
mtd2: 00160000 00020000 "initrd"
mtd3: 00020000 00020000 "reset"
mtd4: 00800000 00020000 "jffs2"
EOF
    (
        . "$functions"
        PROC_MTD="$mock_proc_mtd"
        root_mtd=$(mtdblock "root")
        if [ "$root_mtd" != "/dev/mtdblock0" ]; then
            echo "Expected root mtd to be /dev/mtdblock0 but got $root_mtd" >&2
            exit 1
        fi
        jffs2_mtd=$(mtdblock "jffs2")
        if [ "$jffs2_mtd" != "/dev/mtdblock4" ]; then
            echo "Expected jffs2 mtd to be /dev/mtdblock4 but got $jffs2_mtd" >&2
            exit 1
        fi
    )
}
add_test test_mtdblock

test_mtdchar() {
    get_tempfile
    mock_proc_mtd="$last_tempfile"
    cat >"$mock_proc_mtd" <<EOF
dev:    size   erasesize  name
mtd0: 00580000 00020000 "root"
mtd1: 00100000 00020000 "kernel"
mtd2: 00160000 00020000 "initrd"
mtd3: 00020000 00020000 "reset"
mtd4: 00800000 00020000 "jffs2"
EOF
    (
        . "$functions"
        PROC_MTD="$mock_proc_mtd"
        root_mtd=$(mtdchar "root")
        if [ "$root_mtd" != "/dev/mtd0" ]; then
            echo "Expected root mtd to be /dev/mtd0 but got $root_mtd" >&2
            exit 1
        fi
        jffs2_mtd=$(mtdchar "jffs2")
        if [ "$jffs2_mtd" != "/dev/mtd4" ]; then
            echo "Expected jffs2 mtd to be /dev/mtd4 but got $jffs2_mtd" >&2
            exit 1
        fi
    )
}
add_test test_mtdchar

test_mtdsize() {
    get_tempfile
    mock_proc_mtd="$last_tempfile"
    cat >"$mock_proc_mtd" <<EOF
dev:    size   erasesize  name
mtd0: 00580000 00020000 "root"
mtd1: 00100000 00020000 "kernel"
mtd2: 00160000 00020000 "initrd"
mtd3: 00020000 00020000 "reset"
mtd4: 00800000 00020000 "jffs2"
EOF
    (
        . "$functions"
        PROC_MTD="$mock_proc_mtd"
        root_size=$(mtdsize "root")
        if [ "$root_size" != 5767168 ]; then
            echo "Expected root size of 5767168 but got $root_size" >&2
            exit 1
        fi
        jffs2_size=$(mtdsize "jffs2")
        if [ "$jffs2_size" != 8388608 ]; then
            echo "Expected jffs2 size of 8388608 but got $jffs2_size" >&2
            exit 1
        fi
    )
}
add_test test_mtdsize

test_check_kflavors() {
    (
        . "$functions"
        if check_kflavors "4.14.0-1-armmp" "armmp-lpae"; then
            echo "Expected check_kflavors to fail with kernel suffix not in expected flavors, but it succeeded" >&2
            exit 1
        fi
        if ! check_kflavors "4.14.0-1-armmp-lpae" "armmp-lpae"; then
            echo "Expected check_kflavors to succeed with kernel suffix in expected flavors, but it failed" >&2
            exit 1
        fi
        if check_kflavors "4.14.0-1-armp-lpae+" "armmp"; then
            echo "Expected check_kflavors to fail with kernel suffix (with additional +) not in expected flavors, but it succeeded" >&2
            exit 1
        fi
        if ! check_kflavors "4.14.0-1-armmp-lpae+" "armmp-lpae"; then
            echo "Expected check_kflavours to succeed with kernel suffix (with additional +) in expected flavors, but it failed" >&2
            exit 1
        fi
        if ! check_kflavors "4.14.0-1-armmp-lpae" "any"; then
            echo "Expected check_kflavours to succeed with kernel suffix 'any' in expected flavors, but it failed" >&2
            exit 1
        fi
    )
}
add_test test_check_kflavors

test_check_size() {
    (
        . "$functions"
        error() {
            return 1
        }
        if check_mtd_size "MTD" 2 1; then
            echo "Expected check_mtd_size to fail for too small size, but it succeeded" >&2
            exit 1
        fi
        if ! check_mtd_size "MTD" 1 1; then
            echo "Expected check_supported to succeed with large enough size, but it failed" >&2
            exit 1
        fi
    )
}
add_test test_check_size

test_check_supported() {
    (
        . "$functions"
        if check_supported "Dummy"; then
            echo "Expected check_supported to fail for non-existent board, but it succeeded" >&2
            exit 1
        fi
        machine="Marvell SheevaPlug Reference Board"
        if ! check_supported "$machine"; then
            echo "Expected check_supported to succeed with machine $machine, but it failed" >&2
            exit 1
        fi
    )
}
add_test test_check_supported

test_get_cpuinfo_hardware() {
    get_tempfile
    mock_proc_cpuinfo="$last_tempfile"
    cat >"$mock_proc_cpuinfo" <<EOF
Processor       : Feroceon 88FR131 rev 1 (v5l)
BogoMIPS        : 1192.75
Features        : swp half thumb fastmult edsp
CPU implementer : 0x56
CPU architecture: 5TE
CPU variant     : 0x2
CPU part        : 0x131
CPU revision    : 1

Hardware        : Marvell SheevaPlug Reference Board
Revision        : 0000
Serial          : 0000000000000000
EOF
    (
        . "$functions"
        PROC_CPUINFO="$mock_proc_cpuinfo"
        PROC_DTMODEL="/this/must/not/exist"
        FK_ETC_MACHINE="/this/must/not/exist"
        get_machine
        if [ "$machine" != "Marvell SheevaPlug Reference Board" ]; then
            echo "Expected machine to be Marvell SheevaPlug Reference Board but got $machine" >&2
            exit 1
        fi
    )
}
add_test test_get_cpuinfo_hardware

test_get_dt_hardware() {
    get_tempfile
    mock_proc_cpuinfo="$last_tempfile"
    cat >"$mock_proc_cpuinfo" <<EOF
Processor       : Feroceon 88FR131 rev 1 (v5l)
BogoMIPS        : 1191.11
Features        : swp half thumb fastmult edsp 
CPU implementer : 0x56
CPU architecture: 5TE
CPU variant     : 0x2
CPU part        : 0x131
CPU revision    : 1

Hardware        : Marvell Kirkwood (Flattened Device Tree)
Revision        : 0000
Serial          : 0000000000000000
EOF

    get_tempfile
    mock_dt_model="$last_tempfile"
    echo -n "Globalscale Technologies Dreamplug" >"$mock_dt_model"

    (
        . "$functions"
        PROC_CPUINFO="$mock_proc_cpuinfo"
        PROC_DTMODEL="$mock_dt_model"
        FK_ETC_MACHINE="/this/must/not/exist"
        get_machine
        if [ "$machine" != "Globalscale Technologies Dreamplug" ]; then
            echo "Expected machine to be Globalscale Technologies Dreamplug but got $machine" >&2
            exit 1
        fi
    )

}
add_test test_get_dt_hardware

test_get_machine() {
    get_tempfile
    mock_etc_machine="$last_tempfile"
    echo "Freescale MX53 LOCO Board" >"$mock_etc_machine"

    get_tempfile
    mock_proc_cpuinfo="$last_tempfile"
    cat >"$mock_proc_cpuinfo" <<EOF
Processor       : Feroceon 88FR131 rev 1 (v5l)
BogoMIPS        : 1192.75
Features        : swp half thumb fastmult edsp
CPU implementer : 0x56
CPU architecture: 5TE
CPU variant     : 0x2
CPU part        : 0x131
CPU revision    : 1

Hardware        : Marvell SheevaPlug Reference Board
Revision        : 0000
Serial          : 0000000000000000
EOF

    get_tempfile
    mock_dt_model="$last_tempfile"
    echo -n "Globalscale Technologies Dreamplug" >"$mock_dt_model"
    (
        . "$functions"
        FK_MACHINE=""
        PROC_DTMODEL="/this/must/not/exist"
        FK_ETC_MACHINE="/this/must/not/exist"
        PROC_CPUINFO="$mock_proc_cpuinfo"
        if get_machine; then
            if [ "$machine" != "Marvell SheevaPlug Reference Board" ]; then
                echo "Expected get_machine to return Marvell SheevaPlug Reference Board but got $machine" >&2
                exit 1
            fi
        else
            echo "Expected get_machine to succeed with mocked /proc/cpuinfo but it failed" >&2
            exit 1
        fi
        PROC_DTMODEL="$mock_dt_model"
        if get_machine; then
            if [ "$machine" != "Globalscale Technologies Dreamplug" ]; then
                echo "Expected get_machine to return Globalscale Technologies Dreamplug but got $machine" >&2
                exit 1
            fi
        else
            echo "Expected get_machine to succeed with mocked /proc/dtmodel but it failed" >&2
            exit 1
        fi
        FK_ETC_MACHINE="$mock_etc_machine"
        if get_machine; then
            if [ "$machine" != "Freescale MX53 LOCO Board" ]; then
                echo "Expected get_machine to return Freescale MX53 LOCO Board but got $machine" >&2
                exit 1
            fi
        else
            echo "Expected get_machine to succeed with mocked /etc/flash-kernel/machine but it failed" >&2
            exit 1
        fi
        FK_MACHINE="Genesi EfikaMX nettop"
        if get_machine; then
            if [ "$machine" != "Genesi EfikaMX nettop" ]; then
                echo "Expected get_machine to return Genesi EfikaMX nettop but got $machine" >&2
                exit 1
            fi
        else
            echo "Expected get_machine to succeed with valid FK_MACHINE but it failed" >&2
            exit 1
        fi
        FK_MACHINE="none"
        if get_machine; then
            if [ -n "$none_machine" ]; then
                echo "Expected get_machine to return an empty string but got $machine" >&2
                exit 1
            fi
        else
            echo "Expected get_machine to succeed with FK_MACHINE=\"none\" but it failed" >&2
            exit 1
        fi
    )
}
add_test test_get_machine

test_get_kfile_suffix() {
    (
        . "$functions"
        kfile_suffix=$(get_kfile_suffix "/boot/vmlinuz-2.6.32-5-kirkwood")
        if [ "$kfile_suffix" != "kirkwood" ]; then
            echo "Expected kernel file suffix to be kirkwood but got $kfile_suffix" >&2
            exit 1
        fi
        kfile_suffix=""
        kfile_suffix=$(get_kfile_suffix "/boot/vmlinuz-3.10-1-armmp-lpae" "$kfile_suffix")
        if [ "$kfile_suffix" != "lpae" ]; then
            echo "Expected kernel file suffix to be lpae but got $kfile_suffix" >&2
            exit 1
        fi
        kfile_suffix=$(get_kfile_suffix "/boot/vmlinuz-3.10-1-armmp-lpae" "$kfile_suffix")
        if [ "$kfile_suffix" != "armmp-lpae" ]; then
            echo "Expected kernel file suffix to be armmp-lpae but got $kfile_suffix" >&2
            exit 1
        fi
        kfile_suffix=$(get_kfile_suffix "/boot/vmlinuz-3.10-1-armmp")
        if [ "$kfile_suffix" != "armmp" ]; then
            echo "Expected kernel file suffix to be armmp but got $kfile_suffix" >&2
            exit 1
        fi
    )
}
add_test test_get_kfile_suffix

test_get_machine_field() {
    (
        . "$functions"
        machine="Marvell SheevaPlug Reference Board"
        if machine_field="$(get_machine_field "$machine" "Machine")"; then
            if [ "$machine_field" != "$machine" ]; then
                echo "Expected Machine field to be $machine but got $machine_field" >&2
                exit 1
            fi
        else
            echo "Expected get_machine_field to succeed on Machine field but it failed" >&2
            exit 1
        fi
        kflavors="$(get_machine_field "$machine" "Kernel-Flavors")"
        if [ "$kflavors" != "kirkwood marvell" ]; then
            echo "Expected Kernel-Flavors field to be 'kirkwood marvell' but got $kflavors" >&2
            exit 1
        fi
        if dummy_field="$(get_machine_field "$machine" "Dummy")"; then
            echo "Expected get_machine_field to fail on unknown field Dummy but it succeeded" >&2
            exit 1
        fi
    )

    get_tempfile
    mock_etc_db="$last_tempfile"
    cat >"$mock_etc_db" <<EOF
Machine: Board File Machine A
Machine: DT Machine A
Machine: DT Machine A v2
Kernel-Flavors: machinea

Machine: Board File Machine B
Kernel-Flavors: machineb

Machine: DT Machine B
Kernel-Flavors: machineb-dt

Machine: Machine C
Machine: Machine C
Kernel-Flavors: machinec
Machine: Invalid
Dummy: Dummy

Machine: Generic * Machine
Method: pi
EOF
    (
        FK_ETC_DB="$mock_etc_db"
        . "$functions"
        machine="Board File Machine A"
        if machine_field="$(get_machine_field "$machine" "Machine")"; then
            if [ "$machine_field" != "$machine" ]; then
                echo "Expected Machine field to be $machine but got $machine_field" >&2
                exit 1
            fi
        else
            echo "Expected get_machine_field to succeed on Machine field but it failed" >&2
            exit 1
        fi
        kflavors=$(get_machine_field "$machine" "Kernel-Flavors")
        if [ "$kflavors" != "machinea" ]; then
            echo "Expected Kernel-Flavors field to be machinea but got $kflavors" >&2
            exit 1
        fi
        machine="DT Machine A"
        kflavors=$(get_machine_field "$machine" "Kernel-Flavors")
        if [ "$kflavors" != "machinea" ]; then
            echo "Expected Kernel-Flavors field to be machinea but got $kflavors" >&2
            exit 1
        fi
        if machine_field="$(get_machine_field "$machine" "Machine")"; then
            if [ "$machine_field" != "$machine" ]; then
                echo "Expected Machine field to be $machine but got $machine_field" >&2
                exit 1
            fi
        else
            echo "Expected get_machine_field to succeed on Machine field but it failed" >&2
            exit 1
        fi
        machine="DT Machine A v2"
        kflavors=$(get_machine_field "$machine" "Kernel-Flavors")
        if [ "$kflavors" != "machinea" ]; then
            echo "Expected Kernel-Flavors field to be machinea but got $kflavors" >&2
            exit 1
        fi
        if machine_field="$(get_machine_field "$machine" "Machine")"; then
            if [ "$machine_field" != "$machine" ]; then
                echo "Expected Machine field to be $machine but got $machine_field" >&2
                exit 1
            fi
        else
            echo "Expected get_machine_field to succeed on Machine field but it failed" >&2
            exit 1
        fi

        machine="Board File Machine B"
        kflavors=$(get_machine_field "$machine" "Kernel-Flavors")
        if [ "$kflavors" != "machineb" ]; then
            echo "Expected Kernel-Flavors field to be machineb but got $kflavors" >&2
            exit 1
        fi
        if machine_field="$(get_machine_field "$machine" "Machine")"; then
            if [ "$machine_field" != "$machine" ]; then
                echo "Expected Machine field to be $machine but got $machine_field" >&2
                exit 1
            fi
        else
            echo "Expected get_machine_field to succeed on Machine field but it failed" >&2
            exit 1
        fi

        machine="DT Machine B"
        kflavors=$(get_machine_field "$machine" "Kernel-Flavors")
        if [ "$kflavors" != "machineb-dt" ]; then
            echo "Expected Kernel-Flavors field to be machineb-dt but got $kflavors" >&2
            exit 1
        fi
        if machine_field="$(get_machine_field "$machine" "Machine")"; then
            if [ "$machine_field" != "$machine" ]; then
                echo "Expected Machine field to be $machine but got $machine_field" >&2
                exit 1
            fi
        else
            echo "Expected get_machine_field to succeed on Machine field but it failed" >&2
            exit 1
        fi

        machine="Machine C"
        kflavors=$(get_machine_field "$machine" "Kernel-Flavors")
        if [ "$kflavors" != "machinec" ]; then
            echo "Expected Kernel-Flavors field to be machinec but got $kflavors" >&2
            exit 1
        fi
        if field="$(get_machine_field "$machine" "Dummy" 2>/dev/null)"; then
            echo "Expected Dummy field to hit syntax error but got $field" >&2
            exit 1
        fi

        machine="Generic Foo Machine"
        method=$(get_machine_field "$machine" "Method")
        if [ "$method" != "pi" ]; then
            echo "Expected Method field to be pi but got $method" >&2
            exit 1
        fi
    )
}
add_test test_get_machine_field

test_etc_db() {
    get_tempfile
    mock_etc_db="$last_tempfile"
    cat >"$mock_etc_db" <<EOF
Machine: Marvell SheevaPlug Reference Board
Kernel-Flavors: Dummy
EOF

    (
        FK_ETC_DB="$mock_etc_db"
        . "$functions"
        machine="Marvell SheevaPlug Reference Board"
        kflavors=$(get_machine_field "$machine" "Kernel-Flavors")
        if [ "$kflavors" != "Dummy" ]; then
            echo "Expected Kernel-Flavors field to be overridden to Dummy but got $kflavors" >&2
            exit 1
        fi
        kaddress=$(get_machine_field "$machine" "U-Boot-Kernel-Address")
        if [ "$kaddress" != "0x00008000" ]; then
            echo "Expected U-Boot-Kernel-Address to be 0x00008000 but got $kaddress" >&2
            exit 1
        fi
    )
}
add_test test_etc_db

test_machine_uses_flash() {
    (
        . "$functions"
        if ! machine_uses_flash "Dummy"; then
            echo "Expected machine_uses_flash to succeed for non-existent board, but it failed" >&2
            exit 1
        fi
        machine="Buffalo Linkstation Mini"
        if machine_uses_flash "$machine"; then
            echo "Expected machine_uses_flash to fail for $machine, but it succeeded" >&2
            exit 1
        fi
        machine="Lanner EM7210"
        if ! machine_uses_flash "$machine"; then
            echo "Expected machine_uses_flash to succeed for $machine, but it failed" >&2
            exit 1
        fi
    )
}
add_test test_machine_uses_flash

test_set_machine_id() {
    (
        . "$functions"
        arm_code="$(set_machine_id 2097 | od -x)"
        expected="0000000 1c08 e3a0 1031 e381
0000010"
        if [ "$arm_code" != "$expected" ]; then
            echo "Expected \"$expected\" for machine-id 2097 but got \"$arm_code\"" >&2
            exit 1
        fi
        arm_code="$(set_machine_id "" | od -x)"
        expected="0000000"
        if [ "$arm_code" != "$expected" ]; then
            echo "Expected \"$expected\" for empty machine-id but got \"$arm_code\"" >&2
            exit 1
        fi
    )
}
add_test test_set_machine_id

_test_mkimage_kernel() {
    local kdata="$1"
    local expected="$2"
    (
        mkimage() {
            saved_args="$@"
        }
        . "$functions"
        saved_args=""
        mkarch="arm"
        mkimage_kernel "0xdeadbeef" "0xbaddcafe" "desc" "$kdata" "output" 2>/dev/null
        if [ "$expected" != "$saved_args" ]; then
            echo "Expected mkimage_kernel to be called with \"$expected\" but it was called with \"$saved_args\"" >&2
            exit 1
        fi
    )
}

test_mkimage_kernel() {
    get_tempfile
    local kdata="$last_tempfile"
    echo "uncompressed" > "$kdata"
    local expected="-A arm -O linux -T kernel -C none -a 0xdeadbeef -e 0xbaddcafe -n desc -d $kdata output"
    _test_mkimage_kernel "$kdata" "$expected"
}
add_test test_mkimage_kernel

test_mkimage_kernel_gzip() {
    get_tempfile
    local kdata="$last_tempfile"
    gzip < /dev/null > "$kdata"

    local expected="-A arm -O linux -T kernel -C gzip -a 0xdeadbeef -e 0xbaddcafe -n desc -d $kdata output"
    _test_mkimage_kernel "$kdata" "$expected"
}
add_test test_mkimage_kernel_gzip

test_mkimage_initrd() {
    (
        mkimage() {
            saved_args="$@"
        }
        . "$functions"
        saved_args=""
        mkarch="arm"
        mkimage_initrd "0xdeadbeef" "desc" "input" "output" 2>/dev/null
        expected="-A arm -O linux -T ramdisk -C none -a 0xdeadbeef -e 0xdeadbeef -n desc -d input output"
        if [ "$expected" != "$saved_args" ]; then
            echo "Expected mkimage_initrd to be called with \"$expected\" but it was called with \"$saved_args\"" >&2
            exit 1
        fi
    )
}
add_test test_mkimage_initrd

test_mkimage_script() {
    get_tempfile
    mock_fk_defaults="$last_tempfile"
    cat >"$mock_fk_defaults" <<EOF
LINUX_KERNEL_CMDLINE="baz quux"
LINUX_KERNEL_CMDLINE_DEFAULTS="foo"
EOF
    get_tempfile
    mock_script="$last_tempfile"
    cat >"$mock_script" <<EOF
setenv bootargs @@LINUX_KERNEL_CMDLINE_DEFAULTS@@ bar @@LINUX_KERNEL_CMDLINE@@
@@UBOOT_ENV_EXTRA@@
bar
@@UBOOT_PREBOOT_EXTRA@@
end
EOF
    (
        mkimage() {
            saved_args="$@"
            shift 15
            generated_script="$(cat $1)"
        }
        . "$functions"
        # Duplicate (some of) cleanups and tmpdir from main()
        cleanups() {
            rm -rf "$tmpdir"
        }
        trap cleanups EXIT HUP INT QUIT ILL KILL SEGV PIPE TERM
        tmpdir="$(mktemp -dt "test_mkimage_script.XXXXXXXX")"
        gen_ubootenv() {
            echo foo
        }
        gen_preboot() {
            echo baz
        }
        FK_DEFAULTS=$mock_fk_defaults
        saved_args=""
        generated_script=""
        mkarch="arm"
        mkimage_script "0xdeadbeef" "desc" "$mock_script" "script" 2>/dev/null
        expected="-A arm -O linux -T script -C none -a 0xdeadbeef -e 0xdeadbeef -n desc -d $tmpdir/$(basename $mock_script).out script"
        expected_script="$(printf "setenv bootargs foo bar baz quux\n\nfoo\nbar\n\nbaz\nend")"
        if [ "$expected" != "$saved_args" ]; then
            echo "Expected mkimage_script to be called with \"$expected\" but it was called with \"$saved_args\"" >&2
            exit 1
        fi
        if [ "$generated_script" != "$expected_script" ]; then
            echo "The script generated by mkimage_script did not match the expected output" >&2
            exit 1
        fi
    )
}
add_test test_mkimage_script

test_mkimage_multi() {
    (
        mkimage() {
            saved_args="$@"
        }
        . "$functions"
        saved_args=""
        mkarch="arm"
        mkimage_multi "0xdeadbeef" "desc" "kinput" "iinput" "output" 2>/dev/null
        expected="-A arm -O linux -T multi -C none -a 0xdeadbeef -e 0xdeadbeef -n desc -d kinput:iinput output"
        if [ "$expected" != "$saved_args" ]; then
            echo "Expected mkimage_multi to be called with \"$expected\" but it was called with \"$saved_args\"" >&2
            exit 1
        fi
    )
}
add_test test_mkimage_multi

test_check_kernel_size_no_max() {
    get_tempfile
    local kdata="$last_tempfile"
    # Larger than the smallest Boot-Kernel-Max-Size in all.db
    dd if=/dev/zero of="$kdata" seek=16777153 bs=1 count=0 status=none
    (
	. "$functions"
	machine="none"
	if ! check_kernel_size "$kdata"; then
	    echo "Did not expect an error from check_kernel_size()" >&2
	    exit 1
	fi
    )
}
add_test test_check_kernel_size_no_max

test_check_kernel_size_fits() {
    get_tempfile
    local kdata="$last_tempfile"
    # Within the machine's Boot-Kernel-Max-Size
    dd if=/dev/zero of="$kdata" seek=16777152 bs=1 count=0 status=none
    (
	. "$functions"
	machine="HP ProLiant m400 Server Cartridge"
	if ! check_kernel_size "$kdata"; then
	    echo "Did not expect an error from check_kernel_size()" >&2
	    exit 1
	fi
    )
}
add_test test_check_kernel_size_fits

test_check_kernel_size_too_big() {
    get_tempfile
    local kdata="$last_tempfile"
    # Larger than the machine's Boot-Kernel-Max-Size
    dd if=/dev/zero of="$kdata" seek=16777153 bs=1 count=0 status=none
    (
	. "$functions"
	machine="HP ProLiant m400 Server Cartridge"
	if check_kernel_size "$kdata"; then
	    echo "Expected an error from check_kernel_size()" >&2
	    exit 1
	fi
    )
}
add_test test_check_kernel_size_too_big

test_try_shrink_kernel_should_compress() {
    get_tempfile
    local kdata="$last_tempfile"
    echo uncompressed > "$kdata"
    (
	. "$functions"
        # Duplicate (some of) cleanups and tmpdir from main()
        cleanups() {
            rm -rf "$tmpdir"
        }
        trap cleanups EXIT HUP INT QUIT ILL KILL SEGV PIPE TERM
        tmpdir="$(mktemp -dt "test_mkimage_script.XXXXXXXX")"
	new_kdata="$(try_shrink_kernel "$kdata")"
	if [ "$new_kdata" = "$kdata" ]; then
	    echo "Expected a new (compressed) file" >&2
	    exit 1
	fi
	if [ "$(compress_type "$new_kdata")" != "gzip" ]; then
	    echo "Expected $new_kdata to be gzipped" >&2
	    exit 1
	fi
    )
}
add_test test_try_shrink_kernel_should_compress

test_try_shrink_kernel_should_NOT_compress() {
    get_tempfile
    local kdata="$last_tempfile"
    gzip < /dev/null > "$kdata"
    (
	. "$functions"
	new_kdata="$(try_shrink_kernel "$kdata")"
	if [ "$new_kdata" != "$kdata" ]; then
	    echo "Expected function to return input file as-is" >&2
	    exit 1
	fi
    )
}
add_test test_try_shrink_kernel_should_NOT_compress

test_gen_kernel() {
    get_tempfile
    kernel_input="$last_tempfile"
    echo "foo" >"$kernel_input"
    get_tempfile
    kernel_output="$last_tempfile"
    (
        . "$functions"
        gen_kernel "$kernel_input" "$kernel_output" 2097
        result="$(od -t x1 "$kernel_output")"
        expected="0000000 08 1c a0 e3 31 10 81 e3 66 6f 6f 0a
0000014"
        if [ "$result" != "$expected" ]; then
            echo "With machine id 2097, expected \"$expected\" but got \"$result\"" >&2
            exit 1
        fi
        gen_kernel "$kernel_input" "$kernel_output" ""
        result="$(od -t x1 "$kernel_output")"
        expected="0000000 66 6f 6f 0a
0000004"
        if [ "$result" != "$expected" ]; then
            echo "With no machine id, expected \"$expected\" but got \"$result\"" >&2
            exit 1
        fi
    )
}
add_test test_gen_kernel

test_flash_initrd() {
    get_tempfile
    initrd_input="$last_tempfile"
    echo "foo" >"$initrd_input"
    get_tempfile
    initrd_output="$last_tempfile"
    (
        . "$functions"
        flash_initrd "$initrd_input" "$initrd_output" 3 2>/dev/null
        result="$(od -t x1 "$initrd_output")"
        expected="0000000 66 6f 6f 0a 00 00 00
0000007"
        if [ "$result" != "$expected" ]; then
            echo "With 3 bytes of padding, expected \"$expected\" but got \"$result\"" >&2
            exit 1
        fi
        flash_initrd "$initrd_input" "$initrd_output" 0 2>/dev/null
        result="$(od -t x1 "$initrd_output")"
        expected="0000000 66 6f 6f 0a
0000004"
        if [ "$result" != "$expected" ]; then
            echo "With no padding, expected \"$expected\" but got \"$result\"" >&2
            exit 1
        fi
    )
}
add_test test_flash_initrd

test_dtb_append_from() {
    (
        . "$functions"
        dtb_append_from="3.12"
        kvers=3.11-1-kirkwood
        if dtb_append_required ; then
            echo "Kernel $kvers does not need appended DTB, but got true" >&2
            exit 1
        fi
        kvers=3.12-1-kirkwood
        if ! dtb_append_required ; then
            echo "Kernel $kvers does need appended DTB, but got false" >&2
            exit 1
        fi
    )
}
add_test test_dtb_append_from

test_abootimg_get_image_size() {
    abootimg_output="

Android Boot Image Info:

* file name = boot.img

* image size = 8388608 bytes (8.00 MB)
  page size  = 2048 bytes

* Boot Name = \"\"

* kernel size       = 3002744 bytes (2.86 MB)
  ramdisk size      = 1639626 bytes (1.56 MB)

* load addresses:
  kernel:       0x10008000
  ramdisk:      0x11000000
  tags:         0x10000100

* cmdline = mem=448M@0M nvmem=64M@448M vmalloc=320M video=tegrafb console=tty0 usbcore.old_scheme_first=1 quiet splash elevator=noop tegraboot=sdmmc cmdpart=1:7168:10240,2:17408:16384,3:35840:614400,4:4004864:27096064

* id = 0x07571070 0x13950a6a 0x185c996f 0x9ab7b64d 0xcccd09bd 0x00000000 0x00000000 0x00000000
"
    (
        . "$functions"
        size=$(abootimg_get_image_size "$abootimg_output")
        if [ "$size" -ne 8388608 ]; then
            echo "Expected 8388608 but got $size" >&2
            exit 1
        fi
    )
}
add_test test_abootimg_get_image_size

test_android_flash() {
    (
        abootimg() {
            saved_args="$@"
        }
        . "$functions"
        saved_args=""
        kfile="vmlinuz"
        ifile="initrd.img"
        android_flash /dev/some-dev 2>/dev/null
        expected="-u /dev/some-dev -k vmlinuz -r initrd.img"
        if [ "$expected" != "$saved_args" ]; then
            echo "Expected abootimg to be called with \"$expected\" but it was called with \"$saved_args\"" >&2
            exit 1
        fi
        saved_args=""
        android_skip_initrd=1 android_flash /dev/some-dev 2>/dev/null
        expected="-u /dev/some-dev -k vmlinuz"
        if [ "$expected" != "$saved_args" ]; then
            echo "Expected abootimg to be called with \"$expected\" but it was called with \"$saved_args\"" >&2
            exit 1
        fi
    )
}
add_test test_android_flash

test_find_pi_firmware() {
    get_tempfile
    mock_find_output="$last_tempfile"
    cat >"$mock_find_output" <<EOF
/usr/lib/linux-firmware-raspi/bootcode.bin
/usr/lib/linux-firmware-raspi2/bootcode.bin
/usr/lib/linux-firmware-raspi2/start.elf
/usr/lib/linux-firmware-raspi2/fixup.dat
EOF
    (
        find() {
            saved_args="$@"
            cat "$mock_find_output"
        }
        . "$functions"
        expected="\
/usr/lib/linux-firmware-raspi/bootcode.bin
/usr/lib/linux-firmware-raspi2/fixup.dat
/usr/lib/linux-firmware-raspi2/start.elf"
        if [ "$(find_pi_firmware | sort)" != "$(echo "$expected" | sort)" ]; then
            echo "find_pi_firmware did not output the expected list of files" >&2
            exit 1
        fi
    )
}
add_test test_find_pi_firmware

test_find_all_dtbs() {
    kvers="3.14"
    get_tempfile
    mock_find_output="$last_tempfile"
    cat >"$mock_find_output" <<EOF
/etc/flash-kernel/dtbs/bcm2709-rpi-2-b.dtb
/lib/firmware/$kvers/device-tree/broadcom/bcm2709-rpi-2-b.dtb
/lib/firmware/$kvers/device-tree/broadcom/bcm2710-rpi-3-b.dtb
/lib/firmware/$kvers/device-tree/broadcom/bcm2711-rpi-4-b.dtb
EOF
    (
        find() {
            saved_args="$@"
            cat "$mock_find_output"
        }
        . "$functions"
        expected="\
/etc/flash-kernel/dtbs/bcm2709-rpi-2-b.dtb
/lib/firmware/$kvers/device-tree/broadcom/bcm2710-rpi-3-b.dtb
/lib/firmware/$kvers/device-tree/broadcom/bcm2711-rpi-4-b.dtb"
        if [ "$(find_all_dtbs | sort)" != "$(echo "$expected" | sort)" ]; then
            echo "find_all_dtbs did not output the expected list of files" >&2
            exit 1
        fi
    )
}
add_test test_find_all_dtbs

test_find_all_overlays() {
    kvers="3.14"
    get_tempfile
    mock_find_output="$last_tempfile"
    cat >"$mock_find_output" <<EOF
/etc/flash-kernel/dtbs/pi3-disable-bt.dtbo
/lib/firmware/$kvers/device-tree/overlays/i2c0.dtbo
/lib/firmware/$kvers/device-tree/overlays/vc4-fkms-v3d.dtbo
/lib/firmware/$kvers/device-tree/overlays/pi3-disable-bt.dtbo
/lib/firmware/$kvers/device-tree/broadcom/overlay_map.dtb
EOF
    (
        find() {
            saved_args="$@"
            if [ "${saved_args##*README}" = "${saved_args%%README*}" ]; then
                cat "$mock_find_output"
            fi
        }
        . "$functions"
        expected="\
/etc/flash-kernel/dtbs/pi3-disable-bt.dtbo
/lib/firmware/$kvers/device-tree/overlays/i2c0.dtbo
/lib/firmware/$kvers/device-tree/overlays/vc4-fkms-v3d.dtbo
/lib/firmware/$kvers/device-tree/broadcom/overlay_map.dtb"
        if [ "$(find_all_overlays | sort)" != "$(echo "$expected" | sort)" ]; then
            echo "find_all_overlays did not output the expected list of files" >&2
            exit 1
        fi
    )
}
add_test test_find_all_overlays

test_get_kernel_status() {
    available="
5.15.0-1021-generic /boot/vmlinuz-5.15.0-1021-generic
5.15.0-1022-raspi /boot/vmlinuz-5.15.0-1022-raspi
5.15.0-1022-raspi-nolpae /boot/vmlinuz-5.15.0-1022-raspi-nolpae
5.15.0-1023-raspi /boot/vmlinuz-5.15.0-1023-raspi"
    (
        linux_version() {
            case "$1" in
                list)
                    if [ "$2" = "--paths" ]; then
                        echo "$available"
                    else
                        echo "$available" | while read -r ver path; do
                            echo "$ver"
                        done
                    fi
                    ;;
                compare)
                    case "$3" in
                        eq) [ "$2" = "$4" ] ;;
                        ne) [ "$2" != "$4" ] ;;
                        *)
                            echo "Unexpected arg in test-case"
                            exit 1
                            ;;
                    esac
                    ;;
            esac
        }
        dpkg_query() {
            case "$1" in
                --search)
                    shift
                    while [ -n "$1" ]; do
                        case "$1" in
                            /boot/vmlinuz-5.15.0-*)
                                echo "linux-image-${1#/boot/vmlinuz-}: $1"
                                ;;
                            *)
                                echo "Unexpected arg in test-case"
                                exit 1
                                ;;
                        esac
                        shift
                    done
                    ;;
                --show)
                    shift
                    while [ -n "$1" ]; do
                        case "$1" in
                            --showformat)
                                shift
                                ;;
                            linux-image-5.15.0-1022-raspi*)
                                echo -n installed
                                ;;
                            linux-image-5.15.0-1023-*)
                                echo -n triggers-pending
                                ;;
                            linux-image-*)
                                echo -n not-installed
                                ;;
                            *)
                                echo "Unexpected arg in test-case"
                                exit 1
                                ;;
                        esac
                        shift
                    done
                    ;;
            esac
        }
        # Can't define a function with a hyphen in the name but luckily, dash
        # does permit them in alias names
        alias dpkg-query=dpkg_query
        alias linux-version=linux_version
        . "$functions"
        if [ "$(get_kernel_status 5.15.0-1022-raspi)" != "installed" ]; then
            echo "get_kernel_status did not output the expected result" >&2
            exit 1
        fi
        if [ "$(get_kernel_status 5.15.0-1023-raspi)" != "triggers-pending" ]; then
            echo "get_kernel_status did not output the expected result" >&2
            exit 1
        fi
        if [ "$(get_kernel_status 5.15.0-1021-generic)" != "not-installed" ]; then
            echo "get_kernel_status did not output the expected result" >&2
            exit 1
        fi
    )
}
add_test test_get_kernel_status

test_main

# vim:syntax=sh
