]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add test script for radclient
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 12 Jan 2015 01:04:04 +0000 (08:04 +0700)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 12 Jan 2015 01:04:11 +0000 (08:04 +0700)
scripts/raduat [new file with mode: 0755]

diff --git a/scripts/raduat b/scripts/raduat
new file mode 100755 (executable)
index 0000000..feeb137
--- /dev/null
@@ -0,0 +1,359 @@
+#!/bin/bash
+
+# Simple test wrapper around radclient to allow automated UATs
+#
+# Author Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+# Copyright 2014-2015 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+# Copyright 2015 The FreeRADIUS Project
+
+# A POSIX variable
+OPTIND=1         # Reset in case getopts has been used previously in the shell.
+
+# Environmental variables
+: ${TESTDIR=$(dirname $0)"/tests"}
+: ${RADCLIENT='radclient'}
+: ${FILTER_SUFFIX='_expected'}
+: ${DICTPATH=$(dirname $0)/share}
+PATH="$(dirname $0)/bin:${PATH}"
+
+# Initialize our own variables
+verbose=0
+cluster=
+role=
+type=
+parallel=40
+retries=3
+timeout=2
+target='127.0.0.1'
+secret='testing123'
+
+# Some very basic logging functions
+function ERROR
+{
+    echo "$@" 1>&2;
+}
+
+function INFO
+{
+    echo "$@"
+}
+
+function DEBUG
+{
+    if [ $verbose -gt 0 ]; then
+        echo "$@"
+    fi
+}
+
+function show_help
+{
+    echo $(basename $0)" [options] [-- <test_glob0> <test_glob1> <test_globN>]"
+    echo "  -h                        Display this help message."
+    echo "  -H <host>[:port]          Send test packets to specified host and port (defaults to 127.0.0.1)"
+    echo "  -v                        Verbose mode."
+    echo "  -p <number>               Run tests in parallel (defaults to 20)."
+    if [ ! -z "$role_types" ]; then
+        echo "  -c <cluster>              Specify cluster type one of ($cluster_types)."
+        echo "  -r <type>                 Specify server role one of ($role_types)."
+        echo
+        echo "Note: Test path globs are relative to ${TESTDIR}/<cluster>/<type>/"
+    fi
+
+    echo
+    echo "For role based test file layout create test files under ${TESTDIR}/<cluster>/<type>"
+    echo "Where <cluster> and <type> are substrings found in the FQDN of <host>."
+    echo "For simplified test layout create test files under ${TESTDIR}"
+    echo
+    echo "The directory containing the tests should contains pairs of request files and filter files."
+    echo "The request file name must contain 'test<num><num><num>."
+    echo "The filter name must match the test name but with a '${FILTER_SUFFIX}' suffix."
+    echo "For example:"
+    echo "  ${TESTDIR}/test000_my_first_test"
+    echo "  ${TESTDIR}/test000_my_first_test${FILTER_SUFFIX}"
+    echo
+    echo "The directory containing the tests may have multiple subdirectories to group the tests."
+}
+
+RADCLIENT=$(which "$RADCLIENT")
+if [ ! -x "$RADCLIENT" ]; then
+    ERROR "Can't find radclient binary, modify your \$PATH or set RADCLIENT"
+    exit 64
+fi
+
+if [ ! -d "$TESTDIR" ]; then
+    ERROR "Test dir $TESTDIR does not exist, create it or specify it with TESTDIR=<dir>"
+    show_help
+    exit 64
+fi
+
+# Definitions (build these dynamically by looking at the files under tests)
+cluster_dirs=$(find "$TESTDIR/" -mindepth 1 -maxdepth 1 -type d)
+cluster_types=$(echo $cluster_dirs | sed 's/\s/ /g')
+
+role_types=
+for i in $cluster_dirs; do
+    for j in $(find "$TESTDIR/$i/" -mindepth 1 -maxdepth 1 -type d); do
+        role=$(basename "$j")
+        if [ "$role_types" == '' ]; then
+            role_types="$role"
+        else
+            role_types+="\n$role"
+        fi
+    done
+done
+
+if [ -z "$role_types" ]; then
+    DEBUG "Using simple test file layout"
+else
+    DEBUG "Using role based test file layout"
+    role_types=$(echo -e "$role_types" | sort | uniq)   # Remove duplicates
+    role_types=$(echo $role_types | sed 's/\s/ /g')     # Change \n back to spaces
+fi
+
+while getopts "h?vc:r:p:" opt; do
+    case "$opt" in
+    h|\?)
+        show_help
+        exit 0
+        ;;
+
+    v)
+        verbose=1
+        ;;
+
+    c)
+        found=0
+        for i in $cluster_types; do
+            if [ "$i" == "$OPTARG" ]; then
+                found=1
+            fi
+        done
+        if [ $found -ne 1 ]; then
+            ERROR "'$OPTARG' is not a valid cluster type"
+            show_help
+            exit 64
+        fi
+        cluster="$OPTARG"
+        ;;
+
+    r)
+        found=0
+        for i in $role_types; do
+            if [ "$i" == "$OPTARG" ]; then
+                found=1
+            fi
+        done
+        if [ $found -ne 1 ]; then
+            ERROR "'$OPTARG' is not a valid role type"
+            show_help
+            exit 64
+        fi
+        role="$OPTARG"
+        ;;
+
+    p)
+        if ! echo "$OPTARG" | grep -E '^[0-9]+$' > /dev/null; then
+            ERROR "Non integer argument '$OPTARG' specified for -p"
+            show_help
+            exit 64
+        fi
+        parallel=$OPTARG
+        ;;
+
+    H)
+        target="$OPTARG"
+        ;;
+
+    esac
+done
+
+shift $((OPTIND-1))
+
+[ "$1" = "--" ] && shift
+test_files=$@
+
+#
+#  Match keywords from the hostname to clusters or roles
+#
+if [ ! -z "$role_types" ]; then
+    this_host=$(hostname -f)
+    for tok in $(echo "$this_host" | sed 's/\./ /g'); do
+        for key in ${cluster_types}; do
+            if echo "$tok" | grep "$key" > /dev/null && [ "$cluster" = '' ]; then cluster="$key"; fi
+        done
+        for key in ${role_types}; do
+            if echo "$tok" | grep "$key" > /dev/null && [ "$role" = '' ]; then role="$key"; fi
+        done
+    done
+
+    if [ "$cluster" == '' ]; then
+        ERROR "Couldn't determine the cluster $this_host belongs to";
+        show_help
+        exit 64;
+    fi
+
+    if [ "$role" == '' ]; then
+        ERROR "Couldn't determine the role $this_host performs";
+        show_help
+        exit 64;
+    fi
+
+    test_path="${TESTDIR}/${cluster}/${role}"
+#
+#  Otherwise just use the tests in the test dir
+#
+else
+    test_path="${TESTDIR}"
+fi
+
+if [ "$test_files" != '' ]; then
+    tmp=
+    for glob in $test_files; do
+        # Filter out response files (makes wildcards easier), and expand the globs
+        for file in $(find "${test_path}" -depth -path "*${glob}" -and -not -path "*${FILTER_SUFFIX}" -and '(' -type f -or -type l ')'); do
+            tmp+="${file} "
+        done
+    done
+    test_files="${tmp}"
+else
+    # Lexicographical, depth-first
+    test_files=$(find "$test_path" -depth -path '*test[0-9][0-9][0-9]*' -and -not -path "*${FILTER_SUFFIX}" -and '(' -type f -or -type l ')')
+    if [ "$test_files" == '' ]; then
+        ERROR "No test files found in $test_path"
+        exit 64;
+    fi
+    INFO "Executing"$(echo "$test_files" | wc -l)" test(s) from ${test_path}"
+fi
+
+#
+#  Check if we got any test files
+#
+if [ "$test_files" == '' ]; then
+    ERROR "No test files to process"
+    exit 1
+fi
+
+#
+#  Output which files were going to be using for testing
+#
+if [ $verbose -eq 0 ]; then
+    INFO "Executing specified tests"
+    INFO "Use -v to see full list"
+else
+    INFO "Executing specified tests:"
+    for i in $test_files; do
+        DEBUG "$i"
+    done
+fi
+
+#
+#  Figure out which tests we can munge into a single file which we can
+#  use to parallelise testing
+#
+base=$(basename $0)
+packets=$(mktemp -t "${base}XXX") || exit 1
+filters=$(mktemp -t "${base}XXX") || exit 1
+
+args=
+file_args=
+serial_file_args=
+for i in $test_files; do
+    if [ ! -f "$i" -a ! -L "$i" ]; then
+        INFO "Skipping $i: not file"
+        continue
+    fi
+
+    if [ ! -r "$i" ]; then
+        INFO "Skipping $i: not readable (check permissions)"
+        continue
+    fi
+
+    expected="${i}${FILTER_SUFFIX}"
+    if [ ! -f "$expected" -a ! -L "$expected" ]; then
+        DEBUG "$i cannot be parallelised: Can't find 'expected' file"
+        file_args+=" -f \"$i\""
+        continue
+    fi
+
+    if [ ! -r "$expected" ]; then
+        INFO "$i cannot be parallelised: 'expected' file not readable"
+        file_args+=" -f \"${i}:${expected}\""
+        continue
+    fi
+
+    if head -n 1 "$i" | grep -i -E '^#\s*serial' > /dev/null; then
+        DEBUG "$i marked as serial only"
+        serial_file_args+=" -f \"${i}:${expected}\""
+        continue
+    fi
+
+    # Else add it to the master test file
+    cat "$i" >> "$packets"
+
+    # Add the name of the file so it appears in radclient debug output
+    # and can later be specified with -v -- <test> to drill down.
+    echo "Radclient-Test-Name := \""$(echo "$i" | sed -e "s@${test_path}/\?@@")"\"" >> "$packets"
+    echo >> "$packets"
+    cat "${i}_expected" >> "$filters"
+    echo >> "$filters"
+done
+
+if [ `cat "$packets" | wc -l` -gt 0 ]; then
+    file_args+=" -f \"${packets}:${filters}\""
+fi
+
+if [ ! -z "$file_args" ]; then
+       args="$file_args"
+
+       if [ $verbose -ne 0 ]; then
+               args+=" -x"
+       fi
+
+       args+=" -s"
+       args+=" -t \"$timeout\""
+       args+=" -r \"$retries\""
+       args+=" -p \"$parallel\""
+       args+=" \"$target\""
+       args+=" auto"
+       args+=" \"$secret\""
+
+       DEBUG "Executing: radclient $args"
+       eval radclient $args; ret=$?
+       INFO "(Parallelised tests)"
+       INFO ""
+
+       rm -f "$packets" 2>&1 > /dev/null
+       rm -f "$filters" 2>&1 > /dev/null
+
+       if [ $ret -ne 0 ]; then
+               ERROR "One or more tests failed (radclient exited with $ret)"
+               exit $ret
+       fi
+fi
+
+if [ ! -z "$serial_file_args" ]; then
+       args="$serial_file_args"
+
+       if [ $verbose -ne 0 ]; then
+               args+=" -x"
+       fi
+
+       args+=" -s"
+       args+=" -t \"$timeout\""
+       args+=" -r \"$retries\""
+       args+=" -p 1"
+       args+=" \"$target\""
+       args+=" auto"
+       args+=" \"$secret\""
+
+       DEBUG "Executing: radclient $args"
+       eval radclient $args; ret=$?
+       INFO "(Serialised tests)"
+
+       if [ $ret -ne 0 ]; then
+               ERROR "One or more tests failed (radclient exited with $ret)"
+               exit $ret
+       fi
+fi
+
+exit 0