zeek/auxil/zeekctl/testing/Scripts/zeekctl-test-setup
Patrick Kelley 8fd444092b initial
2025-05-07 15:35:15 -04:00

256 lines
8.4 KiB
Bash
Executable File

#! /usr/bin/env bash
#
# Zeekctl test setup script. This script should be sourced in each test
# script. This script requires that some env. vars. are correctly defined
# in btest.cfg.
#
# This script installs Zeek to a directory that is unique to each test,
# and provides a few functions and environment variables that can be used
# directly by test scripts.
#
# This script provides these functions that can be used directly in
# test scripts:
# installfile Install a file into the test-specific Zeek install dir.
# replaceprefix Replace text "@PREFIX@" in a specified file with the
# test-specific directory path of the Zeek install.
#
# This script automatically exports some environment variables that are needed
# by test scripts:
# ZEEKCTL_INSTALL_PREFIX - Test-specific directory path of the Zeek install.
# ZEEKCTL_INSTALL_PYTHON_DIR - Absolute path of the Python module directory
# for the above install.
# PATH - Enable test scripts to run the correct copy of "zeekctl" without
# specifying a path.
#
# A user can modify the behavior of this script by setting any of the
# following env. variables:
# ZEEKCTL_TEST_DEBUG - If this is set (value doesn't matter), then the
# test-specific Zeek install directory will not be removed
# when a test terminates (this is useful for debugging).
# installfile <rel.path> [<destdir>] [--new]
#
# Install a file to the test-specific Zeek installation directory.
#
# The <rel.path> is the pathname (relative to the "Cfg" directory, which is
# located in the btest base directory) of the file to be installed,
# 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 file (to allow choosing
# among different variations of the same file).
# The file will be copied to $ZEEKCTL_INSTALL_PREFIX/<dir>/<dest.name>
#
# If <destdir> is specified, then the file will be copied to
# $ZEEKCTL_INSTALL_PREFIX/<destdir>/<dest.name>
#
# The destination directory and file must already exist.
# If "--new" is given, then skip check for existence of destination file.
installfile() {
set +x
if [ -z "$1" ]; then
return
fi
newfile="no"
destdir=""
origrelpath=$1
if [ -n "$2" ]; then
if [ "$2" = "--new" ]; then
newfile="yes"
else
destdir=$2
fi
if [ "$3" = "--new" ]; then
newfile="yes"
fi
fi
# Make sure original file exists
origpath=$ZEEKCTLCFG/$origrelpath
if [ ! -f "$origpath" ]; then
echo "Error: source file not found: $origpath" 1>&2
exit 1
fi
# Remove the optional double-underscore delimiter (and following text) to
# derive the destination filename
relpath=$(echo $origrelpath | awk -F'__' '{print $1}')
destfile=$(basename "$relpath")
# Destination directory is either specified by user or is the original
# directory path
if [ -z "$destdir" ]; then
destdir=$(dirname "$relpath")
fi
# If destination directory is not yet absolute, make it so:
if [[ "$destdir" != /* ]]; then
destdir="$ZEEKCTL_INSTALL_PREFIX/$destdir"
fi
# Make sure destination directory exists
if [ ! -d "$destdir" ]; then
echo "Error: destination directory not found: $destdir" 1>&2
exit 1
fi
# Finally, build the destination pathname
destpath=$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 (if this is a new file, use the --new option)" 1>&2
exit 1
fi
fi
cp $origpath $destpath
set -x
}
# replaceprefix <rel.path>
#
# Replace the text "@PREFIX@" with the zeek install prefix in the specified
# file (given as a relative pathname).
replaceprefix() {
set +x
if [ -z "$1" ]; then
return
fi
destfile=$ZEEKCTL_INSTALL_PREFIX/$1
if [ ! -f $destfile ]; then
echo "Error: file not found: $destfile" 1>&2
exit 1
fi
# Using "cp" and "rm" here in order to preserve permissions of file
sed "s#@PREFIX@#${ZEEKCTL_INSTALL_PREFIX}#g" $destfile > $destfile.new && cp $destfile.new $destfile && rm $destfile.new
test $? -ne 0 && exit 1
set -x
}
#####
# The following functions are needed by this script, but are not likely to be
# needed by any zeekctl test scripts.
# Normalize the specified pathname by resolving any ".." and symlinks in
# the path.
canonicalpath() {
newpath=`python3 -c "from __future__ import print_function; import os,sys; print(os.path.realpath(sys.argv[1]))" "$1"`
test $? -ne 0 && exit 1
echo $newpath
}
# Set the correct install prefix directory in all files where it's needed
# (this is done immediately after untarring the Zeek install).
replaceprefixes() {
# Put in place the test's actual prefix in files where we
# previously put in place the @PREFIX@ pattern:
for i in etc/zeekctl.cfg bin/zeekctl bin/zeek-config ; do
sed "s#@PREFIX@#${ZEEKCTL_INSTALL_PREFIX}#" $i > $i.new && cp $i.new $i && rm $i.new
if [ $? -ne 0 ]; then
return 1
fi
done
# We can now use zeek-config to figure out additional paths. This
# avoids assumptions about where Zeek places directories.
local pydir=$(./bin/zeek-config --python_dir)
# Finally, substitute those in additional files whose location we
# didn't previously know.
for i in $pydir/zeekctl/ZeekControl/version.py ; do
sed "s#@PREFIX@#${ZEEKCTL_INSTALL_PREFIX}#" $i > $i.new && cp $i.new $i && rm $i.new
if [ $? -ne 0 ]; then
return 1
fi
done
}
# Cleanup when a zeekctl test script terminates for any reason (this is called
# automatically).
cleanup() {
set +x
set +e
# Make sure all Zeek instances started by this test are stopped.
# Hide the output to avoid user confusion if a test fails (for example,
# this command will fail if "zeekctl install" was not run).
zeekctl stop > /dev/null 2>&1
# Cleanup the test-specific Zeek install directory only if ZEEKCTL_TEST_DEBUG
# is not set.
if [ -z "${ZEEKCTL_TEST_DEBUG}" ]; then
test -n "$ZEEKCTL_INSTALL_PREFIX" && rm -rf "$ZEEKCTL_INSTALL_PREFIX"
fi
}
# Create a test-specific directory, install Zeek to this directory, and export
# the env. vars. ZEEKCTL_INSTALL_PREFIX and PATH which are both needed by
# zeekctl test scripts.
main() {
# Exit if any command fails (this is useful to debug a failing zeekctl test
# script).
set -e
if [ -z "${INSTALL}" ]; then
echo "Error: the INSTALL env. variable is not defined (should be in btest.cfg)" 1>&2
exit 1
fi
basedir="${INSTALL}"
tarfile=$basedir/zeek-test-install.tar
if [ ! -f "$tarfile" ]; then
echo "Error: $tarfile doesn't exist (run the 'Scripts/build-zeek' script)" 1>&2
exit 1
fi
trap "cleanup" EXIT
# Export "ZEEKCTL_INSTALL_PREFIX" which is used in test scripts that need
# the directory path of the Zeek install.
export ZEEKCTL_INSTALL_PREFIX=`canonicalpath "$basedir/test.$$"`
# Create test-specific zeek installation directory
mkdir "$ZEEKCTL_INSTALL_PREFIX"
# Install zeek
(cd "$ZEEKCTL_INSTALL_PREFIX" && tar xf "$tarfile" && replaceprefixes)
# Update PATH to ensure that test scripts are running the correct copy of
# zeekctl.
export PATH=$ZEEKCTL_INSTALL_PREFIX/bin:$PATH
# Provide the Python module installation directory to the tests.
# This avoids hardwiring assumptions about the location of that
# directory into the tests.
export ZEEKCTL_INSTALL_PYTHON_DIR=$(zeek-config --python_dir)
# If the user set the env. var. ZEEKCTL_TEST_DEBUG, then leave a file in
# the test directory to help setup the environment for running zeekctl
# manually.
if [ -n "${ZEEKCTL_TEST_DEBUG}" ]; then
how2run=${ZEEKCTL_INSTALL_PREFIX}/how_to_run_zeekctl
echo "# In order to run zeekctl in this directory, type '. ./how_to_run_zeekctl'" >> $how2run
echo "export PATH=$ZEEKCTL_INSTALL_PREFIX/bin:\$PATH" >> $how2run
fi
# Output all commands in a zeekctl test script (if a test fails, this might
# be useful for debugging).
set -x
}
main