AT_TESTED([ovs-vswitchd]) AT_TESTED([ovs-vsctl]) m4_include([m4/compat.m4]) dnl Make AT_SETUP automatically run the ovs_init() shell function dnl as the first step in every test. m4_rename([AT_SETUP], [OVS_AT_SETUP]) m4_define([AT_SETUP], [OVS_AT_SETUP($@) ovs_init ]) dnl OVS_START_SHELL_HELPERS...OVS_END_SHELL_HELPERS may bracket shell dnl function definitions that invoke AT_CHECK and other Autotest macros dnl that can ordinarily be run only within AT_SETUP...AT_CLEANUP. m4_define([OVS_START_SHELL_HELPERS], [m4_ifdef([AT_ingroup], [m4_fatal([$0: AT_SETUP and OVS_DEFINE_SHELL_HELPERS may not nest])]) m4_define([AT_ingroup]) m4_divert_push([PREPARE_TESTS])]) m4_define([OVS_END_SHELL_HELPERS], [ m4_divert_pop([PREPARE_TESTS]) m4_undefine([AT_ingroup])]) m4_divert_push([PREPARE_TESTS]) [ # Set ovs_base to the base directory in which the test is running and # initialize the OVS_*DIR environment variables to point to this # directory. ovs_init() { ovs_base=`pwd` trap '. "$ovs_base/cleanup"' 0 : > cleanup ovs_setenv } # With no parameter or an empty parameter, sets the OVS_*DIR # environment variables to point to $ovs_base, the base directory in # which the test is running. # # With a parameter, sets them to $ovs_base/$1. ovs_setenv() { sandbox=$1 ovs_dir=$ovs_base${1:+/$1} OVS_RUNDIR=$ovs_dir; export OVS_RUNDIR OVS_LOGDIR=$ovs_dir; export OVS_LOGDIR OVS_DBDIR=$ovs_dir; export OVS_DBDIR OVS_SYSCONFDIR=$ovs_dir; export OVS_SYSCONFDIR OVS_PKGDATADIR=$ovs_dir; export OVS_PKGDATADIR } ovs_wait () { # First try the condition without waiting. ovs_wait_cond && return 0 # Try a quick sleep, so that the test completes very quickly # in the normal case. POSIX doesn't require fractional times to # work, so this might not work. sleep 0.1 ovs_wait_cond && return 0 # Then wait up to 10 seconds. for d in 0 1 2 3 4 5 6 7 8 9; do sleep 1 ovs_wait_cond && return 0 done return 1 } # Prints the integers from $1 to $2, increasing by $3 (default 1) on stdout. seq () { if test $# = 1; then set 1 $1 fi while test $1 -le $2; do echo $1 set `expr $1 + ${3-1}` $2 $3 done } if test "$IS_WIN32" = "yes"; then pwd () { command pwd -W "$@" } diff () { command diff --strip-trailing-cr "$@" } # tskill is more effective than taskkill but it isn't always installed. if (tskill //?) >/dev/null 2>&1; then :; else tskill () { taskkill //F //PID $1 >/dev/null; } fi kill () { signal= retval=0 for arg; do case $arg in -*) signal=$arg ;; [1-9][0-9]*) # tasklist always returns 0. # If pid does exist, there will be a line with the pid. if tasklist //fi "PID eq $arg" | grep $arg >/dev/null; then if test "X$signal" != "X-0"; then tskill $arg fi else retval=1 fi ;; esac done return $retval } fi # Try to add a default timeout for the following control utilities: # - ovs-vsctl # - ovs-ofctl # - ovs-appctl # - ovn-sbctl # - ovn-nbctl # - vtep-ctl # Set default timeout for 30 seconds. # This should be sufficient on all platforms. OVS_TIMEOUT=30 alias ovs-vsctl='OVS_VSCTL_TIMEOUT' >/dev/null 2>&1 if [ $? -eq 0 ]; then OVS_VSCTL_TIMEOUT () { command ovs-vsctl --timeout=$OVS_TIMEOUT "$@" } alias ovs-ofctl='OVS_OFCTL_TIMEOUT' alias ovs-appctl='OVS_APPCTL_TIMEOUT' alias ovn-sbctl='OVS_SBCTL_TIMEOUT' alias ovn-nbctl='OVN_NBCTL_TIMEOUT' alias vtep-ctl='VTEP_CTL_TIMEOUT' alias ovsdb-client='OVSDB_CLIENT_TIMEOUT' OVS_OFCTL_TIMEOUT () { command ovs-ofctl --timeout=$OVS_TIMEOUT "$@" } OVS_APPCTL_TIMEOUT () { command ovs-appctl --timeout=$OVS_TIMEOUT "$@" } OVS_SBCTL_TIMEOUT () { command ovn-sbctl --timeout=$OVS_TIMEOUT "$@" } OVN_NBCTL_TIMEOUT () { command ovn-nbctl --timeout=$OVS_TIMEOUT "$@" } VTEP_CTL_TIMEOUT () { command vtep-ctl --timeout=$OVS_TIMEOUT "$@" } OVSDB_CLIENT_TIMEOUT () { command ovsdb-client --timeout=$OVS_TIMEOUT "$@" } fi # parent_pid PID # # Prints the PID of the parent of process PID. parent_pid () { # Using "ps" is portable to any POSIX system, but busybox "ps" (used in # e.g. Alpine Linux) is noncompliant, so we use a Linux-specific approach # when it's available. We check the format of the status file to avoid # the NetBSD file with the same name but different contents. if egrep '^PPid:[[:space:]]*[0-9]*$' /proc/$1/status > /dev/null 2>&1; then sed -n 's/^PPid: \([0-9]*\)/\1/p' /proc/$1/status else ps -o ppid= -p $1 fi } # kill_ovs_vswitchd [PID] # # Signal the ovs-vswitchd daemon to exit gracefully and wait for it to # terminate or kill it if that takes too long. # # It is used to cleanup all sorts of tests and results. It can't assume # any state, including the availability of PID file which can be provided. kill_ovs_vswitchd () { # Use provided PID or save the current PID if available. TMPPID=$1 if test -z "$TMPPID"; then TMPPID=$(cat $OVS_RUNDIR/ovs-vswitchd.pid 2>/dev/null) fi # Tell the daemon to terminate gracefully ovs-appctl --timeout=10 -t ovs-vswitchd exit --cleanup 2>/dev/null # Nothing else to be done if there is no PID test -z "$TMPPID" && return for i in 1 2 3 4 5 6 7 8 9; do # Check if the daemon is alive. kill -0 $TMPPID 2>/dev/null || return # Fallback to whole number since POSIX doesn't require # fractional times to work. sleep 0.1 || sleep 1 done # Make sure it is terminated. kill $TMPPID } # Normalize the output of 'wc' to match POSIX. # POSIX says 'wc' should print "%d %d %d", but GNU prints "%7d %7d %7d". # POSIX says 'wc -l' should print "%d %s", but BSD prints "%8d". # # This fixes all of those (it will screw up filenames that contain # multiple sequential spaces, but that doesn't really matter). wc () { command wc "$@" | tr -s ' ' ' ' | sed 's/^ *//' } uuidfilt () { $PYTHON "$top_srcdir"/tests/uuidfilt.py "$@" } # run_as PROGRAM_NAME COMMAND [ARG...] # # Runs a command with argv[0] set to PROGRAM_NAME, if possible, in a # subshell. Most utilities print argc[0] as part of their messages, # so this makes it easier to figure out which particular utility # prints a message if a bunch of identical processes are running. # # Not all shells support "exec -a NAME", so test for it. if (exec -a myname true); then run_as () { (exec -a "$@") } else run_as () { shift (exec "$@") } fi ] m4_divert_pop([PREPARE_TESTS]) m4_define([OVS_WAIT], [dnl AS_ECHO(["AS_ESCAPE([$3: waiting $4...])"]) >&AS_MESSAGE_LOG_FD ovs_wait_cond () { $1 } if ovs_wait; then : else AS_ECHO(["AS_ESCAPE([$3: wait failed])"]) >&AS_MESSAGE_LOG_FD $2 AT_FAIL_IF([:]) fi ]) dnl OVS_WAIT_UNTIL(COMMAND) dnl dnl Executes shell COMMAND in a loop until it returns dnl zero return code. If COMMAND did not return dnl zero code within reasonable time limit, then dnl the test fails. m4_define([OVS_WAIT_UNTIL], [OVS_WAIT([$1], [$2], [AT_LINE], [until $1])]) dnl OVS_WAIT_WHILE(COMMAND) dnl dnl Executes shell COMMAND in a loop until it returns dnl non-zero return code. If COMMAND did not return dnl non-zero code within reasonable time limit, then dnl the test fails. m4_define([OVS_WAIT_WHILE], [OVS_WAIT([if $1; then return 1; else return 0; fi], [$2], [AT_LINE], [while $1])]) dnl OVS_APP_EXIT_AND_WAIT(DAEMON) dnl dnl Ask the daemon named DAEMON to exit, via ovs-appctl, and then wait for it dnl to exit. m4_define([OVS_APP_EXIT_AND_WAIT], [AT_CHECK([test -e $OVS_RUNDIR/$1.pid]) TMPPID=$(cat $OVS_RUNDIR/$1.pid) AT_CHECK(m4_if([$1],[ovs-vswitchd], [ovs-appctl --timeout=10 -t $1 exit --cleanup], [ovs-appctl --timeout=10 -t $1 exit])) OVS_WAIT_WHILE([kill -0 $TMPPID 2>/dev/null])]) dnl OVS_APP_EXIT_AND_WAIT_BY_TARGET(TARGET, PIDFILE) dnl dnl Ask the daemon identified by TARGET to exit, via ovs-appctl (using the target dnl argument), and then wait for it to exit. m4_define([OVS_APP_EXIT_AND_WAIT_BY_TARGET], [AT_CHECK([test -e $2]) TMPPID=$(cat $2) AT_CHECK([ovs-appctl --timeout=10 --target=$1 exit]) OVS_WAIT_WHILE([kill -0 $TMPPID 2>/dev/null])]) dnl on_exit "COMMAND" dnl dnl Add the shell COMMAND to a collection executed when the current test dnl completes, as a cleanup action. (The most common use is to kill a dnl daemon started by the test. This is important to prevent tests that dnl start daemons from hanging at exit.) dnl dnl Cleanup commands are executed in the reverse order of calls to this dnl function. m4_divert_text([PREPARE_TESTS], [dnl on_exit () { (echo "$1"; cat cleanup) > cleanup.tmp mv cleanup.tmp cleanup } ]) dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64: m4_ifndef([AS_VAR_APPEND], [m4_divert_text([PREPARE_TESTS], [as_var_append () { eval $1=\$$1\$2 } ]) m4_define([AS_VAR_APPEND], [as_var_append $1 $2])]) dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64: m4_ifndef([AT_CHECK_UNQUOTED], [m4_define([AT_CHECK_UNQUOTED], [_AT_CHECK([$1], [$2], AS_ESCAPE(m4_dquote(m4_expand([$3])), [""]), AS_ESCAPE(m4_dquote(m4_expand([$4])),[""]), [$5], [$6])])]) dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64: m4_ifndef([AT_SKIP_IF], [m4_define([AT_SKIP_IF], [AT_CHECK([($1) \ && exit 77 || exit 0], [0], [ignore], [ignore])])]) dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64: m4_ifndef([AT_FAIL_IF], [m4_define([AT_FAIL_IF], [AT_CHECK([($1) \ && exit 99 || exit 0], [0], [ignore], [ignore])])])