[libvirt] [PATCH] [TCK] network: create networks and check for exected results

Eric Blake eblake at redhat.com
Tue Oct 26 23:08:39 UTC 2010


subject line: s/exected/expected/

On 10/22/2010 06:06 PM, Stefan Berger wrote:
> Derived from the nwfilter test program, this one works with libvirt's
> networks. It creates networks from provided xml files and checks for
> expected configuration in iptables, running processes and virsh output
> using provided data files with commands to execute and the expected
> results for after creating the network and after tearing it down
> (*.post.dat). 3 tests are currently not passing due to a bug in
> libvirt...

Now that the libvirt bug is squashed,

>
> Signed-off-by: Stefan Berger<stefanb at us.ibm.com>
>
> ---
>   Build.PL                                                   |    2
>   scripts/networks/100-apply-verify-host.t                   |   10
>   scripts/networks/networkApplyTest.sh                       |  343 +++++++++++++
>   scripts/networks/networkxml2hostout/tck-testnet-1.dat      |   11
>   scripts/networks/networkxml2hostout/tck-testnet-1.post.dat |    4
>   scripts/networks/networkxml2hostout/tck-testnet-2.dat      |    8
>   scripts/networks/networkxml2hostout/tck-testnet-2.post.dat |    4
>   scripts/networks/networkxml2xmlin/tck-testnet-1.xml        |   12
>   scripts/networks/networkxml2xmlin/tck-testnet-2.xml        |   12
>   9 files changed, 405 insertions(+), 1 deletion(-)
>
> Index: libvirt-tck/scripts/networks/networkApplyTest.sh
> ===================================================================
> --- /dev/null
> +++ libvirt-tck/scripts/networks/networkApplyTest.sh
> @@ -0,0 +1,343 @@
> +#!/bin/bash

Is this really bash-specific, or can we shoot for /bin/sh?

> +
> +VIRSH=virsh
> +
> +uri=
> +if [ "x${LIBVIRT_TCK_CONFIG}x" != "xx" ]; then
> +    uri_exp=`cat ${LIBVIRT_TCK_CONFIG} | grep "^uri\s*=" | sed -e 's/uri\s*=\s*//' | tail -n 1`

If it's bash-specific, I'd prefer to see $() rather than ``.  But until 
I see a definite bash-ism, I'd shoot for /bin/sh instead.

Missing "" around ${LIBVIRT_TCK_CONFIG}.

\s is non-portable; you can't expect either grep or sed to understand it.

cat | grep | sed | tail wastes 3 processes; you can do it all with a 
single sed:

uri_exp=`sed -n '/^uri[	 ]*=[	 ]*/ {
   s///
   h
}
$ {
   x
   p
}' < "$LIBVIRT_TCK_CONFIG"`

[Sed deciphered: for lines that match ^uri\s*=\s*, delete the matched 
prefix, and put the line in hold space, overriding anything already 
there. Then, at end of input, exchange the hold space back out and print 
it, which will thus be the last uri= line found.]


> +    if [ "x${uri_exp}x" != "xx" ]; then
> +        eval "uri=${uri_exp}"

This is unsafe - it can end up executing arbitrary user input from the 
config file.  And why do you need the eval in the first place?  Isn't it 
just sufficient to do:

uri=${uri_exp}

Also, this is not robust if $uri_exp is inherited from the environment, 
because you failed to initialize uri_exp when LIBVIRT_TCK_CONFIG is not 
specified.

> +    fi
> +    if [ "x${uri}x" == "xx" ]; then
> +        uri="qemu:///system"
> +    fi
> +else
> +    uri="qemu:///system"
> +fi
> +LIBVIRT_URI=${uri}
> +
> +
> +FLAG_WAIT="$((1<<0))"

$(()) assumes POSIX, but is not portable to Solaris.  It's easy to work 
around:

FLAG_WAIT=1

> +FLAG_VERBOSE="$((1<<2))"

FLAG_VERBOSE=2

> +FLAG_LIBVIRT_TEST="$((1<<3))"

FLAG_LIBVIRT_TEST=4

> +FLAG_TAP_TEST="$((1<<4))"

FLAG_TAP_TEST=8

> +FLAG_FORCE_CLEAN="$((1<<5))"

FLAG_FORCE_CLEAN=16

> +
> +failctr=0
> +passctr=0
> +attachfailctr=0
> +attachctr=0
> +
> +TAP_FAIL_LIST=""
> +TAP_FAIL_CTR=0
> +TAP_TOT_CTR=0
> +
> +function usage() {
> +  local cmd="$0"

local is a non-POSIX bash-ism.  Also, $0 is non-portable to some 
versions of zsh; better would be:

cmd="$0"
function_usage() {
   ... $cmd ...


> +cat<<EOF
> +Usage: ${cmd} [--help|-h|-?] [--noattach] [--wait] [--verbose]
> +              [--libvirt-test] [--tap-test]
> +
> +Options:
> + --help,-h,-?   : Display this help screen.
> + --wait         : Wait for the user to press the enter key once an error
> +                  was detected
> + --verbose      : Verbose output
> + --libvirt-test : Use the libvirt test output format
> + --tap-test     : TAP format output
> + --force        : Allow the automatic cleaning of VMs and networks
> +                  previously created by the TCK test suite
> +
> +This test creates libvirt 'networks' and checks for expected results
> +(iptables, running processes (dnsmasq)) using provided xml and data
> +file respectively.
> +EOF
> +}
> +
> +
> +function tap_fail() {
> +  echo "not ok $1 - ${2:0:66}"

Bash-ism; do you really have to truncate to just the first 66 bytes, or 
can you use the portable:

echo "not ok $1 - $2"

assuming that $2 does not contain any \ (if it does, you'd have to use 
'printf %s\\n' instead of 'echo').

> +  TAP_FAIL_LIST+="$1 "

Bash-ism; you can use the portable:

TAP_FAIL_LIST="$TAP_FAIL_LIST$1 "

> +  ((TAP_FAIL_CTR++))

Bash-ism; you can use the portable:

TAP_FAIL_CTR=`expr $TAP_FAIL_CTR + 1`

> +  ((TAP_TOT_CTR++))

Likewise.

> +}
> +
> +function tap_pass() {
> +  echo "ok $1 - ${2:0:70}"
> +  ((TAP_TOT_CTR++))

Similar comments.

> +}
> +
> +function tap_final() {
> +  local okay

Another use of local.

> +
> +  [ -n "${TAP_FAIL_LIST}" ]&&  echo "FAILED tests ${TAP_FAIL_LIST}"
> +
> +  okay=`echo "($TAP_TOT_CTR-$TAP_FAIL_CTR)*100/$TAP_TOT_CTR" | bc -l`
> +  echo "Failed ${TAP_FAIL_CTR}/${TAP_TOT_CTR} tests, ${okay:0:5}% okay"

Bash-ism; do we really need to output percentage passing, or can we just 
get rid of $okay?

> +}
> +
> +# A wrapper for mktemp in case it does not exist
> +# Echos the name of a temporary file.
> +function mktmpfile() {
> +  local tmp

Another local.

> +  type -P mktemp>  /dev/null

Bash-ism.

> +  if [ $? -eq 0 ]; then
> +    tmp=$(mktemp -t nwfvmtest.XXXXXX)
> +    echo ${tmp}
> +  else
> +    while :; do
> +      tmp="/tmp/nwfvmtest.${RANDOM}"

Bash-ism, with a VERY predictable filename on dash; two runs are 
guaranteed to collide.

> +      if [ ! -f ${tmp} ]; then
> +          touch ${tmp}
> +          chmod 666 ${tmp}

Ouch - that's multiple security holes.  Someone could inject a symlink 
at $tmp in between your [ ! f ] and touch, and your chmod makes the file 
world-writeable.  All told, that means you may have just granted an 
arbitrary user write access to a file they shouldn't know about, just 
because they won the race at creating the symlink.

> +          echo ${tmp}
> +          break
> +      fi
> +    done
> +  fi
> +  return 0
> +}

Rather than trying to securely create a temporary file in shell (which 
is nigh impossible if mktemp doesn't exist), it is MUCH better to create 
a secure temporary directory, then create arbitrary files within that 
directory.  Here's how autoconf creates secure directories:

# Create a (secure) tmp directory for tmp files.
{
   tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
   test -n "$tmp" && test -d "$tmp"
}  ||
{
   tmp=./conf$$-$RANDOM
   (umask 077 && mkdir "$tmp")
} || { echo failed... >&2; exit 1; }

And while that use of $RANDOM will still be worthless on dash, the 
addition of $$ adds a bit of collision avoidance, and the atomicity of 
mkdir is the final piece of the puzzle to guarantee that you did not 
lose a race.

> +
> +
> +function checkExpectedOutput() {
> +  local xmlfile="$1"
> +  local datafile="$2"
> +  local flags="$3"
> +  local skipregex="$4"
> +  local cmd line tmpfile tmpfile2 skip

More instances of local.

> +
> +  tmpfile=`mktmpfile`
> +  tmpfile2=`mktmpfile`
> +
> +  exec 4<${datafile}
> +
> +  read<&4
> +  line="${REPLY}"
> +
> +  while [ "x${line}x" != "xx" ]; do
> +    cmd=`echo ${line##\#}`

Bash-ism, and underquoted if $line contains spaces.  You could use:

case $line in
   #*) cmd=`echo "$line" | sed 's/^#//'` ;;
   *) cmd=$line ;;
esac

> +
> +    skip=0
> +    if [ "x${skipregex}x" != "xx" ]; then
> +    	skip=`echo ${cmd} | grep -c -E ${skipregex}`

On some systems, you still have to use egrep instead of grep -E. 
Usually, this involves populating $EGREP to one of the two variants up 
front.

> +    fi
> +
> +    eval ${cmd} 2>&1 | tee ${tmpfile} 1>/dev/null
> +
> +    rm ${tmpfile2} 2>/dev/null

This is usually written as rm -f $tmpfile2, rather than redirecting stderr.

> +    touch ${tmpfile2}

Removing and then recreating a temporary file is unsafe, if the 
temporary file did not already reside in a secure temporary directory. 
It's faster to do:

: >"$tmpfile2"

to do the truncation in one step, rather than the two-step rm/touch.

> +
> +    while [ 1 ]; do

This is generally written 'while :; do' in shell.

> +      read<&4
> +      line="${REPLY}"
> +
> +      if [ "${line:0:1}" == "#" ] || [ "x${line}x" == "xx"  ]; then

Bash-ism.  Portable alternative:

case $line in
   '' | #*) continue ;;
esac

> +
> +	if [ ${skip} -ne 0 ]; then

TAB indentation; libvirt-TCK is probably a bit more relaxed, but I'm 
rather used to space indentation.

> +	  break
> +	fi
> +
> +        diff ${tmpfile} ${tmpfile2}>/dev/null
> +
> +        if [ $? -ne 0 ]; then
> +          if [ $((flags&  FLAG_VERBOSE)) -ne 0 ]; then

Bash-ism.  What's setting $flags in the first place?  Can we re-write 
this to instead use 5 flag variables, which either contain : or false, 
so that you can do:

if $flag_verbose; then

> +            echo "FAIL ${xmlfile} : ${cmd}"
> +            diff ${tmpfile} ${tmpfile2}
> +          fi
> +          ((failctr++))

bash-ism

> +          if [ $((flags&  FLAG_WAIT)) -ne 0 ]; then
> +                echo "tmp files: $tmpfile, $tmpfile2"
> +          	echo "Press enter"
> +          	read
> +          fi
> +          [ $((flags&  FLAG_LIBVIRT_TEST)) -ne 0 ]&&  \
> +              test_result $((passctr+failctr)) "" 1
> +          [ $((flags&  FLAG_TAP_TEST)) -ne 0 ]&&  \
> +             tap_fail $((passctr+failctr)) "${xmlfile} : ${cmd}"
> +        else
> +          ((passctr++))
> +          [ $((flags&  FLAG_VERBOSE)) -ne 0 ]&&  \
> +              echo "PASS ${xmlfile} : ${cmd}"
> +          [ $((flags&  FLAG_LIBVIRT_TEST)) -ne 0 ]&&  \
> +              test_result $((passctr+failctr)) "" 0
> +          [ $((flags&  FLAG_TAP_TEST)) -ne 0 ]&&  \
> +              tap_pass $((passctr+failctr)) "${xmlfile} : ${cmd}"

Etc.

> +        fi
> +
> +        break
> +
> +      fi
> +      echo "${line}">>  ${tmpfile2}
> +    done
> +  done
> +
> +  exec 4>&-
> +
> +  rm -rf "${tmpfile}" "${tmpfile2}" 2>/dev/null

Don't mix rm -f and redirecting stderr; do only one or the other (I 
prefer -f).

> +}
> +
> +
> +function doTest() {
> +  local xmlfile="$1"
> +  local datafile="$2"
> +  local postdatafile="$3"
> +  local flags="$4"
> +  local netname

More use of local.

> +
> +  if [ ! -r "${xmlfile}" ]; then
> +    echo "FAIL : Cannot access filter XML file ${xmlfile}."
> +    return 1
> +  fi
> +
> +  netname=`cat "${xmlfile}" | sed -n 's/.*<name>\([[:print:]]*\)<.*/\1/p'`

Useless use of cat.

Unfortunately, it is not yet portable to use [[:print:]] in sed.  The 
alternative is:

netname=`sed -n 's/.*<name>\([^<]*\).*/\1p' < "$xmlfile"`

> +
> +  ${VIRSH} net-create "${xmlfile}">  /dev/null
> +
> +  checkExpectedOutput "${xmlfile}" "${datafile}" "${flags}" ""
> +
> +  ${VIRSH} net-destroy "${netname}">  /dev/null
> +
> +  if [ -r ${postdatafile} ]; then
> +    checkExpectedOutput "${xmlfile}" "${postdatafile}" "${flags}" ""
> +  fi
> +
> +  return 0
> +}
> +
> +
> +function runTests() {
> +  local xmldir="$1"
> +  local hostoutdir="$2"
> +  local flags="$3"
> +  local datafiles f c
> +  local tap_total=0 ctr=0

More use of local.

> +
> +  pushd ${PWD}>  /dev/null

bash-ism.

> +  cd ${hostoutdir}
> +  datafiles=`ls *.dat`
> +  popd>  /dev/null

Rather than rely on pushd/popd, you could do:

datafiles=`cd "$hostoutdir" && echo *.dat`

> +
> +  if [ $((flags&  FLAG_TAP_TEST)) -ne 0 ]; then

again wondering if we can use a /bin/sh portable means of tracking flags.

> +    # Need to count the number of total tests
> +    for fil in ${datafiles}; do
> +      c=$(grep -c "^#" ${hostoutdir}/${fil})
> +      ((tap_total+=c))
> +      ((ctr++))

bash-isms

> +    done
> +    echo "1..${tap_total}"
> +  fi
> +
> +  for fil in `echo "${datafiles}" | grep -v "\.post\.dat$"`; do

Wasted subprocesses.  Why not:

for fil in $datafiles; do
   case $fil in
     *.post.dat) continue;;
   esac

> +    f=${fil%%.dat}

POSIX-ism that won't work on Solaris.  But the alternative requires 
forking a sed process, even on bash.

> +    doTest "${xmldir}/${f}.xml" "${hostoutdir}/${fil}" \
> +           "${hostoutdir}/${f}.post.dat" "${flags}"
> +  done
> +
> +  if [ $((flags&  FLAG_LIBVIRT_TEST)) -ne 0 ]; then
> +    test_final $((passctr+failctr)) $failctr

bash-isms

> +  elif [ $((flags&  FLAG_TAP_TEST)) -ne 0 ]; then
> +    tap_final
> +  else
> +    echo ""
> +    echo "Summary: ${failctr} failures, ${passctr} passes,"
> +    if [ ${attachctr} -ne 0 ]; then
> +      echo "         ${attachfailctr} interface attachment failures with ${attachctr} attempts"
> +    fi
> +  fi
> +}
> +
> +
> +function main() {
> +  local prgname="$0"
> +  local vm1 vm2
> +  local xmldir="networkxml2xmlin"
> +  local hostoutdir="networkxml2hostout"
> +  local res rc
> +  local flags

More uses of local

> +
> +  while [ $# -ne 0 ]; do
> +    case "$1" in
> +    --help|-h|-\?) usage ${prgname}; exit 0;;
> +    --wait)         ((flags |= FLAG_WAIT    ));;
> +    --verbose)      ((flags |= FLAG_VERBOSE ));;
> +    --libvirt-test) ((flags |= FLAG_LIBVIRT_TEST ));;
> +    --tap-test)     ((flags |= FLAG_TAP_TEST ));;
> +    --force)        ((flags |= FLAG_FORCE_CLEAN ));;

Ah; here's where you were setting $flags.  Like I said, it would be more 
portable to set five different variables; pre-set them to false, and 
then convert them to : if the command line option is supplied.  It makes 
testing avoid arithmetic in the first place:

flag_wait=false
case "$1" in
   --wait) flag_wait=:;;
...
esac
if $flag_wait; then
...
fi

> +    *) usage ${prgname}; exit 1;;
> +    esac
> +    shift 1
> +  done
> +
> +  if [ `uname` != "Linux" ]; then
> +    if [ $((flags&  FLAG_TAP_TEST)) -ne 0 ]; then
> +      echo "1..0 # Skipped: Only valid on Linux hosts"
> +    else
> +      echo "This script will only run on Linux."
> +    fi
> +    exit 1;
> +  fi
> +
> +  if [ $((flags&  FLAG_TAP_TEST)) -ne 0 ]; then
> +    if [ "${LIBVIRT_URI}" != "qemu:///system" ]; then
> +        echo "1..0 # Skipped: Only valid for Qemu system driver"
> +        exit 0
> +    fi
> +
> +    for name in `virsh list | awk '{print $2}'`
> +    do
> +      case ${name} in
> +      tck*)
> +        if [ "x${LIBVIRT_TCK_AUTOCLEAN}" == "x1" -o \
> +             $((flags&  FLAG_FORCE_CLEAN)) -ne 0 ]; then
> +          res=$(virsh destroy  ${name} 2>&1)
> +          res=$(virsh undefine ${name} 2>&1)
> +          if [ $? -ne 0 ]; then
> +            echo "Bail out! Could not undefine VM ${name}: ${res}"
> +            exit 0
> +          fi
> +        else
> +          echo "Bail out! TCK VMs from previous tests still exist, use --force to clean"
> +          exit 1
> +        fi
> +      esac
> +    done
> +
> +    for name in `virsh net-list | sed -n '3,$p'`
> +    do
> +      case ${name} in
> +      tck*)
> +        if [ "x${LIBVIRT_TCK_AUTOCLEAN}" == "x1" -o \
> +             $((flags&  FLAG_FORCE_CLEAN)) -ne 0 ]; then
> +          res=$(virsh net-destroy ${name} 2>&1)
> +          rc=$?
> +          res=$(virsh net-undefine ${name} 2>&1)
> +          if [ $rc -ne 0 -a $? -ne 0 ]; then
> +            echo "Bail out! Could not destroy/undefine network ${name}: ${res}"
> +            exit 1
> +          fi
> +        else
> +          echo "Bail out! Network ${name} already exists, use --force to clean"
> +          exit 1
> +        fi
> +      esac
> +    done
> +  fi
> +
> +  if [ $((flags&  FLAG_LIBVIRT_TEST)) -ne 0 ]; then
> +    pushd ${PWD}>  /dev/null

Another non-portable use of pushd.  If sourcing test-lib.sh leaves us in 
a different directory, then we should fix the bug in test-lib.sh.

> +    . test-lib.sh

This assumes that test-lib.sh is on $PATH; if you want to explicitly run 
the file in the current directory, it needs to be

. ./test-lib.sh

> +    if [ $? -ne 0 ]; then
> +        exit 1
> +    fi
> +    test_intro $this_test
> +    popd>  /dev/null
> +  fi
> +
> +  res=$(${VIRSH} capabilities 2>&1)
> +
> +  runTests "${xmldir}" "${hostoutdir}" "${flags}"
> +
> +  return 0
> +}
> +
> +main "$@"

Hopefully you aren't too depressed with me picking apart your shell 
scripting :)


> Index: libvirt-tck/scripts/networks/networkxml2hostout/tck-testnet-1.dat
> ===================================================================
> --- /dev/null
> +++ libvirt-tck/scripts/networks/networkxml2hostout/tck-testnet-1.dat
> @@ -0,0 +1,11 @@
> +#iptables -t nat -L -n | grep 10.1.2
> +MASQUERADE  tcp  --  10.1.2.0/24         !10.1.2.0/24         masq ports: 1024-65535
> +MASQUERADE  udp  --  10.1.2.0/24         !10.1.2.0/24         masq ports: 1024-65535
> +MASQUERADE  all  --  10.1.2.0/24         !10.1.2.0/24
> +#iptables -n -L FORWARD | grep 10.1.2

Oh, so you really DO want .dat files to specify a combination of shell 
commands to eval, followed by expected output of those commands.  Hmm, I 
probably missed that point in my shell script evaluation above.

> +ACCEPT     all  --  anywhere             10.1.2.0/24          state RELATED,ESTABLISHED
> +ACCEPT     all  --  10.1.2.0/24          anywhere
> +#ps aux | grep dnsmasq  | grep 10.1.2 | sed -n 's/.*\\(dnsmasq[[:print:]*]\\)/\\1/p'

Again, [[:print:]] is not portable to all sed; but given that your test 
only runs on Linux, I guess we can safely assume GNU (or busybox) sed, 
where it does work.

Should you be a little tighter on the first grep, to require '/dnsmasq '?

The second grep would match a10b1c2, which you didn't intend.  grep | 
sed wastes a process; you could do:

ps aux | sed -n '|/dnsmasq .*10\.1\.2\./ 
s/.*\\(dnsmasq[[:print:]*]\\)|\\1|p'

> +dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/tck-testnet.pid --conf-file=  --listen-address 10.1.2.1 --except-interface lo --dhcp-range 10.1.2.2,10.1.2.254 --dhcp-lease-max=253 --dhcp-no-override
> +#virsh net-list | grep tck-testnet
> +tck-testnet          active     no
> Index: libvirt-tck/scripts/networks/networkxml2xmlin/tck-testnet-1.xml
> ===================================================================
> --- /dev/null
> +++ libvirt-tck/scripts/networks/networkxml2xmlin/tck-testnet-1.xml
> @@ -0,0 +1,12 @@
> +<network>
> +<name>tck-testnet</name>
> +<uuid>aadc8920-502a-4774-ac2b-cd382a204d06</uuid>
> +<forward mode='nat'/>
> +<bridge name='testbr' stp='on' delay='0' />
> +<ip address='10.1.2.1' netmask='255.255.255.0'>
> +<dhcp>
> +<range start='10.1.2.2' end='10.1.2.254' />
> +</dhcp>
> +</ip>
> +</network>
> +
> Index: libvirt-tck/scripts/networks/networkxml2hostout/tck-testnet-2.dat
> ===================================================================
> --- /dev/null
> +++ libvirt-tck/scripts/networks/networkxml2hostout/tck-testnet-2.dat
> @@ -0,0 +1,8 @@
> +#iptables -L FORWARD  | grep 10.1.2
> +ACCEPT     all  --  anywhere             10.1.2.0/24
> +ACCEPT     all  --  10.1.2.0/24          anywhere
> +#iptables -t nat -L | grep 10.1.2
> +#ps aux | grep dnsmasq  | grep 10.1.2 | sed -n 's/.*\\(dnsmasq[[:print:]*]\\)/\\1/p'

same comments on grep|sed

> +dnsmasq --strict-order --bind-interfaces --pid-file=/var/run/libvirt/network/tck-testnet.pid --conf-file=  --listen-address 10.1.2.1 --except-interface lo --dhcp-range 10.1.2.2,10.1.2.254 --dhcp-lease-max=253 --dhcp-no-override
> +#virsh net-list | grep tck-testnet
> +tck-testnet          active     no
> Index: libvirt-tck/scripts/networks/networkxml2xmlin/tck-testnet-2.xml
> ===================================================================
> --- /dev/null
> +++ libvirt-tck/scripts/networks/networkxml2xmlin/tck-testnet-2.xml
> @@ -0,0 +1,12 @@
> +<network>
> +<name>tck-testnet</name>
> +<uuid>aadc8920-502a-4774-ac2b-cd382a204d06</uuid>
> +<forward mode='route'/>
> +<bridge name='testbr' stp='on' delay='0' />
> +<ip address='10.1.2.1' netmask='255.255.255.0'>
> +<dhcp>
> +<range start='10.1.2.2' end='10.1.2.254' />
> +</dhcp>
> +</ip>
> +</network>
> +
> Index: libvirt-tck/scripts/networks/100-apply-verify-host.t
> ===================================================================
> --- /dev/null
> +++ libvirt-tck/scripts/networks/100-apply-verify-host.t
> @@ -0,0 +1,10 @@
> +#!/bin/bash
> +
> +pwd=$(dirname $0)

Underquoted, if $0 contains spaces.  Technically, it could also be 
problematic if $0 starts with -, although that is less likely, and 
'dirname -- "$0"' is unfortunately not portable.

> +
> +pushd ${PWD}>  /dev/null
> +
> +cd ${pwd}
> +bash ./networkApplyTest.sh --tap-test
> +
> +popd>  /dev/null

I'm still not convinced whether we need to require bash for all of 
these.  What's wrong with:

#!/bin/sh
dir=`dirname "$0"`
(cd "$dir" && ./networkApplyTest.sh --tap-test)


> Index: libvirt-tck/scripts/networks/networkxml2hostout/tck-testnet-1.post.dat
> ===================================================================
> --- /dev/null
> +++ libvirt-tck/scripts/networks/networkxml2hostout/tck-testnet-1.post.dat
> @@ -0,0 +1,4 @@
> +#iptables -t nat -L -n | grep 10.1.2

This grep is too weak.  You want:

#iptables -t nat -L -n | grep ' 10\.1\.2'

> +#iptables -n -L FORWARD | grep 10.1.2
> +#ps aux | grep dnsmasq  | grep 10.1.2 | sed -n 's/.*\\(dnsmasq[[:print:]*]\\)/\\1/p'

Same grep | sed comments.

> +#virsh net-list | grep tck-testnet
> Index: libvirt-tck/scripts/networks/networkxml2hostout/tck-testnet-2.post.dat
> ===================================================================
> --- /dev/null
> +++ libvirt-tck/scripts/networks/networkxml2hostout/tck-testnet-2.post.dat
> @@ -0,0 +1,4 @@
> +#iptables -t nat -L -n | grep 10.1.2
> +#iptables -n -L FORWARD | grep 10.1.2
> +#ps aux | grep dnsmasq  | grep 10.1.2 | sed -n 's/.*\\(dnsmasq[[:print:]*]\\)/\\1/p'

And again.

> +#virsh net-list | grep tck-testnet
> Index: libvirt-tck/Build.PL
> ===================================================================
> --- libvirt-tck.orig/Build.PL
> +++ libvirt-tck/Build.PL
> @@ -29,7 +29,7 @@ sub process_pkgdata_files {
>           my $name = $File::Find::name;
>   	if (-d) {
>   	    $tck_dirs{$name} = [];
> -	} elsif (-f&&  (/\.t$/ || /\.sh$/ || /\.fwall$/ || /\.xml$/)) {
> +	} elsif (-f&&  /\.(t|sh|fwall|xml|dat)$/) {
>   	    push @{$tck_dirs{$dir}}, $name;
>   	}
>       };
>
>

Sorry for sounding so depressing; I'm very pleased to see your efforts 
in providing tests for the code you've written.  Even though this test 
is intended to be skipped on non-Linux, you still have to worry about 
merely parsing through the test on other platforms like Solaris, where 
/bin/sh won't understand the bash-isms and where /bin/bash is not 
guaranteed to exist.  But if we decide that requiring the presence of 
/bin/bash is acceptable for the TCK, then a lot of my review becomes 
irrelevant; but my comments about your mkstemp replacement being 
insecure are still applicable even in that case.

-- 
Eric Blake   eblake at redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org




More information about the libvir-list mailing list