[virt-tools-list] [PATCH libosinfo 4/4] Add a test case which validates all schemas in tree

Daniel P. Berrange berrange at redhat.com
Thu Feb 23 17:20:02 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

---
 Makefile.am            |    4 +-
 build-aux/mktempd      |  135 ++++++++++++++++++++++++++++
 test/Makefile.am       |   30 +++++--
 test/test-lib.sh       |  228 ++++++++++++++++++++++++++++++++++++++++++++++++
 test/test-xml-validate |   48 ++++++++++
 5 files changed, 438 insertions(+), 7 deletions(-)
 create mode 100755 build-aux/mktempd
 create mode 100644 test/test-lib.sh
 create mode 100755 test/test-xml-validate

diff --git a/Makefile.am b/Makefile.am
index a8df435..e63f391 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,9 @@ EXTRA_DIST = \
   COPYING.LIB \
   libosinfo.spec \
   libosinfo.spec.in \
-  mingw32-libosinfo.spec.in
+  mingw32-libosinfo.spec.in \
+  build-aux/mktempd \
+  $(NULL)
 
 DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc
 
diff --git a/build-aux/mktempd b/build-aux/mktempd
new file mode 100755
index 0000000..ab3cf14
--- /dev/null
+++ b/build-aux/mktempd
@@ -0,0 +1,135 @@
+#!/bin/sh
+# Create a temporary directory, much like mktemp -d does.
+
+# Copyright (C) 2007-2012 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# 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.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Written by Jim Meyering.
+
+# Usage: mktempd /tmp phoey.XXXXXXXXXX
+
+# First, try to use the mktemp program.
+# Failing that, we'll roll our own mktemp-like function:
+#  - try to get random bytes from /dev/urandom
+#  - failing that, generate output from a combination of quickly-varying
+#      sources and gzip.  Ignore non-varying gzip header, and extract
+#      "random" bits from there.
+#  - given those bits, map to file-name bytes using tr, and try to create
+#      the desired directory.
+#  - make only $MAX_TRIES attempts
+
+ME=`basename "$0"`
+die() { echo >&2 "$ME: $@"; exit 1; }
+
+MAX_TRIES=4
+
+rand_bytes()
+{
+  n=$1
+
+  chars=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
+
+  dev_rand=/dev/urandom
+  if test -r "$dev_rand"; then
+    # Note: 256-length($chars) == 194; 3 copies of $chars is 186 + 8 = 194.
+    dd ibs=$n count=1 if="$dev_rand" 2>/dev/null \
+      | tr -c $chars 01234567$chars$chars$chars
+    return
+  fi
+
+  cmds='date; date +%N; free; who -a; w; ps auxww; ps ef; netstat -n'
+  data=` (eval "$cmds") 2>&1 | gzip `
+
+  n_plus_50=`expr $n + 50`
+
+  # Ensure that $data has length at least 50+$n
+  while :; do
+    len=`echo "$data"|wc -c`
+    test $n_plus_50 -le $len && break;
+    data=` (echo "$data"; eval "$cmds") 2>&1 | gzip `
+  done
+
+  echo "$data" \
+    | dd bs=1 skip=50 count=$n 2>/dev/null \
+    | tr -c $chars 01234567$chars$chars$chars
+}
+
+mktempd()
+{
+  case $# in
+  2);;
+  *) die "Usage: $ME DIR TEMPLATE";;
+  esac
+
+  destdir=$1
+  template=$2
+
+  # Disallow any trailing slash on specified destdir:
+  # it would subvert the post-mktemp "case"-based destdir test.
+  case $destdir in
+  /) ;;
+  */) die "invalid destination dir: remove trailing slash(es)";;
+  esac
+
+  case $template in
+  *XXXX) ;;
+  *) die "invalid template: $template (must have a suffix of at least 4 X's)";;
+  esac
+
+  fail=0
+
+  # First, try to use mktemp.
+  d=`env -u TMPDIR mktemp -d -t -p "$destdir" "$template" 2>/dev/null` \
+    || fail=1
+
+  # The resulting name must be in the specified directory.
+  case $d in "$destdir"*);; *) fail=1;; esac
+
+  # It must have created the directory.
+  test -d "$d" || fail=1
+
+  # It must have 0700 permissions.  Handle sticky "S" bits.
+  perms=`ls -dgo "$d" 2>/dev/null|tr S -` || fail=1
+  case $perms in drwx------*) ;; *) fail=1;; esac
+
+  test $fail = 0 && {
+    echo "$d"
+    return
+  }
+
+  # If we reach this point, we'll have to create a directory manually.
+
+  # Get a copy of the template without its suffix of X's.
+  base_template=`echo "$template"|sed 's/XX*$//'`
+
+  # Calculate how many X's we've just removed.
+  template_length=`echo "$template" | wc -c`
+  nx=`echo "$base_template" | wc -c`
+  nx=`expr $template_length - $nx`
+
+  err=
+  i=1
+  while :; do
+    X=`rand_bytes $nx`
+    candidate_dir="$destdir/$base_template$X"
+    err=`mkdir -m 0700 "$candidate_dir" 2>&1` \
+      && { echo "$candidate_dir"; return; }
+    test $MAX_TRIES -le $i && break;
+    i=`expr $i + 1`
+  done
+  die "$err"
+}
+
+mktempd "$@"
diff --git a/test/Makefile.am b/test/Makefile.am
index 94543ef..83ecd7d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -101,12 +101,30 @@ test_treeuris_LDADD = $(COMMON_LDADD)
 test_treeuris_CFLAGS = $(COMMON_CFLAGS)
 test_treeuris_SOURCES = test-treeuris.c
 
-TESTS = $(check_PROGRAMS)
-
-TESTS_ENVIRONMENT = \
-	LC_ALL=C \
-	G_SLICE=always-malloc G_DEBUG=gc-friendly \
+TEST_SCRIPT_FILES = \
+	test-xml-validate
+
+TESTS = $(check_PROGRAMS) \
+	$(TEST_SCRIPT_FILES)
+	$(NULL)
+
+EXTRA_DIST += \
+	$(TEST_SCRIPT_FILES) \
+	test-lib.sh \
+	$(NULL)
+
+TESTS_ENVIRONMENT =						\
+	abs_top_builddir=$(lv_abs_top_builddir)			\
+	abs_top_srcdir=`cd '$(top_srcdir)'; pwd`		\
+	abs_builddir=`pwd`					\
+	abs_srcdir=`cd '$(srcdir)'; pwd`			\
+	CONFIG_HEADER="`cd '$(top_builddir)'; pwd`/config.h"	\
+	PATH="$(path_add)$(PATH_SEPARATOR)$$PATH"		\
+	SHELL="$(SHELL)"					\
+	LIBVIRT_DRIVER_DIR="$(abs_top_builddir)/src/.libs"	\
+	LC_ALL=C						\
+	G_SLICE=always-malloc G_DEBUG=gc-friendly		\
 	$(VG)
 
 valgrind:
-	$(MAKE) check VG="libtool --mode=execute valgrind --quiet --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=20  --suppressions=osinfo.suppression"
+	$(MAKE) check VG="libtool --mode=execute valgrind --quiet --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=20 --suppressions=osinfo.suppression"
diff --git a/test/test-lib.sh b/test/test-lib.sh
new file mode 100644
index 0000000..918bf73
--- /dev/null
+++ b/test/test-lib.sh
@@ -0,0 +1,228 @@
+# source this file; set up for tests
+
+test -z "$abs_srcdir" && abs_srcdir=$(pwd)
+test -z "$abs_builddir" && abs_builddir=$(pwd)
+test -z "$abs_top_srcdir" && abs_top_srcdir=$(pwd)/..
+test -z "$abs_top_builddir" && abs_top_builddir=$(pwd)/..
+test -z "$LC_ALL" && LC_ALL=C
+
+# Skip this test if the shell lacks support for functions.
+unset function_test
+eval 'function_test() { return 11; }; function_test'
+if test $? != 11; then
+  echo "$0: /bin/sh lacks support for functions; skipping this test." 1>&2
+  (exit 77); exit 77
+fi
+
+test_intro()
+{
+  name=$1
+  if test "$verbose" = "0" ; then
+    echo "TEST: $name"
+    printf "      "
+  fi
+}
+
+test_result()
+{
+  counter=$1
+  name=$2
+  status=$3
+  if test "$verbose" = "0" ; then
+    mod=`expr \( $counter + 40 - 1 \) % 40`
+    if test "$counter" != 1 && test "$mod" = 0 ; then
+        printf " %-3d\n" `expr $counter - 1`
+        printf "      "
+    fi
+    if test "$status" = "0" ; then
+        printf "."
+    else
+        printf "!"
+    fi
+  else
+    if test "$status" = "0" ; then
+      printf "%3d) %-60s ... OK\n" "$counter" "$name"
+    else
+      printf "%3d) %-60s ... FAILED\n" "$counter" "$name"
+    fi
+  fi
+}
+
+test_final()
+{
+  counter=$1
+  status=$2
+
+  if test "$verbose" = "0" ; then
+    len=`expr 39 - \( \( $counter - 1 \) % 40 \)`
+    printf "%${len}s" ""
+    if test "$status" = "0" ; then
+      printf " %-3d OK\n" $counter
+    else
+      printf " %-3d FAILED\n" $counter
+    fi
+  fi
+}
+
+skip_test_()
+{
+  echo "$0: skipping test: $@" 1>&2
+  (exit 77); exit 77
+}
+
+require_acl_()
+{
+  getfacl --version < /dev/null > /dev/null 2>&1 \
+    && setfacl --version < /dev/null > /dev/null 2>&1 \
+      || skip_test_ "This test requires getfacl and setfacl."
+
+  id -u bin > /dev/null 2>&1 \
+    || skip_test_ "This test requires a local user named bin."
+}
+
+require_ulimit_()
+{
+  ulimit_works=yes
+  # Expect to be able to exec a program in 10MB of virtual memory,
+  # but not in 20KB.  I chose "date".  It must not be a shell built-in
+  # function, so you can't use echo, printf, true, etc.
+  # Of course, in coreutils, I could use $top_builddir/src/true,
+  # but this should be able to work for other projects, too.
+  ( ulimit -v 10000; date ) > /dev/null 2>&1 || ulimit_works=no
+  ( ulimit -v 20;    date ) > /dev/null 2>&1 && ulimit_works=no
+
+  test $ulimit_works = no \
+    && skip_test_ "this shell lacks ulimit support"
+}
+
+require_readable_root_()
+{
+  test -r / || skip_test_ "/ is not readable"
+}
+
+# Skip the current test if strace is not available or doesn't work.
+require_strace_()
+{
+  strace -V < /dev/null > /dev/null 2>&1 ||
+    skip_test_ 'no strace program'
+
+  strace -qe unlink echo > /dev/null 2>&1 ||
+    skip_test_ 'strace does not work'
+}
+
+require_built_()
+{
+  skip_=no
+  for i in "$@"; do
+    case " $built_programs " in
+      *" $i "*) ;;
+      *) echo "$i: not built" 1>&2; skip_=yes ;;
+    esac
+  done
+
+  test $skip_ = yes && skip_test_ "required program(s) not built"
+}
+
+uid_is_privileged_()
+{
+  # Make sure id -u succeeds.
+  my_uid=$(id -u) \
+    || { echo "$0: cannot run \`id -u'" 1>&2; return 1; }
+
+  # Make sure it gives valid output.
+  case $my_uid in
+    0) ;;
+    *[!0-9]*)
+      echo "$0: invalid output (\`$my_uid') from \`id -u'" 1>&2
+      return 1 ;;
+    *) return 1 ;;
+  esac
+}
+
+skip_if_()
+{
+  case $1 in
+    root) skip_test_ must be run as root ;;
+    non-root) skip_test_ must be run as non-root ;;
+    *) ;;  # FIXME?
+  esac
+}
+
+require_selinux_()
+{
+  case `ls -Zd .` in
+    '? .'|'unlabeled .')
+      skip_test_ "this system (or maybe just" \
+        "the current file system) lacks SELinux support"
+    ;;
+  esac
+}
+
+very_expensive_()
+{
+  if test "$RUN_VERY_EXPENSIVE_TESTS" != yes; then
+    skip_test_ '
+This test is very expensive, so it is disabled by default.
+To run it anyway, rerun make check with the RUN_VERY_EXPENSIVE_TESTS
+environment variable set to yes.  E.g.,
+
+  env RUN_VERY_EXPENSIVE_TESTS=yes make check
+'
+  fi
+}
+
+require_root_() { uid_is_privileged_ || skip_test_ "must be run as root"; }
+skip_if_root_() { uid_is_privileged_ && skip_test_ "must be run as non-root"; }
+error_() { echo "$0: $@" 1>&2; (exit 1); exit 1; }
+framework_failure() { error_ 'failure in testing framework'; }
+
+mkfifo_or_skip_()
+{
+  test $# = 1 || framework_failure
+  if ! mkfifo "$1"; then
+    # Make an exception of this case -- usually we interpret framework-creation
+    # failure as a test failure.  However, in this case, when running on a SunOS
+    # system using a disk NFS mounted from OpenBSD, the above fails like this:
+    # mkfifo: cannot make fifo `fifo-10558': Not owner
+    skip_test_ 'NOTICE: unable to create test prerequisites'
+  fi
+}
+
+test_dir_=$(pwd)
+
+this_test_() { echo "./$0" | sed 's,.*/,,'; }
+this_test=$(this_test_)
+
+verbose=0
+if test -n "$VIR_TEST_DEBUG" || test -n "$VIR_TEST_VERBOSE" ; then
+  verbose=1
+fi
+
+# This is a stub function that is run upon trap (upon regular exit and
+# interrupt).  Override it with a per-test function, e.g., to unmount
+# a partition, or to undo any other global state changes.
+cleanup_() { :; }
+
+mktempd="$abs_top_srcdir/build-aux/mktempd"
+t_=$("$SHELL" "$mktempd" "$test_dir_" lv-$this_test.XXXXXXXXXX) \
+    || error_ "failed to create temporary directory in $test_dir_"
+
+# Run each test from within a temporary sub-directory named after the
+# test itself, and arrange to remove it upon exception or normal exit.
+trap 'st=$?; cleanup_; d='"$t_"';
+    cd '"$test_dir_"' && chmod -R u+rwx "$d" && rm -rf "$d" && exit $st' 0
+trap '(exit $?); exit $?' 1 2 13 15
+
+cd "$t_" || error_ "failed to cd to $t_"
+
+if ( diff --version < /dev/null 2>&1 | grep GNU ) 2>&1 > /dev/null; then
+  compare() { diff -u "$@"; }
+elif ( cmp --version < /dev/null 2>&1 | grep GNU ) 2>&1 > /dev/null; then
+  compare() { cmp -s "$@"; }
+else
+  compare() { cmp "$@"; }
+fi
+
+# Local Variables:
+# indent-tabs-mode: nil
+# End:
diff --git a/test/test-xml-validate b/test/test-xml-validate
new file mode 100755
index 0000000..e5be325
--- /dev/null
+++ b/test/test-xml-validate
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+check_schema () {
+
+DIRS=$1
+SCHEMA="$abs_srcdir/../data/schemas/$2"
+
+test_intro $this_test
+
+n=0
+f=0
+for dir in $DIRS
+do
+  XML=`find $abs_srcdir/../data/$dir -name '*.xml'` || exit 1
+
+  for xml in `echo "$XML" | sort`
+  do
+    n=`expr $n + 1`
+    cmd="xmllint --relaxng $SCHEMA --noout $xml"
+    result=`$cmd 2>&1`
+    ret=$?
+
+    test_result $n $(basename $(dirname $xml))"/"$(basename $xml) $ret
+    if test "$verbose" = "1" && test $ret != 0 ; then
+        printf '%s\n' "$cmd" "$result"
+    fi
+    if test "$ret" != 0 ; then
+        f=`expr $f + 1`
+    fi
+  done
+done
+
+test_final $n $f
+
+ret=0
+test $f != 0 && ret=255
+exit $ret
+
+}
+
+
+: ${srcdir=.}
+. $srcdir/test-lib.sh
+
+DIRS="oses hypervisors devices"
+SCHEMA="libosinfo.rng"
+
+check_schema "$DIRS" "$SCHEMA"
-- 
1.7.7.6




More information about the virt-tools-list mailing list