#! /usr/bin/env bash
#
# Broctl test setup script (source this at the start of each test script).
#
# This script installs Bro to a directory that is unique to each test,
# and provides a function "installcfgfile" that a test script can 
# optionally use to install files, and a function "replaceprefix" that a
# test script can use to alter the contents of a test file to set the
# correct install directory path.  This script also exports an environment
# variable "BROCTL_INSTALL_PREFIX" that provides a test script with the
# directory path of the Bro install.


# installcfgfile <rel.path> [--new]
#
# This function can be used to install a test-specific config file.
# The <rel.path> is the relative pathname of the config file to install
# and it must follow a naming convention: <dir>/<dest.name>__<text>
# where <dir> is the directory, <dest.name> is the destination filename, and
# <text> is some descriptive text for the config file.
# If "--new" is given, then skip check for existence of destination file.
installcfgfile() {
    set +x

    if [ -z "$1" ]; then
        return
    fi

    # Split input into two cmd-line args.
    origrelpath=`echo $1 | awk '{print $1}'`
    newfile=`echo $1 | awk '{print $2}'`
    if [ "$newfile" = "--new" ]; then
        newfile="yes"
    else
        newfile="no"
    fi

    # Make sure original file exists
    origpath=$BROCTLCFG/$origrelpath
    if [ ! -f "$origpath" ]; then
        echo "Error: source file not found: $origpath" 1>&2
        exit 1
    fi

    # Use the double-underscore delimiter to derive the destination filename
    relpath=$(echo $origrelpath | awk -F'__' '{print $1}')
    if [ "$origrelpath" = "$relpath" ]; then
        echo "Error: source filename needs '__': $origrelpath" 1>&2
        exit 1
    fi
    destfile=$(basename "$relpath")

    # Derive the destination directory based on the original directory
    destdir=$(dirname "$relpath")

    # Make sure destination directory exists
    if [ ! -d "$BROCTL_INSTALL_PREFIX/$destdir" ]; then
        echo "Error: destination directory not found: $BROCTL_INSTALL_PREFIX/$destdir" 1>&2
        exit 1
    fi

    # Finally, build the destination pathname
    destpath=$BROCTL_INSTALL_PREFIX/$destdir/$destfile

    if [ "$newfile" = "no" ]; then
        # Make sure destination file exists (usually, we're overwriting an
        # existing file, so this is a good safety check to catch typos)
        if [ ! -f "$destpath" ]; then
            echo "Error: destination file not found: $destpath (maybe try --new option?)" 1>&2
            exit 1
        fi
    fi

    cp $origpath $destpath
    set -x
}


# replaceprefix <rel.path>
#
# Replace the text "@PREFIX@" with the bro install prefix in the specified
# file (given as a relative pathname).
replaceprefix() {
    set +x

    if [ -z "$1" ]; then
        return
    fi

    destfile=$BROCTL_INSTALL_PREFIX/$1
    if [ ! -f $destfile ]; then
        echo "Error: file not found: $destfile" 1>&2
        exit 1
    fi

    sed "s#@PREFIX@#${BROCTL_INSTALL_PREFIX}#g" $destfile > $destfile.new && mv $destfile.new $destfile
    test $? -ne 0 && exit 1

    set -x
}


# This function sets the correct install prefix directory in all files where
# it's needed (this is done immediately after untarring the Bro install).
replaceprefixes() {
    for i in etc/broctl.cfg bin/broctl lib/broctl/BroControl/version.py ; do
        sed "s#@PREFIX@#${BROCTL_INSTALL_PREFIX}#" $i > $i.new && cp $i.new $i && rm $i.new
        if [ $? -ne 0 ]; then
            return 1
        fi
    done
}


# This function creates a test-specific directory, installs Bro to this
# directory, and exports some env. vars. with the path of this directory.
# Cleanup happens automatically unless BROCTL_TEST_DEBUG is defined.
installbro() {
    if [ -z "${INSTALL}" ]; then
        echo "Error: INSTALL not defined (check btest.cfg)" 1>&2
        exit 1
    fi

    basedir="${INSTALL}"
    tarfile=$basedir/bro-test-install.tar

    if [ ! -f "$tarfile" ]; then
        echo "Error: $tarfile doesn't exist ('make buildbro' to create)" 1>&2
        exit 1
    fi

    # Cleanup the test directory only if BROCTL_TEST_DEBUG is not set.
    if [ -z "${BROCTL_TEST_DEBUG}" ]; then
        trap "cleanup" EXIT
    fi

    # Create test-specific bro installation directory
    export BROCTL_INSTALL_PREFIX=$basedir/test.$$
    mkdir "$BROCTL_INSTALL_PREFIX"
    test $? -ne 0 && exit 1

    # Install bro
    (cd "$BROCTL_INSTALL_PREFIX" && tar xf "$tarfile" && replaceprefixes)
    test $? -ne 0 && exit 1

    export PATH=$BROCTL_INSTALL_PREFIX/bin:$PATH
    export LD_LIBRARY_PATH=$BROCTL_INSTALL_PREFIX/lib

    # If BROCTL_TEST_DEBUG is set, then leave a file in the test directory
    # to help setup environment for running broctl manually.
    if [ -n "${BROCTL_TEST_DEBUG}" ]; then
        how2run=${BROCTL_INSTALL_PREFIX}/how_to_run_broctl
        echo "# In order to run broctl in this directory, first type '. how_to_run_broctl'" >> $how2run
        echo "export PATH=$BROCTL_INSTALL_PREFIX/bin:\$PATH" >> $how2run
        echo "export LD_LIBRARY_PATH=$BROCTL_INSTALL_PREFIX/lib" >> $how2run
    fi
}

cleanup() {
    set +x
    test -n "$BROCTL_INSTALL_PREFIX" && rm -rf "$BROCTL_INSTALL_PREFIX"
}

installbro

# Output test commands (if a test fails, this might be useful for debugging)
set -x

