#!/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 "ksuffix" "kflavor1" "kflavor2"; then
            echo "Expected check_kflavors to fail with kernel suffix not in expected flavors, but it succeeded" >&2
            exit 1
        fi
        if ! check_kflavors "foo" "kflavor1" "foo" "kflavor3"; then
            echo "Expected check_kflavors to succeed with kernel suffix in expected flavors, but it failed" >&2
            exit 1
        fi
        if ! check_kflavors "kflavor1-suffix" "klavor1" "kflavor1-suffix" "kflavor2"; then
            echo "Expected check_kflavours to succeed with double-barrelled kernel suffix in expected flavours, but it failed" >&2
            exit 1
        fi
        if check_kflavors "kflavor1-suffix" "klavor1" "kflavor2"; then
            echo "Expected check_kflavours to fail with double-barrelled kernel suffix not in expected flavours, but it succeeded" >&2
            exit 1
        fi
        if ! check_kflavors "" "kflavor1" "kflavor2" "kflavor3"; then
            echo "Expected check_kflavors to succeed with empty kernel suffix, but it failed" >&2
            exit 1
        fi
        if check_kflavors "ksuffix+" "kflavor1" "kflavor2"; 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 "foo+" "kflavor1" "foo" "kflavor2"; then
            echo "Expected check_kflavours to succeed with kernel suffix (with additional +) 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
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

    )
}
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() {
    (
        mkimage() {
            saved_args="$@"
        }
        . "$functions"
        saved_args=""
        mkarch="arm"
        mkimage_kernel "0xdeadbeef" "0xbaddcafe" "desc" "input" "output" 2>/dev/null
        expected="-A arm -O linux -T kernel -C none -a 0xdeadbeef -e 0xbaddcafe -n desc -d input output"
        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
    )
}
add_test test_mkimage_kernel

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_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_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_main

# vim:syntax=sh
