1#!/bin/bash 2 3set -e 4 5if [ -x ./xl ] ; then 6 export LD_LIBRARY_PATH=.:../libxc:../xenstore: 7 XL=./xl 8else 9 XL=xl 10fi 11 12fprefix=tmp.check-xl-vcpupin-parse 13outfile=check-xl-vcpupin-parse.data 14 15usage () { 16cat <<END 17usage: $0 [options] 18 19Tests various vcpu-pinning strings. If run without arguments acts 20as follows: 21 - generates some test data and saves them in $outfile; 22 - tests all the generated configurations (reading them back from 23 $outfile). 24 25An example of a test vector file is provided in ${outfile}-example. 26 27Options: 28 -h prints this message 29 -r seed uses seed for initializing the rundom number generator 30 (default: the script PID) 31 -s string tries using string as a vcpu pinning configuration and 32 reports whether that succeeds or not 33 -o ofile save the test data in ofile (default: $outfile) 34 -i ifile read test data from ifile 35END 36} 37 38expected () { 39 cat >$fprefix.expected 40} 41 42# by default, re-seed with our PID 43seed=$$ 44failures=0 45 46# Execute one test and check the result against the provided 47# rc value and output 48one () { 49 expected_rc=$1; shift 50 printf "test case %s...\n" "$*" 51 set +e 52 ${XL} -N vcpu-pin 0 all "$@" </dev/null >$fprefix.actual 2>/dev/null 53 actual_rc=$? 54 if [ $actual_rc != $expected_rc ]; then 55 diff -u $fprefix.expected $fprefix.actual 56 echo >&2 "test case \`$*' failed ($actual_rc $diff_rc)" 57 failures=$(( $failures + 1 )) 58 fi 59 set -e 60} 61 62# Write an entry in the test vector file. Format is as follows: 63# test-string*expected-rc*expected-output 64write () { 65 printf "$1*$2*$3\n" >> $outfile 66} 67 68complete () { 69 if [ "$failures" = 0 ]; then 70 echo all ok.; exit 0 71 else 72 echo "$failures tests failed."; exit 1 73 fi 74} 75 76# Test a specific pinning string 77string () { 78 expected_rc=$1; shift 79 printf "test case %s...\n" "$*" 80 set +e 81 ${XL} -N vcpu-pin 0 all "$@" &> /dev/null 82 actual_rc=$? 83 set -e 84 85 if [ $actual_rc != $expected_rc ]; then 86 echo >&2 "test case \`$*' failed ($actual_rc)" 87 else 88 echo >&2 "test case \`$*' succeeded" 89 fi 90 91 exit 0 92} 93 94# Read a test vector file (provided as $1) line by line and 95# test all the entries it contains 96run () 97{ 98 while read line 99 do 100 if [ ${line:0:1} != '#' ]; then 101 test_string="`echo $line | cut -f1 -d'*'`" 102 exp_rc="`echo $line | cut -f2 -d'*'`" 103 exp_output="`echo $line | cut -f3 -d'*'`" 104 105 expected <<END 106$exp_output 107END 108 one $exp_rc "$test_string" 109 fi 110 done < $1 111 112 complete 113 114 exit 0 115} 116 117while getopts "hr:s:o:i:" option 118do 119 case $option in 120 h) 121 usage 122 exit 0 123 ;; 124 r) 125 seed=$OPTARG 126 ;; 127 s) 128 string 0 "$OPTARG" 129 ;; 130 o) 131 outfile=$OPTARG 132 ;; 133 i) 134 run $OPTARG 135 ;; 136 esac 137done 138 139#---------- test data ---------- 140# 141nr_cpus=`xl info | grep nr_cpus | cut -f2 -d':'` 142nr_nodes=`xl info | grep nr_nodes | cut -f2 -d':'` 143nr_cpus_per_node=`xl info -n | sed '/cpu:/,/numa_info/!d' | head -n -1 | \ 144 awk '{print $4}' | uniq -c | tail -1 | awk '{print $1}'` 145cat >$outfile <<END 146# WARNING: some of these tests are topology based tests. 147# Expect failures if the topology is not detected correctly 148# detected topology: $nr_cpus CPUs, $nr_nodes nodes, $nr_cpus_per_node CPUs per node. 149# 150# seed used for random number generation: seed=${seed}. 151# 152# Format is as follows: 153# test-string*expected-return-code*expected-output 154# 155END 156 157# Re-seed the random number generator 158RANDOM=$seed 159 160echo "# Testing a wrong configuration" >> $outfile 161write foo 255 "" 162 163echo "# Testing the 'all' syntax" >> $outfile 164write "all" 0 "cpumap: all" 165write "nodes:all" 0 "cpumap: all" 166write "all,nodes:all" 0 "cpumap: all" 167write "all,^nodes:0,all" 0 "cpumap: all" 168 169echo "# Testing the empty cpumap case" >> $outfile 170write "^0" 0 "cpumap: none" 171 172echo "# A few attempts of pinning to just one random cpu" >> $outfile 173if [ $nr_cpus -gt 1 ]; then 174 for i in `seq 0 3`; do 175 cpu=$(($RANDOM % nr_cpus)) 176 write "$cpu" 0 "cpumap: $cpu" 177 done 178fi 179 180echo "# A few attempts of pinning to all but one random cpu" >> $outfile 181if [ $nr_cpus -gt 2 ]; then 182 for i in `seq 0 3`; do 183 cpu=$(($RANDOM % nr_cpus)) 184 if [ $cpu -eq 0 ]; then 185 expected_range="1-$((nr_cpus - 1))" 186 elif [ $cpu -eq 1 ]; then 187 expected_range="0,2-$((nr_cpus - 1))" 188 elif [ $cpu -eq $((nr_cpus - 2)) ]; then 189 expected_range="0-$((cpu - 1)),$((nr_cpus - 1))" 190 elif [ $cpu -eq $((nr_cpus - 1)) ]; then 191 expected_range="0-$((nr_cpus - 2))" 192 else 193 expected_range="0-$((cpu - 1)),$((cpu + 1))-$((nr_cpus - 1))" 194 fi 195 write "all,^$cpu" 0 "cpumap: $expected_range" 196 done 197fi 198 199echo "# A few attempts of pinning to a random range of cpus" >> $outfile 200if [ $nr_cpus -gt 2 ]; then 201 for i in `seq 0 3`; do 202 cpua=$(($RANDOM % nr_cpus)) 203 range=$((nr_cpus - cpua)) 204 cpub=$(($RANDOM % range)) 205 cpubb=$((cpua + cpub)) 206 if [ $cpua -eq $cpubb ]; then 207 expected_range="$cpua" 208 else 209 expected_range="$cpua-$cpubb" 210 fi 211 write "$expected_range" 0 "cpumap: $expected_range" 212 done 213fi 214 215echo "# A few attempts of pinning to just one random node" >> $outfile 216if [ $nr_nodes -gt 1 ]; then 217 for i in `seq 0 3`; do 218 node=$(($RANDOM % nr_nodes)) 219 # this assumes that the first $nr_cpus_per_node (from cpu 220 # 0 to cpu $nr_cpus_per_node-1) are assigned to the first node 221 # (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node 222 # to 2*$nr_cpus_per_node-1) are assigned to the second node (node 223 # 1), etc. Expect failures if that is not the case. 224 write "nodes:$node" 0 "cpumap: $((nr_cpus_per_node*node))-$((nr_cpus_per_node*(node+1)-1))" 225 done 226fi 227 228echo "# A few attempts of pinning to all but one random node" >> $outfile 229if [ $nr_nodes -gt 1 ]; then 230 for i in `seq 0 3`; do 231 node=$(($RANDOM % nr_nodes)) 232 # this assumes that the first $nr_cpus_per_node (from cpu 233 # 0 to cpu $nr_cpus_per_node-1) are assigned to the first node 234 # (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node 235 # to 2*$nr_cpus_per_node-1) are assigned to the second node (node 236 # 1), etc. Expect failures if that is not the case. 237 if [ $node -eq 0 ]; then 238 expected_range="$nr_cpus_per_node-$((nr_cpus - 1))" 239 elif [ $node -eq $((nr_nodes - 1)) ]; then 240 expected_range="0-$((nr_cpus - nr_cpus_per_node - 1))" 241 else 242 expected_range="0-$((nr_cpus_per_node*node-1)),$((nr_cpus_per_node*(node+1)))-$nr_cpus" 243 fi 244 write "all,^nodes:$node" 0 "cpumap: $expected_range" 245 done 246fi 247 248echo "# A few attempts of pinning to a random range of nodes" >> $outfile 249if [ $nr_nodes -gt 1 ]; then 250 for i in `seq 0 3`; do 251 nodea=$(($RANDOM % nr_nodes)) 252 range=$((nr_nodes - nodea)) 253 nodeb=$(($RANDOM % range)) 254 nodebb=$((nodea + nodeb)) 255 # this assumes that the first $nr_cpus_per_node (from cpu 256 # 0 to cpu $nr_cpus_per_node-1) are assigned to the first node 257 # (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node 258 # to 2*$nr_cpus_per_node-1) are assigned to the second node (node 259 # 1), etc. Expect failures if that is not the case. 260 if [ $nodea -eq 0 ] && [ $nodebb -eq $((nr_nodes - 1)) ]; then 261 expected_range="all" 262 else 263 expected_range="$((nr_cpus_per_node*nodea))-$((nr_cpus_per_node*(nodebb+1) - 1))" 264 fi 265 write "nodes:$nodea-$nodebb" 0 "cpumap: $expected_range" 266 done 267fi 268 269echo "# A few attempts of pinning to a node but excluding one random cpu" >> $outfile 270if [ $nr_nodes -gt 1 ]; then 271 for i in `seq 0 3`; do 272 node=$(($RANDOM % nr_nodes)) 273 # this assumes that the first $nr_cpus_per_node (from cpu 274 # 0 to cpu $nr_cpus_per_node-1) are assigned to the first node 275 # (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node 276 # to 2*$nr_cpus_per_node-1) are assigned to the second node (node 277 # 1), etc. Expect failures if that is not the case. 278 cpu=$(($RANDOM % nr_cpus_per_node + nr_cpus_per_node*node)) 279 if [ $cpu -eq $((nr_cpus_per_node*node)) ]; then 280 expected_range="$((nr_cpus_per_node*node + 1))-$((nr_cpus_per_node*(node+1) - 1))" 281 elif [ $cpu -eq $((nr_cpus_per_node*node + 1)) ]; then 282 expected_range="$((nr_cpus_per_node*node)),$((nr_cpus_per_node*node + 2))-$((nr_cpus_per_node*(node+1) - 1))" 283 elif [ $cpu -eq $((nr_cpus_per_node*(node+1) - 2)) ]; then 284 expected_range="$((nr_cpus_per_node*node))-$((nr_cpus_per_node*(node+1) - 3)),$((nr_cpus_per_node*(node+1) - 1))" 285 elif [ $cpu -eq $((nr_cpus_per_node*(node+1) - 1)) ]; then 286 expected_range="$((nr_cpus_per_node*node))-$((nr_cpus_per_node*(node+1) - 2))" 287 else 288 expected_range="$((nr_cpus_per_node*node))-$((cpu - 1)),$((cpu + 1))-$((nr_cpus_per_node*(node+1) - 1))" 289 fi 290 write "nodes:$node,^$cpu" 0 "cpumap: $expected_range" 291 done 292fi 293 294run $outfile 295