Whamcloud - gitweb
b=21881 mdt_num_threads tuning
[fs/lustre-release.git] / lustre / tests / functions.sh
index 1dd9ac5..9442145 100644 (file)
@@ -13,6 +13,150 @@ assert_env() {
     [ $failed ] && exit 1 || true
 }
 
+# lrepl - Lustre test Read-Eval-Print Loop.
+#
+# This function implements a REPL for the Lustre test framework.  It
+# doesn't exec an actual shell because the user may want to inspect
+# variables and use functions from the test framework.
+lrepl() {
+    local line
+    local rawline
+    local prompt
+
+    cat <<EOF
+        This is an interactive read-eval-print loop interactive shell
+        simulation that you can use to debug failing tests.  You can
+        enter most bash command lines (see notes below).
+
+        Use this REPL to inspect variables, set them, call test
+        framework shell functions, etcetera.
+
+        'exit' or EOF to exit this shell.
+
+        set \$retcode to 0 to cause the assertion failure that
+        triggered this REPL to be ignored.
+
+        Examples:
+            do_facet ost1 lctl get_param ost.*.ost.threads_*
+            do_rpc_nodes \$OSTNODES unload_modules
+
+        NOTES:
+            All but the last line of multi-line statements or blocks
+            must end in a backslash.
+
+            "Here documents" are not supported.
+
+            History is not supported, but command-line editing is.
+
+EOF
+
+    # Prompt escapes don't work in read -p, sadly.
+    prompt=":test_${testnum:-UNKNOWN}:$(uname -n):$(basename $PWD)% "
+
+    # We use read -r to get close to a shell experience
+    while read -e -r -p "$prompt" rawline; do
+        line=
+        case "$rawline" in
+        # Don't want to exit-exit, just exit the REPL
+        exit) break;;
+        # We need to handle continuations, and read -r doesn't do
+        # that for us.  Yet we need read -r.
+        #
+        # We also use case/esac to compare lines read to "*\\"
+        # because [ "$line" = *\\ ] and variants of that don't work.
+        *\\) line="$rawline"
+            while read -e -r -p '> ' rawline
+            do
+                line="$line"$'\n'"$rawline"
+                case "$rawline" in
+                # We could check for here documents by matching
+                # against *<<*, but who cares.
+                *\\) continue;;
+                *) break;;
+                esac
+            done
+            ;;
+        *) line=$rawline
+        esac
+
+        case "$line" in
+        *\\) break;;
+        esac
+
+        # Finally!  Time to eval.
+        eval "$line"
+    done
+
+    echo $'\n\tExiting interactive shell...\n'
+    return 0
+}
+
+# lassert - Lustre test framework assert
+#
+# Arguments: failure code, failure message, expression/statement
+#
+# lassert evaluates the expression given, and, if false, calls
+# error() to trigger test failure.  If REPL_ON_LASSERT is true then
+# lassert will call lrepl() to give the user an interactive shell.
+# If the REPL sets retcode=0 then the assertion failure will be
+# ignored.
+lassert() {
+    local retcode=$1
+    local msg=$2
+    shift 2
+
+    echo "checking $* ($(eval echo \""$*"\"))..."
+    eval "$@" && return 0;
+
+    if ${REPL_ON_LASSERT:-false}; then
+        echo "Assertion $retcode failed: $* (expanded: $(eval echo \""$*"\"))
+$msg"
+        lrepl
+    fi
+
+    error "Assertion $retcode failed: $* (expanded: $(eval echo \""$*"\"))
+$msg"
+    return $retcode
+}
+
+# setmodopts- set module options for subsequent calls to load_modules
+#
+# Usage: setmodopts module_name new_value [var_in_which_to_save_old_value]
+#        setmodopts -a module_name new_value [var_in_which_to_save_old_value]
+#
+# In the second usage the new value is appended to the old.
+setmodopts() {
+        local _append=false
+
+        if [ "$1" = -a ]; then
+            _append=true
+            shift
+        fi
+
+        local _var=MODOPTS_$1
+        local _newvalue=$2
+        local _savevar=$3
+        local _oldvalue
+
+        # Dynamic naming of variables is a pain in bash.  In ksh93 we could
+        # write "nameref opts_var=${modname}_MODOPTS" then assign directly
+        # to opts_var.  Associative arrays would also help, alternatively.
+        # Alas, we're stuck with eval until all distros move to a more recent
+        # version of bash.  Fortunately we don't need to eval unset and export.
+
+        if [ -z "$_newvalue" ]; then
+            unset $_var
+            return 0
+        fi
+
+        _oldvalue=${!var}
+        $_append && _newvalue="$_oldvalue $_newvalue"
+        export $_var="$_newvalue"
+        echo setmodopts: ${_var}=${_newvalue}
+
+        [ -n "$_savevar" ] && eval $_savevar=\""$_oldvalue"\"
+}
+
 echoerr () { echo "$@" 1>&2 ; }
 
 signaled() {