# # Reports generator funcitons lives here # # List of xfstests's enviroment variables to include reports ## TODO automate list population inside common/conf REPORT_ENV_LIST=("SECTION" "FSTYP" "PLATFORM" "MKFS_OPTIONS" "MOUNT_OPTIONS" \ "HOST_OPTIONS" "CHECK_OPTIONS" "XFS_MKFS_OPTIONS" \ "TIME_FACTOR" "LOAD_FACTOR" "TEST_DIR" "TEST_DEV" \ "SCRATCH_DEV" "SCRATCH_MNT" "OVL_UPPER" "OVL_LOWER" "OVL_WORK") # Variables that are captured in the report /if/ they are set. REPORT_ENV_LIST_OPT=("TAPE_DEV" "RMT_TAPE_DEV" "FSSTRESS_AVOID" "FSX_AVOID" "KCONFIG_PATH" "PERF_CONFIGNAME" "MIN_FSSIZE" "IDMAPPED_MOUNTS") encode_xml() { cat -v | \ sed -e 's/&/\&/g' \ -e 's/>/\>/g' \ -e 's//]]]]>/g' } # Fill out REPORT_VARS with information about the block device referred to by # the passed-in bash variable. __generate_blockdev_report_vars() { local bdev_var="$1" local bdev="${!bdev_var}" test -z "$bdev" && return test -b "$bdev" || return local sysfs_bdev="$(_sysfs_dev "$bdev")" REPORT_VARS["${bdev_var}_SIZE_KB"]="$(( "$(blockdev --getsz "$bdev")" / 2 ))" REPORT_VARS["${bdev_var}_ROTATIONAL"]="$(cat "$sysfs_bdev/queue/rotational" 2>/dev/null)" REPORT_VARS["${bdev_var}_DAX"]="$(cat "$sysfs_bdev/queue/dax" 2>/dev/null)" REPORT_VARS["${bdev_var}_DISCARD"]="$(sed -e 's/[1-9][0-9]*/1/g' "$sysfs_bdev/queue/discard_max_bytes" 2>/dev/null)" REPORT_VARS["${bdev_var}_WRITE_ZEROES"]="$(sed -e 's/[1-9][0-9]*/1/g' "$sysfs_bdev/queue/write_zeroes_max_bytes" 2>/dev/null)" REPORT_VARS["${bdev_var}_PHYS_BLOCK_BYTES"]="$(cat "$sysfs_bdev/queue/physical_block_size" 2>/dev/null)" REPORT_VARS["${bdev_var}_LBA_BYTES"]="$(cat "$sysfs_bdev/queue/logical_block_size" 2>/dev/null)" REPORT_VARS["${bdev_var}_ZONES"]="$(cat "$sysfs_bdev/queue/nr_zones" 2>/dev/null)" } __import_report_vars() { local fname="$1" while IFS=':' read key value; do REPORT_VARS["${key%% }"]="${value## }" done < "$1" } # Fill out REPORT_VARS with tidbits about our test runner configuration. # Caller is required to declare REPORT_VARS to be an associative array. __generate_report_vars() { test "$REPORT_VARS_FILE" && __import_report_vars "$REPORT_VARS_FILE" REPORT_VARS["ARCH"]="$(uname -m)" REPORT_VARS["KERNEL"]="$(uname -r)" REPORT_VARS["CPUS"]="$(getconf _NPROCESSORS_ONLN 2>/dev/null)" REPORT_VARS["MEM_KB"]="$(grep MemTotal: /proc/meminfo | awk '{print $2}')" REPORT_VARS["SWAP_KB"]="$(grep SwapTotal: /proc/meminfo | awk '{print $2}')" test -n "$SOAK_DURATION" && REPORT_VARS["SOAK_DURATION"]="$SOAK_DURATION" test -e /sys/devices/system/node/possible && \ REPORT_VARS["NUMA_NODES"]="$(cat /sys/devices/system/node/possible 2>/dev/null)" __generate_blockdev_report_vars "TEST_DEV" __generate_blockdev_report_vars "SCRATCH_DEV" # Add per-filesystem variables to the report variable list test "$FSTYP" = "xfs" && __generate_xfs_report_vars [[ "$FSTYP" == ext[0-9]* ]] && __generate_ext4_report_vars # Optional environmental variables for varname in "${REPORT_ENV_LIST_OPT[@]}"; do test -n "${!varname}" && REPORT_VARS["${varname}"]="${!varname}" done } # # Xunit format report functions _xunit_add_property() { local name="$1" local value="$2" test -z "$value" && return local xname="$(echo "$name" | encode_xml)" local xvalue="$(echo "$value" | encode_xml)" echo -e "\t\t" } _xunit_make_section_report() { # xfstest:section ==> xunit:testsuite local sect_name="$1" local tests_count="$2" local bad_count="$3" local notrun_count="$4" local sect_time="$5" local timestamp local tmp_fn="$REPORT_DIR/result.xml.new" local out_fn="$REPORT_DIR/result.xml" if [ $sect_name == '-no-sections-' ]; then sect_name='global' fi local report=$tmp.report.xunit.$sect_name.xml rm -f "$tmp_fn" # Header echo "" > "$tmp_fn" if [ -n "$test_start_time" ]; then timestamp="$(date -Iseconds --date="$test_start_time")" else timestamp="$(date -Iseconds)" fi local fstests_ns="https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git" cat >> "$tmp_fn" << ENDL ENDL declare -A REPORT_VARS __generate_report_vars # Properties echo -e "\t" >> "$tmp_fn" (for key in "${!REPORT_VARS[@]}"; do _xunit_add_property "$key" "${REPORT_VARS["$key"]}" done; for p in "${REPORT_ENV_LIST[@]}"; do _xunit_add_property "$p" "${!p}" done) | sort >> "$tmp_fn" echo -e "\t" >> "$tmp_fn" if [ -f $report ]; then cat $report >> "$tmp_fn" fi echo "" >> "$tmp_fn" sync "$tmp_fn" && mv "$tmp_fn" "$out_fn" echo "Xunit report: $out_fn" } _xunit_make_testcase_report() { local sect_name="$1" local test_name="$2" local test_status="$3" local test_time="$4" local report_format="$5" local quiet if [ "$report_format" = xunit-quiet ]; then quiet=yes fi # TODO: other places may also win if no-section mode will be named like 'default/global' if [ $sect_name == '-no-sections-' ]; then sect_name='global' fi local report=$tmp.report.xunit.$sect_name.xml echo -e "\t" >> $report case $test_status in "pass") ;; "notrun") local notrun_file="${REPORT_DIR}/${test_name}.notrun" if [ -f "$notrun_file" ]; then local msg=`cat "$notrun_file" | encode_xml` echo -e "\t\t" >> $report else echo -e "\t\t" >> $report fi ;; "list") echo -e "\t\t" >> $report ;; "fail") local out_src="${SRC_DIR}/${test_name}.out" local full_file="${REPORT_DIR}/${test_name}.full" local dmesg_file="${REPORT_DIR}/${test_name}.dmesg" local outbad_file="${REPORT_DIR}/${test_name}.out.bad" if [ -z "$_err_msg" ]; then _err_msg="Test $test_name failed, reason unknown" fi echo -e "\t\t" >> $report if [ -z "$quiet" -a -s "$full_file" ]; then echo -e "\t\t" >> $report printf '>$report cat "$full_file" | tr -dc '[:print:][:space:]' | encode_cdata >>$report printf ']]>\n' >>$report echo -e "\t\t" >> $report fi if [ -z "$quiet" -a -f "$dmesg_file" ]; then echo -e "\t\t" >> $report printf '>$report cat "$dmesg_file" | tr -dc '[:print:][:space:]' | encode_cdata >>$report printf ']]>\n' >>$report echo -e "\t\t" >> $report fi if [ -z "$quiet" -a -s "$outbad_file" ]; then echo -e "\t\t" >> $report printf '>$report $diff "$out_src" "$outbad_file" | encode_cdata >>$report printf ']]>\n' >>$report echo -e "\t\t" >> $report fi ;; *) echo -e "\t\t" >> $report ;; esac echo -e "\t" >> $report } # # Common report generator entry points _make_section_report() { local sect_name="$1" local tests_count="$2" local bad_count="$3" local notrun_count="$4" local sect_time="$5" for report in $REPORT_LIST; do case "$report" in "xunit"|"xunit-quiet") _xunit_make_section_report "$sect_name" "$tests_count" \ "$bad_count" "$notrun_count" \ "$sect_time" ;; *) _dump_err "format '$report' is not supported" ;; esac done } _make_testcase_report() { local sect_name="$1" local test_seq="$2" local test_status="$3" local test_time="$4" for report in $REPORT_LIST; do case "$report" in "xunit"|"xunit-quiet") _xunit_make_testcase_report "$sect_name" "$test_seq" \ "$test_status" "$test_time" "$report" ;; *) _dump_err "report format '$report' is not supported" ;; esac done } _assert_report_list() { for report in $REPORT_LIST; do case "$report" in "xunit"|"xunit-quiet") ;; *) _fatal "report format '$report' is not supported" ;; esac done }