#!/bin/bash
cd $(dirname $0)
nft=../../src/nft
debug=false
test_json=false
mydiff() {
diff -w -I '^# ' "$@"
}
if [ "$(id -u)" != "0" ] ; then
echo "this requires root!"
exit 1
fi
testdir=$(mktemp -d)
if [ ! -d $testdir ]; then
echo "Failed to create test directory" >&2
exit 1
fi
trap "rm -rf $testdir; $nft flush ruleset" EXIT
command_file=$(mktemp -p $testdir)
output_file=$(mktemp -p $testdir)
cmd_append() {
echo "$*" >>$command_file
}
monitor_output_append() {
[[ "$*" == '-' ]] && {
cat $command_file >>$output_file
return
}
echo "$*" >>$output_file
}
echo_output_append() {
# this is a bit tricky: for replace commands, nft prints a delete
# command - so in case there is a replace command in $command_file,
# just assume any other commands in the same file are sane
grep -q '^replace' $command_file >/dev/null 2>&1 && {
monitor_output_append "$*"
return
}
[[ "$*" == '-' ]] && {
grep '^\(add\|replace\|insert\)' $command_file >>$output_file
return
}
[[ "$*" =~ ^add|replace|insert ]] && echo "$*" >>$output_file
}
json_output_filter() { # (filename)
# unify handle values
sed -i -e 's/\("handle":\) [0-9][0-9]*/\1 0/g' "$1"
}
monitor_run_test() {
monitor_output=$(mktemp -p $testdir)
monitor_args=""
$test_json && monitor_args="vm json"
$nft -nn monitor $monitor_args >$monitor_output &
monitor_pid=$!
sleep 0.5
$debug && {
echo "command file:"
cat $command_file
}
$nft -f $command_file || {
echo "nft command failed!"
kill $monitor_pid
wait >/dev/null 2>&1
exit 1
}
sleep 0.5
kill $monitor_pid
wait >/dev/null 2>&1
$test_json && json_output_filter $monitor_output
if ! mydiff -q $monitor_output $output_file >/dev/null 2>&1; then
echo "monitor output differs!"
mydiff -u $output_file $monitor_output
exit 1
fi
rm $command_file
rm $output_file
touch $command_file
touch $output_file
}
echo_run_test() {
echo_output=$(mktemp -p $testdir)
$debug && {
echo "command file:"
cat $command_file
}
$nft -nn -e -f $command_file >$echo_output || {
echo "nft command failed!"
exit 1
}
if ! mydiff -q $echo_output $output_file >/dev/null 2>&1; then
echo "echo output differs!"
mydiff -u $output_file $echo_output
exit 1
fi
rm $command_file
rm $output_file
touch $command_file
touch $output_file
}
while [ -n "$1" ]; do
case "$1" in
-d|--debug)
debug=true
shift
;;
-j|--json)
test_json=true
shift
;;
*)
echo "unknown option '$1'"
;&
-h|--help)
echo "Usage: $(basename $0) [-j|--json] [-d|--debug]"
exit 1
;;
esac
done
if $test_json; then
variants="monitor"
else
variants="monitor echo"
fi
for variant in $variants; do
run_test=${variant}_run_test
output_append=${variant}_output_append
for testcase in testcases/*.t; do
echo "$variant: running tests from file $(basename $testcase)"
# files are like this:
#
# I add table ip t
# O add table ip t
# I add chain ip t c
# O add chain ip t c
$nft flush ruleset
input_complete=false
while read dir line; do
case $dir in
I)
$input_complete && $run_test
input_complete=false
cmd_append "$line"
;;
O)
input_complete=true
$test_json || $output_append "$line"
;;
J)
input_complete=true
$test_json && $output_append "$line"
;;
'#'|'')
# ignore comments and empty lines
;;
esac
done <$testcase
$input_complete && $run_test
done
done