diff --git a/cet/tests b/cet/tests index caa44b44..658826a0 100755 --- a/cet/tests +++ b/cet/tests @@ -1,5 +1,8 @@ # This file collects the CET(Control-flow Enforcement Technology) tests on # IntelĀ® Architecture-based platforms. +# @hw_dep: cpuid_check 7 0 0 0 c 7 @ HW cpuid could not support CET SHSTK +# @other_dep: general_test.sh -t kconfig -k "CONFIG_X86_USER_SHADOW_STACK=y" +# @other_warn: quick_test @ Glibc could not support CET # User space SHSTK tests without SHSTK Glibc supported cet_tests.sh -t cp_test -n shstk_cp -k "control protection" diff --git a/common/common.sh b/common/common.sh index b66b1db7..dd4af6c5 100755 --- a/common/common.sh +++ b/common/common.sh @@ -236,13 +236,13 @@ test_kconfig() { local name="$2" if [[ ! "$value" =~ [ymn] ]]; then - test_print_err "Invalid koption value!" + test_print_err "Invalid koption value:$value" return 1 fi # For each expression between '|' separators if [[ $(get_kconfig "$name") != "$value" ]]; then - test_print_err "$name does not match $value!" + test_print_trc "$name does not match $value!" return 1 else test_print_trc "$name matches with expect $value" @@ -359,6 +359,52 @@ dmesg_pattern_check() { return 1 } +# Check whole dmesg, which should contain key words +# Input $1: key word +# Output: 0 for true, otherwise false or die +full_dmesg_check() { + local type=$1 + local keyword1=$2 + local keyword2=$3 + local keyword3=$4 + local null="null" + local contain="contain" + local dmesg_head="" + local check_log="" + + dmesg_head=$(dmesg | grep "\[ 0.000000\]" | head -n 1) + [[ -n $dmesg_head ]] \ + || test_print_wrg "Dmesg is not started from 0.000000!" + check_log=$(dmesg | grep -v "dmesg" | grep -i "$keyword1" \ + | grep -i "$keyword2" \ + | grep -i "$keyword3") + + case $type in + "$contain") + if [[ -n "$check_log" ]]; then + test_print_trc "Dmesg contains $keyword1 $keyword2:$check_log, pass" + else + test_print_wrg "Dmesg doesn't contain $keyword1 $keyword2:$check_log, fail" + return 1 + fi + ;; + "$null") + if [[ -z "$check_log" ]]; then + test_print_trc "Dmesg doesn't contain $keyword1 $keyword2:$check_log, pass" + else + test_print_wrg "Dmesg contains $keyword1 $keyword2:$check_log, fail" + return 1 + fi + ;; + *) + test_print_wrg "Invalid type:$type" + return 2 + ;; + esac + + return 0 +} + # Record last timestamp in dmesg and store the value in variable # LAST_DMESG_TIMESTAMP. The value is refered in function extract_case_dmesg. last_dmesg_timestamp() { diff --git a/common/general_test.sh b/common/general_test.sh new file mode 100755 index 00000000..37e2db9e --- /dev/null +++ b/common/general_test.sh @@ -0,0 +1,66 @@ +#!/bin/bash +############################################################################### +# SPDX-License-Identifier: GPL-2.0-only # +# Copyright (c) 2024 Intel Corporation. # +# For general check like KCONFIG, CPU family model stepping # +############################################################################### + +# shellcheck source=/dev/null +cd "$(dirname "$0")" 2>/dev/null && source ../.env + +usage() { + cat <<__EOF + usage: ./${0##*/} [-t TEST_TYPE][-k KCONFIG or keywrod][-p parm][-h] + -t Test type like KCONFIG, FMS + -k KCONFIG name like CONFIG_XXX or keyword + -p PARM like y, null + -h show This +__EOF +} + +general_test() { + case $TYPE in + kconfig) + config_name=$(echo "$KEYWORD" | cut -d '=' -f1) + config_val=$(echo "$KEYWORD" | cut -d '=' -f2) + test_any_kconfig_match "$config_name" "$config_val" + ;; + # family model stepping check + fms) + #TODO, will add the fms check function + ;; + dmesg) + key1=$(echo "$KEYWORD" | awk -F '&' '{print $1}') + key2=$(echo "$KEYWORD" | awk -F '&' '{print $2}')\ + key3=$(echo "$KEYWORD" | awk -F '&' '{print $3}') + full_dmesg_check "$PARM" "$key1" "$key2" "$key3" || return $? + ;; + *) + die "Invalid TYPE:$TYPE" + ;; + esac +} + +while getopts :t:p:k:h arg; do + case $arg in + t) + TYPE=$OPTARG + ;; + p) + PARM=$OPTARG + ;; + k) + KEYWORD=$OPTARG + ;; + h) + usage + exit 0 + ;; + *) + usage + die "Option -$OPTARG requires an argument." + ;; + esac +done + +general_test diff --git a/ifs/ifs_tests.sh b/ifs/ifs_tests.sh index 49a039f8..0e65bd5d 100755 --- a/ifs/ifs_tests.sh +++ b/ifs/ifs_tests.sh @@ -5,8 +5,9 @@ # Description: Test script to verify Intel IFS(In Field SCAN) functionality cd "$(dirname "$0")" 2>/dev/null || exit 1 +# shellcheck source=/dev/null source ../.env - +# shellcheck source=/dev/null source "ifs_common.sh" basic_usage() { @@ -56,7 +57,6 @@ run_ifs_tests() { check_file_content "${IFS_PATH}/${BATCH}" "none" "$CONTAIN" check_file_content "${IFS_PATH}/${VERSION}" "none" "$CONTAIN" init_log "$NAME" - dump_ifs_test "$NAME" ;; ifs_batch) modprobe -r "$IFS_NAME" @@ -70,9 +70,9 @@ run_ifs_tests() { check_file_content "${IFS_PATH}/${VERSION}" "none" "$NE" else test_print_wrg "No ${IFS_PATH}/${BATCH} file, is it 5.15 or old ifs kernel?" + return 2 fi init_log "$NAME" - dump_ifs_test "$NAME" ;; "$IMG_VERSION") modprobe -r "$IFS_NAME" diff --git a/ifs/tests b/ifs/tests index c86db81e..0298bf40 100755 --- a/ifs/tests +++ b/ifs/tests @@ -1,6 +1,8 @@ # This file collects Intel IFS(In Field SCAN) tests on # IntelĀ® Architecture-based platforms. - +# @hw_dep: +# @other_dep: general_test.sh -t kconfig -k "CONFIG_INTEL_IFS=m" +# @other_warn: ifs_tests.sh -m 0 -p all -b 1 -n ifs_batch @ check if SGX init ok and DIMM proper set as IFS relies on enabled SGX # ifs_0 scan test cases, it works on SPR(Sapphire Rapids) platform and future server ifs_tests.sh -m 0 -p all -n load_ifs ifs_tests.sh -m 0 -p all -b 1 -n ifs_batch diff --git a/runtests b/runtests index 2f00dc0d..a528babf 100755 --- a/runtests +++ b/runtests @@ -2,8 +2,19 @@ # SPDX-License-Identifier: GPL-2.0-only # Copyright (c) 2022 Intel Corporation. +# shellcheck source=/dev/null source .env +readonly PASS_CODE=0 +readonly BLOCK_CODE=2 +readonly SKIP_CODE=4 +readonly NA_CODE=32 +PASS="PASS" +BLOCK="BLOCK" +SKIP="SKIP" +FAIL="FAIL" +NA="NA" + START_TIME="" SUMMRY_LOG="" TESTS_CLIENT="tests-client" @@ -13,10 +24,21 @@ SUB_FOLDERS="" TEST_LIST_FILE="/tmp/tests" OLD_IFS="" +# For dependence check parameters, set skip for unknow staus as default +readonly MARK_HW_DEP="@hw_dep:" +readonly MARK_OTHER_DEP="@other_dep:" +readonly MARK_WARN_DEP="@other_warn:" +export HW_DEP="$SKIP_CODE" +export OTHER_DEP="$SKIP_CODE" +export OTHER_WARN="$SKIP_CODE" +REASON="" +DEP_LOG="/tmp/lkvs_dependence.log" + usage() { cat << _EOF Usage: ${0##*/} [-f CMDFILES] [-c CMDLINE] [-o LOGFILE] -f CMDFILES execute user defined list of tests in files separated by ',' + -d DEPENDENCE_FILE check dependence for specified feature tests -c CMDLINE execute test case -o LOGFILE redirect output of tests to file @@ -26,14 +48,172 @@ Examples: ./runtests -f tests-client // exeucte tests-client/tests for all subfolders ./runtests -f tests-server // exeucte tests-server/tests for all subfolders ./runtests -c ./cet/quick_test -o cet_quick_test.log + ./runtests -d cet/tests // check cet dependence + ./runtests -d tests-server // check tests-server/tests for all subfolders dependence _EOF } +append_log() { + local info=$1 + local log_file=$2 + + if [[ -z "$log_file" ]]; then + echo -e "$info" + else + echo -e "$info" | tee -a "$log_file" + fi +} + err() { echo -e "\n$*" >&2 exit 1 } +check_test_file_legal() { + local cmdfile=$1 + + if [[ ! -f "$cmdfile" ]]; then + append_log "WARNING: $cmdfile not found!" "$LOGFILE" + return "$NA_CODE" + fi + + [[ $(which file) ]] && { + file_type="" + file_type=$(file "$cmdfile") + [[ "$file_type" == *"text"* ]] || { + append_log "WARNING: -f $cmdfile is not a text type, it's real type:|$file_type|" "$LOGFILE" + append_log "Please choose the correct tests file." "$LOGFILE" + return "$NA_CODE" + } + } + + return 0 +} + +init_dep_log() { + local dep_log=$1 + + cat /dev/null > "$dep_log" + { + echo "-----------------------------------------------------------------" + printf "%-16s%-13s%-16s%-13s%-20s\n" "Feature" "|HW_support" "|Other_support" \ + "|Other_WARN" "|Reason" + printf "%-16s%-13s%-16s%-13s%-20s\n" "-------" "-----------" "--------------" \ + "-----------" "-------" + } >> "$dep_log" +} + +check_dep_cmd() { + local dep_info=$1 + local dep=$2 + local dep_cmd dep_reason + + dep_cmd=$(echo "$dep_info" | awk -F "@" '{print $1}') + dep_reason=$(echo "$dep_info" | awk -F "@" '{print $2}') + + # Execute ret not zero, will return below error code as failed + eval "$dep_cmd" 1>/dev/null || { + if [[ -z "$dep_reason" ]]; then + REASON="${dep} ${dep_cmd} failed" + else + REASON="${dep}${dep_reason}" + fi + return "$BLOCK_CODE" + } + + return 0 +} + +check_dep_info() { + local dep_infos=$1 + local subfolder=$2 + local dep=$3 + local ret="" + + if [[ -z "$dep_infos" ]]; then + REASON="No dependence for $subfolder" + return "$SKIP_CODE" + fi + + IFS=$'\n' + for dep_info in $dep_infos; do + check_dep_cmd "$dep_info" "$dep" || { + ret=$? + IFS="$(printf ' \t\n')" + return "$ret" + } + done + IFS="$(printf ' \t\n')" +} + +# Don't input any other echo in it +get_ret_status() { + local ret=$1 + + case $ret in + "$PASS_CODE") #0 + echo "$PASS" + ;; + "$BLOCK_CODE") #2 + echo "$BLOCK" + ;; + "$SKIP_CODE") #4 + echo "$SKIP" + ;; + *) + echo "$NA" + ;; + esac +} + +check_dep_feature() { + local cmdfile=$1 + local subfolder="" + local hw_dep_info other_dep_info other_warn_info + local hw_sta other_sta warn_sta + + if [[ "$cmdfile" == *"/"* ]]; then + subfolder=${cmdfile%/*} + else + append_log "cmdfile:$cmdfile(no '/') is not in a subfolder, skip dependence check!" "$LOGFILE" + return "$SKIP_CODE" + fi + + hw_dep_info=$(grep "$MARK_HW_DEP" "$cmdfile" | awk -F "$MARK_HW_DEP" '{print $2}' | sed -e 's/^ *//g') + other_dep_info=$(grep "$MARK_OTHER_DEP" "$cmdfile" | awk -F "$MARK_OTHER_DEP" '{print $2}' | sed -e 's/^ *//g') + other_warn_info=$(grep "$MARK_WARN_DEP" "$cmdfile" | awk -F "$MARK_WARN_DEP" '{print $2}' | sed -e 's/^ *//g') + + check_dep_info "$hw_dep_info" "$subfolder" "$MARK_HW_DEP" + ret=$? + hw_sta=$(get_ret_status "$ret") + [[ "$ret" == "$NA_CODE" || "$ret" == "$BLOCK_CODE" ]] && { + printf "%-16s%-13s%-16s%-13s%-20s\n" "$subfolder" "|$hw_sta" "|$SKIP" "|$SKIP" \ + "|$REASON" >> "$DEP_LOG" + return "$ret" + } + + check_dep_info "$other_dep_info" "$subfolder" "$MARK_OTHER_DEP" + ret=$? + other_sta=$(get_ret_status "$ret") + [[ "$ret" == "$NA_CODE" || "$ret" == "$BLOCK_CODE" ]] && { + printf "%-16s%-13s%-16s%-13s%-20s\n" "$subfolder" "|$hw_sta" "|$other_sta" "|$SKIP" \ + "|$REASON" >> "$DEP_LOG" + return "$ret" + } + + # It's a warning, will not block the subfolder test cases + check_dep_info "$other_warn_info" "$subfolder" "$MARK_WARN_DEP" + ret=$? + warn_sta=$(get_ret_status "$ret") + # warn_sta does not set the block, just NA to fail in some cases of this feature + [[ "$ret" == "$BLOCK_CODE" ]] && warn_sta="$NA" + + [[ -z "$REASON" ]] && REASON="No dependence for $subfolder" + printf "%-16s%-13s%-16s%-13s%-20s\n" "$subfolder" "|$hw_sta" "|$other_sta" "|$warn_sta" \ + "|$REASON" >> "$DEP_LOG" + return 0 +} + runtest() { local cmdline=$1 local logfile=$2 @@ -45,11 +225,7 @@ runtest() { local result local case_result="" - if [[ -n "$logfile" ]]; then - echo "<<>" | tee -a "$logfile" - else - echo "<<>" - fi + append_log "<<>" "$logfile" if [[ -z "$subfolder" ]]; then echo "LKVS tests: $cmdline" >> /dev/kmsg @@ -74,26 +250,23 @@ runtest() { set +o pipefail case $code in - 0) - result="PASS" + "$PASS_CODE") + result="$PASS" ;; - 2) - result="BLOCK" + "$BLOCK_CODE") + result="$BLOCK" ;; - 32) - result="NA" + "$NA_CODE") + result="$NA" ;; *) - result="FAIL" + result="$FAIL" ;; esac - if [[ -n "$logfile" ]]; then - echo -e "<<>\n" | tee -a "$logfile" - else - echo -e "<<>\n" - fi - case_result=$(printf "[RESULT]%-68s%-11s%-12s%-8s" "[$cmdline]" " [$result]" "[$code]" "[${duration}s]") + append_log "<<>\n" "$logfile" + case_result=$(printf "[RESULT]%-68s%-11s%-12s%-8s" "[$cmdline]" " [$result]" "[$code]" \ + "[${duration}s]") echo "$case_result" >> "$SUMMRY_LOG" } @@ -108,7 +281,7 @@ runcmdfile() { if [[ "$cmdfile" == *"/"* ]]; then subfolder=${cmdfile%/*} else - echo "cmdfile:$cmdfile(no '/') is not in a subfolder!" + append_log "cmdfile:$cmdfile(no '/') is not in a subfolder!" "$logfile" fi grep -v "^#.*" "$cmdfile" | grep -v "^$" > "$TEST_LIST_FILE" @@ -126,9 +299,9 @@ prepare_files_list() { local sub_folder="" for sub_folder in $SUB_FOLDERS; do - # Remov the / in the end + # Remove the / in the end sub_folder="${sub_folder%/}" - [[ "$sub_folder" == "common" ]] && continue + [[ "$sub_folder" == "common" || "$sub_folder" == "tools" ]] && continue if [[ -e "${sub_folder}/${test_file_type}" ]]; then if [[ -z "$TEST_FILES" ]]; then @@ -143,7 +316,7 @@ prepare_files_list() { TEST_FILES="${TEST_FILES},${sub_folder}/tests" fi else - echo "WARNING: No $test_file_type or tests file under $sub_folder folder." + append_log "WARNING: No $test_file_type or tests file under $sub_folder folder." "$LOGFILE" fi done } @@ -156,10 +329,56 @@ test_all() { prepare_files_list "$test_file_type" CMDFILES="$TEST_FILES" - if [[ -z "$LOGFILE" ]]; then - echo "Test files: $CMDFILES" - else - echo "Test files: $CMDFILES" | tee "$LOGFILE" + append_log "Test files: $CMDFILES" "$LOGFILE" +} + +show_result() { + # Add the following print for the end of the case summary. + echo "--------------------------------------------------------" >> "$SUMMRY_LOG" + + [[ -z "$LOGFILE" ]] || cat "$SUMMRY_LOG" >> "$LOGFILE" + cat "$SUMMRY_LOG" + echo "Dependence info in $DEP_LOG and runtests log in $LOGFILE" +} + +# runtests_cleanup to show test result. TODO: restore the env if needed +runtests_cleanup() { + show_result + exit 0 +} + +run_tests() { + if [[ -z "$CMDFILES" ]] && [[ -z "$CMDLINE" ]]; then + usage + err "no test to run!" + fi + + cat /dev/null > "$LOGFILE" + + START_TIME="$(date +%Y-%m-%d_%H-%M-%S)" + SUMMRY_LOG="/tmp/lkvs_${START_TIME}_summary.log" + echo "Test Start Time: $START_TIME" > "$SUMMRY_LOG" + { + echo "--------------------------------------------------------" + printf "%-76s%-11s%-12s%-8s\n" "Testcase" "Result" "Exit Value" "Duration" + printf "%-76s%-11s%-12s%-8s\n" "--------" "------" "----------" "--------" + } >> "$SUMMRY_LOG" + + init_dep_log "$DEP_LOG" + + for cmdfile in $(tr "," " " <<< "$CMDFILES"); do + check_test_file_legal "$cmdfile" || continue + + check_dep_feature "$cmdfile" || { + append_log "Skip $cmdfile due to dependece, please check $DEP_LOG" "$LOGFILE" + continue + } + + runcmdfile "$cmdfile" "$LOGFILE" + done + + if [[ -n "$CMDLINE" ]]; then + runtest "$CMDLINE" "$LOGFILE" fi } @@ -168,11 +387,27 @@ test_all() { : CMDFILES="" : CMDLINE="" -while getopts ":o:f:c:h" opt; do +while getopts ":o:d:f:c:h" opt; do case "$opt" in o) LOGFILE=$OPTARG ;; + d) + init_dep_log "$DEP_LOG" + CMDFILES=$OPTARG + [[ "$CMDFILES" == "$TESTS_CLIENT" ]] && test_all "$TESTS_CLIENT" + [[ "$CMDFILES" == "$TESTS_SERVER" ]] && test_all "$TESTS_SERVER" + for cmdfile in $(tr "," " " <<< "$CMDFILES"); do + check_test_file_legal "$cmdfile" + + check_dep_feature "$cmdfile" || { + append_log "Skip $cmdfile due to dependece, please check $DEP_LOG" "$LOGFILE" + continue + } + done + cat "$DEP_LOG" + exit 0 + ;; f) CMDFILES=$OPTARG [[ "$CMDFILES" == "$TESTS_CLIENT" ]] && test_all "$TESTS_CLIENT" @@ -196,46 +431,6 @@ while getopts ":o:f:c:h" opt; do esac done -if [[ -z "$CMDFILES" ]] && [[ -z "$CMDLINE" ]]; then - usage - err "no test to run!" -fi - -START_TIME="$(date +%Y-%m-%d_%H-%M-%S)" -SUMMRY_LOG="/tmp/lkvs_${START_TIME}_summary.log" -echo "Test Start Time: $START_TIME" > "$SUMMRY_LOG" -{ - echo "--------------------------------------------------------" - printf "%-76s%-11s%-12s%-8s\n" "Testcase" "Result" "Exit Value" "Duration" - printf "%-76s%-11s%-12s%-8s\n" "--------" "------" "----------" "--------" -} >> "$SUMMRY_LOG" - -for cmdfile in $(tr "," " " <<< "$CMDFILES"); do - if [[ ! -f "$cmdfile" ]]; then - echo "WARNING: $cmdfile not found!" - continue - fi - - [[ $(which file) ]] && { - file_type="" - file_type=$(file "$cmdfile") - [[ "$file_type" == *"text"* ]] || { - echo "WARNING: -f $cmdfile is not a text type file, it's real type:|$file_type|" - echo "Please choose the correct tests file." - usage - continue - } - } - - runcmdfile "$cmdfile" "$LOGFILE" -done - -if [[ -n "$CMDLINE" ]]; then - runtest "$CMDLINE" "$LOGFILE" -fi - -# Add the following print for the end of the case summary. -echo "--------------------------------------------------------" >> "$SUMMRY_LOG" - -[[ -z "$LOGFILE" ]] || cat "$SUMMRY_LOG" >> "$LOGFILE" -cat "$SUMMRY_LOG" +trap runtests_cleanup SIGTERM SIGINT +run_tests +runtests_cleanup