#!/usr/bin/env bash
#Copyright (C) 2009-2010:
#    Gabes Jean, naparuba@gmail.com
#    Gerhard Lausser, Gerhard.Lausser@consol.de
#
#This file is part of Shinken.
#
#Shinken is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#Shinken 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 Affero General Public License for more details.
#
#You should have received a copy of the GNU Affero General Public License
#along with Shinken.  If not, see <http://www.gnu.org/licenses/>.






MODULELIST=$(readlink -f $2)
COVERAGE=$3
PYLINT=$4
PEP8=$5

if [[ "$(echo $1 | tr [A-Z] [a-z])" == "long" ]]; then
    REGEXPCMD=";" # Mod is long, we will take all tests
else
    REGEXPCMD="| grep -v test_long.*\.py" # Mod is normal, we will skip long tests
fi
test "$COVERAGE" == "COVERAGE" || COVERAGE="NOCOVERAGE"
test "$PYLINT" == "PYLINT" || PYLINT="NOPYLINT"
test "$PEP8" == "PEP8" || PYLINT="NOPEP8"

PIP_DOWNLOAD_CACHE=$HOME/.pip/download_cache
COVERAGE_PROCESS_START=$DIR/.coveragerc

# Will be /path/to/shinken/test/jenkins
DIR=$(dirname $(readlink -f "$0"))

SHINKENDIR=$(readlink -f "$DIR/../..")
RESULTSDIR="results"
SHINKENCLI=$SHINKENDIR/bin/shinken

#Check virtualenv, pip and nosetests
function check_req {
    if [[ "$(which virtualenv)" == "" ]];then
        echo "virtualenv needed, please install it"
        exit 2
    fi

    if [[ "$(which pip)" == "" ]];then
        echo "pip needed, please install it"
        exit 2
    fi

}

# Check if the reqs changed
# If the reqs match the previous, copy the previous environment
# Otherwise, create a new one, calc the hash and before going anywhere, copy it under here.
function prepare_environment {

    HASH=$(cat requirements.tests.freeze|md5sum|cut -d' ' -f1)
    if [ -e last_env_hash ]; then
        OLDHASH=$(cat last_env_hash)
    else
        OLDHASH=""
    fi

    echo $HASH > last_env_hash

    echo OLD REQS HASH AND NEW REQS HASH: $OLDHASH $HASH


    # Cache the environment if it hasn't changed.
    if [ "$OLDHASH" != "$HASH" ]; then
        echo "ENVIRONMENT SPECS CHANGED - CREATING A NEW ENVIRONMENT"
        virtualenv --distribute env
        . env/bin/activate
        pip install --upgrade pip
        pip install -r requirements.tests.freeze
        rm -rf last_env
        cp -ar env last_env
    else
        echo "ENVIRONMENT SPECS HAVE NOT CHANGED - USING CACHED ENVIRONMENT"
        cp -ar last_env env
        . env/bin/activate
    fi

    pip install -e $SHINKENDIR
    echo "Done Installing"
}


# Launch the given test with nose test. Nose test has a different behavior than the standard unit test.
function launch_and_assert {
    SCRIPT=$1
    NAME=$(echo $(basename $SCRIPT) | sed s/\\.py$//g | tr [a-z] [A-Z])
    if test $COVERAGE == "NOCOVERAGE"; then
      ${PYTHONTOOLS}/nosetests -v -s --with-xunit ./$SCRIPT --xunit-file="$RESULTSDIR/xml/$NAME.xml"
    else
      ${PYTHONTOOLS}/nosetests -v -s --with-xunit --with-coverage ./$SCRIPT --xunit-file="$RESULTSDIR/xml/$NAME.xml"
      mv .coverage .coverage.$COUNT
      COUNT=$((COUNT + 1))
    fi
    if [ $? != 0 ]
        then
        echo "Error: the test $SCRIPT failed"
        return 2
    else
        echo "test $SCRIPT succeeded, next one"
    fi
}


# Put into a file the test list
function generate_all_tests {
    echo "#All tests in the tests directory are listed below" >  $DIR/all_tests.txt
    echo "#### AUTOGENERATED ####" >> $DIR/all_tests.txt

    for file in test_*.py; do
        echo "$file" >>  $DIR/all_tests.txt
    done
}


# Must be in repos/test before launching
function grab_modules {
    GIT_URL="https://github.com/shinken-monitoring"
    for module in $(cat $MODULELIST); do
        git clone $GIT_URL/$module.git tmp/$module
        $SHINKENCLI install --local tmp/$module > /dev/null
        cp __import_shinken.py shinken_test.py shinken_modules.py tmp/$module/test
        # Symlink of config files to etc
        if [ -d "tmp/$module/test/etc" ]; then
            for conf_file in tmp/$module/test/etc/*; do
               ln -s ../$conf_file etc/
            done
        fi
    done
}


function test_modules {
    for line in $(grep -vE "#|^ *$" $MODULELIST);do
        if [ -d "tmp/$line/test/" ]; then
            for ptest in $(eval "ls tmp/$line/test/test_*.py $REGEXPCMD");do
                launch_and_assert $ptest
                test $? -eq 0 || echo "A test failed : $ptest"
            done
        else :
            echo "No tests found for $line. Skipping"
        fi
    done
}

function test_core {
    # REGEXPCMD is ; or grep -v blabla
    # If ;, we are in normal mode
    for test in $(eval "ls test_*.py $REGEXPCMD") ;do
        launch_and_assert $test
        test $? -eq 0 || echo "A test failed : $line"
    done
}

function main {

    check_req

    cd ${DIR}

    prepare_environment

    . env/bin/activate
    PYTHONBIN="python"
    PYTHONTOOLS=$(dirname $(which $PYTHONBIN))
    echo "PYTHONTOOLS=$PYTHONTOOLS"
    # We should be into /path/to/shinken/test/
    cd ..

    if [[ ! -d "$RESULTSDIR" ]]; then
        mkdir -p $RESULTSDIR
        echo "Creation dir $RESULTSDIR"
    fi

    for dir in "xml" "htmlcov"; do
        if [[ ! -d "$RESULTSDIR/$dir" ]]; then
            mkdir $RESULTSDIR/$dir
        fi
    done

    # Cleanup leftover files from former runs
    rm -f "$RESULTSDIR/xml/nosetests.xml"
    test $COVERAGE == "COVERAGE" && rm -f "$RESULTSDIR/xml/*"
    test $COVERAGE == "COVERAGE" && rm -f "$RESULTSDIR/htmlcov/*"
    test $COVERAGE == "COVERAGE" && rm -f ".coverage*"
    rm -rf tmp/*
    # Clean previous symlinks
    find etc/ -maxdepth 1 -type l -exec rm {} \;
    ln -s /var/lib/shinken/modules tmp/modules

    generate_all_tests

    # Init Count for coverage
    COUNT=1
    test_core
    grab_modules
    test_modules

    # Create the coverage file
    if [[ $COVERAGE == "COVERAGE" ]]; then
        echo "Merging coverage files"
        ${PYTHONTOOLS}/coverage combine
        ${PYTHONTOOLS}/coverage xml --omit=/usr/lib -o "$RESULTSDIR/xml/coverage.xml"
        ${PYTHONTOOLS}/coverage html --omit=/usr/lib -d "$RESULTSDIR/htmlcov"
    fi

    if [[ $PYLINT == "PYLINT" ]]; then
        echo "Pylint Checking"
        cd $SHINKENDIR
        ${PYTHONTOOLS}/pylint --rcfile $DIR/pylint.rc shinken > "test/$RESULTSDIR/pylint.txt"
        cd -
    fi

    if [[ $PEP8 == "PEP8" ]]; then
        echo "Pep8 Checking"
        cd $SHINKENDIR
        ${PYTHONTOOLS}/pep8 --max-line-length=100 --ignore=E303 shinken > "test/$RESULTSDIR/pep8.txt"
        cd -
    fi

    if [[ $COVERAGE == "COVERAGE" && $PYLINT == "PYLINT" ]]; then
        # this run's purpose was to collect metrics, so let jenkins think, it's ok
        # Compile coverage info.
        #coverage combine
        #coverage xml
        return 0
    fi
}


main
exit $?
