#!/bin/bash # # Copyright(c) 2012-2021 Intel Corporation # SPDX-License-Identifier: BSD-3-Clause # export NAME=`basename $0` export RESTORE='\033[0m' export RED='\033[00;31m' export GREEN='\033[00;32m' export YELLOW='\033[00;33m' if [ -z $TESTS_DIR ] ; then export TESTS_DIR="$(dirname $0)" fi export LOGS_FOLDER="$TESTS_DIR/logs" if [ -z "$TEST_LOG_DIR" ] ; then export TEST_LOG_DIR="$TESTS_DIR/logs" fi export TEST_TIME="" check_if_root_or_exit() { if [[ $EUID -ne 0 ]] ; then echo "You need to have root privileges to launch DVT tests" exit 1 fi } resolve_path() { local BY_ID_DIR="/dev/disk/by-id" local BY_ID_LINKS=$(ls $BY_ID_DIR) for BY_ID_PATH in $BY_ID_LINKS do FULL_PATH="${BY_ID_DIR}/${BY_ID_PATH}" if [[ "$(realpath $FULL_PATH)" -ef "$(realpath $DEVICE)" ]] then DEVICE=$FULL_PATH break fi done } parse_args() { while [ -n "$1" ] ; do case $1 in -a | --all ) export TEST_MODE="all" ;; -x | --dir ) shift export TEST_MODE="dir" TEST_MODE_DIR="$1" ;; -b | --bvt ) export TEST_MODE="bvt" ;; -f | --atomic ) export TEST_MODE="atomic" ;; -n | --nightly ) export TEST_MODE="nightly" ;; -s | --sanity ) export TEST_MODE="sanity" ;; -i | --ignore ) export IGNORE_WARNINGS="1" ;; -c | --cache ) shift DEVICE="$1" resolve_path CACHE_DEVICE=$DEVICE ;; -d | --core ) shift DEVICE="$1" resolve_path CORE_DEVICE=$DEVICE ;; * ) echo "Unrecognized option" usage exit 1 esac shift done } usage() { echo "example: ./${NAME} -b" echo " -a | --all - run all TESTS" echo " -b | --bvt - run BVT" echo " -n | --nightly - run nightly" echo " -s | --sanity - sanity check" echo " -i | --ignore - ignore config warnings" echo " -c | --cache - override cache device from settings file" echo " -d | --core - override core device from settings file" echo " -x | --dir - performs tests for specified directory (e.g. --dir basic)" } load_cas_lib() { if [ -z $CAS_CONFIGURATION_LOADED ] ; then . $TESTS_DIR/cas_config fi if [ -z $CAS_FUNCTIONS_LOADED ] ; then . $TESTS_DIR/cas_functions fi if [ -z $CAS_OPTIONS_LOADED ] ; then . $TESTS_DIR/cas_options fi if [ -f ~/cas_local_config ] ; then . ~/cas_local_config echo "--- Using home config file ---" elif [ -f $TESTS_DIR/cas_local_config ] ; then . $TESTS_DIR/cas_local_config echo "--- Using local config file ---" fi } start_test() { if [ -z $LOG_FILE ] ; then load_cas_lib else load_cas_lib >> $LOG_FILE fi parse_args $* check_config if [ -z $DESCRIPTION ] then DESCRIPTION=$(cat $0 | grep "# DESCRIPTION" | sed 's/# DESCRIPTION //g') export DESCRIPTION="$DESCRIPTION" fi STORE_CONFIG_OPTION=1 clear_config clear_options echo "*** Starting test $0 - $DESCRIPTION ***" TEST_TIME="$(date +%s)" } end_test() { TEST_TIME="$(($(date +%s) - TEST_TIME))" echo "*** Finished test $NAME ***" echo "*** The test took $TEST_TIME seconds ***" echo "result : $1" restore_config if [ $1 -ne 0 ] ; then # Try to cleanup in case of failure - it might not always work, but could help to # execute remaining tests umount ${CORE_DEVICE}* &>/dev/null remove_caches test_log_stop fi # Delete all temporary files rm -rf $TMP_DIR/* # Delete created symlinks for NVMes if [[ $CACHE_DEVICE != "/dev/nvme"* ]] ; then exit $1 fi local L_NVME_SYM_LINKS=`ls /dev/ | grep -E -w "${CACHE_DEVICE:5}[1-9][1-9]?"` for SYM_LINK in $L_NVME_SYM_LINKS do if [ -L "/dev/${SYM_LINK}" ] then rm -f "/dev/${SYM_LINK}" fi done exit $1 } echo_green() { echo -e "${GREEN}$*${RESTORE}" } echo_red() { echo -e "${RED}$*${RESTORE}" } echo_yellow() { echo -e "${YELLOW}$*${RESTORE}" } echo_green_n() { echo -ne "${GREEN}$*${RESTORE}" } echo_red_n() { echo -ne "${RED}$*${RESTORE}" } echo_yellow_n() { echo -ne "${YELLOW}$*${RESTORE}" } success() { echo -n "$*" echo_green "[OK]" } error() { echo -n "$*" echo_red "[ERROR]" } not_run() { echo -n "$*" echo_yellow "[NOT RUN]" } warning() { echo -n "$*" echo_yellow "[WARNING]" } # This function should be used by all API wrappers and may be also used # directly in tests. It runs the command passed to it and checks the return # code against NEGATIVE_TEST_OPTION. If the NEGATIVE_TEST_OPTION is set, then # we assume the command should fail - otherwise the command should succeed. # If the output is correct, the command is printed and the test continues; # if not, we print an error message and end the test immediately. run_cmd() { export RUN_CMD_OUTPUT="" local L_RUN_CMD_START=$SECONDS if [ -z "$SILENT_COMMAND_OPTION" ] ; then echo -n "$(date +%Y-%m-%d_%H:%M:%S) " echo -n "Running $* " fi OUTPUT=$(eval "$*" 2>&1) STATUS=$? export RUN_CMD_OUTPUT="${OUTPUT}" export RUN_CMD_TIME=$(( $SECONDS - $L_RUN_CMD_START )) if [ -z "$SILENT_COMMAND_OPTION" ] ; then if [ -n "$NEGATIVE_TEST_OPTION" ] && [ "$NEGATIVE_TEST_OPTION" -ne 0 ] ; then echo -n "(negative test) " if [ $STATUS -ne 0 ] ; then success else error echo "--- Command output:" echo "$OUTPUT" if [ -z $DONT_FAIL_ON_ERROR_OPTION ]; then end_test 1 fi return 1 fi else if [ $STATUS -eq 0 ] ; then success else error echo "--- Command output:" echo "$OUTPUT" if [ -z $DONT_FAIL_ON_ERROR_OPTION ]; then end_test 1 fi return 1 fi fi fi } # This function converts size to bytes amount. It takes one parameter and # the format of it is: [0-9][b|kB|kiB|k|M|MiB|MB|G|GiB|GB|T|TiB|TB] # # example of usage: BYTES=$(get_bytes 128kB) # return : 128*1024 = 131,072 # get_bytes () { local PARAM local FACTOR local BYTES if [[ $1 =~ ^([0-9]*)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=1 elif [[ $1 =~ ^(b)$ ]] ; then PARAM=1 FACTOR=512 elif [[ $1 =~ ^([0-9]*)(b)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=512 elif [[ $1 =~ ^(kB)$ ]] ; then PARAM=1 FACTOR=1000 elif [[ $1 =~ ^(k|kiB)$ ]] ; then PARAM=1 FACTOR=1024 elif [[ $1 =~ ^([0-9]*)(kB)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=1000 elif [[ $1 =~ ^([0-9]*)(k|kiB)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=1024 elif [[ $1 =~ ^(MB)$ ]] ; then PARAM=1 FACTOR=1000*1000 elif [[ $1 =~ ^(M|MiB)$ ]] ; then PARAM=1 FACTOR=1024*1024 elif [[ $1 =~ ^([0-9]*)(MB)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=1000*1000 elif [[ $1 =~ ^([0-9]*)(M|MiB)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=1024*1024 elif [[ $1 =~ ^(GB)$ ]] ; then PARAM=1 FACTOR=1000*1000*1000 elif [[ $1 =~ ^(G|GiB)$ ]] ; then PARAM=1 FACTOR=1024*1024*1024 elif [[ $1 =~ ^([0-9]*)(GB)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=1000*1000*1000 elif [[ $1 =~ ^([0-9]*)(G|GiB)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=1024*1024*1024 elif [[ $1 =~ ^(T|TiB)$ ]] ; then PARAM=1 FACTOR=1024*1024*1024*1024 elif [[ $1 =~ ^(TB)$ ]] ; then PARAM=1 FACTOR=1000*1000*1000*1000 elif [[ $1 =~ ^([0-9]*)(T|TiB)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=1024*1024*1024*1024 elif [[ $1 =~ ^([0-9]*)(TB)$ ]] ; then PARAM=${BASH_REMATCH[1]} FACTOR=1000*1000*1000*1000 else echo "Input parameter error, ($1) is not [0-9](b|kB|kiB|k|M|MiB|MB|G|GiB|GB|T|TiB|TB)" exit 1 fi let BYTES=$PARAM*$FACTOR echo $BYTES } # This function returns pages amount for specified byte size. It takes # folowing parameters: # size - size that will be computed to number of pages # [page_size] - optional, if ommited then page size is 4k # # example of usage: PAGES=$(get_bytes 128kB [$PAGE_SIZE=4k]) # return : 128kB / $PAGE_SIZE = 32 # get_pages () { local PAGES local PAGE_SIZE local BYTES if [ -z "$2" ] then PAGE_SIZE=4096 else PAGE_SIZE=$2 fi PAGE_SIZE=$(get_bytes $PAGE_SIZE) BYTES=$(get_bytes $1) let PAGES=$BYTES/$PAGE_SIZE echo $PAGES } TEST_LOG_PID="${TEST_LOG_DIR}/.test_log_pid" # Start print log to the STD # # usage: # test_log_tail test_log_tail () { # # Check if traicing in progress # if [ -f $TEST_LOG_PID ] then local L_PID=$(ps | grep tail | grep $(cat $TEST_LOG_PID)) if [ "" != "$L_PID" ] then return 0 fi fi tail -f $1 & echo $! > $TEST_LOG_PID return 0 } # Test Log Utils Function # It shall be used in following order # test_log_start() # # # test_log_trace() # Do tracing # # # test_log_stop() # # Start trace loging. Function takes following parameters: # [TEST_LOG_FILE_NAME] File where log will be captured. If omitted log file name # id "cas_test_log" # # example of usage: test_log_start [$TEST_LOG_FILE_NAME] # test_log_start() { if [ -n "$1" ] then export TEST_LOG="${TEST_LOG_DIR}/$1" else export TEST_LOG="${TEST_LOG_DIR}/cas_test_log_ext" fi if [ ! -d $TEST_LOG_DIR ] ; then mkdir -p $TEST_LOG_DIR fi echo >> $TEST_LOG echo "********************************************************" >> $TEST_LOG echo "* Test log start : $(date)" >> $TEST_LOG echo "* $DESCRIPTION - $TEST_LOG" >> $TEST_LOG echo "********************************************************" >> $TEST_LOG if [ -z $DISABLE_EXTERNAL_LOGGING ] then test_log_tail $TEST_LOG fi } # Stop trace loging test_log_stop() { if [ -n "${TEST_LOG}" ]; then echo "########################################################" >> $TEST_LOG echo "* $DESCRIPTION - $TEST_LOG" >> $TEST_LOG echo "# Test log stop : $(date)" >> $TEST_LOG echo "########################################################" >> $TEST_LOG echo >> $TEST_LOG sleep 1 fi if [ -f $TEST_LOG_PID ] then local L_PID=$(ps | grep tail | grep $(cat $TEST_LOG_PID)) if [ "" != "$L_PID" ] then kill $(cat $TEST_LOG_PID) rm -f $TEST_LOG_PID fi fi } # # Trace log message. # # example of usage: test_log_trace "Some message to store in file" # test_log_trace() { if [[ ! -z $1 ]] then echo "$DESCRIPTION : $1" >> $TEST_LOG fi } set_categories() { if [ "" != "$TEST_MODE_DIR" ] then export CATEGORIES=$TEST_MODE_DIR return 0 fi local TMP_CATEGORIES="$(find $TESTS_DIR -type d | grep -v old | grep -v logs | grep -v ^.$)" for CATEGORY in $TMP_CATEGORIES ; do CATEGORIES="$(basename $CATEGORY) $CATEGORIES" done export CATEGORIES=$(echo $CATEGORIES | tr ' ' '\n' | sort | tr '\n' ' ' && echo) } # # Warmup device # #param1 - Input #param2 - Output #param3 - Block Size #param4 - Count #param5 - Seek #param6 - Skip warmup() { local L_IF=$1 local L_OF=$2 local L_BS=$3 local L_COUNT=$4 local L_SEEK=$5 local L_SKIP=$6 local I_SEEK local I_SKIP if [ "$L_OF" = "/dev/null" ] ; then DD_CONF='if=${L_IF} of=${L_OF} count=1 bs=${L_BS} skip=$I_SKIP iflag=direct' else DD_CONF='if=${L_IF} of=${L_OF} count=1 bs=${L_BS} seek=$I_SEEK skip=$I_SKIP oflag=direct iflag=direct conv=notrunc' fi for (( I=0; I<$L_COUNT; I=I+2 )) do let I_SEEK=${L_SEEK}+${I} let I_SKIP=${L_SKIP}+${I} eval "dd $DD_CONF &>/dev/null" if [ $? != 0 ] then return 1 fi done for (( I=1; I<$L_COUNT; I=I+2 )) do let I_SEEK=${L_SEEK}+${I} let I_SKIP=${L_SKIP}+${I} eval "dd $DD_CONF &>/dev/null" if [ $? != 0 ] then return 1 fi done return 0 } cas_version () { local L_CAS_VERSION=$(LANG=1 casadm -V -o csv 2>/dev/null | grep "CLI" | cut -d ',' -f2) echo $L_CAS_VERSION } check_if_root_or_exit