Files
xen/tools/libxl/check-xl-vcpupin-parse
T
Dario Faggioli caee9a0362 xl: test script for the cpumap parser (for vCPU pinning)
This commit introduces "check-xl-vcpupin-parse" for helping
verifying and debugging the (v)CPU bitmap parsing code in xl.

The script runs "xl -N vcpu-pin 0 all <some strings>"
repeatedly, with various input strings, and checks that the
output is as expected.

This is what the script can do:

# ./check-xl-vcpupin-parse -h
 usage: ./check-xl-vcpupin-parse [options]

 Tests various vcpu-pinning strings. If run without arguments acts
 as follows:
  - generates some test data and saves them in
    check-xl-vcpupin-parse.data;
  - tests all the generated configurations (reading them back from
    check-xl-vcpupin-parse.data).

 An example of a test vector file is provided in
 check-xl-vcpupin-parse.data-example.

 Options:
  -h         prints this message
  -r seed    uses seed for initializing the rundom number generator
             (default: the script PID)
  -s string  tries using string as a vcpu pinning configuration and
             reports whether that succeeds or not
  -o ofile   save the test data in ofile
             (default: check-xl-vcpupin-parse.data)
  -i ifile   read test data from ifile

An example test data file (generated on a 2 NUMA nodes, 16 CPUs
host) is being provided in check-xl-vcpupin-parse.data-example.

Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
2013-12-09 15:20:12 +00:00

295 lines
9.0 KiB
Bash
Executable File

#!/bin/bash
set -e
if [ -x ./xl ] ; then
export LD_LIBRARY_PATH=.:../libxc:../xenstore:
XL=./xl
else
XL=xl
fi
fprefix=tmp.check-xl-vcpupin-parse
outfile=check-xl-vcpupin-parse.data
usage () {
cat <<END
usage: $0 [options]
Tests various vcpu-pinning strings. If run without arguments acts
as follows:
- generates some test data and saves them in $outfile;
- tests all the generated configurations (reading them back from
$outfile).
An example of a test vector file is provided in ${outfile}-example.
Options:
-h prints this message
-r seed uses seed for initializing the rundom number generator
(default: the script PID)
-s string tries using string as a vcpu pinning configuration and
reports whether that succeeds or not
-o ofile save the test data in ofile (default: $outfile)
-i ifile read test data from ifile
END
}
expected () {
cat >$fprefix.expected
}
# by default, re-seed with our PID
seed=$$
failures=0
# Execute one test and check the result against the provided
# rc value and output
one () {
expected_rc=$1; shift
printf "test case %s...\n" "$*"
set +e
${XL} -N vcpu-pin 0 all "$@" </dev/null >$fprefix.actual 2>/dev/null
actual_rc=$?
if [ $actual_rc != $expected_rc ]; then
diff -u $fprefix.expected $fprefix.actual
echo >&2 "test case \`$*' failed ($actual_rc $diff_rc)"
failures=$(( $failures + 1 ))
fi
set -e
}
# Write an entry in the test vector file. Format is as follows:
# test-string*expected-rc*expected-output
write () {
printf "$1*$2*$3\n" >> $outfile
}
complete () {
if [ "$failures" = 0 ]; then
echo all ok.; exit 0
else
echo "$failures tests failed."; exit 1
fi
}
# Test a specific pinning string
string () {
expected_rc=$1; shift
printf "test case %s...\n" "$*"
set +e
${XL} -N vcpu-pin 0 all "$@" &> /dev/null
actual_rc=$?
set -e
if [ $actual_rc != $expected_rc ]; then
echo >&2 "test case \`$*' failed ($actual_rc)"
else
echo >&2 "test case \`$*' succeeded"
fi
exit 0
}
# Read a test vector file (provided as $1) line by line and
# test all the entries it contains
run ()
{
while read line
do
if [ ${line:0:1} != '#' ]; then
test_string="`echo $line | cut -f1 -d'*'`"
exp_rc="`echo $line | cut -f2 -d'*'`"
exp_output="`echo $line | cut -f3 -d'*'`"
expected <<END
$exp_output
END
one $exp_rc "$test_string"
fi
done < $1
complete
exit 0
}
while getopts "hr:s:o:i:" option
do
case $option in
h)
usage
exit 0
;;
r)
seed=$OPTARG
;;
s)
string 0 "$OPTARG"
;;
o)
outfile=$OPTARG
;;
i)
run $OPTARG
;;
esac
done
#---------- test data ----------
#
nr_cpus=`xl info | grep nr_cpus | cut -f2 -d':'`
nr_nodes=`xl info | grep nr_nodes | cut -f2 -d':'`
nr_cpus_per_node=`xl info -n | sed '/cpu:/,/numa_info/!d' | head -n -1 | \
awk '{print $4}' | uniq -c | tail -1 | awk '{print $1}'`
cat >$outfile <<END
# WARNING: some of these tests are topology based tests.
# Expect failures if the topology is not detected correctly
# detected topology: $nr_cpus CPUs, $nr_nodes nodes, $nr_cpus_per_node CPUs per node.
#
# seed used for random number generation: seed=${seed}.
#
# Format is as follows:
# test-string*expected-return-code*expected-output
#
END
# Re-seed the random number generator
RANDOM=$seed
echo "# Testing a wrong configuration" >> $outfile
write foo 255 ""
echo "# Testing the 'all' syntax" >> $outfile
write "all" 0 "cpumap: all"
write "nodes:all" 0 "cpumap: all"
write "all,nodes:all" 0 "cpumap: all"
write "all,^nodes:0,all" 0 "cpumap: all"
echo "# Testing the empty cpumap case" >> $outfile
write "^0" 0 "cpumap: none"
echo "# A few attempts of pinning to just one random cpu" >> $outfile
if [ $nr_cpus -gt 1 ]; then
for i in `seq 0 3`; do
cpu=$(($RANDOM % nr_cpus))
write "$cpu" 0 "cpumap: $cpu"
done
fi
echo "# A few attempts of pinning to all but one random cpu" >> $outfile
if [ $nr_cpus -gt 2 ]; then
for i in `seq 0 3`; do
cpu=$(($RANDOM % nr_cpus))
if [ $cpu -eq 0 ]; then
expected_range="1-$((nr_cpus - 1))"
elif [ $cpu -eq 1 ]; then
expected_range="0,2-$((nr_cpus - 1))"
elif [ $cpu -eq $((nr_cpus - 2)) ]; then
expected_range="0-$((cpu - 1)),$((nr_cpus - 1))"
elif [ $cpu -eq $((nr_cpus - 1)) ]; then
expected_range="0-$((nr_cpus - 2))"
else
expected_range="0-$((cpu - 1)),$((cpu + 1))-$((nr_cpus - 1))"
fi
write "all,^$cpu" 0 "cpumap: $expected_range"
done
fi
echo "# A few attempts of pinning to a random range of cpus" >> $outfile
if [ $nr_cpus -gt 2 ]; then
for i in `seq 0 3`; do
cpua=$(($RANDOM % nr_cpus))
range=$((nr_cpus - cpua))
cpub=$(($RANDOM % range))
cpubb=$((cpua + cpub))
if [ $cpua -eq $cpubb ]; then
expected_range="$cpua"
else
expected_range="$cpua-$cpubb"
fi
write "$expected_range" 0 "cpumap: $expected_range"
done
fi
echo "# A few attempts of pinning to just one random node" >> $outfile
if [ $nr_nodes -gt 1 ]; then
for i in `seq 0 3`; do
node=$(($RANDOM % nr_nodes))
# this assumes that the first $nr_cpus_per_node (from cpu
# 0 to cpu $nr_cpus_per_node-1) are assigned to the first node
# (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node
# to 2*$nr_cpus_per_node-1) are assigned to the second node (node
# 1), etc. Expect failures if that is not the case.
write "nodes:$node" 0 "cpumap: $((nr_cpus_per_node*node))-$((nr_cpus_per_node*(node+1)-1))"
done
fi
echo "# A few attempts of pinning to all but one random node" >> $outfile
if [ $nr_nodes -gt 1 ]; then
for i in `seq 0 3`; do
node=$(($RANDOM % nr_nodes))
# this assumes that the first $nr_cpus_per_node (from cpu
# 0 to cpu $nr_cpus_per_node-1) are assigned to the first node
# (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node
# to 2*$nr_cpus_per_node-1) are assigned to the second node (node
# 1), etc. Expect failures if that is not the case.
if [ $node -eq 0 ]; then
expected_range="$nr_cpus_per_node-$((nr_cpus - 1))"
elif [ $node -eq $((nr_nodes - 1)) ]; then
expected_range="0-$((nr_cpus - nr_cpus_per_node - 1))"
else
expected_range="0-$((nr_cpus_per_node*node-1)),$((nr_cpus_per_node*(node+1)))-$nr_cpus"
fi
write "all,^nodes:$node" 0 "cpumap: $expected_range"
done
fi
echo "# A few attempts of pinning to a random range of nodes" >> $outfile
if [ $nr_nodes -gt 1 ]; then
for i in `seq 0 3`; do
nodea=$(($RANDOM % nr_nodes))
range=$((nr_nodes - nodea))
nodeb=$(($RANDOM % range))
nodebb=$((nodea + nodeb))
# this assumes that the first $nr_cpus_per_node (from cpu
# 0 to cpu $nr_cpus_per_node-1) are assigned to the first node
# (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node
# to 2*$nr_cpus_per_node-1) are assigned to the second node (node
# 1), etc. Expect failures if that is not the case.
if [ $nodea -eq 0 ] && [ $nodebb -eq $((nr_nodes - 1)) ]; then
expected_range="all"
else
expected_range="$((nr_cpus_per_node*nodea))-$((nr_cpus_per_node*(nodebb+1) - 1))"
fi
write "nodes:$nodea-$nodebb" 0 "cpumap: $expected_range"
done
fi
echo "# A few attempts of pinning to a node but excluding one random cpu" >> $outfile
if [ $nr_nodes -gt 1 ]; then
for i in `seq 0 3`; do
node=$(($RANDOM % nr_nodes))
# this assumes that the first $nr_cpus_per_node (from cpu
# 0 to cpu $nr_cpus_per_node-1) are assigned to the first node
# (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node
# to 2*$nr_cpus_per_node-1) are assigned to the second node (node
# 1), etc. Expect failures if that is not the case.
cpu=$(($RANDOM % nr_cpus_per_node + nr_cpus_per_node*node))
if [ $cpu -eq $((nr_cpus_per_node*node)) ]; then
expected_range="$((nr_cpus_per_node*node + 1))-$((nr_cpus_per_node*(node+1) - 1))"
elif [ $cpu -eq $((nr_cpus_per_node*node + 1)) ]; then
expected_range="$((nr_cpus_per_node*node)),$((nr_cpus_per_node*node + 2))-$((nr_cpus_per_node*(node+1) - 1))"
elif [ $cpu -eq $((nr_cpus_per_node*(node+1) - 2)) ]; then
expected_range="$((nr_cpus_per_node*node))-$((nr_cpus_per_node*(node+1) - 3)),$((nr_cpus_per_node*(node+1) - 1))"
elif [ $cpu -eq $((nr_cpus_per_node*(node+1) - 1)) ]; then
expected_range="$((nr_cpus_per_node*node))-$((nr_cpus_per_node*(node+1) - 2))"
else
expected_range="$((nr_cpus_per_node*node))-$((cpu - 1)),$((cpu + 1))-$((nr_cpus_per_node*(node+1) - 1))"
fi
write "nodes:$node,^$cpu" 0 "cpumap: $expected_range"
done
fi
run $outfile