#! /bin/bash
# ====================================================================
#
# tapper-autoreport
# -----------------
#
# This is the "tapper-autoreport" bash utility -- a bash include file
# that you include ("source") at the end of your own bash script.
#
# It then magically turns your bash script into a Tapper test suite.
#
# It collects meta information from system, reports test results via
# network and uploads files.
#
# It also allows your bash script to be used with the "prove" command,
# a tool to run test scripts that produce TAP output (Test Anything
# Protocol).
#
# It is licensed under a 2-clause BSD license. See the LICENSE file.
#
# ====================================================================
# ==================== Utility functions =============================
# constants
_SUCCESS=0
_FAILURE=1
# gets vendor "AMD" or "Intel" from /proc/cpuinfo
get_vendor () {
vendor=$(echo $(grep vendor_id /proc/cpuinfo |head -1|cut -d: -f2|sed -e "s/Genuine\|Authentic//"))
echo $vendor
}
# checks for vendor "Intel" in /proc/cpuinfo
vendor_intel () {
grep -Eq 'vendor_id.*:.*Intel' /proc/cpuinfo
}
# checks for vendor "AMD" in /proc/cpuinfo
vendor_amd () {
grep -Eq 'vendor_id.*:.*AMD' /proc/cpuinfo
}
# stops testscript if not matching required cpu vendor
require_vendor_intel () {
if vendor_intel
then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok 0 "require_vendor_intel" ; fi
return $_SUCCESS
else
explanation="${1:-vendor does not match Intel}"
autoreport_skip_all "$explanation"
fi
}
# stops testscript if not matching required cpu vendor
require_vendor_amd () {
if vendor_amd
then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok 0 "require_vendor_amd" ; fi
return $_SUCCESS
else
explanation="${1:-vendor does not match AMD}"
autoreport_skip_all "$explanation"
fi
}
# Checks for ARM cpu
arm_cpu () {
grep -Eqi 'Processor.*:.*ARM' /proc/cpuinfo
}
# outputs cpu stepping from /proc/cpuinfo
get_cpu_stepping () {
echo $(echo $(grep "^stepping" /proc/cpuinfo |head -1|cut -d: -f2))
}
# outputs cpu model from /proc/cpuinfo
get_cpu_model () {
echo $(echo $(grep "^model[^ ]" /proc/cpuinfo |head -1|cut -d: -f2))
}
# outputs cpu model from /proc/cpuinfo
get_cpu_model_hex () {
echo "0x"$(get_hex_from_int $(get_cpu_model))
}
# checks cpu model from /proc/cpuinfo against a minimum model
cpu_model_min () {
min=${1:-0}
mod=$(get_cpu_model)
[ $(($mod)) -ge $(($min)) ]
}
# checks cpu model from /proc/cpuinfo against a maximum model
cpu_model_max () {
max=${1:-0x999}
mod=$(get_cpu_model)
[ $(($mod)) -le $(($max)) ]
}
# outputs cpu family from /proc/cpuinfo
# since all testsuites using hex values, return value in hex format
get_cpu_family () {
echo $(echo $(grep "^cpu family" /proc/cpuinfo |head -1|cut -d: -f2))
}
get_cpu_family_hex () {
echo "0x"$(get_hex_from_int $(get_cpu_family))
}
# checks cpu family from /proc/cpuinfo against a minimum family
cpu_family_min () {
min=${1:-0}
fam=$(get_cpu_family)
[ $(($fam)) -ge $(($min)) ]
}
# checks cpu family from /proc/cpuinfo against a maximum family
cpu_family_max () {
max=${1:-0x999}
fam=$(get_cpu_family)
[ $(($fam)) -le $(($max)) ]
}
is_amd_family_range () {
min="${1:-0}"
max="${2:-$min}"
if vendor_amd && cpu_family_min "$min" && cpu_family_max "$max" ; then
return $_SUCCESS
else
return $_FAILURE
fi
}
# stops testscript if not matching required cpu family from
# /proc/cpuinfo of a minimum/maximum range
require_amd_family_range () {
min="${1:-0}"
max="${2:-$min}"
if is_amd_family_range "$min" "$max" ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok 0 "require_amd_family_range $min $max" ; fi
return $_SUCCESS
else
vendor=$(get_vendor);
fam=$(printf "0x%x" $(get_cpu_family));
explanation="${3:-Family $vendor/$fam does not match AMD/$min..$max}"
autoreport_skip_all "$explanation"
fi
}
# Checks all nodes for NB devices with one of the supplied PCI device ids
# Note: Call it separately for different PCI device functions
has_amd_nb_function_id () {
devids=${@:-"0xffffffff"}
for devid in $devids; do
devid=$(printf '0x%x' $devid)
nbdevs="/sys/bus/pci/devices/0000:00:1[89abcdef].*"
[ $(ls $nbdevs 2>/dev/null | wc -l) -gt 0 ] || continue
f0devs="/sys/bus/pci/devices/0000:00:1[89abcdef].0/vendor"
northbridges=$(ls $f0devs 2>/dev/null | wc -l)
devices=0
for nbdev in $nbdevs; do
vendor=$(cat $nbdev/vendor 2>/dev/null)
if [ "$vendor" != "0x1022" ]; then
return $_FAILURE
fi
device=$(cat $nbdev/device 2>/dev/null)
if [ "$device" = "$devid" ]; then
let devices++
fi
done
if [ $devices -gt 0 -a $devices -eq $northbridges ]; then
return $_SUCCESS
fi
done
return $_FAILURE
}
# Stops if no NB devices with one of supplied PCI device ids exist on all nodes
# Note: Call it separately for different PCI device functions
require_amd_nb_function_id () {
devids=${@:-"0xffffffff"}
if has_amd_nb_function_id "$devids"; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_amd_nb_function_id" ; fi
else
autoreport_skip_all "No supported AMD northbridge function devices"
fi
}
get_number_cpus () {
(getconf _NPROCESSORS_ONLN || grep -ci "^bogomips" /proc/cpuinfo || echo -1) 2>/dev/null
}
# check sysfs whether cpu has L3 cache
has_l3cache () {
if [ -d /sys/devices/system/cpu/cpu0/cache/index3 ] ; then
return $_SUCCESS
else
return $_FAILURE
fi
}
# stops testscript if cpu does not have L3 cache
require_l3cache () {
explanation="${1:-No L3 cache}"
if has_l3cache ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_l3cache" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# check x86_64
is_x86_64 () {
if uname -m | grep -q x86_64 ; then
return $_SUCCESS
else
return $_FAILURE
fi
}
# stops testscript if is not x86_64
require_x86_64 () {
explanation="${1:-No x86_64}"
if is_x86_64 ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_x86_64" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# scan all PCI devices for one with XenSource's PCI-ID
has_xen_pci_device() {
# try lspci (not in PATH if not root)
_ta_xen_LSPCI=$(which lspci 2> /dev/null) || _ta_xen_LSPCI=/sbin/lspci
if [ -x "$_ta_xen_LSPCI" ]
then
$_ta_xen_LSPCI -n | grep -q " 5853:"
return $?
else
# directly query sysfs and check for XenSource's PCI-ID
if [ -r /sys/bus/pci/devices/0000:00:00.0/vendor ] ; then
cat /sys/bus/pci/devices/*/vendor | grep -q 0x5853
return $?
else
return $_FAILURE
fi
fi
}
# checks the PCI hostbridge's vendor and optionally device ID
# usage: check_hostbridge 0x1022 (for checking for AMD northbridge)
# check_hostbridge 0x8086 0x1237 (for QEMU host bridge)
check_hostbridge() (
LSPCI=$(which lspci 2> /dev/null) || LSPCI=/sbin/lspci
if [ -x "$LSPCI" ]
then
lspciout=$($LSPCI -s 0:0.0 -n | cut -d: -f3- | tr -d \ )
vendor="0x$(echo $lspciout | cut -d: -f1)"
device="0x$(echo $lspciout | cut -d: -f2)"
else
vendor=$(cat /sys/bus/pci/devices/0000:00:00.0/vendor)
device=$(cat /sys/bus/pci/devices/0000:00:00.0/device)
fi
[ "$vendor" = "$1" ] || return $_FAILURE
[ -z "$2" ] && return $_SUCCESS
[ "$device" = "$2" ]
return $?
)
# checks whether the Xen hypervisor is running
# this returns 0 if we are a Dom0 or PV DomU or HVM DomU
is_running_under_xen_hv () {
if [ -r /sys/hypervisor/type ] ; then
[ $(cat /sys/hypervisor/type) = "xen" ]
return $?
fi
[ -r /proc/xen/capabilities ] && return $_SUCCESS
# Linux denies registering XenFS if not running under Xen
if has_kernel_config CONFIG_XENFS ; then
grep -q xenfs /proc/filesystems
return $?
fi
# TODO: do older kernels support this? At least RHEL5 does
has_cpufeature hypervisor || return $_FAILURE
_ta_e820prov=$(dmesg | sed -e 's/^\[.*\] *//' | grep -A1 "^BIOS-provided physical RAM map:" | tail -1 | cut -d: -f1)
[ -n "$_ta_820prov" ] && [ "$_ta_e820prov" = "Xen" ] && return $_SUCCESS
dmesg | grep -q "Booting paravirtualized kernel on Xen" && return $_SUCCESS
return $_FAILURE
}
# check if we are in a Xen host
# it is a bit tricky to differentiate Dom0 and (PV-)DomU
is_running_in_xen_dom0 () {
# this is a definite way to check for Dom0, but not always available, since
# XENFS could not be mounted
if [ -r /proc/xen/capabilities ] ; then
grep -q control_d /proc/xen/capabilities
return $?
fi
# this should sort out most of the other possibilities
is_running_under_xen_hv || return $_FAILURE
# we need to sort out only Dom0 vs. DomU from now on
# an ATI or AMD northbridge means Dom0
if check_hostbridge 0x1002 || check_hostbridge 0x1022 ; then
return $_SUCCESS
fi
# a QEMU northbridge cannot be Dom0
check_hostbridge 0x8086 0x1237 && return $_FAILURE
# out of clues, but we are probably not Dom0 at this point anymore
return $_FAILURE
}
# check if we are in a KVM host
is_running_in_kvm_host () {
[ -e /dev/kvm ]
}
# check if we have KVM guests running
has_kvm_guests () {
counter=$(lsmod |grep '^kvm_'|awk '{print $3}')
if [ $counter -gt 0 ] ; then
return $_SUCCESS
else
return $_FAILURE
fi
}
get_xen_tool() {
which xl 2> /dev/null || which xm 2> /dev/null
}
get_number_xen_guests() {
XL=$(get_xen_tool) || return $_FAILURE
res=$($XL list | wc -l)
if [ -n "$res" -a "$res" -ge 2 ] ; then
echo "$((res-2))"
return $_SUCCESS
else
echo "0"
return $_FAILURE
fi
}
# check if we are in a Xen guest
# Note:
# In Xen the dom0 reports the same 'hypervisor' flag and CPUID entry
# as in domU therefore the CPUID check is not enough, but dmidecode
# and lspci show different devices inside a domU.
is_running_in_xen_guest () {
is_running_under_xen_hv || return $_FAILURE
has_xen_pci_device && return $_SUCCESS
check_hostbridge 0x8086 0x1237 && return $_SUCCESS
# try dmidecode
if dmidecode > /dev/null 2>&1 ; then
_dmi_chassis=$(dmidecode -s chassis-manufacturer)
# dmidecode does not output anything in PV Xen
if [ -n "$_dmi_chassis" ] ; then
echo "$_dmi_chassis" | grep -q Xen
return $?
fi
fi
# last resort: check for Xen Dom0
is_running_in_xen_dom0 && return $_FAILURE
# there are no PCI device by default in PV guests
_nr_pci_devices=$(ls /sys/bus/pci/devices | wc -l)
[ "$_nr_pci_devices" -eq 0 ] && return $_SUCCESS
# no more clues at this point, assume we are some kind of DomU
return $_SUCCESS
}
# check if we are in a KVM guest
# Note:
# In KVM the hypervisor CPUID check is relieable and we can first
# narrow it against being not a Xen guest. After that the devices
# are less significant in KVM so here we then check for the CPUID.
is_running_in_kvm_guest () {
is_running_in_xen_guest && return $_FAILURE
has_cpufeature hypervisor || return $_FAILURE
# try to load the cpuid module if not already done
[ -c /dev/cpu/0/cpuid ] || modprobe cpuid > /dev/null 2>&1
if [ -c /dev/cpu/0/cpuid ] ; then
virtvendor=$(dd if=/dev/cpu/0/cpuid bs=16 skip=67108864 count=1 2> /dev/null)
[ "$virtvendor" = "KVMKVMKVM" ]
return $?
fi
return 1
}
# check for Tapper automation guest environment
is_running_in_tapper_guest () {
SUCC=1
if [ -n "$TAPPER_GUESTNUMBER" ] ; then
if [ $TAPPER_GUESTNUMBER -gt 0 ] ; then
SUCC=0
fi
fi
return $SUCC
}
# check if we are in a virtualized guest (Xen or KVM)
# Note:
# We could combine the _tapper_guest checking in here but I wanted
# to keep the "real detection" separated from the "artificial
# definition" that TAPPER_* environment variables represent.
is_running_in_virtualized_guest () {
is_running_in_xen_guest || is_running_in_kvm_guest
return $?
}
# stops testscript if we aren't a Xen guest
require_running_in_xen_guest () {
explanation="${1:-Needs to run in Xen guest}"
if is_running_in_xen_guest ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_running_in_xen_guest" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# stops testscript if we aren't a Xen dom0
require_running_in_xen_dom0 () {
explanation="${1:-Needs to run in Xen dom0}"
if is_running_in_xen_dom0 ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_running_in_xen_dom0" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# stops testscript if we aren't a KVM guest
require_running_in_kvm_guest () {
explanation="${1:-Needs to run in KVM guest}"
if is_running_in_kvm_guest ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_running_in_kvm_guest" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# stops testscript if we aren't a KVM host
require_running_in_kvm_host () {
explanation="${1:-Needs to run in KVM host}"
if is_running_in_kvm_host ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_running_in_kvm_host" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# stops testscript if we aren't a virtualized guest
require_running_in_virtualized_guest () {
explanation="${1:-Needs to run in virtualized guest}"
if is_running_in_virtualized_guest ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_running_in_virtualized_guest" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# stops testscript if we aren't a Tapper automation guest environment
require_running_in_tapper_guest () {
explanation="${1:-Needs to run in Tapper guest}"
if is_running_in_tapper_guest ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_running_in_tapper_guest" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# checks for a feature flag in /proc/cpuinfo
has_cpufeature () {
_ta_feature="${1:-UNKNOWNFEATURE}"
if cat /proc/cpuinfo | grep -E '^flags\W*:' | head -1 | sed -e 's/^flags\W*://' | grep -q "\<${_ta_feature}\>" 2>&1 ; then
return $_SUCCESS
else
return $_FAILURE
fi
}
# stops testscript if a feature flag is not found in /proc/cpuinfo
require_cpufeature () {
_ta2_feature="${1:-UNKNOWNFEATURE}"
explanation="${2:-Missing cpufeature $_ta2_feature}"
if has_cpufeature "$_ta2_feature" ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_cpufeature $_ta2_feature" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# checks for a config in /proc/config.gz or /boot/config/$(uname -r)
has_kernel_config () {
_ta3_feature="${1:-UNKNOWNFEATURE}"
CONFIG=$(get_first_file "/proc/config.gz" "/boot/config-$(uname -r)")
if [ -z "$CONFIG" ] ; then
return $_FAILURE
fi
if echo $CONFIG | grep -q '\.gz' ; then
gzip -cd "$CONFIG" | grep -q "^${_ta3_feature}=."
else
grep -q "^${_ta3_feature}=." "$CONFIG"
fi
}
# stops testscript if a feature flag is not found in /proc/cpuinfo
require_kernel_config () {
_ta4_feature="${1:-UNKNOWNFEATURE}"
explanation="${2:-Missing kernel config $_ta4_feature}"
if has_kernel_config "$_ta4_feature" ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_kernel_config $_ta4_feature" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# checks for availability of kernel sources
has_kernel_sources () {
if [ -e /lib/modules/`uname -r`/build ]; then
return $_SUCCESS
else
return $_FAILURE
fi
}
# stops testscript if kernel sources aren't available
require_kernel_sources () {
explanation="${1:-Missing kernel sources}"
if has_kernel_sources ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_kernel_sources" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# prepares kernel sources
prepare_kernel_sources () {
if [ -d /usr/src/linux ]; then
cd /usr/src/linux
make oldconfig prepare modules_prepare >/dev/null
cd - >/dev/null
fi
}
# Enable CPU frequency scaling and set sane defaults
# - Makes sure the appropriate cpufreq driver is loaded
# - Enables ondemand governor on all cores
# - Sets the boost state, on=1 (default), off=0
enable_cpufreq () {
booststate="$1"
[ "$booststate" != "0" ] && booststate=1
# Load cpufreq driver module
for module in acpi-cpufreq powernow-k8; do
[ -d /sys/devices/system/cpu/cpu0/cpufreq ] && break
modprobe $module 2>/dev/null
done
if [ ! -d /sys/devices/system/cpu/cpu0/cpufreq ]; then
echo "failed to load cpufreq driver"
return $_FAILURE
fi
# Load ondemand governor module and set ondemand governor
if ! grep -q ondemand /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors; then
modprobe cpufreq-ondemand 2>/dev/null
fi
for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
echo ondemand > $cpu 2>/dev/null
if [ "$(cat $cpu)" != "ondemand" ]; then
echo "failed to set ondemand governor"
return $_FAILURE
fi
done
# Set requested boost state
if ! has_cpufeature cpb; then
return $_SUCCESS
elif [ -f /sys/devices/system/cpu/cpufreq/boost ]; then
interfaces="/sys/devices/system/cpu/cpufreq/boost"
elif [ $(ls /sys/devices/system/cpu/cpu*/cpufreq/cpb 2>/dev/null | wc -l) -gt 0 ]; then
interfaces="/sys/devices/system/cpu/cpu*/cpufreq/cpb"
elif grep -q " show_cpb\| show_global_boost" /proc/kallsyms; then
echo "failed to find sysfs boost state interface"
return $_FAILURE
elif [ $booststate -eq 0 ]; then
echo "cpufreq driver doesn't provide sysfs boost state interface"
return $_FAILURE
else
return $_SUCCESS
fi
for interface in $interfaces; do
echo $booststate > $interface 2>/dev/null
if [ "$(cat $interface)" != "$booststate" ]; then
echo "failed to set requested boost state"
return $_FAILURE
fi
done
return $_SUCCESS
}
require_cpufreq_enabled () {
explanation="${1:-CPUFreq not available}"
reason=$(enable_cpufreq 1)
if [ $? -eq $_SUCCESS ] ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_cpufreq_enabled" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation ($reason)"
fi
}
require_cpb_disabled () {
explanation="${1:-Failed to disable Core Boosting}"
reason=$(enable_cpufreq 0)
if [ $? -eq $_SUCCESS ] ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_cpufreq_enabled" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation ($reason)"
fi
}
request_cpufreq_enabled () {
todo="# TODO $(enable_cpufreq 1)" && todo=""
ok $? "request_cpufreq_enabled $todo"
[ -n "$todo" ] && return $_FAILURE
return $_SUCCESS
}
request_cpb_disabled () {
todo="# TODO $(enable_cpufreq 0)" && todo=""
ok $? "request_cpb_disabled $todo"
[ -n "$todo" ] && return $_FAILURE
return $_SUCCESS
}
# disables core performance boosting for reproducable and well scaling
# benchmarks. Tries hard to learn the actual state and to really disable
# it. Diagnostic messages will be print to stdout, the return value
# describes the success: 0=CPB is disabled, 1=CPB is (probably) still enabled.
# possible usage (failed disabling is non-fatal, but report it):
# todostem="# TODO "
# expl=$(disable_cpb) && todostem=""
# ok $? "disable CPB $todostem$expl"
# or a fatal version ending the script:
# expl=$(disable_cpb)
# require_ok $? "disable CPB"
# or: just try to disable it, but don't care if we fail
# disable_cpb > /dev/null
disable_cpb() {
# check whether the CPB sysfs knob is there
if [ ! -r /sys/devices/system/cpu/cpu0/cpufreq/cpb ] ; then
is_running_in_virtualized_guest && _cpbhint=" (running virtualized)"
# if the CPU does not support boosting, we dont care
if ! has_cpufeature cpb ; then
echo "# CPU has no CPB support$_cpbhint"
return 0
fi
# is the powernow_k8 driver loaded?
if ! grep -q " powernowk8_init" /proc/kallsyms; then
# if not, try to load it
if ! _modprobe_res=$(modprobe powernow_k8 2>&1) ; then
echo "# modprobe powernow_k8: $_modprobe_res"
return 1
fi
fi
# does this version of powernow_k8 support CPB?
if ! grep -q " show_cpb" /proc/kallsyms ; then
echo "# powernow_k8 loaded, but no CPB support"
return 1
fi
fi
# now check for the sysfs knob again (we may have loaded the driver)
if [ ! -r /sys/devices/system/cpu/cpu0/cpufreq/cpb ] ; then
echo "# no sysfs knob for disabling CPB, probably still active"
return 1
fi
# if the knob is there and it reads 0, everything is fine
if [ $(cat /sys/devices/system/cpu/cpu0/cpufreq/cpb) = "0" ] ; then
echo "# CPB already disabled"
return 0
fi
# try to disable CPB on all cores and count the number of failures
failures=0
for cpb in /sys/devices/system/cpu/cpu*/cpufreq/cpb; do
echo 0 2> /dev/null > $cpb || let failures++
done
# no failures means everything is fine
if [ "$failures" = 0 ] ; then
echo "# CPB successfully disabled"
return 0
fi
# don't give up so quickly, try to explore dmesg for the right message
if $(dmesg | grep -q "Core Boosting .*abled") ; then
# there was at least one messages, check the last one
if dmesg | grep -q "Core Boosting .*abled" | tail -1 | grep -q "Core Boosting disabled" ; then
# the last message says its disabled, believe this
echo "# CPB disabling failed, but probably disabled before"
return 0
else
# the last message says its enabled, we failed eventually
echo "# CPB disabling failed (no permissions), CPB active"
return 1
fi
fi
# we have no real clue at this point, but assume the worst
echo "# CPB disabling failed, probably still active"
return 1
}
# checks whether the cpbdisable file exists in sysfs
has_cpbdisable () {
# This file's existence is not the best check.
# It also exists on non-cpb systems.
if [ -e /sys/devices/system/cpu/cpu0/cpufreq/cpb ] ; then
return $_SUCCESS
else
return $_FAILURE
fi
}
# stops testscript if the cpbdisable file does not exist in sysfs
require_cpbdisable () {
explanation="${1:-No CPB disable}"
if has_cpbdisable ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_cpbdisable" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# checks whether the module is ther
has_module () {
module="${1:-UNKNOWNMODULE}"
if lsmod | grep -q "^$module\b" ; then
return $_SUCCESS
else
return $_FAILURE
fi
}
# stops testscript if the cpbdisable file does not exist in sysfs
require_module () {
module="${1:-UNKNOWNMODULE}"
explanation="${2:-No module $module disable}"
if has_module "$module"; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_module" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# checks whether the program is available
has_program () {
program="${1:-UNKNOWNPROGRAM}"
if which "$program" > /dev/null 2>&1 ; then
return $_SUCCESS
else
return $_FAILURE
fi
}
# stops testscript if program not available
require_program () {
program="${1:-UNKNOWNPROGRAM}"
explanation="${2:-Missing program $program}"
if has_program "$program" ; then
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# checks whether the file is available
has_file () {
file="${1:-UNKNOWNFILE}"
explanation="${2:-Missing file $file}"
if [ -e "$file" ] ; then
return $_SUCCESS
else
return $_FAILURE
fi
}
# stops testscript if file not available
require_file () {
file="${1:-UNKNOWNFILE}"
explanation="${2:-Missing file $file}"
if has_file "$file" ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_file $file" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# checks whether the script's criticality is in allowed range
has_crit_level () {
_ta_crit_level="${1:-5}"
_ta_crit_level_allowed="${CRITICALITY:-0}"
if [ $_ta_crit_level -le $_ta_crit_level_allowed ] ; then
return $_SUCCESS;
else
return $_FAILURE
fi
}
# stops testscript if script's criticality is not in allowed range
require_crit_level () {
_ta_crit_level="${1:-5}"
_ta_crit_level_allowed="${CRITICALITY:-0}"
explanation="${2:-Too high criticality level: $_ta_crit_level (CRITICALITY=$_ta_crit_level_allowed)}"
if has_crit_level $_ta_crit_level ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "criticality level $_ta_crit_level (CRITICALITY=$_ta_crit_level_allowed)" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
# stops testscript if netcat not available
require_netcat () {
explanation="${2:-Missing program netcat}"
if has_program "netcat" ; then
return $_SUCCESS
elif has_program "nc" ; then
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
require_root () {
explanation="${1:-Need to run as root}"
ID=$(id|cut -d" " -f1|cut -d= -f2|cut -d\( -f1)
if [ "x$ID" == "x0" ] ; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_root" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
get_first_file () {
for i in $(seq 1 $#) ; do
file=${!i}
if [ -r "$file" ] ; then
echo "$file"
return
fi
done
}
# checks whether MSRs could be read from userspace
# will try to load the appropriate kernel module if not already done
# will return an error if the file is not readable (not root)
has_msr_access() (
cpu=${1:-0}
if [ ! -e /dev/cpu/$cpu/msr ] ; then
has_program modprobe || return 1
modprobe msr || return 1
fi
[ -r /dev/cpu/$cpu/msr ]
)
# reads a MSR via the /dev/cpu/<n>/msr device
# expects the MSR number (in hex) as the first parameter and optionally the
# CPU number from which to read as the second argument (defaults to 0)
# outputs a 16 char hex value (lower case letters) to stdout
# returns 0 on success, 1 for an invalid MSR and 2 for permission issues
read_msr() (
cpu=${2:-0}
if has_program rdmsr ; then
rdmsr -x -0 -p $cpu "$1" 2> /dev/null
return $?
fi
[ -r /dev/cpu/$cpu/msr ] || return 2
perl -e 'my $msr;sysseek(STDIN,hex($ARGV[0]),0);sysread(STDIN,$msr,8) or exit(1);my @words=unpack("LL",$msr);printf("%08x%08x\n",$words[1],$words[0]);' $1 < /dev/cpu/$cpu/msr
)
# writes a MSR via the /dev/cpu/<n>/msr device
# expects the MSR number (in hex) as the first parameter, the value (in hex)
# is the second one. Optionally the CPU number to use for the write can be
# given as the third argument (defaults to 0)
# returns 0 on success, 1 for an invalid MSR and 2 for permission issues
write_msr() (
[ $# -lt 2 ] && return 3
cpu=${3:-0}
if has_program wrmsr ; then
wrmsr -p $cpu "$1" "$2" 2> /dev/null
return $?
fi
[ -w /dev/cpu/$cpu/msr ] || return 2
low=$(printf "0x%x" $(($2 & (2**32 - 1))))
high=$(printf "0x%x" $((($2 >> 32) & (2**32 - 1))))
perl -e 'my $value=pack("LL",hex($ARGV[1]),hex($ARGV[2]));sysseek(STDOUT,hex($ARGV[0]),0);syswrite(STDOUT,$value,8) or exit(1);' $1 $low $high > /dev/cpu/$cpu/msr
)
# Reads an entire cpuid register
# Usage: get_cpuid_register <leafnr_in_hex> e[abcd]x
# Example: get_cpuid_register 0x80000001 ecx
# Outputs the decimal register value to stdout
# Returns 0 for success, 1 for invalid cpuid leaf, 2 for permission
get_cpuid_register() {
[ $# -lt 2 ] && return 3
cpu=${3:-0}
# try to load the cpuid module if not already done
[ -c /dev/cpu/$cpu/cpuid ] || modprobe cpuid > /dev/null 2>&1
[ -r /dev/cpu/$cpu/cpuid ] || return 2
perl -e 'my $leaf;sysseek(STDIN, hex($ARGV[0]),0);sysread(STDIN,$leaf,16) or exit(1);my @regs=unpack("LLLL",$leaf);printf("%u\n",$regs[ord(substr($ARGV[1],1,1))-ord("a")]);' $1 $2 < /dev/cpu/$cpu/cpuid
}
# Reads a cpuid register and filters a certain bit
# Usage: get_cpuid_bit <leafnr_in_hex> e[abcd]x <bitnr>
# Example: get_cpuid_bit 0x80000001 ecx 2
# Outputs either 0 or 1 to stdout
# Returns 0 for success, 1 for invalid cpuid leaf, 2 for permission
get_cpuid_bit() {
[ $# -lt 3 ] && return 3
cpu=${4:-0}
reg=$(get_cpuid_register $1 $2 $4) || return $?
echo $(($reg >> $3 & 1))
}
# Get a space separated list of CPUs from a sysfs cpumap file
# Example:
# get_cpus_from_cpumap /sys/devices/system/node/node0/cpumap
# 0 1 2 3
# Notes:
# Result may be an empty string
# Result may be -1 in case of parsing errors
get_cpus_from_cpumap () {
cpumap="${1}"
cpus=""
wordcnt=$(cat $cpumap | sed -e 's/,/ /g' | wc -w)
if [ $wordcnt -eq 0 ]; then
echo -1
return
fi
for i in $(seq $wordcnt -1 1); do
offset=$(($wordcnt - $i))
word=$((0x$(cat $cpumap | cut -d , -f $i)))
if [ $? -ne 0 ]; then cpus=-1; break; fi
for j in $(seq 0 31); do
if [ $(($word >> $j & 1 )) -eq 1 ]; then
cpus="$cpus $((32 * $offset + $j))"
fi
done
done
echo $cpus
}
# Get a space separated list of CPUs from a sysfs cpulist file
# Example:
# get_cpus_from_cpulist /sys/devices/system/cpu/online
# 0 1 2 3
# Notes:
# Result may be an empty string
# Result may be -1 in case of parsing errors
get_cpus_from_cpulist () {
cpulist="${1}"
cpus=""
ranges=$(cat $cpulist | sed -e 's/,/ /g')
if [ -z "$ranges" ]; then
echo -1
return
fi
for range in $ranges; do
if echo $range | grep -q '^[0-9]\+-[0-9]\+$'; then
min=$(echo $range | sed 's/-[0-9]\+$//')
max=$(echo $range | sed 's/^[0-9]\+-//')
if [ $min -ge $max ]; then cpus=-1; break; fi
for cpu in $(seq $min $max); do cpus="$cpus $cpu"; done
elif echo $range | grep -q '^[0-9]\+$'; then
cpus="$cpus $range"
else
cpus=-1; break
fi
done
echo $cpus
}
autoreport_skip_all () {
explanation="${1:-'no explanation'}"
SKIPALL="1..0 # skip $explanation"
NOUPLOAD=1
if [[ -n $EXIT_ON_SKIPALL ]]; then
exit 254
else
autoreport_start
exit 0
fi
}
# ==================== TAP utils ====================
get_tap_counter () {
echo ${#TAP[@]}
}
get_tapdata_counter () {
echo ${#TAPDATA[@]}
}
append_tap () {
tapline="${1:-'not ok - unknown TAP line in utility function append_tap'}"
TAP=( "${TAP[@]}" "$tapline" )
}
append_tapdata () {
tapline="${1:-'not ok - unknown TAP line in utility function append_tapdata'}"
TAPDATA=( "${TAPDATA[@]}" "$tapline" )
}
append_comment () {
tapline="# ${@:-''}"
TAP=( "${TAP[@]}" "$tapline" )
COMMENTCOUNTER=$((COMMENTCOUNTER + 1))
}
diag () {
append_comment "${@}"
}
is () {
A="${1:-}"
B="${2:-}"
msg="${3:-unknown}"
if [ "x$A" != "x$B" ] ; then
append_tap "not ok - $msg"
append_comment "Failed test '$msg'"
append_comment "got: '$A'"
append_comment "expected: '$B'"
else
append_tap "ok - $msg"
fi
}
isnt () {
A="${1:-}"
B="${2:-}"
msg="${3:-unknown}"
if [ "x$A" = "x$B" ] ; then
append_tap "not ok - $msg"
append_comment "Failed test '$msg'"
append_comment "got: '$A'"
append_comment "expected: anything else"
else
append_tap "ok - $msg"
fi
}
require_ok () {
success="${1:-0}"
msg="${2:-unknown}"
if [ "$success" != "0" ] ; then
NOT="not "
else
NOT=""
fi
append_tap "${NOT}ok - $msg"
if [ "$success" = "0" ] ; then
return
fi
# similar to SKIPALL but report what we have so far
if [[ -n $EXIT_ON_SKIPALL ]]; then
exit 254
else
autoreport_start
exit 0
fi
}
ok () {
success="${1:-0}"
msg="${2:-unknown}"
if [ "$success" != "0" ] ; then
NOT="not "
else
NOT=""
fi
append_tap "${NOT}ok - $msg"
return $success
}
negate_ok () {
success="${1:-0}"
msg="${2:-unknown}"
if [ "$success" == "0" ] ; then
NOT="not "
else
NOT=""
fi
append_tap "${NOT}ok - $msg"
return $success
}
get_hex_from_int() { # returns lower case
printf "%x\n" "$1"
}
lower_case () {
string="${1:-}"
echo $(echo "$string" | tr '[A-Z]' '[a-z]')
}
get_random_number () {
range_max="${1:-32768}"
number=$RANDOM
let "number %= $range_max"
echo "$number"
}
get_kernel_release_1 () {
uname -r | cut -d. -f1
}
get_kernel_release_2 () {
uname -r | cut -d. -f2
}
get_kernel_release_3 () {
uname -r | cut -d. -f3 | sed -s 's/^\([0-9]*\).*$/\1/'
}
get_kernel_release () {
echo $(uname -r | cut -d. -f1-2).$(get_kernel_release_3)
}
normalize_version_number () {
A="${1:-0}"
# triplets x.y.z are converted to x + y/thousands + z/millions
# easier, but requires awk:
# awk -F. '{printf ("%d.%03d%03d\n",$1,$2,$3);}'
# we have to do a trick do avoid octal interpretation due to leading
# zeros, we use $((10#<number>)), which overrides with a base of 10
if echo $A | grep -q '\.' ; then
printf "%d.%03d%03d\n" $((10#$(echo "$A" | cut -d. -f1))) $((10#$(echo "$A" | cut -d. -f2))) $((10#$(echo "$A" | cut -d. -f3)))
else
echo "$A.000000"
fi
}
version_number_compare () {
A="${1:-0}"
COMPARATOR="${2:-'-eq'}"
B="${3:-0}"
An=$(normalize_version_number $A | tr -d .)
Bn=$(normalize_version_number $B | tr -d .)
test "$An" $COMPARATOR "$Bn"
}
version_number_gt () {
A="${1:-0}"
B="${2:-0}"
return $(version_number_compare "$A" -gt "$B")
}
version_number_ge () {
A="${1:-0}"
B="${2:-0}"
return $(version_number_compare "$A" -ge "$B")
}
version_number_lt () {
A="${1:-0}"
B="${2:-0}"
return $(version_number_compare "$A" -lt "$B")
}
version_number_le () {
A="${1:-0}"
B="${2:-0}"
return $(version_number_compare "$A" -le "$B")
}
has_kernel_release_min () {
_ta_autoreport_v="${1:-0}"
version_number_compare $(get_kernel_release) -gt $_ta_autoreport_v
}
has_kernel_release_min_1 () {
# check if current LK 1st level release number is greater or equal release_req
release_req="${1:-}"
[ "$release_req" -ne $(echo $release_req|sed -e 's/^\([0-9]\+\).*/\1/') ] && return $_FAILURE
[ $(get_kernel_release_1) -ge "$release_req" ] && return $_SUCCESS
return $_FAILURE
}
has_kernel_release_min_2 () {
# check if current LK 1st level release number is greater or equal release_req
release_req="${1:-}"
[ "$release_req" -ne $(echo $release_req|sed -e 's/^\([0-9]\+\).*/\1/') ] && return $_FAILURE
[ $(get_kernel_release_2) -ge "$release_req" ] && return $_SUCCESS
return $_FAILURE
}
has_kernel_release_min_3 () {
# check if current LK 1st level release number is greater or equal release_req
release_req="${1:-}"
[ "$release_req" -ne $(echo $release_req|sed -e 's/^\([0-9]\+\).*/\1/') ] && return $_FAILURE
[ $(get_kernel_release_3) -ge "$release_req" ] && return $_SUCCESS
return $_FAILURE
}
require_kernel_release_min_1 () {
# exit 0 if current LK release is less than required 3rd level version number
release_req="${1:-}"
explanation="${2:-Linux Kernel must be newer than ${release_req}.x.x}"
if has_kernel_release_min_1 "$release_req"; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_kernel_release_min_1 $release_req" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
require_kernel_release_min_2 () {
# exit 0 if current LK release is less than required 2nd level version number
release_req="${1:-}"
explanation="${2:-Linux Kernel must be newer than x.${release_req}.x}"
if has_kernel_release_min_2 "$release_req"; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_kernel_release_min_2 $release_req" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
require_kernel_release_min_3 () {
# exit 0 if current LK release is less than required 3rd level version number
release_req="${1:-}"
explanation="${2:-Linux Kernel must be newer than x.x-${release_req}}"
if has_kernel_release_min_3 "$release_req"; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_kernel_release_min_3 $release_req" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
require_kernel_release_min () {
release_req="${1:-}"
explanation="${2:-Linux Kernel must be newer than ${release_req}}"
if has_kernel_release_min "$release_req"; then
if [ "x1" = "x$REQUIRES_GENERATE_TAP" ] ; then ok $_SUCCESS "require_kernel_release_min $release_req" ; fi
return $_SUCCESS
else
autoreport_skip_all "$explanation"
fi
}
is_element_in_list () {
# check if element is in list
element="${1:-unknown}"
list="${2:-unknown}"
echo "$list"|egrep -q "\b$element\b"
result=$?
return $result
}
prepare_information() {
# ===== control variables defaults ==================
# by default require_* functions generate TAP ok lines
REQUIRES_GENERATE_TAP=${REQUIRES_GENERATE_TAP:-1}
# ===== kernel details ==================
kernelrelease=$(uname -r)
# ===== suite name ==================
SUITEKEYWORDS=$(for k in $KEYWORDS ; do echo $k ; done | sort | paste -sd-)
myname=$(echo $(basename -- $0 | sed -e 's/\.\w*$//i')${SUITEKEYWORDS:+-$SUITEKEYWORDS} | sed -e "s/^tapper-//" | sed -e "s/^artemis-//" )
SUITE=${myname:-autoreport}
VERSION=3.002
# ===== other meta info ==================
suite_name=${SUITENAME:-$(echo $SUITE)}
suite_version=${SUITEVERSION:-$VERSION}
hostname=${HOSTNAME:-$(hostname)}
hostname=$(echo $hostname | cut -d. -f1)
# combined machine name in Tapper automation guest environment
if is_running_in_virtualized_guest ; then
if [ "x$TAPPER_HOSTNAME" != "x" ] ; then
hostname="${TAPPER_HOSTNAME}:$hostname"
elif [ -r /etc/tapper ] ; then
TAPPER_HOSTNAME=$(echo $(grep hostname: /etc/tapper | cut -d: -f2))
hostname="${TAPPER_HOSTNAME}:$hostname"
fi
fi
reportername=${REPORTERNAME:-$USER}
if [ -e /etc/issue.net ]
then
osname=${OSNAME:-$(cat /etc/issue.net | head -1)}
else
osname=${OSNAME:-$(uname -o)}
fi
changeset=${CHANGESET:-$(cat /proc/version | head -1)}
kernelflags=$(cat /proc/cmdline)
uname=$(uname -a)
ram=$(free -m | grep -i mem: | awk '{print $2}'MB)
starttime_test_program=${starttime_test_program:-$(date --rfc-2822)} # first occurrence
starttime_test_program_epoch=${starttime_test_program_epoch:-$(date +"%s")}
endtime_test_program=$(date --rfc-2822) # last occurrence
endtime_test_program_epoch=$(date +"%s")
bogomips=$(echo $(cat /proc/cpuinfo | grep -i bogomips | head -1 | cut -d: -f2))
cpuinfo=$(
if arm_cpu
then
cpu=$(grep 'Processor' < /proc/cpuinfo | cut -d: -f2- |head -1 | cut -d" " -f2);
else
cpu=$(grep 'model name' < /proc/cpuinfo | cut -d: -f2- | head -1 | sed -e "s/^ *//");
fi
echo "$(get_number_cpus) cores [$cpu]";
)
# TODO: bogomips from /proc/cpuinfo
if [ -e "/boot/config-$kernelrelease" ]
then
BOOTCONFIG="/boot/config-$kernelrelease"
else
BOOTCONFIG=
fi
PROCCONFIG="/proc/config.gz"
ticketurl=${TICKETURL:-""}
wikiurl=${WIKIURL:-""}
planningid=${PLANNINGID:-""}
moreinfourl=${MOREINFOURL:-""}
# group reports with similar environment:
# - hostname
# - date
# - uname
# - cpuinfo
# - kernel config
TESTRUN_FROM_CONFIG=""
if [ -r /test.config ] ; then
TESTRUN_FROM_CONFIG=$(grep -E '^test_run:' /test.config | cut -d: -f2)
fi
reportgroup_testrun=${TAPPER_TESTRUN:-${ARTEMIS_TESTRUN:-${TESTRUN_FROM_CONFIG:-}}}
reportgroup=${REPORTGROUP:-$((echo $HOSTNAME ; date +%Y-%m-%d ; uname -a ; cat /proc/cpuinfo | grep -v MHz | grep -vi bogomips ; cat $(ls -1 $BOOTCONFIG $PROCCONFIG /dev/null 2> /dev/null | sort) ) | md5sum | cut -d" " -f1 )}
if [ ! "$reportgroup_testrun" ] ; then
reportgroup_arbitrary=${TAPPER_REPORT_GROUP:-$reportgroup}
fi
} # prepare_information()
tapper_read_config_key () {
key="${1:-test_run}"
echo $(grep -E "^ *$key: " /etc/tapper |cut -d: -f2)
}
tapper_output_dir () {
echo "$(tapper_read_config_key output_dir)/$(tapper_read_config_key test_run)" | sed -e 's/\/\+/\//g'
}
tapper_all_meta () {
prepare_information
tapper_suite_meta
tapper_section_meta
}
tapper_suite_meta() {
echo "# Tapper-section: $suite_name";
echo "# Tapper-suite-name: $suite_name";
echo "# Tapper-suite-version: $suite_version";
echo "# Tapper-machine-name: $hostname";
echo "# Tapper-reportername: $reportername";
if [ -n "$reportgroup_arbitrary" ] ; then
echo "# Tapper-reportgroup-arbitrary: $reportgroup_arbitrary";
fi
if [ -n "$reportgroup_testrun" ] ; then
echo "# Tapper-reportgroup-testrun: $reportgroup_testrun";
fi
if [ -n "$ticketurl" ] ; then
echo "# Tapper-ticket-url: $ticketurl";
fi
if [ -n "$wikiurl" ] ; then
echo "# Tapper-wiki-url: $wikiurl";
fi
if [ -n "$planningid" ] ; then
echo "# Tapper-planning-id: $planningid";
fi
if [ -n "$moreinfourl" ] ; then
echo "# Tapper-moreinfo-url: $moreinfourl";
fi
}
tapper_base_os_description () {
if [ -r /etc/lsb-release ] ; then
. /etc/lsb-release
BASE_OS_DESCRIPTION="$DISTRIB_DESCRIPTION"
else
RELEASE_FILES="/etc/slackware-version /etc/gentoo-release /etc/SuSE-release /etc/issue /etc/issue.net /etc/motd"
for i in $RELEASE_FILES ; do if [ -r $i ] ; then RELEASE_FILE=$i ; break ; fi; done
BASE_OS_DESCRIPTION=$(cat $RELEASE_FILE | perl -ne 'print if /\w/' | head -1)
fi
echo $BASE_OS_DESCRIPTION
}
# we could as well use uname -r here, but lets explicitly ask Xen
# first what it thinks the Dom0 kernel version is
tapper_xen_dom0_kernel () {
XL=$(get_xen_tool)
if [ "$?" -eq 0 ] ; then
$XL info 2> /dev/null | grep '^release.*:' | cut -d: -f2 || uname -r
else
uname -r
fi
}
tapper_xen_changeset () {
if [ -r /sys/hypervisor/properties/changeset ] ; then
cat /sys/hypervisor/properties/changeset | sed -e 's/^.* \([^ ]*\)/\1/'
else
XL=$(get_xen_tool) || return $_FAILURE
echo $($XL info|grep '^xen_changeset.*:'|sed -e 's/^.* \([^ ]*\)/\1/')
fi
}
tapper_xen_version () {
if [ -r /sys/hypervisor/version/major ] ; then
_VPATH="/sys/hypervisor/version"
echo "$(cat $_VPATH/major).$(cat $_VPATH/minor)$(cat $_VPATH/extra)"
else
XL=$(get_xen_tool) || return $_FAILURE
XEN_VERSION_MAJOR=$(echo $($XL info|grep '^xen_major.*:'|cut -d: -f2))
XEN_VERSION_MINOR=$(echo $($XL info|grep '^xen_minor.*:'|cut -d: -f2))
XEN_VERSION_EXTRA=$(echo $($XL info|grep '^xen_extra.*:'|cut -d: -f2))
XEN_VERSION=""
if [ -n "$XEN_VERSION_MAJOR" ] ; then
XEN_VERSION="$XEN_VERSION_MAJOR.$XEN_VERSION_MINOR$XEN_VERSION_EXTRA"
fi
echo $XEN_VERSION
fi
}
tapper_xen_meta () {
echo "# Tapper-xen-dom0-kernel: $(tapper_xen_dom0_kernel)"
echo "# Tapper-xen-version: $(tapper_xen_version)"
echo "# Tapper-xen-changeset: $(tapper_xen_changeset)"
echo "# Tapper-xen-base-os-description: $(tapper_base_os_description)"
}
tapper_kvm_meta () {
# echo "# Tapper-kvm-module-kernel: $(uname -r)"
# echo "# Tapper-kvm-kernel: $(uname -r)"
echo "# Tapper-kvm-version: $(uname -r)"
echo "# Tapper-kvm-base-os-description: $(tapper_base_os_description)"
}
tapper_section_meta() {
if [ ! "x1" = "x$DONTREPEATMETA" ] ; then
echo "# Tapper-uname: $uname"
echo "# Tapper-osname: $osname"
echo "# Tapper-kernel: $kernelrelease"
echo "# Tapper-changeset: $changeset"
echo "# Tapper-flags: $kernelflags"
echo "# Tapper-cpuinfo: $cpuinfo"
echo "# Tapper-ram: $ram"
echo "# Tapper-starttime-test-program: $starttime_test_program"
echo "# Tapper-endtime-test-program: $endtime_test_program"
if is_running_in_xen_dom0 ; then
tapper_xen_meta
fi
if is_running_in_kvm_host ; then
tapper_kvm_meta
fi
fi
if [ -n "$SECTION" ] ; then
echo "# Tapper-section: $SECTION"
fi
}
tapper_help () {
echo "tapper-autoreport"
echo ""
echo "For more info please see"
echo " https://github.com/tapper/Tapper-autoreport/blob/master/autoreport-manual.md"
echo ""
}
tapper_version () {
echo "$VERSION"
}
# ===== param evaluation ==============================
prepare_start () {
prepare_information
if [ x"$HARNESS_ACTIVE" == x"1" ] ; then
NOSEND=1
else
require_netcat
fi
EXITCODE=0
OK=1
FILECOUNT=0
# do not implicitely upload files like kernel config
noupload=${NOUPLOAD:-0}
# extend that list with usernames that should magically be recognized
# as test owner when listing them as argument
[ -r ./TAPPER_KNOWNUSERS ] && . ./TAPPER_KNOWNUSERS
KNOWNUSERS=${KNOWNUSERS:-"root tapper"}
KNOWNUSERS_REGEX=$(for k in $KNOWNUSERS ; do echo $k ; done | sort | paste -sd- | sed -e 's/-/\\|/g')
for i in $(seq 1 $#) ; do
a=${!i}
# echo "<${a}>"
if echo "$a" | grep -Eq '^-?[0-9]+$' ; then
if [ "$a" != "0" ] ; then
EXITCODE=$a
fi
elif [ x"$a" == x"nok" ] ; then
OK=0
elif [ -e "$a" ] ; then
FILES[$FILECOUNT]="$a"
let FILECOUNT=FILECOUNT+1
elif echo "$a" | grep -qi "^\\($KNOWNUSERS_REGEX\\)\$" ; then
REPORTERNAME="$a"
fi
done
# ===== kernel config files ==================
if [ ! "$NOUPLOAD" ] ; then
if [ ! "x1" = "x$DONTREPEATMETA" ] ; then
if [ -n "$BOOTCONFIG" ] ; then
FILES[$FILECOUNT]="$BOOTCONFIG"
let FILECOUNT=FILECOUNT+1
fi
if [ -e "$PROCCONFIG" ] ; then
FILES[$FILECOUNT]="$PROCCONFIG"
let FILECOUNT=FILECOUNT+1
fi
fi
fi
# ===== upload ourself ===============
if [ ! "x1" = "x$DONTREPEATMETA" ] ; then
FILES[$FILECOUNT]="$0"; let FILECOUNT=FILECOUNT+1
fi
# ===== /proc files ==================
if [ ! "x1" = "x$DONTREPEATMETA" ] ; then
FILES[$FILECOUNT]="/proc/cpuinfo"; let FILECOUNT=FILECOUNT+1
FILES[$FILECOUNT]="/proc/devices"; let FILECOUNT=FILECOUNT+1
FILES[$FILECOUNT]="/proc/version"; let FILECOUNT=FILECOUNT+1
fi
# ===== utility functions ==================
TAPPER_REPORT_SERVER=${TAPPER_REPORT_SERVER:-${ARTEMIS_REPORT_SERVER:-tapper}}
TAPPER_REPORT_PORT=${TAPPER_REPORT_PORT:-${ARTEMIS_REPORT_PORT:-7357}}
TAPPER_API_PORT=${TAPPER_API_PORT:-${ARTEMIS_API_PORT:-7358}}
} # prepare_start()
prepare_plan() {
# count of our own tests
COUNT=${#TAP[@]}
PLAN=$(($MYPLAN + $COUNT - $COMMENTCOUNTER))
}
upload_files() {
MYNETCAT="$NETCAT $TAPPER_REPORT_SERVER $TAPPER_API_PORT"
# echo "# Uploading: $MYNETCAT ..." 1>&2
for f in $(seq 0 $(($FILECOUNT - 1))) ; do
file="${FILES[f]}"
filetype=""
if echo $file | grep -Eq '\.(gz|bz2)$' ; then
filetype="application/octet-stream"
fi
echo -n "# - upload $file" 1>&2
if [ "$filetype" ] ; then
echo -n " ($filetype)" 1>&2
fi
echo " ..." 1>&2
(
echo "#! upload $reportid $file $filetype"
cat $file
) | $MYNETCAT
done
}
# ===== main =========================================
autoreport_main() {
COMMENTCOUNTER=${COMMENTCOUNTER:-0}
if [ -n "$SKIPALL" ] ; then
echo "$SKIPALL"
tapper_suite_meta
tapper_section_meta
export NOUPLOAD=1
return
fi
# ==================== prepare plan
# count of tests until "END of own tests"
MYPLAN=4
prepare_plan
echo "TAP Version 13"
echo "1..$PLAN"
# ==================== meta info ====================
tapper_suite_meta
tapper_section_meta
# =============== own headers (later entries win) ===============
HEADERSCOUNT=${#HEADERS[@]}
for l in $(seq 0 $(($HEADERSCOUNT - 1))) ; do
echo ${HEADERS[l]}
done
# ,==================== BEGIN of own tests ====================
# |
#
echo "ok - autoreport"
# optionally provided exit code
if [ x"$EXITCODE" != x"0" ] ; then echo -n "not " ; fi
echo "ok - exitcode"
if [ -n "$EXITCODE" ] ; then
echo " ---"
echo " exitcode: $EXITCODE"
echo " ..."
fi
# optionally provided "not ok"
if [ x"$OK" = x"0" ] ; then echo -n "not " ; fi
echo "ok - success"
#
# |
# `==================== END of own tests ====================
# ==================== remaining TAP ====================
for l in $(seq 0 $(($COUNT - 1))) ; do
echo ${TAP[l]}
done
# ==================== additional TAP/YAML data ====================
echo "ok - tapdata"
echo " ---"
echo " tapdata: 1"
if [ -n "$starttime_test_program_epoch" ] && [ -n "$endtime_test_program_epoch" ] ; then
echo " starttime: $starttime_test_program_epoch"
echo " endtime: $endtime_test_program_epoch"
echo " runtime: $((endtime_test_program_epoch-starttime_test_program_epoch))"
fi
TAPDATACOUNT=${#TAPDATA[@]}
if [ "$TAPDATACOUNT" -gt 0 ] ; then
for l in $(seq 0 $(($TAPDATACOUNT - 1))) ; do
echo " ${TAPDATA[l]}"
done
fi
echo " ..."
# ==================== remaining output ====================
OUTPUTCOUNT=${#OUTPUT[@]}
for l in $(seq 0 $(($OUTPUTCOUNT - 1))) ; do
echo ${OUTPUT[l]}
done
# ==================== files ====================
for f in $(seq 0 $(($FILECOUNT - 1))) ; do
echo "# File upload: '${FILES[f]}'"
done
if set | grep -q '^main_after_hook \(\)' ; then
main_after_hook
fi
}
# ===== main =========================================
autoreport_start () {
prepare_start "${@}"
if [ ! "x1" = "x$NOSEND" ] ; then
NETCAT=$(which netcat 2> /dev/null || which nc 2> /dev/null)
# does it provide -q option
if $NETCAT -h 2>&1 |grep -q -- '-q.*quit' ; then
NETCAT="$NETCAT -q7"
else
NETCAT="$NETCAT -w7"
fi
else
NETCAT=cat
fi
#echo "# NETCAT: $NETCAT"
if [ -n "$TAPPER_REPORT_SERVER" ] ; then
if [ ! "x1" = "x$NOSEND" ] ; then
MYNETCAT="$NETCAT $TAPPER_REPORT_SERVER $TAPPER_REPORT_PORT"
# echo "# Reporting: $MYNETCAT ..." 1>&2
output=$( (autoreport_main | $MYNETCAT ; if [ "x1" = "x$NOSEND" ] ; then echo $NOSEND ; fi ) | tail -1 )
reportid=$(echo $output | sed -e 's/^.*::Reports::Receiver. Protocol is TAP. Your report id: //')
if [ ! "x1" = "x$NOSEND" ] ; then
echo -n "# http://$TAPPER_REPORT_SERVER" 1>&2
if [ -n "$TAPPER_WEB_PORT" ] ; then
echo -n ":$TAPPER_WEB_PORT"
elif echo $TAPPER_REPORT_SERVER | grep -q "localhost" ; then
# heuristically localhost is running a development server
echo -n ":3000"
else
# be explicit
echo -n ":80"
fi
if echo $TAPPER_REPORT_SERVER | grep -q "artemis" ; then
echo "/artemis/reports/id/$reportid" 1>&2
else
echo "/tapper/reports/id/$reportid" 1>&2
fi
upload_files
fi
else
autoreport_main
fi
fi
}
done_testing () {
autoreport_start "${@}"
}
# =====================================================
function recover_kill {
ok 1 'GOT KILLED EXTERNALLY'
done_testing
exit
}
trap "recover_kill" SIGTERM SIGHUP SIGINT SIGKILL
# =====================================================
# up to here functions are sourced by test scripts
[ "$1" == "--import-utils" ] && prepare_information && return $_SUCCESS
[ "$1" == "--help" ] && tapper_help && exit $_SUCCESS
[ "$1" == "--version" ] && tapper_version && exit $_SUCCESS
# =====================================================
autoreport_start "${@}"