#!/usr/bin/env bash set -e LINE_SPACES=${LINE_SPACES:-48} STRACE_EXEC="${STRACE_EXEC}" MYDIR="$(realpath "$(dirname ${0})")" nDPId_test_EXEC="$(realpath "${2:-"${MYDIR}/../nDPId-test"}")" NETCAT_EXEC="$(which nc) -q 0 -l 127.0.0.1 9000" JSON_VALIDATOR="$(realpath "${3:-"${MYDIR}/../examples/py-schema-validation/py-schema-validation.py"}")" SEMN_VALIDATOR="$(realpath "${4:-"${MYDIR}/../examples/py-semantic-validation/py-semantic-validation.py"}")" FLOW_INFO="$(realpath "${5:-"${MYDIR}/../examples/py-flow-info/flow-info.py"}")" NDPISRVD_ANALYSED="$(realpath "${6:-"$(dirname ${nDPId_test_EXEC})/nDPIsrvd-analysed"}")" NDPISRVD_COLLECTD="$(realpath "${6:-"$(dirname ${nDPId_test_EXEC})/nDPIsrvd-collectd"}")" IS_GIT=$(test -d "${MYDIR}/../.git" -o -f "${MYDIR}/../.git" && printf '1' || printf '0') function usage() { cat <<EOF usage: ${0} [path-to-nDPI-source-root] \\ [path-to-nDPId-test-exec] [path-to-nDPId-JSON-validator] [path-to-nDPId-SEMANTIC-validator] path-to-nDPId-test-exec defaults to ${nDPId_test_EXEC} path-to-nDPId-JSON-validator defaults to ${JSON_VALIDATOR} path-to-nDPId-SEMANTIC-validator default to ${SEMN_VALIDATOR} path-to-nDPId-flow-info defaults to ${FLOW_INFO} path-to-nDPIsrvd-analysed defaults to ${NDPISRVD_ANALYSED} path-to-nDPIsrvd-collectd defaults to ${NDPISRVD_COLLECTD} EOF return 0 } test -z "$(which flock)" && { printf '%s\n' 'flock not found'; exit 1; } test -z "$(which pkill)" && { printf '%s\n' 'pkill not found'; exit 1; } test -z "$(which nc)" && { printf '%s\n' 'nc not found'; exit 1; } test -z "$(which ss)" && { printf '%s\n' 'ss not found'; exit 1; } test -z "$(which cat)" && { printf '%s\n' 'cat not found'; exit 1; } test -z "$(which grep)" && { printf '%s\n' 'grep not found'; exit 1; } if [ $# -eq 0 -a -x "${MYDIR}/../libnDPI/tests/pcap" ]; then nDPI_SOURCE_ROOT="${MYDIR}/../libnDPI" elif [ $# -ne 1 -a $# -ne 2 -a $# -ne 3 -a $# -ne 4 ]; then usage exit 2 else nDPI_SOURCE_ROOT="$(realpath "${1}")" fi if [ ! -x "${nDPI_SOURCE_ROOT}/tests/pcap" ]; then printf 'PCAP directory %s does not exist or you do not have the permission to access it.\n' "${nDPI_SOURCE_ROOT}/tests/pcap" >&2 exit 2 fi LOCKFILE="$(realpath "${0}").lock" touch "${LOCKFILE}" exec 42< "${LOCKFILE}" $(which flock) -x -n 42 || { printf '%s\n' "Could not aquire file lock for ${0}. Already running instance?" >&2; exit 3; } function sighandler() { printf '%s\n' ' Received shutdown SIGNAL, bye' >&2 $(which pkill) -P $$ wait rm -f "${LOCKFILE}" exit 4 } trap sighandler SIGINT SIGTERM if [ ! -x "${nDPId_test_EXEC}" ]; then usage printf '\n%s\n' "Required nDPId-test executable does not exist; ${nDPId_test_EXEC}" exit 5 fi $(which nc) -h |& head -n1 | grep -qoE '^OpenBSD netcat' || { printf '%s\n' "$(which nc): OpenBSD netcat (nc) version required!" >&2; printf '%s\n' "$(which nc): Your version: $(nc -h |& head -n1)" >&2; exit 6; } nDPI_TEST_DIR="$(realpath "${nDPI_SOURCE_ROOT}/tests/pcap")" cd "${nDPI_TEST_DIR}" cat <<EOF nDPId-test: ${nDPId_test_EXEC} nDPI pcaps: ${nDPI_TEST_DIR} ($(ls -l *.pcap *.pcapng *.cap | wc -l) total) -------------------------- -- nDPId PCAP diff tests -- -------------------------- EOF mkdir -p /tmp/nDPId-test-stderr mkdir -p /tmp/nDPId-test-stdout set +e TESTS_FAILED=0 ${nDPId_test_EXEC} -h 2>/dev/null if [ $? -ne 1 ]; then printf '%s\n' "nDPId-test: ${nDPId_test_EXEC} seems to be an invalid executable" exit 7 fi for pcap_file in *.pcap *.pcapng *.cap; do printf '%s\n' "-- CMD: ${nDPId_test_EXEC} $(realpath "${pcap_file}")" \ >"/tmp/nDPId-test-stderr/${pcap_file}.out" printf '%s\n' "-- OUT: ${MYDIR}/results/${pcap_file}.out" \ >>"/tmp/nDPId-test-stderr/${pcap_file}.out" printf "%-${LINE_SPACES}s\t" "${pcap_file}" if [ ! -z "${STRACE_EXEC}" ]; then STRACE_CMD="${STRACE_EXEC} -f -e decode-fds=path,socket,dev,pidfd -s 1024 -o /tmp/nDPId-test-stderr/${pcap_file}.strace.out" else STRACE_CMD="" fi ${STRACE_CMD} ${nDPId_test_EXEC} "${pcap_file}" \ >"/tmp/nDPId-test-stdout/${pcap_file}.out.new" \ 2>>"/tmp/nDPId-test-stderr/${pcap_file}.out" nDPId_test_RETVAL=$? if [ ${nDPId_test_RETVAL} -eq 0 ]; then if [ ! -r "${MYDIR}/results/${pcap_file}.out" ]; then printf '%s\n' '[NEW]' test ${IS_GIT} -eq 1 && \ mv -v "/tmp/nDPId-test-stdout/${pcap_file}.out.new" \ "${MYDIR}/results/${pcap_file}.out" TESTS_FAILED=$((TESTS_FAILED + 1)) elif diff -u0 "${MYDIR}/results/${pcap_file}.out" \ "/tmp/nDPId-test-stdout/${pcap_file}.out.new" >/dev/null; then printf '%s\n' '[OK]' rm -f "/tmp/nDPId-test-stdout/${pcap_file}.out.new" else printf '%s\n' '[DIFF]' diff -u0 "${MYDIR}/results/${pcap_file}.out" \ "/tmp/nDPId-test-stdout/${pcap_file}.out.new" test ${IS_GIT} -eq 1 && \ mv -v "/tmp/nDPId-test-stdout/${pcap_file}.out.new" \ "${MYDIR}/results/${pcap_file}.out" TESTS_FAILED=$((TESTS_FAILED + 1)) fi else printf '%s\n' '[FAIL]' printf '%s\n' '----------------------------------------' printf '%s\n' "-- STDERR of ${pcap_file}: /tmp/nDPId-test-stderr/${pcap_file}.out" cat "/tmp/nDPId-test-stderr/${pcap_file}.out" TESTS_FAILED=$((TESTS_FAILED + 1)) fi done for out_file in ${MYDIR}/results/*.out; do pcap_file="$(basename ${out_file%.out})" if [ ! -r "${pcap_file}" ]; then printf "%-${LINE_SPACES}s\t%s\n" "${pcap_file}" "[MISSING]" TESTS_FAILED=$((TESTS_FAILED + 1)) fi done function validate_results() { prefix_str="${1}" pcap_file="$(basename ${2})" result_file="${3}" validator_exec="${4}" printf "%s %-$((${LINE_SPACES} - ${#prefix_str}))s\t" "${prefix_str}" "${pcap_file}" printf '%s\n' "-- ${prefix_str}" >>"/tmp/nDPId-test-stderr/${pcap_file}.out" if [ ! -r "${result_file}" ]; then printf ' %s\n' '[MISSING]' return 1 fi # Note that the grep command is required as we generate a summary in the results file. cat "${result_file}" | grep -vE '^~~.*$' | ${NETCAT_EXEC} & nc_pid=$! printf '%s\n' "-- ${validator_exec}" >>"/tmp/nDPId-test-stderr/${pcap_file}.out" ${validator_exec} 2>>"/tmp/nDPId-test-stderr/${pcap_file}.out" if [ $? -eq 0 ]; then printf ' %s\n' '[OK]' else printf ' %s\n' '[FAIL]' printf '%s\n' '----------------------------------------' printf '%s\n' "-- STDERR of ${pcap_file}: /tmp/nDPId-test-stderr/${pcap_file}.out" cat "/tmp/nDPId-test-stderr/${pcap_file}.out" return 1 fi kill -SIGTERM ${nc_pid} 2>/dev/null wait ${nc_pid} 2>/dev/null return 0 } cat <<EOF -------------------- -- Flow Info DIFF -- -------------------- EOF cd "${MYDIR}" for out_file in results/*.out; do result_file="$(basename ${out_file})" printf "%-${LINE_SPACES}s\t" "${result_file}" cat "${out_file}" | grep -vE '^~~.*$' | ${NETCAT_EXEC} & nc_pid=$! ${FLOW_INFO} --host 127.0.0.1 --port 9000 \ --no-color --no-statusbar --hide-instance-info \ --print-analyse-results --print-hostname >"/tmp/nDPId-test-stdout/${result_file}.new" 2>>"/tmp/nDPId-test-stderr/${result_file}" kill -SIGTERM ${nc_pid} 2>/dev/null wait ${nc_pid} 2>/dev/null if [ ! -r "${MYDIR}/results/flow-info/${result_file}" ]; then printf '%s\n' '[NEW]' test ${IS_GIT} -eq 1 && \ mv -v "/tmp/nDPId-test-stdout/${result_file}.new" \ "${MYDIR}/results/flow-info/${result_file}" TESTS_FAILED=$((TESTS_FAILED + 1)) elif diff -u0 "${MYDIR}/results/flow-info/${result_file}" \ "/tmp/nDPId-test-stdout/${result_file}.new" >/dev/null; then printf '%s\n' '[OK]' rm -f "/tmp/nDPId-test-stdout/${result_file}.new" else printf '%s\n' '[DIFF]' diff -u0 "${MYDIR}/results/flow-info/${result_file}" \ "/tmp/nDPId-test-stdout/${result_file}.new" test ${IS_GIT} -eq 1 && \ mv -v "/tmp/nDPId-test-stdout/${result_file}.new" \ "${MYDIR}/results/flow-info/${result_file}" TESTS_FAILED=$((TESTS_FAILED + 1)) fi done for out_file in ${MYDIR}/results/flow-info/*.out; do result_file="$(basename ${out_file})" if [ ! -r "${MYDIR}/results/${result_file}" ]; then printf "%-${LINE_SPACES}s\t%s\n" "${result_file}" "[MISSING]" TESTS_FAILED=$((TESTS_FAILED + 1)) fi done cat <<EOF ----------------------- -- Flow Analyse DIFF -- ----------------------- EOF if [ -x "${NDPISRVD_ANALYSED}" ]; then cd "${MYDIR}" for out_file in results/*.out; do result_file="$(basename ${out_file})" printf "%-${LINE_SPACES}s\t" "${result_file}" cat "${out_file}" | grep -vE '^~~.*$' | ${NETCAT_EXEC} & nc_pid=$! while ! ss -4 -t -n -l | grep -q '127.0.0.1:9000'; do sleep 0.5; printf '%s\n' 'Waiting until socket 127.0.0.1:9000 is available..' >>"/tmp/nDPId-test-stderr/${result_file}"; done ${NDPISRVD_ANALYSED} -s '127.0.0.1:9000' -o "/tmp/nDPId-test-stdout/${result_file}.csv.new" 2>>"/tmp/nDPId-test-stderr/${result_file}" 1>&2 kill -SIGTERM ${nc_pid} 2>/dev/null wait ${nc_pid} 2>/dev/null if [ ! -r "${MYDIR}/results/flow-analyse/${result_file}" ]; then printf '%s\n' '[NEW]' test ${IS_GIT} -eq 1 && \ mv -v "/tmp/nDPId-test-stdout/${result_file}.csv.new" \ "${MYDIR}/results/flow-analyse/${result_file}" TESTS_FAILED=$((TESTS_FAILED + 1)) elif diff -u0 "${MYDIR}/results/flow-analyse/${result_file}" \ "/tmp/nDPId-test-stdout/${result_file}.csv.new" >/dev/null; then printf '%s\n' '[OK]' rm -f "/tmp/nDPId-test-stdout/${result_file}.csv.new" else printf '%s\n' '[DIFF]' diff -u0 "${MYDIR}/results/flow-analyse/${result_file}" \ "/tmp/nDPId-test-stdout/${result_file}.csv.new" test ${IS_GIT} -eq 1 && \ mv -v "/tmp/nDPId-test-stdout/${result_file}.csv.new" \ "${MYDIR}/results/flow-analyse/${result_file}" cat "/tmp/nDPId-test-stderr/${result_file}" TESTS_FAILED=$((TESTS_FAILED + 1)) fi done for out_file in ${MYDIR}/results/flow-analyse/*.out; do result_file="$(basename ${out_file})" if [ ! -r "${MYDIR}/results/${result_file}" ]; then printf "%-${LINE_SPACES}s\t%s\n" "${result_file}" "[MISSING]" TESTS_FAILED=$((TESTS_FAILED + 1)) fi done else printf '%s\n' "Not found or not executable: ${NDPISRVD_ANALYSED}" fi cat <<EOF ------------------------------ -- Collectd Statistics DIFF -- ------------------------------ EOF if [ -x "${NDPISRVD_COLLECTD}" ]; then cd "${MYDIR}" for out_file in results/*.out; do result_file="$(basename ${out_file})" printf "%-${LINE_SPACES}s\t" "${result_file}" cat "${out_file}" | grep -vE '^~~.*$' | ${NETCAT_EXEC} & nc_pid=$! while ! ss -4 -t -n -l | grep -q '127.0.0.1:9000'; do sleep 0.5; printf '%s\n' 'Waiting until socket 127.0.0.1:9000 is available..' >>"/tmp/nDPId-test-stderr/${result_file}"; done ${NDPISRVD_COLLECTD} -s '127.0.0.1:9000' 2>>"/tmp/nDPId-test-stderr/${result_file}" 1>"/tmp/nDPId-test-stdout/${result_file}.stats.new" kill -SIGTERM ${nc_pid} 2>/dev/null wait ${nc_pid} 2>/dev/null if [ ! -r "${MYDIR}/results/collectd-stats/${result_file}" ]; then printf '%s\n' '[NEW]' test ${IS_GIT} -eq 1 && \ mv -v "/tmp/nDPId-test-stdout/${result_file}.stats.new" \ "${MYDIR}/results/collectd-stats/${result_file}" TESTS_FAILED=$((TESTS_FAILED + 1)) elif diff -u0 "${MYDIR}/results/collectd-stats/${result_file}" \ "/tmp/nDPId-test-stdout/${result_file}.stats.new" >/dev/null; then printf '%s\n' '[OK]' rm -f "/tmp/nDPId-test-stdout/${result_file}.stats.new" else printf '%s\n' '[DIFF]' diff -u0 "${MYDIR}/results/collectd-stats/${result_file}" \ "/tmp/nDPId-test-stdout/${result_file}.stats.new" test ${IS_GIT} -eq 1 && \ mv -v "/tmp/nDPId-test-stdout/${result_file}.stats.new" \ "${MYDIR}/results/collectd-stats/${result_file}" cat "/tmp/nDPId-test-stderr/${result_file}" TESTS_FAILED=$((TESTS_FAILED + 1)) fi done for out_file in ${MYDIR}/results/collectd-stats/*.out; do result_file="$(basename ${out_file})" if [ ! -r "${MYDIR}/results/${result_file}" ]; then printf "%-${LINE_SPACES}s\t%s\n" "${result_file}" "[MISSING]" TESTS_FAILED=$((TESTS_FAILED + 1)) fi done else printf '%s\n' "Not found or not executable: ${NDPISRVD_COLLECTD}" fi cat <<EOF -------------------------------- -- SCHEMA/SEMANTIC Validation -- -------------------------------- netcat (OpenBSD) exec + args: ${NETCAT_EXEC} EOF cd "${MYDIR}" for out_file in results/*.out; do pcap_file="${nDPI_TEST_DIR}/$(basename ${out_file%.out})" if [ ! -r "${pcap_file}" ]; then printf "%-${LINE_SPACES}s\t%s\n" "$(basename ${pcap_file})" '[MISSING]' TESTS_FAILED=$((TESTS_FAILED + 1)) else validate_results "SCHEMA " "${pcap_file}" "${out_file}" \ "${JSON_VALIDATOR} --host 127.0.0.1 --port 9000" if [ $? -ne 0 ]; then TESTS_FAILED=$((TESTS_FAILED + 1)) continue fi validate_results "SEMANTIC" "${pcap_file}" "${out_file}" \ "${SEMN_VALIDATOR} --host 127.0.0.1 --port 9000 --strict" if [ $? -ne 0 ]; then TESTS_FAILED=$((TESTS_FAILED + 1)) continue fi fi done cat <<EOF Done. For more information see text files in: /tmp/nDPId-test-stdout/ /tmp/nDPId-test-stderr/ EOF if [ ${TESTS_FAILED} -eq 0 ]; then cat <<EOF -------------------------- -- All tests succeeded. -- -------------------------- EOF exit 0 else cat <<EOF *** ${TESTS_FAILED} tests failed. *** EOF exit 1 fi