#!/bin/sh

if [ "$TRAVIS_BUILD_NUMBER" ]; then
    echo travis_fold:start:env
    printenv | sort
    echo travis_fold:end:env
fi

export LANG=C.UTF-8
export LANGUAGE=en
set -eu

if which goctest >/dev/null; then
    goctest="goctest"
else
    goctest="go test"
fi
COVERMODE=${COVERMODE:-atomic}
export GOPATH="${GOPATH:-$(realpath "$(dirname "$0")"/../../../../)}"
export PATH="$PATH:${GOPATH%%:*}/bin"

STATIC=
UNIT=
SPREAD=
DEPRECATED=

case "${1:-all}" in
    all)
        STATIC=1
        UNIT=1
        DEPRECATED=1
        ;;
    --static)
        STATIC=1
        ;;
    --unit)
        UNIT=1
        ;;
    --spread)
        SPREAD=1
        ;;
    *)
        echo "Wrong flag ${1}. To run a single suite use --static, --unit, --spread."
        exit 1
esac

CURRENTTRAP="true"
EXIT_CODE=99
store_exit_code() {
    EXIT_CODE=$?
}
exit_with_exit_code() {
    exit $EXIT_CODE
}
addtrap() {
    CURRENTTRAP="$CURRENTTRAP ; $1"
    # shellcheck disable=SC2064
    trap "store_exit_code; $CURRENTTRAP ; exit_with_exit_code" EXIT
}

endmsg() {
    if [ $EXIT_CODE -eq 0 ]; then
        p="success.txt"
        m="All good, what could possibly go wrong."
    else
        p="failure.txt"
        m="Crushing failure and despair."
    fi
    echo
    if [ -t 1 ] && [ -z "$STATIC" ]; then
        cat "data/$p"
    else
        echo "$m"
    fi
}
addtrap endmsg

# Append the coverage profile of a package to the project coverage.
append_coverage() (
    profile="$1"
    if [ -f "$profile" ]; then
        grep -v "^mode:" -- "$profile" >> .coverage/coverage.out
        rm "$profile"
    fi
)

if [ "$STATIC" = 1 ]; then
    ./get-deps.sh

    # Run static tests.
    echo Checking docs
    ./mdlint.py ./*.md docs/*.md

    echo Checking formatting
    fmt=""
    for dir in $(go list -f '{{.Dir}}' ./... | grep -v '/vendor/' ); do
        s="$(gofmt -s -l "$dir")"
        if [ -n "$s" ]; then
            fmt="$s\n$fmt"
        fi
    done

    if [ -n "$fmt" ]; then
        echo "Formatting wrong in following files:"
        echo "$fmt"
        exit 1
    fi

    # go vet
    echo Running vet
    go list ./... | grep -v '/vendor/' | xargs go vet

    echo 'Check for usages of http.Status*'
    got=""
    for dir in $(go list -f '{{.Dir}}' ./... | grep -v '/vendor/' ); do
        s="$(grep -nP 'http\.Status(?!Text)' "$dir"/*.go || true)"
        if [ -n "$s" ]; then
            got="$s\n$got"
        fi
    done

    if [ -n "$got" ]; then
        echo 'Usages of http.Status*, we prefer the numeric values directly:'
        echo "$got"
        exit 1
    fi

    if which shellcheck >/dev/null; then
        echo Checking shell scripts...
        ( git ls-files -z 2>/dev/null ||
                find . \( -name .git -o -name vendor \) -prune -o -print0 ) |
            xargs -0 file -N |
            awk -F": " '$2~/shell.script/{print $1}' |
            xargs shellcheck
        regexp='GOPATH(?!%%:\*)(?!:)[^=]*/'
        if grep -qPr --exclude HACKING.md --exclude-dir .git --exclude-dir vendor "$regexp"; then
            echo "Using GOPATH as if it were a single entry and not a list:"
            grep -PHrn -C1 --color=auto --exclude HACKING.md --exclude-dir .git --exclude-dir vendor "$regexp"
            exit 1
        fi
        unset regexp
    fi

    echo Checking spelling errors
    if ! which misspell >/dev/null; then
        go get -u github.com/client9/misspell/cmd/misspell
    fi
    for file in *; do
        if [ "$file" = "vendor" ] || [ "$file" = "po" ]; then
            continue
        fi
        misspell -error -i auther,PROCES,PROCESSS,proces,processs "$file"
    done

    echo Checking for ineffective assignments
    if ! which ineffassign >/dev/null; then
        go get -u github.com/gordonklaus/ineffassign
    fi
    # ineffassign knows about ignoring vendor/ \o/
    ineffassign .
fi

if [ "$UNIT" = 1 ]; then
    ./get-deps.sh

    # Prepare the coverage output profile.
    rm -rf .coverage
    mkdir .coverage
    echo "mode: $COVERMODE" > .coverage/coverage.out

    echo Building
    go build -v github.com/snapcore/snapd/...

    # tests
    echo Running tests from "$PWD"
    for pkg in $(go list ./... | grep -v '/vendor/' ); do
        go test -i "$pkg"
        $goctest -v -coverprofile=.coverage/profile.out -covermode="$COVERMODE" "$pkg"
        append_coverage .coverage/profile.out
    done

    # upload to codecov.io if on travis
    if [ "${TRAVIS_BUILD_NUMBER:-}" ]; then
        curl -s https://codecov.io/bash | bash /dev/stdin -f .coverage/coverage.out
    fi
fi

if [ "$SPREAD" = 1 ]; then
    TMP_SPREAD="$(mktemp -d)"
    addtrap "rm -rf \"$TMP_SPREAD\""

    export PATH=$TMP_SPREAD:$PATH
    ( cd "$TMP_SPREAD" && curl -s -O https://niemeyer.s3.amazonaws.com/spread-amd64.tar.gz && tar xzvf spread-amd64.tar.gz )

    spread -v linode:

    # cleanup the debian-ubuntu-14.04
    rm -rf debian-ubuntu-14.04
fi

if [ "$DEPRECATED" = 1 ]; then
    ./get-deps.sh

fi

UNCLEAN="$(git status -s|grep '^??')" || true
if [ -n "$UNCLEAN" ]; then
    cat <<EOF

There are files left in the git tree after the tests:

$UNCLEAN
EOF
    exit 1
fi
