bringing in testkit tools
[feisty_meow.git] / testkit / library / helper_methods.sh
diff --git a/testkit/library/helper_methods.sh b/testkit/library/helper_methods.sh
new file mode 100644 (file)
index 0000000..7be5781
--- /dev/null
@@ -0,0 +1,312 @@
+#!/bin/bash
+
+# useful functions that are somewhat general.  these are not needed for
+# the basic setup of the test environment, but they are used by other
+# test and tool functions and also by specific tests.
+#
+# Author: Chris Koeritz
+
+# prints out a timestamp with the current date and time up to seconds.
+function date_string()
+{
+  date +"%Y_%b_%e_%H%M_%S" | sed -e 's/ //g'
+}
+
+# prints out the timestamp in a somewhat readable way.
+function readable_date_string()
+{
+  date +"%Y-%m-%d %T"
+}
+
+########
+# (donated by the feisty meow scripts at http://feistymeow.org)
+
+  function is_array() {
+    [[ "$(declare -p $1)" =~ "declare -a" ]]
+  }
+
+  function is_alias() {
+    alias $1 &>/dev/null
+    return $?
+  }
+
+  # displays the value of a variable in bash friendly format.
+  function var() {
+    HOLDIFS="$IFS"
+    IFS=""
+    while true; do
+      local varname="$1"; shift
+      if [ -z "$varname" ]; then
+        break
+      fi
+
+      if is_alias "$varname"; then
+#echo found $varname is alias
+        local tmpfile="$(mktemp $TMP/aliasout.XXXXXX)"
+        alias $varname | sed -e 's/.*=//' >$tmpfile
+        echo "alias $varname=$(cat $tmpfile)"
+        \rm $tmpfile
+      elif [ -z "${!varname}" ]; then
+        echo "$varname undefined"
+      else
+        if is_array "$varname"; then
+#echo found $varname is array var 
+          local temparray
+          eval temparray="(\${$varname[@]})"
+          echo "$varname=(${temparray[@]})"
+#hmmm: would be nice to print above with elements enclosed in quotes, so that we can properly
+# see ones that have spaces in them.
+        else
+#echo found $varname is simple
+          echo "$varname=${!varname}"
+        fi
+      fi
+    done
+    IFS="$HOLDIFS"
+  }
+########
+
+# given a file name and a phrase to look for, this replaces all instances of
+# it with a piece of replacement text.  note that slashes are okay in the two
+# text pieces, but we are using pound signs as the regular expression
+# separator; phrases including the octothorpe (#) will cause syntax errors.
+function replace_phrase_in_file()
+{
+  local file="$1"; shift
+  local phrase="$1"; shift
+  local replacement="$1"; shift
+  if [ -z "$file" -o -z "$phrase" ]; then
+    echo "replace_phrase_in_file: needs a filename, a phrase to replace, and the"
+    echo "text to replace that phrase with."
+    return 1
+  fi
+  sed -i -e "s%$phrase%$replacement%g" "$file"
+}
+
+# prints an error message (from parameters) and exits if the previous command failed.
+function check_if_failed()
+{
+  if [ $? -ne 0 ]; then
+    echo Step failed: $*
+    exit 1
+  fi
+}
+
+# takes a first parameter that is the name for a combined error and output log,
+# and then runs all the other parameters as a command.
+function logged_command()
+{
+  local my_output="$1"; shift
+#  echo "logged_command args: $(printf -- "[%s] " "${@}")"
+  eval "${@}" >>"$my_output" 2>&1
+  local retval=$?
+  if [ $retval == 0 ]; then
+    # good so far, but check for more subtle ways of failing; if there is
+    # an occurrence of our fail message in the output, that also indicates
+    # the command did not succeed.
+    grep "\[FAILURE\]" $my_output
+    # we do not want to see that phrase in the log.
+    if [ $? != 0 ]; then
+      return 0  # fine exit, can ignore log.
+    fi
+  fi
+  if [[ ! "$my_output" =~ .*fuse_output.* ]]; then
+    # this was a failure, so we need to see the log.
+    # fuse errors currently don't count since they are multifarious.
+    cat "$my_output"
+  fi
+  return 1
+}
+
+# runs an arbitrary command.  if the command fails, then the output from it is
+# displayed and an error code is returned.  otherwise the output is discarded.
+function run_any_command()
+{
+  local my_output="$(mktemp $TEST_TEMP/test_logs/out_run_any_cmd_$(date_string).XXXXXX)"
+  logged_command "$my_output" "${@}"
+  local retval=$?
+  # make the external version of the log file available.  if we're multiplexing users,
+  # this will be clobbered constantly, which is why we used unique names above.
+  \cp -f "$my_output" "$TESTKIT_OUTPUT_FILE"
+  # then add the logging results to our huge mongo log of all actions.
+  echo >> "$CONGLOMERATED_TESTKIT_OUTPUT"
+  echo "$(readable_date_string) log from: $my_output" >> "$CONGLOMERATED_TESTKIT_OUTPUT"
+  echo "=======" >> "$CONGLOMERATED_TESTKIT_OUTPUT"
+  cat "$my_output" >> "$CONGLOMERATED_TESTKIT_OUTPUT"
+  echo "=======" >> "$CONGLOMERATED_TESTKIT_OUTPUT"
+  # and now remove the tiny individual log file so we don't litter.
+  \rm -f "$my_output"
+  return $retval
+}
+
+
+# returns 0 if there should be no problems using fuse, or non-zero if this platform
+# does not currently support fuse.
+function fuse_supported()
+{
+  local retval=0
+  local platform="$(uname -a | tr A-Z a-z)"
+  if [[ $platform =~ .*darwin.* ]]; then retval=1; fi
+  if [[ $platform =~ .*cygwin.* ]]; then retval=1; fi
+  if [[ $platform =~ .*ming.* ]]; then retval=1; fi
+  return $retval
+}
+
+# returns 0 if there should be no problems creating links in the file system,
+# or non-zero if this platform does not support symbolic links.
+function links_supported()
+{
+  local retval=0
+  local platform="$(uname -a | tr A-Z a-z)"
+  if [[ $platform =~ .*cygwin.* ]]; then retval=1; fi
+  if [[ $platform =~ .*ming.* ]]; then retval=1; fi
+  return $retval
+}
+
+# Create a test directory (in the first parameter) with $2 subdirectories,
+# each with $3 subdirs, each with $4 files.
+fan_out_directories()
+{
+  local dir_name="$1"; shift
+  local top_count=$1; shift
+  local mid_count=$1; shift
+  local file_count=$1; shift
+  mkdir "$dir_name"
+  for (( di=0 ; di<$top_count ; di++ )); do
+    mkdir "$dir_name"/sub$di
+    for (( dj=0 ; dj<$mid_count ; dj++ )); do
+      mkdir "$dir_name"/sub$di/sub$dj
+      for (( dk=0 ; dk<$file_count ; dk++ )); do
+        echo "file $di$dj$dk" > "$dir_name"/sub$di/sub$dj/file$di$dj$dk
+      done
+    done
+  done
+}
+##############
+
+# copied from open source codebase at: http://feistymeow.org with permission of author (chris koeritz),
+# assigned apache ASL license for this usage.
+  # locates a process given a search pattern to match in the process list.
+  # supports a single command line flag style parameter of "-u USERNAME";
+  # if the -u flag is found, a username is expected afterwards, and only the
+  # processes of that user are considered.
+  function psfind() {
+    local -a patterns=("${@}")
+#echo ====
+#echo patterns list is: "${patterns[@]}"
+#echo ====
+
+    local user_flag
+    if [ "${patterns[0]}" == "-u" ]; then
+      user_flag="-u ${patterns[1]}" 
+#echo "found a -u parm and user=${patterns[1]}" 
+      # void the two elements with that user flag so we don't use them as patterns.
+      unset patterns[0] patterns[1]
+    else
+      # select all users.
+      user_flag="-e"
+    fi
+
+    local PID_DUMP="$(mktemp "$TMP/zz_pidlist.XXXXXX")"
+    local -a PIDS_SOUGHT
+
+    if [ "$OS" == "Windows_NT" ]; then
+      # gets cygwin's (god awful) ps to show windoze processes also.
+      local EXTRA_DOZER_FLAGS="-W"
+      # pattern to use for peeling off the process numbers.
+      local pid_finder_pattern='s/ *\([0-9][0-9]*\) *.*$/\1/p'
+
+    else
+      # flags which clean up the output on unixes, which apparently cygwin
+      # doesn't count as.  their crappy specialized ps doesn't support this.
+      local EXTRA_UNIX_FLAGS="-o pid,args"
+      # pattern to use for peeling off the process numbers.
+      local pid_finder_pattern='s/^[[:space:]]*\([0-9][0-9]*\).*$/\1/p'
+    fi
+
+    /bin/ps $EXTRA_DOZER_FLAGS $EXTRA_UNIX_FLAGS $user_flag | tail -n +2 >$PID_DUMP
+#echo ====
+#echo got all this stuff in the pid dump file:
+#cat $PID_DUMP
+#echo ====
+
+    # search for the pattern the user wants to find, and just pluck the process
+    # ids out of the results.
+    local i
+    for i in "${patterns[@]}"; do
+      PIDS_SOUGHT+=($(cat $PID_DUMP \
+        | grep -i "$i" \
+        | sed -n -e "$pid_finder_pattern"))
+    done
+#echo ====
+#echo pids sought list became:
+#echo "${PIDS_SOUGHT[@]}"
+#echo ====
+
+    if [ ${#PIDS_SOUGHT[*]} -ne 0 ]; then
+      local PIDS_SOUGHT2=$(printf -- '%s\n' ${PIDS_SOUGHT[@]} | sort | uniq)
+      PIDS_SOUGHT=()
+      PIDS_SOUGHT=${PIDS_SOUGHT2[*]}
+      echo ${PIDS_SOUGHT[*]}
+    fi
+    /bin/rm $PID_DUMP
+  }
+  
+
+#######
+
+# tests the supposed fuse mount that is passed in as the first parameter.
+function test_fuse_mount()
+{
+  local mount_point="$1"; shift
+  local trunc_mount="$(basename "$(dirname $mount_point)").$(basename "$mount_point")"
+
+  checkMount="$(mount)"
+#echo "checkmount is: '$checkMount'"
+#echo "mount point seeking is: '$trunc_mount'"
+  local retval=1
+  if [[ "$checkMount" =~ .*$trunc_mount.* ]]; then
+#echo found the mount in the list
+    retval=0
+  fi
+  if [ $retval -ne 0 ]; then
+    echo "Finding mount point '$trunc_mount' failed."
+    return 1
+  fi
+  ls -l "$mount_point" &>/dev/null
+  return $?
+}
+
+#######
+
+# also borrowed from feisty meow scripts...  by consent of author (chris koeritz).
+
+  # is this the Mac OS X operating system?
+  function isMacOSX()
+  {
+    if [ ! -z "$(echo $OSTYPE | grep -i darwin)" ]; then
+      true
+    else
+      false
+    fi
+  }
+
+  # switches from a /X/path form to an X:/ form.  this also processes cygwin paths.
+  function unix_to_dos_path() {
+    # we usually remove dos slashes in favor of forward slashes.
+    if [ ! -z "$SERIOUS_SLASH_TREATMENT" ]; then
+      # unless this flag is set, in which case we force dos slashes.
+      echo "$1" | sed -e 's/\\/\//g' | sed -e 's/\/cygdrive//' | sed -e 's/\/\([a-zA-Z]\)\/\(.*\)/\1:\/\2/' | sed -e 's/\//\\/g'
+    else
+      echo "$1" | sed -e 's/\\/\//g' | sed -e 's/\/cygdrive//' | sed -e 's/\/\([a-zA-Z]\)\/\(.*\)/\1:\/\2/'
+    fi
+  }
+  
+  # switches from an X:/ form to an /X/path form.
+  function dos_to_unix_path() {
+    # we always remove dos slashes in favor of forward slashes.
+    echo "$1" | sed -e 's/\\/\//g' | sed -e 's/\([a-zA-Z]\):\/\(.*\)/\/\1\/\2/'
+  }
+
+#######
+