#!/bin/sh # NUT Integration Testing suite, assumes the codebase was built and # arranges running of the binaries to test driver-client-server # ability to start and their interactions. # # Note: currently it is a PoC-quality mess that gets the job done # but could be refactored for better maintainability and generic # approach. Part of the goal was to let this script set up the # sandbox to run tests which could be defined in other files. # # WARNING: Current working directory when starting the script should be # the location where it may create temporary data (e.g. the BUILDDIR). # Caller can export envvars to impact the script behavior, e.g.: # DEBUG=true to print debug messages, running processes, etc. # DEBUG_SLEEP=60 to sleep after tests, with driver+server running # NUT_DEBUG_MIN=3 to set (minimum) debug level for drivers, upsd... # NUT_PORT=12345 custom port for upsd to listen and clients to query # # Design note: written with dumbed-down POSIX shell syntax, to # properly work in whatever different OSes have (bash, dash, # ksh, busybox sh...) # # Copyright # 2022 Jim Klimov # # License: GPLv2+ TZ=UTC LANG=C LC_ALL=C export TZ LANG LC_ALL log_separator() { echo "" >&2 echo "================================" >&2 } shouldDebug() { [ -n "$DEBUG" ] || [ -n "$DEBUG_SLEEP" ] } log_debug() { if shouldDebug ; then echo "[DEBUG] $@" >&2 fi } log_info() { echo "[INFO] $@" >&2 } log_error() { echo "[ERROR] $@" >&2 } die() { echo "[FATAL] $@" >&2 exit 1 } # Note: current directory is assumed to be writeable for temporary # data, e.g. the $(builddir) from the Makefile. Static resources # from the source codebase are where the script resides, e.g. # the $(srcdir) from the Makefile. If we are not in the source # tree, tests would use binaries in PATH (e.g. packaged install). BUILDDIR="`pwd`" TOP_BUILDDIR="" case "${BUILDDIR}" in */tests/NIT) TOP_BUILDDIR="`cd "${BUILDDIR}"/../.. && pwd`" ;; *) log_info "Current directory '${BUILDDIR}' is not a .../tests/NIT" ;; esac if ! test -w "${BUILDDIR}" ; then log_error "BUILDDIR='${BUILDDIR}' is not writeable, tests may fail below" fi SRCDIR="`dirname "$0"`" SRCDIR="`cd "$SRCDIR" && pwd`" TOP_SRCDIR="" case "${SRCDIR}" in */tests/NIT) TOP_SRCDIR="`cd "${SRCDIR}"/../.. && pwd`" ;; *) log_info "Script source directory '${SRCDIR}' is not a .../tests/NIT" ;; esac # No fuss about LD_LIBRARY_PATH: for binaries that need it, # PATH entries below would contain libtool wrapper scripts; # for other builds we use system default or caller's env. PATH_ADD="${BUILDDIR}" if [ x"${SRCDIR}" != x"${BUILDDIR}" ]; then PATH_ADD="${PATH_ADD}:${SRCDIR}" fi if [ x"${TOP_BUILDDIR}" != x ]; then PATH_ADD="${PATH_ADD}:${TOP_BUILDDIR}/clients:${TOP_BUILDDIR}/drivers:${TOP_BUILDDIR}/server:${TOP_BUILDDIR}/tools:${TOP_BUILDDIR}/tools/nut-scanner" fi if [ x"${TOP_SRCDIR}" != x ]; then PATH_ADD="${PATH_ADD}:${TOP_SRCDIR}/clients:${TOP_SRCDIR}/drivers:${TOP_SRCDIR}/server:${TOP_SRCDIR}/tools:${TOP_SRCDIR}/tools/nut-scanner" fi PATH="${PATH_ADD}:${PATH}" export PATH unset PATH_ADD log_debug "Using PATH='$PATH'" for PROG in upsd upsc dummy-ups upsmon ; do (command -v ${PROG}) || die "Useless setup: ${PROG} not found in PATH: ${PATH}" done PID_UPSD="" PID_DUMMYUPS="" PID_DUMMYUPS1="" PID_DUMMYUPS2="" TESTDIR="$BUILDDIR/tmp" # Technically the limit is sizeof(sockaddr.sun_path) for complete socket # pathname, which varies 104-108 chars max on systems seen in CI farm; # we reserve 17 chars for "/dummy-ups-dummy" longest filename. if [ `echo "$TESTDIR" | wc -c` -gt 80 ]; then log_info "'$TESTDIR' is too long to store AF_UNIX socket files, will mktemp" if ! ( [ -n "${TMPDIR-}" ] && [ -d "${TMPDIR-}" ] && [ -w "${TMPDIR-}" ] ) ; then if [ -d /dev/shm ] && [ -w /dev/shm ]; then TMPDIR=/dev/shm ; else TMPDIR=/tmp ; fi fi TESTDIR="`mktemp -d "${TMPDIR}/nit-tmp.$$.XXXXXX"`" || die "Failed to mktemp" else rm -rf "${TESTDIR}" || true fi log_info "Using '$TESTDIR' for generated configs and state files" mkdir -p "${TESTDIR}/etc" "${TESTDIR}/run" && chmod 750 "${TESTDIR}/run" \ || die "Failed to create temporary FS structure for the NIT" stop_daemons() { if [ -n "$PID_UPSD$PID_DUMMYUPS$PID_DUMMYUPS1$PID_DUMMYUPS2" ] ; then log_info "Stopping test daemons" kill -15 $PID_UPSD $PID_DUMMYUPS $PID_DUMMYUPS1 $PID_DUMMYUPS2 2>/dev/null fi } trap 'RES=$?; stop_daemons; if [ "${TESTDIR}" != "${BUILDDIR}/tmp" ] ; then rm -rf "${TESTDIR}" ; fi; exit $RES;' 0 1 2 3 15 NUT_STATEPATH="${TESTDIR}/run" NUT_ALTPIDPATH="${TESTDIR}/run" NUT_CONFPATH="${TESTDIR}/etc" export NUT_STATEPATH NUT_ALTPIDPATH NUT_CONFPATH # TODO: Find a portable way to (check and) grab a random unprivileged port? [ -n "${NUT_PORT-}" ] && [ "$NUT_PORT" -gt 0 ] && [ "$NUT_PORT" -lt 65536 ] \ || { DELTA1="`date +%S`" || DELTA1=0 DELTA2="`expr $$ % 99`" || DELTA2=0 NUT_PORT="`expr 34931 + $DELTA1 + $DELTA2`" \ && [ "$NUT_PORT" -gt 0 ] && [ "$NUT_PORT" -lt 65536 ] \ || NUT_PORT=34931 } export NUT_PORT ### upsd.conf: ################################################## generatecfg_upsd_trivial() { # Populate the configs for the run cat > "$NUT_CONFPATH/upsd.conf" << EOF STATEPATH "$NUT_STATEPATH" LISTEN localhost $NUT_PORT EOF [ $? = 0 ] || die "Failed to populate temporary FS structure for the NIT: upsd.conf" chmod 640 "$NUT_CONFPATH/upsd.conf" # Some systems listining on symbolic "localhost" actually # only bind to IPv6, and Python telnetlib resolves IPv4 # and fails its connection tests. Others fare well with # both addresses in one command. for LH in 127.0.0.1 '::1' ; do if ( ( cat /etc/hosts || getent hosts ) | grep "$LH" \ || ping -c 1 "$LH" ) 2>/dev/null >/dev/null ; then echo "LISTEN $LH $NUT_PORT" >> "$NUT_CONFPATH/upsd.conf" fi done if [ -n "${NUT_DEBUG_MIN-}" ] ; then echo "DEBUG_MIN ${NUT_DEBUG_MIN}" >> "$NUT_CONFPATH/upsd.conf" || exit fi } generatecfg_upsd_nodev() { generatecfg_upsd_trivial echo "ALLOW_NO_DEVICE true" >> "$NUT_CONFPATH/upsd.conf" \ || die "Failed to populate temporary FS structure for the NIT: upsd.conf" } ### upsd.users: ################################################## TESTPASS_ADMIN='mypass' TESTPASS_TESTER='pass words' TESTPASS_UPSMON_PRIMARY='P@ssW0rdAdm' TESTPASS_UPSMON_SECONDARY='P@ssW0rd' generatecfg_upsdusers_trivial() { cat > "$NUT_CONFPATH/upsd.users" << EOF [admin] password = $TESTPASS_ADMIN actions = SET instcmds = ALL [tester] password = "${TESTPASS_TESTER}" instcmds = test.battery.start instcmds = test.battery.stop [dummy-admin-m] password = "${TESTPASS_UPSMON_PRIMARY}" upsmon master [dummy-admin] password = "${TESTPASS_UPSMON_PRIMARY}" upsmon primary [dummy-user-s] password = "${TESTPASS_UPSMON_SECONDARY}" upsmon slave [dummy-user] password = "${TESTPASS_UPSMON_SECONDARY}" upsmon secondary EOF [ $? = 0 ] || die "Failed to populate temporary FS structure for the NIT: upsd.users" chmod 640 "$NUT_CONFPATH/upsd.users" } ### upsmon.conf: ################################################## generatecfg_upsmon_trivial() { # Populate the configs for the run ( echo 'MINSUPPLIES 0' > "$NUT_CONFPATH/upsmon.conf" || exit echo 'SHUTDOWNCMD "echo TESTING_DUMMY_SHUTDOWN_NOW"' >> "$NUT_CONFPATH/upsmon.conf" || exit if [ -n "${NUT_DEBUG_MIN-}" ] ; then echo "DEBUG_MIN ${NUT_DEBUG_MIN}" >> "$NUT_CONFPATH/upsmon.conf" || exit fi ) || die "Failed to populate temporary FS structure for the NIT: upsmon.conf" chmod 640 "$NUT_CONFPATH/upsmon.conf" } generatecfg_upsmon_master() { generatecfg_upsmon_trivial echo "MONITOR 'dummy@localhost:$NUT_PORT' 0 'dummy-admin-m' '${TESTPASS_UPSMON_PRIMARY}' master" >> "$NUT_CONFPATH/upsmon.conf" \ || die "Failed to populate temporary FS structure for the NIT: upsmon.conf" } generatecfg_upsmon_primary() { generatecfg_upsmon_trivial echo "MONITOR 'dummy@localhost:$NUT_PORT' 0 'dummy-admin' '${TESTPASS_UPSMON_PRIMARY}' primary" >> "$NUT_CONFPATH/upsmon.conf" \ || die "Failed to populate temporary FS structure for the NIT: upsmon.conf" } generatecfg_upsmon_slave() { generatecfg_upsmon_trivial echo "MONITOR 'dummy@localhost:$NUT_PORT' 0 'dummy-user-s' '${TESTPASS_UPSMON_SECONDARY}' slave" >> "$NUT_CONFPATH/upsmon.conf" \ || die "Failed to populate temporary FS structure for the NIT: upsmon.conf" } generatecfg_upsmon_secondary() { generatecfg_upsmon_trivial echo "MONITOR 'dummy@localhost:$NUT_PORT' 0 'dummy-user' '${TESTPASS_UPSMON_SECONDARY}' secondary" >> "$NUT_CONFPATH/upsmon.conf" \ || die "Failed to populate temporary FS structure for the NIT: upsmon.conf" } ### ups.conf: ################################################## generatecfg_ups_trivial() { # Populate the configs for the run ( echo 'maxretry = 3' > "$NUT_CONFPATH/ups.conf" || exit if [ x"${TOP_BUILDDIR}" != x ]; then echo "driverpath = '${TOP_BUILDDIR}/drivers'" >> "$NUT_CONFPATH/ups.conf" || exit fi if [ -n "${NUT_DEBUG_MIN-}" ] ; then echo "debug_min = ${NUT_DEBUG_MIN}" >> "$NUT_CONFPATH/ups.conf" || exit fi ) || die "Failed to populate temporary FS structure for the NIT: ups.conf" chmod 640 "$NUT_CONFPATH/ups.conf" } generatecfg_ups_dummy() { generatecfg_ups_trivial cat > "$NUT_CONFPATH/dummy.seq" << EOF ups.status: OB TIMER 5 ups.status: OL TIMER 5 EOF [ $? = 0 ] || die "Failed to populate temporary FS structure for the NIT: dummy.seq" cat >> "$NUT_CONFPATH/ups.conf" << EOF [dummy] driver = dummy-ups desc = "Crash Dummy" port = dummy.seq #mode = dummy-loop EOF [ $? = 0 ] || die "Failed to populate temporary FS structure for the NIT: ups.conf" if [ x"${TOP_SRCDIR}" != x ]; then cp "${TOP_SRCDIR}/data/evolution500.seq" "${TOP_SRCDIR}/data/epdu-managed.dev" "$NUT_CONFPATH/" cat >> "$NUT_CONFPATH/ups.conf" << EOF [UPS1] driver = dummy-ups desc = "Example event sequence" port = evolution500.seq [UPS2] driver = dummy-ups desc = "Example ePDU data dump" port = epdu-managed.dev mode = dummy-once EOF [ $? = 0 ] || die "Failed to populate temporary FS structure for the NIT: ups.conf" # HACK: Avoid empty ups.status that may be present in example docs # FIXME: Might we actually want that value (un-)set for tests?.. # TODO: Check if the problem was with dummy-ups looping? [#1385] for F in "$NUT_CONFPATH/"*.dev "$NUT_CONFPATH/"*.seq ; do sed -e 's,^ups.status: *$,ups.status: OL BOOST,' -i'.bak' "$F" grep -E '^ups.status:' "$F" >/dev/null || { echo "ups.status: OL BOOST" >> "$F"; } done fi } ##################################################### isPidAlive() { [ -n "$1" ] && [ "$1" -gt 0 ] || return [ -d "/proc/$1" ] || kill -0 "$1" 2>/dev/null } FAILED=0 PASSED=0 testcase_upsd_no_configs_at_all() { log_separator log_info "Test UPSD without configs at all" upsd -F if [ "$?" = 0 ]; then log_error "upsd should fail without configs" FAILED="`expr $FAILED + 1`" else log_info "OK, upsd failed to start in wrong conditions" PASSED="`expr $PASSED + 1`" fi } testcase_upsd_no_configs_driver_file() { log_separator log_info "Test UPSD without driver config file" generatecfg_upsd_trivial upsd -F if [ "$?" = 0 ]; then log_error "upsd should fail without driver config file" FAILED="`expr $FAILED + 1`" else log_info "OK, upsd failed to start in wrong conditions" PASSED="`expr $PASSED + 1`" fi } testcase_upsd_no_configs_in_driver_file() { log_separator log_info "Test UPSD without drivers defined in config file" generatecfg_upsd_trivial generatecfg_ups_trivial upsd -F if [ "$?" = 0 ]; then log_error "upsd should fail without drivers defined in config file" FAILED="`expr $FAILED + 1`" else log_info "OK, upsd failed to start in wrong conditions" PASSED="`expr $PASSED + 1`" fi } testcase_upsd_allow_no_device() { log_separator log_info "Test UPSD allowed to run without driver configs" generatecfg_upsd_nodev generatecfg_upsdusers_trivial generatecfg_ups_trivial upsd -F & PID_UPSD="$!" sleep 2 if isPidAlive "$PID_UPSD"; then log_info "OK, upsd is running" PASSED="`expr $PASSED + 1`" log_separator log_info "Test that UPSD responds to UPSC" OUT="`upsc -l localhost:$NUT_PORT`" || die "upsd does not respond: $OUT" if [ -n "$OUT" ] ; then log_error "got reply for upsc listing when none was expected: $OUT" FAILED="`expr $FAILED + 1`" else log_info "OK, empty response as expected" PASSED="`expr $PASSED + 1`" fi else log_error "upsd was expected to be running although no devices are defined" FAILED="`expr $FAILED + 1`" fi kill -15 $PID_UPSD wait $PID_UPSD } testgroup_upsd_invalid_configs() { testcase_upsd_no_configs_at_all testcase_upsd_no_configs_driver_file testcase_upsd_no_configs_in_driver_file } testgroup_upsd_questionable_configs() { testcase_upsd_allow_no_device } ######################################################### ### Tests in a common sandbox with driver(s) + server ### ######################################################### SANDBOX_CONFIG_GENERATED=false sandbox_generate_configs() { if $SANDBOX_CONFIG_GENERATED ; then return ; fi log_info "Generating configs for sandbox" generatecfg_upsd_nodev generatecfg_upsdusers_trivial generatecfg_ups_dummy SANDBOX_CONFIG_GENERATED=true } sandbox_forget_configs() { SANDBOX_CONFIG_GENERATED=false if [ -z "${DEBUG_SLEEP-}" ] ; then stop_daemons fi } sandbox_start_upsd() { if isPidAlive "$PID_UPSD" ; then return 0 fi sandbox_generate_configs log_info "Starting UPSD for sandbox" upsd -F & PID_UPSD="$!" sleep 5 } sandbox_start_drivers() { if isPidAlive "$PID_DUMMYUPS" \ && { [ x"${TOP_SRCDIR}" != x ] && isPidAlive "$PID_DUMMYUPS1" && isPidAlive "$PID_DUMMYUPS2" \ || [ x"${TOP_SRCDIR}" = x ] ; } \ ; then # All drivers expected for this environment are already running return 0 fi sandbox_generate_configs log_info "Starting dummy-ups driver(s) for sandbox" #upsdrvctl -F start dummy & dummy-ups -a dummy -F & PID_DUMMYUPS="$!" if [ x"${TOP_SRCDIR}" != x ]; then dummy-ups -a UPS1 -F & PID_DUMMYUPS1="$!" dummy-ups -a UPS2 -F & PID_DUMMYUPS2="$!" fi sleep 5 if shouldDebug ; then (ps -ef || ps -xawwu) 2>/dev/null | grep -E '(ups|nut|dummy)' || true fi } testcase_sandbox_start_upsd_alone() { log_separator log_info "Test starting UPSD but not a driver before it" sandbox_start_upsd EXPECTED_UPSLIST='dummy' if [ x"${TOP_SRCDIR}" != x ]; then EXPECTED_UPSLIST="$EXPECTED_UPSLIST UPS1 UPS2" fi log_info "Query listing from UPSD by UPSC (driver not running yet)" OUT="`upsc -l localhost:$NUT_PORT`" || die "upsd does not respond: $OUT" if [ x"$OUT" != x"$EXPECTED_UPSLIST" ] ; then log_error "got this reply for upsc listing when '$EXPECTED_UPSLIST' was expected: $OUT" FAILED="`expr $FAILED + 1`" else PASSED="`expr $PASSED + 1`" fi log_info "Query driver state from UPSD by UPSC (driver not running yet)" OUT="`upsc dummy@localhost:$NUT_PORT 2>&1`" && { log_error "upsc was supposed to answer with error exit code: $OUT" FAILED="`expr $FAILED + 1`" } if ! echo "$OUT" | grep 'Error: Driver not connected' ; then log_error "got reply for upsc query when 'Error: Driver not connected' was expected: '$OUT'" FAILED="`expr $FAILED + 1`" else PASSED="`expr $PASSED + 1`" fi } testcase_sandbox_start_upsd_after_drivers() { # Historically this is a fallback from testcase_sandbox_start_drivers_after_upsd kill -15 $PID_UPSD 2>/dev/null wait $PID_UPSD upsd -F & PID_UPSD="$!" sandbox_start_drivers sandbox_start_upsd sleep 5 upsc dummy@localhost:$NUT_PORT || die "upsd does not respond" } testcase_sandbox_start_drivers_after_upsd() { #sandbox_start_upsd testcase_sandbox_start_upsd_alone sandbox_start_drivers log_info "Query driver state from UPSD by UPSC after driver startup" upsc dummy@localhost:$NUT_PORT || { # Should not get to this, except on very laggy systems maybe log_error "Query failed, retrying with UPSD started after drivers" testcase_sandbox_start_upsd_after_drivers } if [ x"${TOP_SRCDIR}" != x ]; then log_info "Wait for dummy UPSes with larger data sets to initialize" for U in UPS1 UPS2 ; do COUNTDOWN=60 while ! upsc $U@localhost:$NUT_PORT ups.status ; do sleep 1 COUNTDOWN="`expr $COUNTDOWN - 1`" # Systemic error, e.g. could not create socket file? [ "$COUNTDOWN" -lt 1 ] && die "Dummy driver did not start or respond in time" done done fi log_info "Expected drivers are now responding via UPSD" } testcase_sandbox_upsc_query_model() { OUT="`upsc dummy@localhost:$NUT_PORT device.model`" || die "upsd does not respond: $OUT" if [ x"$OUT" != x"Dummy UPS" ] ; then log_error "got this reply for upsc query when 'Dummy UPS' was expected: $OUT" FAILED="`expr $FAILED + 1`" else PASSED="`expr $PASSED + 1`" fi } testcase_sandbox_upsc_query_bogus() { log_info "Query driver state from UPSD by UPSC for bogus info" OUT="`upsc dummy@localhost:$NUT_PORT ups.bogus.value 2>&1`" && { log_error "upsc was supposed to answer with error exit code: $OUT" FAILED="`expr $FAILED + 1`" } if ! echo "$OUT" | grep 'Error: Variable not supported by UPS' ; then log_error "got reply for upsc query when 'Error: Variable not supported by UPS' was expected: $OUT" FAILED="`expr $FAILED + 1`" else PASSED="`expr $PASSED + 1`" fi } testcase_sandbox_upsc_query_timer() { log_separator log_info "Test that dummy-ups TIMER action changes the reported state" # Driver is set up to flip ups.status every 5 sec, so check every 3 OUT1="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "upsd does not respond: $OUT1" ; sleep 3 OUT2="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "upsd does not respond: $OUT2" OUT3="" OUT4="" if [ x"$OUT1" = x"$OUT2" ]; then sleep 3 OUT3="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "upsd does not respond: $OUT3" if [ x"$OUT2" = x"$OUT3" ]; then sleep 3 OUT4="`upsc dummy@localhost:$NUT_PORT ups.status`" || die "upsd does not respond: $OUT4" fi fi if echo "$OUT1$OUT2$OUT3$OUT4" | grep "OB" && echo "$OUT1$OUT2$OUT3$OUT4" | grep "OL" ; then log_info "OK, ups.status flips over time" PASSED="`expr $PASSED + 1`" else log_error "ups.status did not flip over time" FAILED="`expr $FAILED + 1`" fi } isTestablePython() { # We optionally make python module (if interpreter is found): if [ x"${TOP_BUILDDIR}" = x ] \ || [ ! -x "${TOP_BUILDDIR}/scripts/python/module/test_nutclient.py" ] \ ; then return 1 fi return 0 } testcase_sandbox_python_without_credentials() { isTestablePython || return 0 log_separator log_info "Call Python module test suite: PyNUT (NUT Python bindings) without login credentials" if ( unset NUT_USER || true unset NUT_PASS || true "${TOP_BUILDDIR}/scripts/python/module/test_nutclient.py" ) ; then log_info "OK, PyNUT did not complain" PASSED="`expr $PASSED + 1`" else log_error "PyNUT complained, check above" FAILED="`expr $FAILED + 1`" fi } testcase_sandbox_python_with_credentials() { isTestablePython || return 0 # That script says it expects data/evolution500.seq (as the UPS1 dummy) # but the dummy data does not currently let issue the commands and # setvars tested from python script. log_separator log_info "Call Python module test suite: PyNUT (NUT Python bindings) with login credentials" if ( NUT_USER='admin' NUT_PASS="${TESTPASS_ADMIN}" export NUT_USER NUT_PASS "${TOP_BUILDDIR}/scripts/python/module/test_nutclient.py" ) ; then log_info "OK, PyNUT did not complain" PASSED="`expr $PASSED + 1`" else log_error "PyNUT complained, check above" FAILED="`expr $FAILED + 1`" fi } testcases_sandbox_python() { isTestablePython || return 0 testcase_sandbox_python_without_credentials testcase_sandbox_python_with_credentials } #################################### isTestableCppNIT() { # We optionally make and here can run C++ client tests: if [ x"${TOP_BUILDDIR}" = x ] \ || [ ! -x "${TOP_BUILDDIR}/tests/cppnit" ] \ ; then return 1 fi return 0 } testcase_sandbox_cppnit_without_creds() { isTestableCppNIT || return 0 log_separator log_info "Call libnutclient test suite: cppnit without login credentials" if ( unset NUT_USER || true unset NUT_PASS || true "${TOP_BUILDDIR}/tests/cppnit" ) ; then log_info "OK, cppnit did not complain" PASSED="`expr $PASSED + 1`" else log_error "cppnit complained, check above" FAILED="`expr $FAILED + 1`" fi } testcase_sandbox_cppnit_simple_admin() { isTestableCppNIT || return 0 log_separator log_info "Call libnutclient test suite: cppnit with login credentials: simple admin" if ( NUT_USER='admin' NUT_PASS="${TESTPASS_ADMIN}" if [ x"${TOP_SRCDIR}" != x ]; then # Avoid dummies with TIMER flip-flops NUT_SETVAR_DEVICE='UPS2' else # Risks failure when lauching sub-test at the wrong second NUT_SETVAR_DEVICE='dummy' fi unset NUT_PRIMARY_DEVICE export NUT_USER NUT_PASS NUT_SETVAR_DEVICE "${TOP_BUILDDIR}/tests/cppnit" ) ; then log_info "OK, cppnit did not complain" PASSED="`expr $PASSED + 1`" else log_error "cppnit complained, check above" FAILED="`expr $FAILED + 1`" fi } testcase_sandbox_cppnit_upsmon_primary() { isTestableCppNIT || return 0 log_separator log_info "Call libnutclient test suite: cppnit with login credentials: upsmon-primary" if ( NUT_USER='dummy-admin' NUT_PASS="${TESTPASS_UPSMON_PRIMARY}" NUT_PRIMARY_DEVICE='dummy' unset NUT_SETVAR_DEVICE export NUT_USER NUT_PASS NUT_PRIMARY_DEVICE "${TOP_BUILDDIR}/tests/cppnit" ) ; then log_info "OK, cppnit did not complain" PASSED="`expr $PASSED + 1`" else log_error "cppnit complained, check above" FAILED="`expr $FAILED + 1`" fi } testcase_sandbox_cppnit_upsmon_master() { isTestableCppNIT || return 0 log_separator log_info "Call libnutclient test suite: cppnit with login credentials: upsmon-master" if ( NUT_USER='dummy-admin-m' NUT_PASS="${TESTPASS_UPSMON_PRIMARY}" NUT_PRIMARY_DEVICE='dummy' unset NUT_SETVAR_DEVICE export NUT_USER NUT_PASS NUT_PRIMARY_DEVICE "${TOP_BUILDDIR}/tests/cppnit" ) ; then log_info "OK, cppnit did not complain" PASSED="`expr $PASSED + 1`" else log_error "cppnit complained, check above" FAILED="`expr $FAILED + 1`" fi } testcases_sandbox_cppnit() { isTestableCppNIT || return 0 testcase_sandbox_cppnit_without_creds testcase_sandbox_cppnit_upsmon_primary testcase_sandbox_cppnit_upsmon_master testcase_sandbox_cppnit_simple_admin } # TODO: Some upsmon tests? testgroup_sandbox() { testcase_sandbox_start_drivers_after_upsd testcase_sandbox_upsc_query_model testcase_sandbox_upsc_query_bogus testcase_sandbox_upsc_query_timer testcases_sandbox_python testcases_sandbox_cppnit sandbox_forget_configs } testgroup_sandbox_python() { # Arrange for quick test iterations testcase_sandbox_start_drivers_after_upsd testcases_sandbox_python sandbox_forget_configs } testgroup_sandbox_cppnit() { # Arrange for quick test iterations testcase_sandbox_start_drivers_after_upsd testcases_sandbox_cppnit sandbox_forget_configs } testgroup_sandbox_cppnit_simple_admin() { # Arrange for quick test iterations testcase_sandbox_start_drivers_after_upsd testcase_sandbox_cppnit_simple_admin sandbox_forget_configs } ################################################################ case "${NIT_CASE}" in cppnit) testgroup_sandbox_cppnit ;; python) testgroup_sandbox_python ;; testcase_*|testgroup_*|testcases_*|testgroups_*) "${NIT_CASE}" ;; "") # Default test groups: testgroup_upsd_invalid_configs testgroup_upsd_questionable_configs testgroup_sandbox ;; *) die "Unsupported NIT_CASE='$NIT_CASE' was requested" ;; esac log_separator log_info "OVERALL: PASSED=$PASSED FAILED=$FAILED" # Allow to leave the sandbox daemons running for a while, # to experiment with them interactively: if [ -n "${DEBUG_SLEEP-}" ] ; then log_separator log_info "Sleeping now as asked, so you can play with the driver and server running; hint: export NUT_PORT=$NUT_PORT" log_separator if [ "${DEBUG_SLEEP-}" -gt 0 ] ; then sleep "${DEBUG_SLEEP}" else sleep 60 fi log_info "Sleep finished" log_separator fi if [ "$PASSED" = 0 ] || [ "$FAILED" != 0 ] ; then die "Some test scenarios failed!" else log_info "SUCCESS" fi