#!/usr/bin/env bash
set -e

TOOLCHAINS_CSV='support/config-fragments/autobuild/toolchain-configs.csv'

main() {
    local o O opts
    local cfg dir pkg random toolchains_dir toolchain
    local ret nb nb_skip nb_fail nb_legal nb_tc build_dir
    local -a toolchains

    o='hc:d:p:r:t:'
    O='help,config-snippet:build-dir:package:,random:,toolchains-dir:'
    opts="$(getopt -n "${my_name}" -o "${o}" -l "${O}" -- "${@}")"
    eval set -- "${opts}"

    random=0
    toolchains_csv="${TOOLCHAINS_CSV}"
    while [ ${#} -gt 0 ]; do
        case "${1}" in
        (-h|--help)
            help; exit 0
            ;;
        (-c|--config-snippet)
            cfg="${2}"; shift 2
            ;;
        (-d|--build-dir)
            dir="${2}"; shift 2
            ;;
        (-p|--package)
            pkg="${2}"; shift 2
            ;;
        (-r|--random)
            random="${2}"; shift 2
            ;;
        (-t|--toolchains-csv)
            toolchains_csv="${2}"; shift 2
            ;;
        (--)
            shift; break
            ;;
        esac
    done
    if [ -z "${cfg}" ]; then
        printf "error: no config snippet specified\n" >&2; exit 1
    fi
    if [ ! -e "${cfg}" ]; then
        printf "error: %s: no such file\n" "${cfg}" >&2; exit 1
    fi
    if [ -z "${dir}" ]; then
        dir="${HOME}/br-test-pkg"
    fi

    # Extract the URLs of the toolchains; drop internal toolchains
    # E.g.: http://server/path/to/name.config,arch,libc
    #  -->  http://server/path/to/name.config
    toolchains=($(sed -r -e 's/,.*//; /internal/d; /^#/d; /^$/d;' "${toolchains_csv}" \
                  |if [ ${random} -gt 0 ]; then \
                      sort -R |head -n ${random}
                   else
                      cat
                   fi |sort
                 )
               )

    nb_tc="${#toolchains[@]}"
    if [ ${nb_tc} -eq 0 ]; then
        printf "error: no toolchain found (networking issue?)\n" >&2; exit 1
    fi

    nb=0
    nb_skip=0
    nb_fail=0
    nb_legal=0
    for toolchainconfig in "${toolchains[@]}"; do
        : $((nb++))
        toolchain="$(basename "${toolchainconfig}" .config)"
        build_dir="${dir}/${toolchain}"
        printf "%40s [%*d/%d]: " "${toolchain}" ${#nb_tc} ${nb} ${nb_tc}
        build_one "${build_dir}" "${toolchainconfig}" "${cfg}" "${pkg}" && ret=0 || ret=${?}
        case ${ret} in
        (0) printf "OK\n";;
        (1) : $((nb_skip++)); printf "SKIPPED\n";;
        (2) : $((nb_fail++)); printf "FAILED\n";;
        (3) : $((nb_legal++)); printf "FAILED\n";;
        esac
    done

    printf "%d builds, %d skipped, %d build failed, %d legal-info failed\n" \
        ${nb} ${nb_skip} ${nb_fail} ${nb_legal}
}

build_one() {
    local dir="${1}"
    local toolchainconfig="${2}"
    local cfg="${3}"
    local pkg="${4}"

    mkdir -p "${dir}"

    support/kconfig/merge_config.sh -O "${dir}" \
        "${toolchainconfig}" "support/config-fragments/minimal.config" "${cfg}" \
        >> "${dir}/logfile" 2>&1
    # We want all the options from the snippet to be present as-is (set
    # or not set) in the actual .config; if one of them is not, it means
    # some dependency from the toolchain or arch is not available, in
    # which case this config is untestable and we skip it.
    # We don't care about the locale to sort in, as long as both sort are
    # done in the same locale.
    comm -23 <(sort "${cfg}") <(sort "${dir}/.config") >"${dir}/missing.config"
    if [ -s "${dir}/missing.config" ]; then
        return 1
    fi
    # Remove file, it's empty anyway.
    rm -f "${dir}/missing.config"

    if [ -n "${pkg}" ]; then
        if ! make O="${dir}" "${pkg}-dirclean" >> "${dir}/logfile" 2>&1; then
            return 2
        fi
    fi

    # shellcheck disable=SC2086
    if ! make O="${dir}" ${pkg} >> "${dir}/logfile" 2>&1; then
        return 2
    fi

    # legal-info done systematically, because some packages have different
    # sources depending on the configuration (e.g. lua-5.2 vs. lua-5.3)
    if ! make O="${dir}" legal-info >> "${dir}/logfile" 2>&1; then
        return 3
    fi
}

help() {
    cat <<_EOF_
test-pkg: test-build a package against various toolchains and architectures

The supplied config snippet is appended to each toolchain config, the
resulting configuration is checked to ensure it still contains all options
specified in the snippet; if any is missing, the build is skipped, on the
assumption that the package under test requires a toolchain or architecture
feature that is missing.

In case failures are noticed, you can fix the package and just re-run the
same command again; it will re-run the test where it failed. If you did
specify a package (with -p), the package build dir will be removed first.

The list of toolchains is retrieved from ${TOOLCHAINS_CSV}.
Only the external toolchains are tried, because building a Buildroot toolchain
would take too long. An alternative toolchains CSV file can be specified with
the -t option. This file should have lines consisting of the path to the
toolchain config fragment and the required host architecture, separated by a
comma. The config fragments should contain only the toolchain and architecture
settings.

Options:

    -h, --help
        Print this help.

    -c CFG, --config-snippet CFG
        Use the CFG file as the source for the config snippet. This file
        should contain all the config options required to build a package.

    -d DIR, --build-dir DIR
        Do the builds in directory DIR, one sub-dir per toolchain.

    -p PKG, --package PKG
        Test-build the package PKG, by running 'make PKG'; if not specified,
        just runs 'make'.

    -r N, --random N
        Limit the tests to the N randomly selected toolchains, instead of
        building with all toolchains.

    -t CSVFILE, --toolchains-csv CSVFILE
        CSV file containing the paths to config fragments of toolchains to
        try. If not specified, the toolchains in ${TOOLCHAINS_CSV} will be
        used.

Example:

    Testing libcec would require a config snippet that contains:
        BR2_PACKAGE_LIBCEC=y

    Testing libcurl with openSSL support would require a snippet such as:
        BR2_PACKAGE_OPENSSL=y
        BR2_PACKAGE_LIBCURL=y

_EOF_
}

my_name="${0##*/}"
main "${@}"
