2022-06-13 19:54:47 +00:00
|
|
|
#!/usr/bin/env bash
|
2022-03-09 13:45:36 +00:00
|
|
|
|
2022-06-15 13:36:36 +00:00
|
|
|
# this should have effect globally, for all tests
|
2022-06-22 08:29:02 +00:00
|
|
|
# https://github.com/bats-core/bats-core/blob/master/docs/source/warnings/BW02.rst
|
2022-06-15 13:36:36 +00:00
|
|
|
bats_require_minimum_version 1.5.0
|
|
|
|
|
2022-03-18 09:13:12 +00:00
|
|
|
debug() {
|
|
|
|
echo 'exec 1<&-; exec 2<&-; exec 1>&3; exec 2>&1'
|
|
|
|
}
|
|
|
|
export -f debug
|
2022-03-09 13:45:36 +00:00
|
|
|
|
2022-03-18 09:13:12 +00:00
|
|
|
# redirects stdout and stderr to &3 otherwise the errors in setup, teardown would
|
|
|
|
# go unreported.
|
|
|
|
# BUT - don't do this in test functions. Everything written to stdout and
|
|
|
|
# stderr after this line will go to the terminal, but in the tests, these
|
|
|
|
# are supposed to be collected and shown only in case of test failure
|
|
|
|
# (see options --print-output-on-failure and --show-output-of-passing-tests)
|
|
|
|
eval "$(debug)"
|
|
|
|
|
|
|
|
# Allow tests to use relative paths for helper scripts.
|
2022-03-09 13:45:36 +00:00
|
|
|
# shellcheck disable=SC2164
|
2022-03-18 09:13:12 +00:00
|
|
|
cd "${TEST_DIR}"
|
2023-11-24 14:57:32 +00:00
|
|
|
export PATH="${TEST_DIR}/bin:${PATH}"
|
2022-03-09 13:45:36 +00:00
|
|
|
|
|
|
|
# complain if there's a crowdsec running system-wide or leftover from a previous test
|
2022-10-04 13:58:10 +00:00
|
|
|
./bin/assert-crowdsec-not-running
|
2022-03-09 13:45:36 +00:00
|
|
|
|
2022-06-17 14:12:49 +00:00
|
|
|
# we can prepend the filename to the test descriptions (useful to feed a TAP consumer)
|
|
|
|
if [[ "${PREFIX_TEST_NAMES_WITH_FILE:-false}" == "true" ]]; then
|
|
|
|
BATS_TEST_NAME_PREFIX="$(basename "${BATS_TEST_FILENAME}" .bats): "
|
|
|
|
export BATS_TEST_NAME_PREFIX
|
|
|
|
fi
|
|
|
|
|
|
|
|
# before bats 1.7, we did that by hand
|
|
|
|
FILE=
|
2022-03-09 13:45:36 +00:00
|
|
|
export FILE
|
|
|
|
|
|
|
|
# the variables exported here can be seen in other setup/teardown/test functions
|
2022-03-18 09:13:12 +00:00
|
|
|
# MYVAR=something
|
|
|
|
# export MYVAR
|
2022-03-09 13:45:36 +00:00
|
|
|
|
|
|
|
# functions too
|
|
|
|
cscli() {
|
|
|
|
"${CSCLI}" "$@"
|
|
|
|
}
|
|
|
|
export -f cscli
|
|
|
|
|
2022-07-01 20:45:55 +00:00
|
|
|
config_get() {
|
2022-10-07 14:17:36 +00:00
|
|
|
local cfg="${CONFIG_YAML}"
|
2022-07-01 20:45:55 +00:00
|
|
|
if [[ $# -ge 2 ]]; then
|
|
|
|
cfg="$1"
|
|
|
|
shift
|
|
|
|
fi
|
|
|
|
|
|
|
|
yq e "$1" "${cfg}"
|
2022-03-18 09:13:12 +00:00
|
|
|
}
|
2022-07-01 20:45:55 +00:00
|
|
|
export -f config_get
|
|
|
|
|
|
|
|
config_set() {
|
2022-10-07 14:17:36 +00:00
|
|
|
local cfg="${CONFIG_YAML}"
|
2022-07-01 20:45:55 +00:00
|
|
|
if [[ $# -ge 2 ]]; then
|
|
|
|
cfg="$1"
|
|
|
|
shift
|
|
|
|
fi
|
|
|
|
|
|
|
|
yq e "$1" -i "${cfg}"
|
|
|
|
}
|
|
|
|
export -f config_set
|
2022-03-18 09:13:12 +00:00
|
|
|
|
2022-07-04 09:26:39 +00:00
|
|
|
config_disable_agent() {
|
2023-07-27 15:02:20 +00:00
|
|
|
config_set '.crowdsec_service.enable=false'
|
|
|
|
# this should be equivalent to:
|
|
|
|
# config_set 'del(.crowdsec_service)'
|
2022-07-04 09:26:39 +00:00
|
|
|
}
|
|
|
|
export -f config_disable_agent
|
|
|
|
|
2023-01-17 11:12:46 +00:00
|
|
|
config_log_stderr() {
|
|
|
|
config_set '.common.log_media="stdout"'
|
|
|
|
}
|
|
|
|
export -f config_log_stderr
|
|
|
|
|
2022-07-04 09:26:39 +00:00
|
|
|
config_disable_lapi() {
|
2023-07-27 15:02:20 +00:00
|
|
|
config_set '.api.server.enable=false'
|
|
|
|
# this should be equivalent to:
|
|
|
|
# config_set 'del(.api.server)'
|
2022-07-04 09:26:39 +00:00
|
|
|
}
|
|
|
|
export -f config_disable_lapi
|
|
|
|
|
|
|
|
config_disable_capi() {
|
|
|
|
config_set 'del(.api.server.online_client)'
|
|
|
|
}
|
|
|
|
export -f config_disable_capi
|
|
|
|
|
|
|
|
config_enable_capi() {
|
|
|
|
online_api_credentials="$(dirname "${CONFIG_YAML}")/online_api_credentials.yaml" \
|
|
|
|
config_set '.api.server.online_client.credentials_path=strenv(online_api_credentials)'
|
|
|
|
}
|
|
|
|
export -f config_enable_capi
|
|
|
|
|
2022-03-09 13:45:36 +00:00
|
|
|
# We use these functions like this:
|
|
|
|
# somecommand <(stderr)
|
|
|
|
# to provide a standard input to "somecommand".
|
|
|
|
# The alternatives echo "$stderr" or <<<"$stderr"
|
|
|
|
# ("here string" in bash jargon)
|
|
|
|
# are worse because they add a newline,
|
|
|
|
# even if the variable is empty.
|
|
|
|
|
|
|
|
# shellcheck disable=SC2154
|
|
|
|
stderr() {
|
2022-06-13 19:54:47 +00:00
|
|
|
printf '%s' "${stderr}"
|
2022-03-09 13:45:36 +00:00
|
|
|
}
|
|
|
|
export -f stderr
|
|
|
|
|
|
|
|
# shellcheck disable=SC2154
|
|
|
|
output() {
|
2022-06-13 19:54:47 +00:00
|
|
|
printf '%s' "${output}"
|
2022-03-09 13:45:36 +00:00
|
|
|
}
|
|
|
|
export -f output
|
2022-03-18 09:13:12 +00:00
|
|
|
|
2023-08-25 14:15:28 +00:00
|
|
|
is_package_testing() {
|
|
|
|
[[ "$PACKAGE_TESTING" != "" ]]
|
|
|
|
}
|
|
|
|
export -f is_package_testing
|
|
|
|
|
2022-04-13 13:17:49 +00:00
|
|
|
is_db_postgres() {
|
2023-08-25 14:15:28 +00:00
|
|
|
[[ "$DB_BACKEND" =~ ^postgres|pgx$ ]]
|
2022-04-13 13:17:49 +00:00
|
|
|
}
|
|
|
|
export -f is_db_postgres
|
|
|
|
|
|
|
|
is_db_mysql() {
|
2023-08-25 14:15:28 +00:00
|
|
|
[[ "$DB_BACKEND" == "mysql" ]]
|
2022-04-13 13:17:49 +00:00
|
|
|
}
|
|
|
|
export -f is_db_mysql
|
|
|
|
|
|
|
|
is_db_sqlite() {
|
2023-08-25 14:15:28 +00:00
|
|
|
[[ "$DB_BACKEND" == "sqlite" ]]
|
2022-04-13 13:17:49 +00:00
|
|
|
}
|
|
|
|
export -f is_db_sqlite
|
|
|
|
|
2023-06-28 08:07:05 +00:00
|
|
|
crowdsec_log() {
|
|
|
|
echo "$(config_get .common.log_dir)"/crowdsec.log
|
|
|
|
}
|
|
|
|
export -f crowdsec_log
|
|
|
|
|
|
|
|
truncate_log() {
|
|
|
|
true > "$(crowdsec_log)"
|
|
|
|
}
|
|
|
|
export -f truncate_log
|
|
|
|
|
|
|
|
assert_log() {
|
|
|
|
local oldout="${output:-}"
|
|
|
|
output="$(cat "$(crowdsec_log)")"
|
|
|
|
assert_output "$@"
|
|
|
|
output="${oldout}"
|
|
|
|
}
|
|
|
|
export -f assert_log
|
|
|
|
|
2022-10-07 14:17:36 +00:00
|
|
|
# Compare ignoring the key order, and allow "expected" without quoted identifiers.
|
|
|
|
# Preserve the output variable in case the following commands require it.
|
2022-08-05 08:54:49 +00:00
|
|
|
assert_json() {
|
2022-10-07 14:17:36 +00:00
|
|
|
local oldout="${output}"
|
2022-08-05 08:54:49 +00:00
|
|
|
# validate actual, sort
|
|
|
|
run -0 jq -Sen "${output}"
|
|
|
|
local actual="${output}"
|
|
|
|
|
|
|
|
# handle stdin, quote identifiers, sort
|
|
|
|
local expected="$1"
|
|
|
|
if [[ "${expected}" == "-" ]]; then
|
|
|
|
expected="$(cat)"
|
|
|
|
fi
|
|
|
|
run -0 jq -Sn "${expected}"
|
|
|
|
expected="${output}"
|
|
|
|
|
|
|
|
#shellcheck disable=SC2016
|
|
|
|
run jq -ne --argjson a "${actual}" --argjson b "${expected}" '$a == $b'
|
|
|
|
#shellcheck disable=SC2154
|
|
|
|
if [[ "${status}" -ne 0 ]]; then
|
|
|
|
echo "expect: $(jq -c <<<"${expected}")"
|
|
|
|
echo "actual: $(jq -c <<<"${actual}")"
|
|
|
|
diff <(echo "${actual}") <(echo "${expected}")
|
|
|
|
fail "json does not match"
|
|
|
|
fi
|
2022-10-07 14:17:36 +00:00
|
|
|
output="${oldout}"
|
2022-08-05 08:54:49 +00:00
|
|
|
}
|
|
|
|
export -f assert_json
|
|
|
|
|
2022-10-07 14:17:36 +00:00
|
|
|
# Check if there's something on stdin by consuming it. Only use this as a way
|
|
|
|
# to check if something was passed by mistake, since if you read it, it will be
|
|
|
|
# incomplete.
|
|
|
|
is_stdin_empty() {
|
2022-10-14 13:48:41 +00:00
|
|
|
if read -r -t 0.1; then
|
2022-10-07 14:17:36 +00:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
export -f is_stdin_empty
|
|
|
|
|
2022-08-05 08:54:49 +00:00
|
|
|
assert_stderr() {
|
2022-10-07 14:17:36 +00:00
|
|
|
# it is never useful to call this without arguments
|
|
|
|
if [[ "$#" -eq 0 ]]; then
|
|
|
|
# maybe the caller forgot to use '-' with an heredoc
|
|
|
|
if ! is_stdin_empty; then
|
|
|
|
fail "${FUNCNAME[0]}: called with stdin and no arguments (heredoc?)"
|
|
|
|
fi
|
|
|
|
fail "${FUNCNAME[0]}: called with no arguments"
|
|
|
|
fi
|
|
|
|
|
|
|
|
local oldout="${output}"
|
2022-08-05 08:54:49 +00:00
|
|
|
run -0 echo "${stderr}"
|
|
|
|
assert_output "$@"
|
|
|
|
output="${oldout}"
|
|
|
|
}
|
|
|
|
export -f assert_stderr
|
|
|
|
|
2022-10-07 09:05:35 +00:00
|
|
|
# like refute_output, but for stderr
|
2022-08-05 08:54:49 +00:00
|
|
|
refute_stderr() {
|
2022-10-07 14:17:36 +00:00
|
|
|
# calling this without arguments is ok, as long as stdin in empty
|
|
|
|
if ! is_stdin_empty; then
|
|
|
|
fail "${FUNCNAME[0]}: called with stdin (heredoc?)"
|
|
|
|
fi
|
|
|
|
|
|
|
|
local oldout="${output}"
|
2022-08-05 08:54:49 +00:00
|
|
|
run -0 echo "${stderr}"
|
|
|
|
refute_output "$@"
|
|
|
|
output="${oldout}"
|
|
|
|
}
|
|
|
|
export -f refute_stderr
|
|
|
|
|
2022-10-07 09:05:35 +00:00
|
|
|
# like assert_output, but for stderr
|
2022-08-05 08:54:49 +00:00
|
|
|
assert_stderr_line() {
|
2022-10-07 14:17:36 +00:00
|
|
|
if [[ "$#" -eq 0 ]]; then
|
|
|
|
fail "${FUNCNAME[0]}: called with no arguments"
|
|
|
|
fi
|
|
|
|
|
|
|
|
local oldout="${output}"
|
2022-08-05 08:54:49 +00:00
|
|
|
run -0 echo "${stderr}"
|
|
|
|
assert_line "$@"
|
|
|
|
output="${oldout}"
|
|
|
|
}
|
|
|
|
export -f assert_stderr_line
|
|
|
|
|
2023-11-24 14:57:32 +00:00
|
|
|
# remove all installed items and data
|
|
|
|
hub_purge_all() {
|
|
|
|
local CONFIG_DIR
|
|
|
|
CONFIG_DIR=$(dirname "$CONFIG_YAML")
|
2023-12-01 08:36:38 +00:00
|
|
|
rm -rf \
|
|
|
|
"$CONFIG_DIR"/collections/* \
|
|
|
|
"$CONFIG_DIR"/parsers/*/* \
|
|
|
|
"$CONFIG_DIR"/scenarios/* \
|
2023-12-07 15:20:13 +00:00
|
|
|
"$CONFIG_DIR"/postoverflows/* \
|
|
|
|
"$CONFIG_DIR"/contexts/*
|
2023-12-01 08:36:38 +00:00
|
|
|
rm -rf \
|
|
|
|
"$CONFIG_DIR"/hub/collections/* \
|
|
|
|
"$CONFIG_DIR"/hub/parsers/*/* \
|
|
|
|
"$CONFIG_DIR"/hub/scenarios/* \
|
2023-12-07 15:20:13 +00:00
|
|
|
"$CONFIG_DIR"/hub/postoverflows/* \
|
|
|
|
"$CONFIG_DIR"/hub/contexts/*
|
2023-11-24 14:57:32 +00:00
|
|
|
local DATA_DIR
|
|
|
|
DATA_DIR=$(config_get .config_paths.data_dir)
|
|
|
|
# should remove everything except the db (find $DATA_DIR -not -name "crowdsec.db*" -delete),
|
|
|
|
# but don't play with fire if there is a misconfiguration
|
|
|
|
rm -rfv "$DATA_DIR"/GeoLite*
|
|
|
|
}
|
|
|
|
export -f hub_purge_all
|
|
|
|
|
|
|
|
# remove unused data from the index, to make sure we don't rely on it in any way
|
|
|
|
hub_strip_index() {
|
|
|
|
local INDEX
|
|
|
|
INDEX=$(config_get .config_paths.index_path)
|
|
|
|
local hub_min
|
|
|
|
hub_min=$(jq <"$INDEX" 'del(..|.content?) | del(..|.long_description?) | del(..|.deprecated?) | del (..|.labels?)')
|
|
|
|
echo "$hub_min" >"$INDEX"
|
|
|
|
}
|
|
|
|
export -f hub_strip_index
|
|
|
|
|
2022-10-07 09:05:35 +00:00
|
|
|
# remove color and style sequences from stdin
|
|
|
|
plaintext() {
|
|
|
|
sed -E 's/\x1B\[[0-9;]*[JKmsu]//g'
|
|
|
|
}
|
|
|
|
export -f plaintext
|
2022-12-30 14:57:24 +00:00
|
|
|
|
|
|
|
# like run but defaults to separate stderr and stdout
|
|
|
|
rune() {
|
|
|
|
run --separate-stderr "$@"
|
|
|
|
}
|
|
|
|
export -f rune
|