#!/bin/bash
# (C) Crown copyright, Met Office. All rights reserved.
#
# This file is part of IMPROVER and is released under a BSD 3-Clause license.
# See LICENSE in the root of the repository for full licensing details.
#------------------------------------------------------------------------------
# NAME
#    improver tests - Run IMPROVER self-tests
#
# SYNOPSIS
#    improver tests
#
# DESCRIPTION
#    Launch all IMPROVER self-tests.
#------------------------------------------------------------------------------

set -eu

function echo_ok {
    echo -e "\033[1;32m[OK]\033[0m $1"
}

function echo_fail {
    echo -e "\033[1;31m[FAIL]\033[0m $1"
}

function get_python_files {
    FILES_TO_TEST=`find $IMPROVER_DIR -type f \( -name '*.py' \
                                              -o -name 'improver-*' \
                                               ! -name 'improver-tests' \
                                               ! -name '*~' \)`
}

function improver_test_black {
    ${BLACK:-black} $FILES_TO_TEST
    echo_ok "black"
}

function improver_test_isort {
    ${ISORT:-isort} $FILES_TO_TEST
    echo_ok "isort"
}

function improver_test_flake8 {
    ${FLAKE8:-flake8} $FILES_TO_TEST
    echo_ok "flake8"
}

function improver_test_doc {
    # Build documentation as test.
    cd $IMPROVER_DIR/doc
    make SPHINXBUILD=${SPHINXBUILD:-sphinx-build} html 1>/dev/null
    echo_ok "sphinx-build -b html"
    cd -
}

function improver_test_unit {
    # Unit tests.
    if [[ -n $DEBUG_OPT ]]; then
        VERBOSE_OPT='-v'
    fi
    pytest -m 'not acc' ${VERBOSE_OPT:-}

    echo_ok "Unit tests"
}

function improver_test_recreate_checksums {
    # Recreate checksums for acceptance test data.
    LC_FORMER=${LC_ALL:-}
    export LC_ALL=C
    pushd $IMPROVER_ACC_TEST_DIR > /dev/null
    find . -not -path '*/\.*' \( -type f -o -type l \) -print0 | \
    sort -zu | xargs -0 sha256sum > $CLISUBTEST/acceptance/SHA256SUMS
    popd > /dev/null
    export LC_ALL=$LC_FORMER

    echo_ok "Checksums recreated"
}

function improver_test_cli {
    # CLI testing.

    if [[ -n ${RECREATE_KGO:-} ]]; then
        echo -e "\nSet to recreate KGO at path $RECREATE_KGO"
        echo -e "To unset this use: unset RECREATE_KGO \n\n"
        read -p "Press enter to continue"
    fi

    if [[ -n $DEBUG_OPT ]]; then
        VERBOSE_OPT='-v'
    fi

    if [[ ! ${IMPROVER_IGNORE_CHECKSUMS:-} = "true" ]]; then
      pytest $CLISUBTEST/acceptance/test_checksums.py
      echo_ok "Acceptance test data checksums validated"
    fi

    pytest -m acc -m "not checksum" ${VERBOSE_OPT:-}

    echo_ok "CLI tests"
}

function print_usage {
    # Output CLI usage information.
    cat <<'__USAGE__'
improver tests [OPTIONS] [SUBTEST...] [SUBCLI...]

Run black, isort, flake8, documentation, unit and CLI acceptance tests.

Optional arguments:
    --debug         Run in verbose mode (may take longer for CLI)
    -h, --help      Show this message and exit

Arguments:
    SUBTEST         Name(s) of a subtest to run without running the rest.
                    Valid names are: black, isort, flake8, doc, unit, cli,
                    and recreate_checksums. The default tests are black,
                    isort, flake8, doc, unit, and cli.  Using
                    recreate_checksums will regenerate the test data
                    checksum file which is used as part of the cli tests.
__USAGE__
}

export IMPROVER_DIR="$(cd $(dirname $0)/../ && pwd -P)"

# Apply site-specific setup if necessary.
if [[ -f "${IMPROVER_SITE_INIT:=$IMPROVER_DIR/etc/site-init}" ]]; then
    . "$IMPROVER_SITE_INIT"
fi

export PYTHONPATH="$IMPROVER_DIR/:${PYTHONPATH:-}"

TEST_INPUT_PWD=$(cd $PWD && pwd -P)
cd $IMPROVER_DIR/

# Find cli test options and format to work with case statement
shopt -s extglob
opts=../tests/*
cli_tasks=('+(')
for i in $opts; do
  fname=${i##*/}
  if [[ "$fname" != "bin" ]] && [[ "$fname" != "lib" ]]; then
    cli_tasks+="${fname##*improver-}|"
    cli_tasks+="*/${fname}?(/)|"
  fi
done
cli_tasks+=')'

DEBUG_OPT=
SUBTESTS=
SUBCLI=
for arg in "$@"; do
    case $arg in
        --debug)
        DEBUG_OPT='--debug'
        ;;
        -h|--help)
        print_usage
        exit 0
        ;;
        black|isort|flake8|doc|unit|cli|recreate_checksums)
        SUBTESTS="$SUBTESTS $arg"
        ;;
        $cli_tasks)
        SUBCLI="$SUBCLI $arg"
        ;;
        *)
        print_usage
        exit 2
        ;;
    esac
done

if [[ -n "$SUBTESTS" ]]; then
    # Custom selection of tests.
    TESTS="$SUBTESTS"
else
    # Default tests.
    TESTS="isort black flake8 doc unit cli"
fi

# If cli sub test is not specified by user, do all cli tests.
# Otherwise set CLISUBTEST to the sub test to run.
CLISUBTEST="$IMPROVER_DIR/improver_tests/"
STRIPPED_TEST="$(echo -e "${TESTS}" | tr -d '[:space:]')"
if [[ $STRIPPED_TEST == "cli" ]]; then
    if [[ -n "$SUBCLI" ]]; then
        CLISUBTEST="$SUBCLI"
    fi
fi

# Build a list of python files throughout IMPROVER.
FILES_TO_TEST=''
get_python_files

for TEST_NAME in $TESTS; do
    "improver_test_$TEST_NAME" "$DEBUG_OPT" "$@" "$CLISUBTEST"
done

if [[ -z "$SUBTESTS" ]]; then
    echo_ok "All tests passed."
fi
