[PATCH 1/2] bash-test-utils: support writing functional tests

From: steffen.schwigon
Date: Tue Oct 23 2012 - 04:05:51 EST


From: Steffen Schwigon <steffen.schwigon@xxxxxxx>

It provides utility functions and facilities to write tests in
baremetal and Xen/KVM contexts (host and guest support) and was
polished to work with i686, x86_64, and ARM under lots of major
Linux distributions (Debian, Ubuntu, RHEL, SLES, Slackware,
Fedora, openSUSE).

It can be run as normal bash script or indirectly via the "prove"
command, a standard Linux tool to run test scripts.

Synopsis:

$ cd /usr/src/linux

$ cat t/my-feature-test.t
#! /bin/bash
. tools/testing/tap/bash-test-utils
test_feature_foo
ok $? "feature foo"
done_testing

$ prove -v t/my-feature-test.t

Signed-off-by: Steffen Schwigon <steffen.schwigon@xxxxxxx>
Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>
Signed-off-by: Frank Arnold <frank.arnold@xxxxxxx>
Signed-off-by: Conny Seidel <conny.seidel@xxxxxxx>
Signed-off-by: Christian Daudt <csd@xxxxxxxxxxxx>
---
tools/testing/tap/bash-test-utils | 1508 +++++++++++++++++++++++++++++++++
tools/testing/tap/bash-test-utils.txt | 320 +++++++
2 files changed, 1828 insertions(+)
create mode 100755 tools/testing/tap/bash-test-utils
create mode 100644 tools/testing/tap/bash-test-utils.txt

diff --git a/tools/testing/tap/bash-test-utils b/tools/testing/tap/bash-test-utils
new file mode 100755
index 0000000..68661dd
--- /dev/null
+++ b/tools/testing/tap/bash-test-utils
@@ -0,0 +1,1508 @@
+#! /bin/bash
+
+# bash-test-utils -- an include file to support writing test scripts.
+#
+# --------------------------------------------------------------------
+#
+# It provides utility functions and facilities to write tests in
+# baremetal and Xen/KVM contexts (host and guest support) and was
+# polished to work with i686, x86_64, and ARM under lots of major
+# Linux distributions (Debian, Ubuntu, RHEL, SLES, Slackware,
+# Fedora, openSUSE).
+#
+# It can be run as normal bash script or indirectly via the "prove"
+# command, a standard Linux tool to run test scripts.
+#
+# Synopsis:
+#
+# $ cd /usr/src/linux
+#
+# $ cat > t/my-feature-test.t
+# #! /bin/bash
+# . tools/testing/tap/bash-test-utils
+# test_feature_foo
+# ok $? "feature foo worked"
+# done_testing
+#
+# $ prove -v t/my-feature-test.t
+#
+# --------------------------------------------------------------------
+#
+# Copyright (c) 2009-2012, Advanced Micro Devices, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software 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. See the
+# GNU General Public License for more details.
+#
+
+
+# ==================== 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 if we are in a virtualized guest (Xen or KVM)
+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
+}
+
+# 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
+}
+
+# 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
+}
+
+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"
+ autoreport_start
+ exit 0
+}
+
+# ==================== 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
+}
+
+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
+}
+
+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 ==================
+
+ myname=$(echo $(basename -- $0 | sed -e 's/\.\w*$//i'))
+
+ SUITE=${myname:-bash-test-utils}
+ VERSION=1.000
+
+ # ===== other meta info ==================
+
+ suite_name=${SUITENAME:-$(echo $SUITE)}
+ suite_version=${SUITEVERSION:-$VERSION}
+ hostname=${HOSTNAME:-$(hostname)}
+ hostname=$(echo $hostname | cut -d. -f1)
+
+ 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"
+
+} # prepare_information()
+
+ltu_suite_meta() {
+ if [[ -n $VERBOSE ]]; then
+ echo "# Test-section: $suite_name";
+ echo "# Test-suite-version: $suite_version";
+ fi
+ echo "# Test-suite-name: $suite_name";
+ echo "# Test-machine-name: $hostname";
+}
+
+ltu_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
+ltu_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
+}
+
+ltu_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
+}
+
+ltu_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
+}
+
+ltu_xen_meta () {
+ echo "# Test-xen-dom0-kernel: $(ltu_xen_dom0_kernel)"
+ echo "# Test-xen-version: $(ltu_xen_version)"
+ echo "# Test-xen-changeset: $(ltu_xen_changeset)"
+ echo "# Test-xen-base-os-description: $(ltu_base_os_description)"
+}
+
+ltu_kvm_meta () {
+ echo "# Test-kvm-version: $(uname -r)"
+ echo "# Test-kvm-base-os-description: $(ltu_base_os_description)"
+}
+
+ltu_section_meta() {
+ if [ ! "x1" = "x$DONTREPEATMETA" ] ; then
+ echo "# Test-uname: $uname"
+ echo "# Test-osname: $osname"
+ echo "# Test-kernel: $kernelrelease"
+ echo "# Test-changeset: $changeset"
+ echo "# Test-flags: $kernelflags"
+ echo "# Test-cpuinfo: $cpuinfo"
+ echo "# Test-ram: $ram"
+ echo "# Test-starttime-test-program: $starttime_test_program"
+ echo "# Test-endtime-test-program: $endtime_test_program"
+ if is_running_in_xen_dom0 ; then
+ ltu_xen_meta
+ fi
+ if is_running_in_kvm_host ; then
+ ltu_kvm_meta
+ fi
+ fi
+
+ if [ -n "$SECTION" ] ; then
+ echo "# Test-section: $SECTION"
+ fi
+}
+
+ltu_help () {
+ echo "bash-test-utils"
+ echo ""
+ echo "This is the 'bash-test-utils' bash utility -- a bash include file"
+ echo "to turn your bash script into a test suite that can optionally be"
+ echo "used with the 'prove' command, a standard tool to run test scripts."
+ echo ""
+ echo "Use in your script:"
+ echo " . ./bash-test-utils"
+ echo " # ... your testing here, eg.:"
+ echo " grep -q foobar /proc/cpuinfo"
+ echo ' ok $? "found foobar in cpuinfo"'
+ echo " done_testing"
+ echo ""
+ echo "Run:"
+ echo " prove ./examples/utils-example-01.t"
+ echo " prove -v ./examples/utils-example-01.t # verbose"
+ echo " prove ./examples/ # whole subdir"
+ echo ""
+}
+
+ltu_version () {
+ echo "$VERSION"
+}
+
+# ===== param evaluation ==============================
+
+prepare_start () {
+ prepare_information
+ # other context sensitive initialization (eg. default, destructive, ...)
+}
+
+prepare_plan() {
+ # count of our own tests
+ COUNT=${#TAP[@]}
+ PLAN=$(($MYPLAN + $COUNT - $COMMENTCOUNTER))
+}
+
+# ===== main =========================================
+
+autoreport_main() {
+
+ COMMENTCOUNTER=${COMMENTCOUNTER:-0}
+
+ if [ -n "$SKIPALL" ] ; then
+ echo "$SKIPALL"
+ ltu_suite_meta
+ if [[ -n $VERBOSE ]]; then
+ ltu_section_meta
+ fi
+ return
+ fi
+
+ # ==================== prepare plan
+
+ # count of tests until "END of own tests"
+ MYPLAN=2
+ prepare_plan
+ echo "TAP Version 13"
+ echo "1..$PLAN"
+
+ # ==================== meta info ====================
+ ltu_suite_meta
+ if [[ -n $VERBOSE ]]; then
+ ltu_section_meta
+ fi
+
+ # =============== 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"
+ #
+ # |
+ # `==================== 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 "${@}"
+ autoreport_main
+}
+
+done_testing () {
+ autoreport_start "${@}"
+}
+
+# =====================================================
+
+function recover_kill {
+ ok 1 'GOT KILLED EXTERNALLY'
+ done_testing
+ exit
+}
+
+trap "recover_kill" SIGTERM SIGHUP SIGINT SIGKILL
+
+# =====================================================
+
+[ "$1" == "--help" ] && ltu_help && exit $_SUCCESS
+[ "$1" == "--version" ] && ltu_version && exit $_SUCCESS
+
+# =====================================================
+
+prepare_information
diff --git a/tools/testing/tap/bash-test-utils.txt b/tools/testing/tap/bash-test-utils.txt
new file mode 100644
index 0000000..b0596db
--- /dev/null
+++ b/tools/testing/tap/bash-test-utils.txt
@@ -0,0 +1,320 @@
+bash-test-utils -- support writing functional tests
+
+ABOUT
+=====
+
+It provides utility functions and facilities to write tests in
+baremetal and Xen/KVM contexts (host and guest support) and was
+polished to work with i686, x86_64, and ARM under lots of major Linux
+distributions (Debian, Ubuntu, RHEL, SLES, Slackware, Fedora,
+openSUSE).
+
+It can be run as normal bash script or indirectly via the "prove"
+command, a standard Linux tool to run test scripts.
+
+
+SYNOPSIS
+========
+
+A test script
+-------------
+
+ #! /bin/bash
+ . ./bash-test-utils
+ # your_feature_test here
+ done_testing
+
+This imports utility functions to be used by your script, then you
+write your tests, and at the end it calls the actual printing of test
+results.
+
+
+Run it via 'prove' (a standard test utility)
+--------------------------------------------
+
+ $ prove ./trivial-example-1.sh
+ ./trivial-example-1.sh .. ok
+ All tests successful.
+ Files=1, Tests=5, 20 wallclock secs
+ Result: PASS
+
+The tool "prove" is a standard tool available in every Linux
+distribution. It runs the script and prints success statistics. See
+"man prove" for more options.
+
+
+UTILITY FUNCTIONS
+=================
+
+Import utility functions at the beginning of the script via
+
+ . tools/testing/tap/bash-test-utils
+
+Then you have several functions available.
+
+Expressing test results
+-----------------------
+
+* ok ARG1 "some description"
+
+ Evaluates the first argument with Shell boolean semantics (0 is
+ true) and appends a corresponding TAP line. See also "require_ok"
+ below.
+
+* negate_ok ARG1 "some description"
+
+ Evaluates the first argument with Shell inverse boolean semantics (0
+ is false) and appends a corresponding TAP line.
+
+* append_tap "ok - some description"
+
+ Appends a complete TAP line where you have taken care for the
+ "ok"/"not ok" at the beginning.
+
+* append_comment "foo bar baz"
+
+ Appends a complete comment line starting with "#". It appears
+ directly after the last added TAP line so it can be used for
+ diagnostics.
+
+* append_tapdata "key: value"
+
+ Appends a key:value line at the final tapdata YAML block. The key
+ must start with letter and consist of only alphanum an underscore.
+
+
+require_* functions
+-------------------
+
+ All require_* functions check for something and gracefully exit the
+ script if the requirement is not fulfilled. Use this to allow the
+ script to run everywhere without polluting results with false
+ negatives.
+
+* require_ok ARG1 "some description"
+
+ Evaluates the first argument with Shell boolean semantics (0 is
+ true) and appends a corresponding TAP line. If it reports "not ok"
+ the script gracefully exits.
+
+* require_amd_family_range [ MIN [ MAX ] ]
+
+ Ensures vendor is AMD and cpu family from /proc/cpuinfo is in a
+ minimum/maximum range. If you don't specify MIN it defaults to 0. If
+ you don't specify MAX it defaults to MIN.
+
+* require_cpufeature "foo"
+
+ Verifies that the string "foo" occurs in /proc/cpuinfo flags section.
+
+* require_kernel_config "CONFIG_FOO"
+
+ Verify that regex "^CONFIG_FOO=." occurs in /proc/config.gz or
+ /boot/config/$ (uname -r).
+
+* require_program "foo"
+
+ Verify that the program "foo" is available. Use it to declare
+ external programs you call, like "awk", "bc", "perl", etc.
+
+* require_l3cache
+
+ Verify that L3 cache is available (checked in
+ /sys/devices/system/cpu/cpu0/ cache/index3).
+
+* require_root
+
+ Verify that the user executing the script is root (UID 0).
+
+* require_crit_level N
+
+ Verify that the criticality level N of the script is allowed to be
+ run, which is controlled by environment variable CRITICALITY. See
+ "has_crit_level" for meaning of criticality levels.
+
+* require_cpb_disabled
+
+ Enables cpufreq and disables boosting. In case of errors the calling
+ test is skipped.
+
+* require_cpufreq_enabled
+
+ Enables cpufreq and also core boosting. In case of errors the
+ calling test is skipped.
+
+* require_kernel_release_min
+
+ Verify that the current LK release is at least the required version
+ number.
+
+* require_running_in_xen_guest
+
+ Verify if we are in a Xen guest.
+
+* require_running_in_kvm_guest
+
+ Verify if we are in a KVM guest.
+
+* require_running_in_virtualized_guest
+
+ Verify if we are in a virtualized guest (Xen or KVM).
+
+
+request_* functions
+-------------------
+
+All request_* functions try to enable something and if that fails mark it as
+#TODO but continue the test. It's kind of an "uncritical require_*".
+
+* request_cpb_disabled
+
+ Enables cpufreq and disables boosting. The result will be reported
+ and returned. Errors are marked as TODO.
+
+* request_cpufreq_enabled
+
+ Enables cpufreq and also core boosting. The result will be reported
+ and returned. Errors are marked as TODO.
+
+
+Misc auxiliary functions
+------------------------
+
+These are really just utilities to help you but they don't influence the
+behaviour like the require_* functions do.
+
+* has_l3cache
+
+ Returns 0 (shell TRUE) if L3 cache is available (checked in
+ /sys/devices/ system/cpu/cpu0/cache/index3).
+
+* has_cpufeature "foo"
+
+ Returns 0 (shell TRUE) if string "foo" occurs in /proc/cpuinfo flags
+ section.
+
+* has_kernel_release_min
+
+ Returns 0 (shell TRUE) if the current LK release is at least the
+ required version number.
+
+* has_kernel_config "CONFIG_FOO"
+
+ Returns 0 (shell TRUE) if regex "^CONFIG_FOO=." occurs in
+ /proc/config.gz or / boot/config/$(uname -r).
+
+* has_program "foo"
+
+ Return 0 (shell TRUE) if the program "foo" is available.
+
+* has_crit_level N
+
+ Checks whether the criticality level N of the script is allowed to
+ be run, which is controlled by environment variable CRITICALITY. The
+ criticality levels are defined as this:
+
+ * 0: not critical
+ * 1: read sysfs/debugfs/proc files
+ * 2: read HW (MSRs/Northbridge)
+ * 3: write sysfs/debugfs/proc files
+ * 4: write HW (MSRs/Northbridge) or potentially crash the machine
+
+* get_vendor
+
+ Prints vendor "AMD" or "Intel" from /proc/cpuinfo.
+
+* vendor_intel
+
+ Returns 0 (shell TRUE) if vendor is Intel.
+
+* vendor_amd
+
+ Returns 0 (shell TRUE) if vendor is AMD.
+
+* get_random_number [ MAX ]
+
+ Prints a random integer between 0 and MAX (default 32768).
+
+* get_cpu_family
+
+ Print cpu family from /proc/cpuinfo.
+
+* get_cpu_family_hex
+
+ Print cpu family from /proc/cpuinfo in hex syntax (0x...).
+
+* cpu_family_min [ MINFAMILY ]
+
+ Returns 0 (shell TRUE) if cpu family from /proc/cpuinfo is greater
+ or equal to MINFAMILY. Defaults to 0.
+
+* cpu_family_max [ MAXFAMILY ]
+
+ Returns 0 (shell TRUE) if cpu family from /proc/cpuinfo is less or
+ equal to MAXFAMILY. Defaults to 999.
+
+* get_first_file [ LIST OF FILENAMES ]
+
+ Goes through all specified filenames and prints the first one that
+ exists and is readable.
+
+* is_element_in_list WORD "SPACE SEPARATED LIST OF WORDS"
+
+ Returns 0 (shell TRUE) if WORD appears in "SPACE SEPARATED LIST OF
+ WORDS". Remember the usual shell quoting rules.
+
+* get_kernel_release
+
+ Prints the kernel version number from uname -r.
+
+* is_running_in_xen_guest
+
+ Check if we are in a Xen guest.
+
+* is_running_in_kvm_guest
+
+ Check if we are in a KVM guest.
+
+* is_running_in_virtualized_guest
+
+ Check if we are in a virtualized guest (Xen or KVM).
+
+
+INFLUENCING BEHAVIOUR
+=====================
+
+Environment Variables
+---------------------
+
+These variables are expected to be set inside the script to declare
+meta information or influence behaviour:
+
+* TAP[*] - Array of TAP lines
+* TAPDATA[*] - Array of YAML lines that contain data in TAP
+* OUTPUT[*] - Array of additional output lines
+* SUITENAME - alternative suite name instead of $0
+* SUITEVERSION - alternative suite version
+* KEYWORDS - space separated keywords to influence suite
+ name
+* OSNAME - alternative OS description
+* CHANGESET - alternative changeset
+* HOSTNAME - alternative hostname
+* TICKETURL - relevant URL in used ticket system
+ (Bugzilla)
+* WIKIURL - relevant URL in used wiki
+* PLANNINGID - relevant task planning id
+ (MS Project, TaskJuggler, etc.)
+* REQUIRES_GENERATE_TAP - if "1" then require_* functions generate
+ additional "ok" line on success
+
+
+External environment variables
+------------------------------
+
+These variables are expected to be set from outside of the script to
+influence behaviour:
+
+* EXIT_ON_SKIPALL - if "1" then on skip_all we immediately exit
+ with exitcode 254.
+* CRITICALITY - Sets the allowed maximal criticality level.
+ Scripts with higher level call skip_all().
--
1.7.10.4


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/