#!/bin/bash
#
#  libTestUtils: Utility functions for HISv tests
#
#  Routines:
#    fErrorExit			- Print an error message and exit with a non-zero value
#    fError				- Print an error message, but don't exit
#    fWarn				- Print a warning
#    fMessage			- Print a message based on verbosity level
#    fShowConfig		- Show the system's configuration
#    fParseCmdline		- Parse common command-line options
#    fCheckRunTest		- Verify that the test suite should be run
#	 fInitTest			- Initialize test variables and print a descriptive header
#	 fPrintHeader		- Print headers for individual tests
#	 fBeginTest			- Initialize test variables and print a "BEGIN" banner
#	 fEndTest			- Capture test results for test summary
#	 fPrintTestSummary	- Print a summary of failed and passing tests
#
#      -*- OpenSAF  -*-
#
# (C) Copyright 2008 The OpenSAF Foundation
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
# under the GNU Lesser General Public License Version 2.1, February 1999.
# The complete license can be accessed from the following location:
# http://opensource.org/licenses/lgpl-license.php
#
################################################################################

#*******************************************************************************
#                         Globals and Default Values
#*******************************************************************************
if [[ -z $__LIB_TEST_UTILS_SOURCED ]]
then
export __LIB_TEST_UTILS_SOURCED=1

 # Output debug information
export VERBOSE=${VERBOSE:-0}
export DRYRUN=${DRYRUN:-0}
 # Tet Exit Values
export PASS=0
export FAIL=1
export UNRESOLVED=2
export NOTINUSE=3
export UNSUPPORTED=4
export UNTESTED=5
export UNINITIATED=6
export NORESULT=6
export SKIPPED=11
 # For messages
export MyName=${0##*/};
 # Time stamps for logs, backup files, etc.
 #  Access real date stamp using "eval $TS"
export TS='date +%m%d_%H%M%S'
 # This is a test ID to aid in identifying results in a file
export TestSuiteName

 # Test statistics
export TotalPassed=0
export TotalFailed=0
export ContinueTest=1	# Flag whether or not to continue the current test

 # Others
[[ $TERM = screen ]] && export TERM=vt100
fi

################################################################################
#                             Subroutines
################################################################################

#*******************************************************************************
#
#  fErrorExit: Print an error message to STDOUT and exit with the specified value
#
#  Input:        $1 - message   => The error message
#                $2 - exitVal   => The exit value
#  Return:       void
#
#*******************************************************************************
function fErrorExit
{
	local message
	local exitVal=1
	if (( $# == 1 ))
	then
		message="$1"
		exitVal=1
	elif [[ $1 = +([0-9]) ]]
	then
		exitVal=$1
		message=$2
    else
    	message=$1
    	exitVal=$2
	fi
    export FAILED=1
	(( exitVal == $SKIPPED )) && touch SKIP_TEST
    echo -e "\n**> ERROR: $message"
    echo ""
	  # Print the test outcome if this occurs during a test
	if [[ -n $TestName ]]
	then
		fEndTest
	fi
    exit $exitVal
}

#*******************************************************************************
#
#  fError: Print an error message to STDOUT, but continue running
#
#  Input:       $1 - message   => The error message 
#
#  Return:      void
#
#  Note: Sets global variables EXIT_VAL and FAILED to keep track of the
#		 status of the test.
#
#*******************************************************************************
function fError
{
    local message="$*"
    echo -e "\n**> ERROR: $message"
    echo ""

    export EXIT_VAL=${exitVal:=1}
    export FAILED=1
}

#*******************************************************************************
#
#  fWarn: Print a warning message to stdout
#
#  Input:        $1 - message   => The warning
#  Return:       void
#
#*******************************************************************************
function fWarn
{
    local message=$1
    echo -e "WARNING: $message"
}

#*******************************************************************************
#
#  fMessage: Print an informational message 
#
#  Input:        $1 - message   => The message
#                $2 - Verbosity level for the message to appear
#  Return:       void
#
#*******************************************************************************
function fMessage
{
   local message=$1
   local level=${2:-0}
   if (( $VERBOSE >= $level ))
   then
      echo -e "$message"
   fi
}

#*******************************************************************************
#
#  fShowConfig: Show the system's hardware and OS configuration information
#
#  Input:       None
#
#  Return:		Sets Global variable CONFIG_SHOWN if the config has been printed
#				before.  This allows the function to be in individual test
#				scripts but the information will only be called once if the
#				tests are run from the top-level Run_all script.
#
#  Note:		Exports several variables that may be useful in testing
#               MODEL	- system model
#               DATE	- Date (YYYY-MM-DD)
#               TOTAL_MEMORY	- Total Memory in the system (in kB)
#
#*******************************************************************************
function fShowConfig
{
	 # Check to see if this information has been printed before, if so,
	 #  just return w/o printing anything.

	if [[ $CONFIG_SHOWN != 1 ]]
	then
		export CONFIG_SHOWN=1
	else
		return
	fi

     # System model
    if [[ -z $MODEL ]]
    then
	   export MODEL=$(dmidecode | \
	   			awk -F: '{	if ($0 ~ /Handle/) { showInfo = 0; }
						if ($0 ~ /System Information/) { showInfo = 1; }
						if ($0 ~ /Product Name/) { if (showInfo) {print $2} }}')
		# Get rid of whitespace
	   MODEL=${MODEL## }
	   MODEL=${MODEL%% }
    fi

     # A date stamp for the tests
    if [[ -z $DATE ]]
    then
       export DATE=$(date +%Y-%m-%d)
    fi
     # Number of CPUs
    if [[ -z $NUM_CPUS ]]
    then
       export NUM_CPUS=$(cat /proc/cpuinfo | grep processor | sed -e "s/processor.*: //" | wc -l)
    fi
     # Amount of memory in the system
    if  [[ -z $TOTAL_MEMORY ]]
    then
        export TOTAL_MEMORY=$(grep "MemTotal" /proc/meminfo | \
             sed -e "s/MemTotal: \{1,\}//" -e "s/ \{1,\}kB//")
    fi
     # Kernel version
    if [[ -z $KERNEL_VERSION ]]
    then
        export KERNEL_VERSION=$(cat /proc/version)
    fi
     # The OS version
    if [[ -z $OS_VERSION ]]
    then
        export OS_VERSION=$(head -1 /etc/issue)
    fi
     # The CPU type
    if [[ -z $CPU_TYPE ]]
    then
        export CPU_TYPE=$(uname -pm)
    fi
    echo "    ==============================="
    echo "      s y s t e m  s u m m a r y   "
    echo "    ==============================="
    echo -e "    DATE:\t$DATE"
    echo -e "    MODEL:\t$MODEL"
    echo -e "    CPUS:\t$NUM_CPUS"
    echo -e "    CPU TYPE:\t$CPU_TYPE"
    echo -e "    MEMORY:\t$TOTAL_MEMORY KiB"
    echo -e "    OS VERSION:\t$OS_VERSION"
    echo -e "    KERN VERS:\t$KERNEL_VERSION"
    echo ""
    
}   # End fShowConfig

#*******************************************************************************
#
#  fParseCmdline: Parse the user's command line, setting global variables
#
#  Input:        $* - The user's command line
#
#  Return:       void
#
#*******************************************************************************
function fParseCmdline
{
   # Allow the user to give command line options with an '=' sign
   set -- $(echo $* | sed -e "s/=/ /g")
   while (( $# ))
   do
  	  local Opt=$1
	  shift
	  case $Opt in
		-h | -help | --help )
			  # This must be defined in each test.
			Usage
			;;

		-dryrun )
			export DRYRUN=1
			;;

		-domain )
			export Domain=$1
			shift
			;;

        -f | -file | -config | -cfg )
			export ConfigFile=$1
			shift
			;;

		-v | -verbose )
			if [[ $1 = +([0-9]) ]]
			then
				VERBOSE=$1
				shift
			else
				VERBOSE=1
			fi
			;;

		-fw_wait | -fwWait | -fw | -fw_sleep | -fwSleep)
			export FwWaitTime=$1
			shift
			;;

		-api_wait | -api_sleep | -api | -apiWait | -apiSleep )
			export ApiWaitTime=$1
			shift
			;;

		-x | -debug )
			set -o xtrace
			;;

		* )
			fErrorExit "Unknown option $Opt" 1
			;;

	  esac
		
   done
}

#*******************************************************************************
#
#  fCheckRunTest: Check if SKIP_TEST file exists, if so, exit with value
#                 $SKIPPED
#  Input:  None
#
#  Return: void
# 
#*******************************************************************************
function fCheckRunTest
{
    if [[ -f SKIP_TEST ]]
    then
		fErrorExit $SKIPPED "Skip Test Detected, Exiting\n"
    fi
}

#*******************************************************************************
#
#  fPrintHeader: Print a header for a test
#  Input: $1 - Test header
#         $2 - level (to choose what kind of divider to print)
#
#  Return: void
# 
#*******************************************************************************
function fPrintHeader
{
    local maxLine=80
    local header="$1"
    local level
    [[ -n $2 ]] && level=$2 || level=0
    local headerChar
    if (( level == 0 ))
    then
	   headerChar="#"
    elif (( level == 1 ))
    then
       headerChar="="
    elif (( level == 2 ))
    then
       headerChar=":"
    elif (( level == 3 ))
    then
       headerChar="\*"
    else
       headerChar="-"
    fi

     # Figure out how long the header string is 
    local numChar=$(echo -n "$header" | wc -c)
    local space=$(( ((maxLine + numChar )) / 2 ))
	(( numChar > maxLine )) && space=0
     # Get the divider line
    local sepLine=$(perl -e "print \"$headerChar\" x $maxLine")
     # Now print the header
    echo -e "\n$sepLine"
    printf "%${space}s\n" "$header"
    echo -e "$sepLine"

    return 
}	# End fPrintHeader

#*******************************************************************************
#
#  fInitTest: Initialize a test suite
#  Input: $1 - Test Name
#
#  Return: void
# 
#  Sets global variables TestName and FAILED
#*******************************************************************************
function fInitTest
{
    export TestSuiteName
	  # Bash always sets $0 to the top-level caller
	(( ! $# )) && TestSuiteName=${0##*/} || TestSuiteName="$*"

	  # Test status values
	export FAILED=0
	export EXIT_VAL=0
	
	  # Test stats for printing out suite summary
    export TotalPassed=0
    export TotalFailed=0

	  # Debug and dryrun variables
	export DRYRUN
		[[ -z $DRYRUN ]] && DRYRUN=0
	export VERBOSE
		[[ -z $VERBOSE ]] && VERBOSE=0

	  # Print the test-suite header
	fPrintHeader "$TestSuiteName" 0
	return
}	# End fInitTest


#*******************************************************************************
#
#  fBeginTest: Begin a test -- print a header and set the global variable FAILED
#  Input: $1 - Test Name
#
#  Return: void
# 
#  Sets global variables TestName and FAILED
#*******************************************************************************
function fBeginTest
{
    export TestName="$*"
    export FAILED=0
	ContinueTest=1

	fPrintHeader "BEGIN: $TestName" 2
}	# End fBeginTest

#*******************************************************************************
#
#  fEndTest: End a test -- print the status of the test
#  Input: 
#         (global) FAILED   -- used to determine if a test passed or failed
#         (global) TestName -- printed to identify which test results are
#                              printed.
#		  (global) TotalPassed -- Keep a running tally of passed tests
#		  (global) TotalFailed -- Keep a running tally of failed tests
#
#  Return: void
# 
#*******************************************************************************
function fEndTest
{
    local result

    [[ -z $TestName ]] && fErrorExit 1 "TestName not set: fBeginTest not called?"
    [[ -z $FAILED ]] && fErrorExit 1 "FAILED global not set: fBeginTest not called?"
    if (( FAILED )) 
	then
		result="FAIL" 
		[[ -z $TotalFailed ]] && TotalFailed=1 || (( TotalFailed += 1 ))
	else
		result="PASS"
		[[ -z $TotalPassed ]] && TotalPassed=1 || (( TotalPassed += 1 ))
	fi
    echo -e "\n$result $TestName"
    echo -e "END  $TestName"
}   # End fEndTest


#*******************************************************************************
#
#  fPrintTestSummary: Print a test summary at the end of a test
#  Input: 
#         (global) TestSuiteName -- printed to identify which test-suite results
#                              		are printed.
#		  (global) TotalPassed	 -- Tally of passed tests
#		  (global) TotalFailed	 -- Tally of failed tests
#
#  Return: void
# 
#*******************************************************************************
function fPrintTestSummary
{
    echo -e "\n\t------------------------------------------"
	echo -e "\tSUMMARY OF $TestSuiteName"
	echo -e "\t------------------------------------------"
	echo -e "\tTotal Tests  : $(( TotalPassed + TotalFailed ))"
	echo -e "\tFailed       : $((TotalFailed))"
	echo -e "\tPassed       : $((TotalPassed))"
	echo -e "\t------------------------------------------"
} # End fPrintTestSummary


#
# vim: tabstop=4
# -*- tab-width:4 -*-
#
