mirror of
git://sourceware.org/git/lvm2.git
synced 2024-09-08 04:26:59 +03:00
[unit-test] Push the new unit test framwork.
See doc/unit-test.txt for details. Some bcache tests failing. Probably due to dct changing semantics, will fix in follow up patch.
This commit is contained in:
parent
c7fdacbc50
commit
ea34dad66f
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -79,3 +79,5 @@ test/lib/vgrename
|
|||
test/lib/vgs
|
||||
test/lib/vgscan
|
||||
test/lib/vgsplit
|
||||
|
||||
unit-test/unit-test
|
||||
|
|
|
@ -43,8 +43,7 @@ endif
|
|||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS = conf include man test scripts \
|
||||
libdaemon lib tools daemons libdm \
|
||||
udev po liblvm python \
|
||||
unit-tests/datastruct unit-tests/mm unit-tests/regex
|
||||
udev po liblvm python
|
||||
tools.distclean: test.distclean
|
||||
endif
|
||||
DISTCLEAN_DIRS += lcov_reports*
|
||||
|
@ -97,7 +96,7 @@ endif
|
|||
DISTCLEAN_TARGETS += cscope.out
|
||||
CLEAN_DIRS += autom4te.cache
|
||||
|
||||
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit: all
|
||||
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit-test: all
|
||||
$(MAKE) -C test $(@)
|
||||
|
||||
conf.generate man.generate: tools
|
||||
|
@ -212,7 +211,7 @@ endif
|
|||
endif
|
||||
|
||||
ifeq ("$(TESTING)", "yes")
|
||||
include test/unit/Makefile
|
||||
include unit-test/Makefile
|
||||
endif
|
||||
|
||||
ifneq ($(shell which ctags),)
|
||||
|
|
175
configure
vendored
175
configure
vendored
|
@ -707,9 +707,7 @@ FSADM
|
|||
ELDFLAGS
|
||||
DM_LIB_PATCHLEVEL
|
||||
DMEVENTD_PATH
|
||||
AIO_LIBS
|
||||
DL_LIBS
|
||||
AIO
|
||||
DEVMAPPER
|
||||
DEFAULT_USE_LVMLOCKD
|
||||
DEFAULT_USE_LVMPOLLD
|
||||
|
@ -783,8 +781,6 @@ LOCKD_SANLOCK_LIBS
|
|||
LOCKD_SANLOCK_CFLAGS
|
||||
VALGRIND_LIBS
|
||||
VALGRIND_CFLAGS
|
||||
CUNIT_LIBS
|
||||
CUNIT_CFLAGS
|
||||
GENPNG
|
||||
GENHTML
|
||||
LCOV
|
||||
|
@ -957,7 +953,6 @@ enable_profiling
|
|||
enable_testing
|
||||
enable_valgrind_pool
|
||||
enable_devmapper
|
||||
enable_aio
|
||||
enable_lvmetad
|
||||
enable_lvmpolld
|
||||
enable_lvmlockd_sanlock
|
||||
|
@ -1047,8 +1042,6 @@ DLM_CFLAGS
|
|||
DLM_LIBS
|
||||
SACKPT_CFLAGS
|
||||
SACKPT_LIBS
|
||||
CUNIT_CFLAGS
|
||||
CUNIT_LIBS
|
||||
VALGRIND_CFLAGS
|
||||
VALGRIND_LIBS
|
||||
LOCKD_SANLOCK_CFLAGS
|
||||
|
@ -1707,7 +1700,6 @@ Optional Features:
|
|||
--enable-testing enable testing targets in the makefile
|
||||
--enable-valgrind-pool enable valgrind awareness of pools
|
||||
--disable-devmapper disable LVM2 device-mapper interaction
|
||||
--disable-aio disable asynchronous I/O
|
||||
--enable-lvmetad enable the LVM Metadata Daemon
|
||||
--enable-lvmpolld enable the LVM Polling Daemon
|
||||
--enable-lvmlockd-sanlock
|
||||
|
@ -1894,9 +1886,6 @@ Some influential environment variables:
|
|||
SACKPT_CFLAGS
|
||||
C compiler flags for SACKPT, overriding pkg-config
|
||||
SACKPT_LIBS linker flags for SACKPT, overriding pkg-config
|
||||
CUNIT_CFLAGS
|
||||
C compiler flags for CUNIT, overriding pkg-config
|
||||
CUNIT_LIBS linker flags for CUNIT, overriding pkg-config
|
||||
VALGRIND_CFLAGS
|
||||
C compiler flags for VALGRIND, overriding pkg-config
|
||||
VALGRIND_LIBS
|
||||
|
@ -3195,7 +3184,6 @@ case "$host_os" in
|
|||
LDDEPS="$LDDEPS .export.sym"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
AIO=yes
|
||||
BUILD_LVMETAD=no
|
||||
BUILD_LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
|
@ -3215,7 +3203,6 @@ case "$host_os" in
|
|||
CLDNOWHOLEARCHIVE=
|
||||
LIB_SUFFIX=dylib
|
||||
DEVMAPPER=yes
|
||||
AIO=no
|
||||
ODIRECT=no
|
||||
DM_IOCTLS=no
|
||||
SELINUX=no
|
||||
|
@ -11623,101 +11610,6 @@ fi
|
|||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TESTING" >&5
|
||||
$as_echo "$TESTING" >&6; }
|
||||
|
||||
if test "$TESTING" = yes; then
|
||||
pkg_config_init
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CUNIT" >&5
|
||||
$as_echo_n "checking for CUNIT... " >&6; }
|
||||
|
||||
if test -n "$CUNIT_CFLAGS"; then
|
||||
pkg_cv_CUNIT_CFLAGS="$CUNIT_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cunit >= 2.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "cunit >= 2.0") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_CUNIT_CFLAGS=`$PKG_CONFIG --cflags "cunit >= 2.0" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$CUNIT_LIBS"; then
|
||||
pkg_cv_CUNIT_LIBS="$CUNIT_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cunit >= 2.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "cunit >= 2.0") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_CUNIT_LIBS=`$PKG_CONFIG --libs "cunit >= 2.0" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
CUNIT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "cunit >= 2.0" 2>&1`
|
||||
else
|
||||
CUNIT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "cunit >= 2.0" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$CUNIT_PKG_ERRORS" >&5
|
||||
|
||||
as_fn_error $? "Package requirements (cunit >= 2.0) were not met:
|
||||
|
||||
$CUNIT_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
Alternatively, you may set the environment variables CUNIT_CFLAGS
|
||||
and CUNIT_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details." "$LINENO" 5
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
Alternatively, you may set the environment variables CUNIT_CFLAGS
|
||||
and CUNIT_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
|
||||
See \`config.log' for more details" "$LINENO" 5; }
|
||||
else
|
||||
CUNIT_CFLAGS=$pkg_cv_CUNIT_CFLAGS
|
||||
CUNIT_LIBS=$pkg_cv_CUNIT_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
TESTSUITE_DATA='${datarootdir}/lvm2-testsuite'
|
||||
# double eval needed ${datarootdir} -> ${prefix}/share -> real path
|
||||
|
@ -11844,67 +11736,6 @@ $as_echo "#define DEVMAPPER_SUPPORT 1" >>confdefs.h
|
|||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use asynchronous I/O" >&5
|
||||
$as_echo_n "checking whether to asynchronous I/O... " >&6; }
|
||||
# Check whether --enable-aio was given.
|
||||
if test "${enable_aio+set}" = set; then :
|
||||
enableval=$enable_aio; AIO=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AIO" >&5
|
||||
$as_echo "$AIO" >&6; }
|
||||
|
||||
if test "$AIO" = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for io_setup in -laio" >&5
|
||||
$as_echo_n "checking for io_setup in -laio... " >&6; }
|
||||
if ${ac_cv_lib_aio_io_setup+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-laio $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char io_setup ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return io_setup ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_aio_io_setup=yes
|
||||
else
|
||||
ac_cv_lib_aio_io_setup=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_aio_io_setup" >&5
|
||||
$as_echo "$ac_cv_lib_aio_io_setup" >&6; }
|
||||
if test "x$ac_cv_lib_aio_io_setup" = xyes; then :
|
||||
|
||||
$as_echo "#define AIO_SUPPORT 1" >>confdefs.h
|
||||
|
||||
AIO_LIBS="-laio"
|
||||
AIO_SUPPORT=yes
|
||||
else
|
||||
AIO_LIBS=
|
||||
AIO_SUPPORT=no
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build LVMetaD" >&5
|
||||
$as_echo_n "checking whether to build LVMetaD... " >&6; }
|
||||
|
@ -15854,13 +15685,11 @@ _ACEOF
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/dmfilemapd/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/lvmdbusd daemons/lvmdbusd/lvmdb.py daemons/lvmdbusd/lvm_shell_proxy.py daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile unit-test/Makefile tools/Makefile udev/Makefile"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
|
@ -16634,7 +16463,7 @@ do
|
|||
"scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
|
||||
"test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
|
||||
"test/api/Makefile") CONFIG_FILES="$CONFIG_FILES test/api/Makefile" ;;
|
||||
"test/unit/Makefile") CONFIG_FILES="$CONFIG_FILES test/unit/Makefile" ;;
|
||||
"unit-test/Makefile") CONFIG_FILES="$CONFIG_FILES unit-test/Makefile" ;;
|
||||
"tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
|
||||
"udev/Makefile") CONFIG_FILES="$CONFIG_FILES udev/Makefile" ;;
|
||||
|
||||
|
|
|
@ -1076,11 +1076,6 @@ AC_ARG_ENABLE(testing,
|
|||
TESTING=$enableval, TESTING=no)
|
||||
AC_MSG_RESULT($TESTING)
|
||||
|
||||
if test "$TESTING" = yes; then
|
||||
pkg_config_init
|
||||
PKG_CHECK_MODULES(CUNIT, cunit >= 2.0)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Set LVM2 testsuite data
|
||||
TESTSUITE_DATA='${datarootdir}/lvm2-testsuite'
|
||||
|
@ -2251,7 +2246,7 @@ scripts/lvmdump.sh
|
|||
scripts/Makefile
|
||||
test/Makefile
|
||||
test/api/Makefile
|
||||
test/unit/Makefile
|
||||
unit-test/Makefile
|
||||
tools/Makefile
|
||||
udev/Makefile
|
||||
])
|
||||
|
|
257
doc/unit-tests.txt
Normal file
257
doc/unit-tests.txt
Normal file
|
@ -0,0 +1,257 @@
|
|||
Building unit tests
|
||||
===================
|
||||
|
||||
make unit-unit/unit-test
|
||||
|
||||
|
||||
Running unit tests
|
||||
==================
|
||||
|
||||
The tests leave no artifacts at the moment, so you can just run
|
||||
unit-test/unit-test from wherever you want.
|
||||
|
||||
./unit-test <list|run> [pattern]
|
||||
|
||||
Listing tests
|
||||
-------------
|
||||
|
||||
Every test has a symbolic path associated with it. Just like file paths they
|
||||
are split into components separated by '/'s. The 'list' command will show you
|
||||
a tree of these tests, along with some description text.
|
||||
|
||||
|
||||
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test list
|
||||
base
|
||||
data-struct
|
||||
bitset
|
||||
and ................................................. and all bits
|
||||
equal ............................................... equality
|
||||
get_next ............................................ get next set bit
|
||||
list
|
||||
splice .............................................. joining lists together
|
||||
string
|
||||
asprint ............................................. tests asprint
|
||||
strncpy ............................................. tests string copying
|
||||
device
|
||||
bcache
|
||||
block-size-multiple-page ............................ block size must be a multiple of page size
|
||||
block-size-positive ................................. block size must be positive
|
||||
blocks-get-evicted .................................. block get evicted with many reads
|
||||
cache-blocks-positive ............................... nr cache blocks must be positive
|
||||
create-destroy ...................................... simple create/destroy
|
||||
flush-waits ......................................... flush waits for all dirty
|
||||
get-reads ........................................... bcache_get() triggers read
|
||||
prefetch-never-waits ................................ too many prefetches does not trigger a wait
|
||||
prefetch-reads ...................................... prefetch issues a read
|
||||
read-multiple-files ................................. read from multiple files
|
||||
reads-cached ........................................ repeated reads are cached
|
||||
writeback-occurs .................................... dirty data gets written back
|
||||
zero-flag-dirties ................................... zeroed data counts as dirty
|
||||
formatting
|
||||
percent
|
||||
0 ................................................... Pretty printing of percentages near 0%
|
||||
100 ................................................. Pretty printing of percentages near 100%
|
||||
regex
|
||||
fingerprints .......................................... not sure
|
||||
matching .............................................. test the matcher with a variety of regexes
|
||||
dm
|
||||
target
|
||||
mirror
|
||||
status .............................................. parsing mirror status
|
||||
metadata
|
||||
config
|
||||
cascade ............................................... cascade
|
||||
clone ................................................. duplicating a config tree
|
||||
parse ................................................. parsing various
|
||||
|
||||
|
||||
An optional 'pattern' argument may be specified to select subsets of tests.
|
||||
This pattern is a posix regex and does a substring match, so you will need to
|
||||
use anchors if you particularly want the match at the beginning or end of the
|
||||
string.
|
||||
|
||||
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test list data-struct
|
||||
base
|
||||
data-struct
|
||||
bitset
|
||||
and ................................................. and all bits
|
||||
equal ............................................... equality
|
||||
get_next ............................................ get next set bit
|
||||
list
|
||||
splice .............................................. joining lists together
|
||||
string
|
||||
asprint ............................................. tests asprint
|
||||
strncpy ............................................. tests string copying
|
||||
|
||||
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test list s$
|
||||
base
|
||||
device
|
||||
bcache
|
||||
flush-waits ......................................... flush waits for all dirty
|
||||
get-reads ........................................... bcache_get() triggers read
|
||||
prefetch-never-waits ................................ too many prefetches does not trigger a wait
|
||||
prefetch-reads ...................................... prefetch issues a read
|
||||
read-multiple-files ................................. read from multiple files
|
||||
writeback-occurs .................................... dirty data gets written back
|
||||
zero-flag-dirties ................................... zeroed data counts as dirty
|
||||
regex
|
||||
fingerprints .......................................... not sure
|
||||
dm
|
||||
target
|
||||
mirror
|
||||
status .............................................. parsing mirror status
|
||||
|
||||
|
||||
Running tests
|
||||
=============
|
||||
|
||||
'make run-unit-test' from the top level will run all unit tests. But I tend to
|
||||
run it by hand to I can select just the tests I'm working on.
|
||||
|
||||
Use the 'run' command to run the tests. Currently all logging goes to stderr,
|
||||
so the test runner prints a line at the start of the test and a line
|
||||
indicating success or failure at the end.
|
||||
|
||||
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test run bcache/block-size
|
||||
[RUN ] /base/device/bcache/block-size-multiple-page
|
||||
bcache block size must be a multiple of page size
|
||||
bcache block size must be a multiple of page size
|
||||
bcache block size must be a multiple of page size
|
||||
bcache block size must be a multiple of page size
|
||||
[ OK] /base/device/bcache/block-size-multiple-page
|
||||
|
||||
[RUN ] /base/device/bcache/block-size-positive
|
||||
bcache must have a non zero block size
|
||||
[ OK] /base/device/bcache/block-size-positive
|
||||
|
||||
|
||||
2/2 tests passed
|
||||
|
||||
|
||||
ejt@devel-vm1:~/lvm2/unit-test/$ ./unit-test run data-struct
|
||||
[RUN ] /base/data-struct/bitset/and
|
||||
[ OK] /base/data-struct/bitset/and
|
||||
|
||||
[RUN ] /base/data-struct/bitset/equal
|
||||
[ OK] /base/data-struct/bitset/equal
|
||||
|
||||
[RUN ] /base/data-struct/bitset/get_next
|
||||
[ OK] /base/data-struct/bitset/get_next
|
||||
|
||||
[RUN ] /base/data-struct/list/splice
|
||||
[ OK] /base/data-struct/list/splice
|
||||
|
||||
[RUN ] /base/data-struct/string/asprint
|
||||
[ OK] /base/data-struct/string/asprint
|
||||
|
||||
[RUN ] /base/data-struct/string/strncpy
|
||||
[ OK] /base/data-struct/string/strncpy
|
||||
|
||||
|
||||
6/6 tests passed
|
||||
|
||||
|
||||
Writing tests
|
||||
=============
|
||||
|
||||
[See unit-test/framework.h and unit-test/units.h for the details]
|
||||
|
||||
Tests are grouped together into 'suites', all tests in a suite share a
|
||||
'fixture'. A fixture is a void * to any object you want; use it to set up any
|
||||
common environment that you need for the tests to run (eg, creating a dm_pool).
|
||||
|
||||
Test suites have nothing to do with the test paths, you can have tests from
|
||||
different suites with similar paths, the runner sorts things for you.
|
||||
|
||||
Put your tests in a file in unit-test/, with '_t' at the end of the name
|
||||
(convention only, nothing relies on this).
|
||||
|
||||
#include "units.h"
|
||||
|
||||
Then write any fixtures you need:
|
||||
|
||||
eg,
|
||||
static void *_mem_init(void) {
|
||||
struct dm_pool *mem = dm_pool_create("bitset test", 1024);
|
||||
if (!mem) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
static void _mem_exit(void *mem)
|
||||
{
|
||||
dm_pool_destroy(mem);
|
||||
}
|
||||
|
||||
Then write your tests, which should take the void * that was returned by your
|
||||
fixture. Use the T_ASSERT* macros to indicate failure.
|
||||
|
||||
eg,
|
||||
static void test_equal(void *fixture)
|
||||
{
|
||||
struct dm_pool *mem = fixture;
|
||||
dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS);
|
||||
dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS);
|
||||
|
||||
int i, j;
|
||||
for (i = 0, j = 1; i < NR_BITS; i += j, j++) {
|
||||
dm_bit_set(bs1, i);
|
||||
dm_bit_set(bs2, i);
|
||||
}
|
||||
|
||||
T_ASSERT(dm_bitset_equal(bs1, bs2));
|
||||
T_ASSERT(dm_bitset_equal(bs2, bs1));
|
||||
|
||||
for (i = 0; i < NR_BITS; i++) {
|
||||
bit_flip(bs1, i);
|
||||
T_ASSERT(!dm_bitset_equal(bs1, bs2));
|
||||
T_ASSERT(!dm_bitset_equal(bs2, bs1));
|
||||
|
||||
T_ASSERT(dm_bitset_equal(bs1, bs1)); /* comparing with self */
|
||||
bit_flip(bs1, i);
|
||||
}
|
||||
}
|
||||
|
||||
At the end of your test file you should write a function that builds one or
|
||||
more test suites and adds them to the list of all suites that is passed in. I
|
||||
tend to write a little macro (T) to save typing the same test path repeatedly.
|
||||
|
||||
eg,
|
||||
#define T(path, desc, fn) register_test(ts, "/base/data-struct/bitset/" path, desc, fn)
|
||||
|
||||
void bitset_tests(struct dm_list *all_tests)
|
||||
{
|
||||
struct test_suite *ts = test_suite_create(_mem_init, _mem_exit);
|
||||
if (!ts) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
T("get_next", "get next set bit", test_get_next);
|
||||
T("equal", "equality", test_equal);
|
||||
T("and", "and all bits", test_and);
|
||||
|
||||
dm_list_add(all_tests, &ts->list);
|
||||
}
|
||||
|
||||
Then you need to declare your registration function and call it in units.h.
|
||||
|
||||
|
||||
// Declare the function that adds tests suites here ...
|
||||
...
|
||||
void bitset_tests(struct dm_list *suites);
|
||||
...
|
||||
|
||||
// ... and call it in here.
|
||||
static inline void register_all_tests(struct dm_list *suites)
|
||||
{
|
||||
...
|
||||
bitset_tests(suites);
|
||||
...
|
||||
}
|
||||
|
||||
Finally add your test file to the Makefile.in and rerun configure.
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Merely wraps the logger library with a bit of standard policy.
|
||||
require 'logger'
|
||||
|
||||
module Log
|
||||
$log = Logger.new(STDERR)
|
||||
|
||||
def init(io_)
|
||||
$log = Logger.new(io_)
|
||||
end
|
||||
end
|
||||
|
||||
def fatal(*args)
|
||||
$log.fatal(*args)
|
||||
end
|
||||
|
||||
def error(*args)
|
||||
$log.error(*args)
|
||||
end
|
||||
|
||||
def info(*args)
|
||||
$log.info(*args)
|
||||
end
|
||||
|
||||
def warning(*args)
|
||||
$log.warn(*args)
|
||||
end
|
||||
|
||||
def debug(*args)
|
||||
$log.debug(*args)
|
||||
end
|
|
@ -1,38 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Policy for the location of report templates
|
||||
require 'string-store'
|
||||
|
||||
class TemplateStringStore < StringStore
|
||||
def initialize()
|
||||
super(['report-generators/templates'])
|
||||
end
|
||||
end
|
||||
|
||||
module ReportTemplates
|
||||
def generate_report(report, bs, dest_path = nil)
|
||||
include Reports
|
||||
reports = ReportRegister.new
|
||||
template_store = TemplateStringStore.new
|
||||
report = reports.get_report(report)
|
||||
erb = ERB.new(template_store.lookup(report.template))
|
||||
body = erb.result(bs)
|
||||
title = report.short_desc
|
||||
|
||||
erb = ERB.new(template_store.lookup("boiler_plate.rhtml"))
|
||||
txt = erb.result(binding)
|
||||
|
||||
dest_path = dest_path.nil? ? report.path : dest_path
|
||||
dest_path.open("w") do |out|
|
||||
out.puts txt
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,58 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Data about the various reports we support
|
||||
require 'log'
|
||||
require 'pathname'
|
||||
|
||||
module Reports
|
||||
Report = Struct.new(:short_desc, :desc, :path, :template)
|
||||
|
||||
class ReportRegister
|
||||
attr_reader :reports
|
||||
|
||||
private
|
||||
def add_report(sym, *args)
|
||||
@reports[sym] = Report.new(*args)
|
||||
end
|
||||
|
||||
public
|
||||
def initialize()
|
||||
@reports = Hash.new
|
||||
|
||||
add_report(:unit_test,
|
||||
"Unit Tests",
|
||||
"unit tests",
|
||||
Pathname.new("reports/unit.html"),
|
||||
Pathname.new("unit_test.rhtml"))
|
||||
|
||||
add_report(:memcheck,
|
||||
"Memory Tests",
|
||||
"unit tests with valgrind memory checking",
|
||||
Pathname.new("reports/memcheck.html"),
|
||||
Pathname.new("memcheck.rhtml"))
|
||||
|
||||
add_report(:unit_detail,
|
||||
"Unit Test Detail",
|
||||
"unit test detail",
|
||||
Pathname.new("reports/unit_detail.html"), # FIXME replace this with a lambda
|
||||
Pathname.new("unit_detail.rhtml"))
|
||||
end
|
||||
|
||||
def get_report(sym)
|
||||
raise RuntimeError, "unknown report '#{sym}'" unless @reports.member?(sym)
|
||||
@reports[sym]
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
@reports.each(&block)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,56 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Parses the simple colon delimited test schedule files.
|
||||
|
||||
ScheduledTest = Struct.new(:desc, :command_line, :status, :output)
|
||||
|
||||
class Schedule
|
||||
attr_reader :dir, :schedules
|
||||
|
||||
def initialize(dir, ss)
|
||||
@dir = dir
|
||||
@schedules = ss
|
||||
end
|
||||
|
||||
def run
|
||||
Dir::chdir(@dir.to_s) do
|
||||
@schedules.each do |s|
|
||||
reader, writer = IO.pipe
|
||||
print "#{s.desc} ... "
|
||||
pid = spawn(s.command_line, [ STDERR, STDOUT ] => writer)
|
||||
writer.close
|
||||
_, s.status = Process::waitpid2(pid)
|
||||
puts (s.status.success? ? "pass" : "fail")
|
||||
s.output = reader.read
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.read(dir, io)
|
||||
ss = Array.new
|
||||
|
||||
io.readlines.each do |line|
|
||||
case line.strip
|
||||
when /^\#.*/
|
||||
next
|
||||
|
||||
when /([^:]+):(.*)/
|
||||
ss << ScheduledTest.new($1.strip, $2.strip)
|
||||
|
||||
else
|
||||
raise RuntimeError, "badly formatted schedule line"
|
||||
end
|
||||
end
|
||||
|
||||
Schedule.new(dir, ss)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Provides a simple way of accessing the contents of files by a symbol
|
||||
# name. Useful for erb templates.
|
||||
|
||||
require 'pathname'
|
||||
|
||||
class StringStore
|
||||
attr_accessor :path
|
||||
|
||||
def initialize(p)
|
||||
@paths = p.nil? ? Array.new : p # FIXME: do we need to copy p ?
|
||||
end
|
||||
|
||||
def lookup(sym)
|
||||
files = expansions(sym)
|
||||
|
||||
@paths.each do |p|
|
||||
files.each do |f|
|
||||
pn = Pathname.new("#{p}/#{f}")
|
||||
if pn.file?
|
||||
return pn.read
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
raise RuntimeError, "unknown string entry: #{sym}"
|
||||
end
|
||||
|
||||
private
|
||||
def expansions(sym)
|
||||
["#{sym}", "#{sym}.txt"]
|
||||
end
|
||||
end
|
|
@ -1,86 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Reads the schedule files given on the command line. Runs them and
|
||||
# generates the reports.
|
||||
|
||||
# FIXME: a lot of duplication with unit_test.rb
|
||||
|
||||
require 'schedule_file'
|
||||
require 'pathname'
|
||||
require 'reports'
|
||||
require 'erb'
|
||||
require 'report_templates'
|
||||
|
||||
include ReportTemplates
|
||||
|
||||
schedules = ARGV.map do |f|
|
||||
p = Pathname.new(f)
|
||||
Schedule.read(p.dirname, p)
|
||||
end
|
||||
|
||||
total_passed = 0
|
||||
total_failed = 0
|
||||
|
||||
# We need to make sure the lvm shared libs are in the LD_LIBRARY_PATH
|
||||
ENV['LD_LIBRARY_PATH'] = `pwd`.strip + "/libdm:" + (ENV['LD_LIBRARY_PATH'] || '')
|
||||
|
||||
ENV['TEST_TOOL'] = "valgrind --leak-check=full --show-reachable=yes"
|
||||
|
||||
schedules.each do |s|
|
||||
s.run
|
||||
|
||||
s.schedules.each do |t|
|
||||
if t.status.success?
|
||||
total_passed += 1
|
||||
else
|
||||
total_failed += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def mangle(txt)
|
||||
txt.gsub(/\s+/, '_')
|
||||
end
|
||||
|
||||
MemcheckStats = Struct.new(:definitely_lost, :indirectly_lost, :possibly_lost, :reachable)
|
||||
|
||||
def format(bytes, blocks)
|
||||
"#{bytes} bytes, #{blocks} blocks"
|
||||
end
|
||||
|
||||
# Examines the output for details of leaks
|
||||
def extract_stats(t)
|
||||
d = i = p = r = '-'
|
||||
|
||||
t.output.split("\n").each do |l|
|
||||
case l
|
||||
when /==\d+== definitely lost: ([0-9,]+) bytes in ([0-9,]+) blocks/
|
||||
d = format($1, $2)
|
||||
when /==\d+== indirectly lost: ([0-9,]+) bytes in ([0-9,]+) blocks/
|
||||
i = format($1, $2)
|
||||
when /==\d+== possibly lost: ([0-9,]+) bytes in ([0-9,]+) blocks/
|
||||
p = format($1, $2)
|
||||
when /==\d+== still reachable: ([0-9,]+) bytes in ([0-9,]+) blocks/
|
||||
r = format($1, $2)
|
||||
end
|
||||
end
|
||||
|
||||
MemcheckStats.new(d, i, p, r)
|
||||
end
|
||||
|
||||
generate_report(:memcheck, binding)
|
||||
|
||||
# now we generate a detail report for each schedule
|
||||
schedules.each do |s|
|
||||
s.schedules.each do |t|
|
||||
generate_report(:unit_detail, binding, Pathname.new("reports/memcheck_#{mangle(t.desc)}.html"))
|
||||
end
|
||||
end
|
|
@ -1,25 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title><%= title %></title>
|
||||
<link title="Style" type="text/css" rel="stylesheet" href="stylesheet.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="banner">
|
||||
<h2><%= title %></h2>
|
||||
</div>
|
||||
<div id="main">
|
||||
<div id="controls">
|
||||
<table>
|
||||
<tr><td><a href="index.html">Generation times</a></td></tr>
|
||||
<tr><td><a href="unit.html">Unit tests</a></td></tr>
|
||||
<tr><td><a href="memcheck.html">Memory tests</a></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="body">
|
||||
<%= body %>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
|
@ -1,17 +0,0 @@
|
|||
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
|
||||
<tr><th>Report</th><th>Generation time</th></tr>
|
||||
<% [:unit_test, :memcheck].each do |sym| %>
|
||||
<% r = reports.get_report(sym) %>
|
||||
<tr>
|
||||
<td>
|
||||
<% if r.path.file? %>
|
||||
<a href="<%= r.path.to_s.gsub(/^reports\//, '') %>"><%= r.short_desc %></a>
|
||||
<% else %>
|
||||
<%= r.short_desc %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td><%= safe_mtime(r) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
|
||||
<tr><th>Tests passed</th><th>Tests failed</th></tr>
|
||||
<tr><td class="pass"><%= total_passed %></td><td <%= total_failed == 0 ? "" : "class=\"fail\""%>><%= total_failed %></td></tr>
|
||||
</table>
|
||||
|
||||
<% schedules.each do |s| %>
|
||||
<h3><%= s.dir.sub('./unit-tests/', '') %></h3>
|
||||
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
|
||||
<tr><th>Test</th><th>Result</th><th>Definitely lost</th><th>indirectly lost</th><th>possibly lost</th><th>still reachable</th><tr>
|
||||
|
||||
<% s.schedules.each do |t| %>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="memcheck_<%= mangle(t.desc) %>.html"><%= t.desc %></a>
|
||||
</td>
|
||||
<% if t.status.success? %>
|
||||
<td class="pass">pass</td>
|
||||
<% else %>
|
||||
<td class="fail">fail</td>
|
||||
<% end %>
|
||||
|
||||
<% stats = extract_stats(t) %>
|
||||
<td><%= stats.definitely_lost %></td>
|
||||
<td><%= stats.indirectly_lost %></td>
|
||||
<td><%= stats.possibly_lost %></td>
|
||||
<td><%= stats.reachable %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
<% end %>
|
|
@ -1,37 +0,0 @@
|
|||
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
|
||||
<tr><th>Test</th><th>Result</th></tr>
|
||||
<tr>
|
||||
<td>
|
||||
<%= t.desc %>
|
||||
</td>
|
||||
<% if t.status.success? %>
|
||||
<td class="pass">pass</td>
|
||||
<% else %>
|
||||
<td class="fail">fail</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
|
||||
<tr><th>Command line</th></tr>
|
||||
<tr>
|
||||
<td>
|
||||
<pre>
|
||||
<%= t.command_line %>
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
|
||||
<tr><th>Output</th></tr>
|
||||
<tr>
|
||||
<td>
|
||||
<pre>
|
||||
<%= t.output %>
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
|
||||
<tr><th>Tests passed</th><th>Tests failed</th></tr>
|
||||
<tr><td class="pass"><%= total_passed %></td><td <%= total_failed == 0 ? "" : "class=\"fail\""%>><%= total_failed %></td></tr>
|
||||
</table>
|
||||
|
||||
<% schedules.each do |s| %>
|
||||
<h3><%= s.dir.sub('./unit-tests/', '') %></h3>
|
||||
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
|
||||
<tr><th>Test</th><th>Result</th></tr>
|
||||
<% s.schedules.each do |t| %>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="detail_<%= mangle(t.desc) %>.html"><%= t.desc %></a>
|
||||
</td>
|
||||
<% if t.status.success? %>
|
||||
<td class="pass">pass</td>
|
||||
<% else %>
|
||||
<td class="fail">fail</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
<% end %>
|
|
@ -1,4 +0,0 @@
|
|||
# This is a comment
|
||||
description number 1:$TEST_TOOL ls
|
||||
foo bar: $TEST_TOOL du -hs .
|
||||
this comment is prefixed with whitespace: $TEST_TOOL date
|
|
@ -1 +0,0 @@
|
|||
lorem
|
|
@ -1 +0,0 @@
|
|||
Hello, world!
|
|
@ -1,3 +0,0 @@
|
|||
one
|
||||
two
|
||||
three
|
|
@ -1,36 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
require 'test/unit'
|
||||
require 'stringio'
|
||||
require 'log'
|
||||
|
||||
class TestLog < Test::Unit::TestCase
|
||||
include Log
|
||||
|
||||
private
|
||||
def remove_timestamps(l)
|
||||
l.gsub(/\[[^\]]*\]/, '')
|
||||
end
|
||||
|
||||
public
|
||||
def test_log
|
||||
StringIO.open do |out|
|
||||
init(out)
|
||||
|
||||
info("msg1")
|
||||
warning("msg2")
|
||||
debug("msg3")
|
||||
|
||||
assert_equal("I, INFO -- : msg1\nW, WARN -- : msg2\nD, DEBUG -- : msg3\n",
|
||||
remove_timestamps(out.string))
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,38 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
require 'test/unit'
|
||||
require 'pathname'
|
||||
require 'schedule_file'
|
||||
|
||||
class TestScheduleFile < Test::Unit::TestCase
|
||||
def test_reading
|
||||
p = Pathname.new("report-generators/test/example.schedule")
|
||||
p.open do |f|
|
||||
s = Schedule.read(p.dirname, f)
|
||||
|
||||
assert_equal(3, s.schedules.size)
|
||||
assert_equal(s.schedules[2].desc, "this comment is prefixed with whitespace")
|
||||
assert_equal(s.schedules[0].command_line, "$TEST_TOOL ls")
|
||||
end
|
||||
end
|
||||
|
||||
def test_running
|
||||
p = Pathname.new("report-generators/test/example.schedule")
|
||||
p.open do |f|
|
||||
s = Schedule.read(p.dirname, f)
|
||||
s.run
|
||||
|
||||
s.schedules.each do |t|
|
||||
assert(t.status.success?)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,29 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
require 'string-store'
|
||||
require 'test/unit'
|
||||
|
||||
class TestStringStore < Test::Unit::TestCase
|
||||
def setup
|
||||
@ss = StringStore.new(['report-generators/test/strings',
|
||||
'report-generators/test/strings/more_strings'])
|
||||
end
|
||||
|
||||
def test_lookup
|
||||
assert_equal("Hello, world!\n", @ss.lookup(:test1))
|
||||
assert_equal("one\ntwo\nthree", @ss.lookup(:test2))
|
||||
assert_equal("lorem\n", @ss.lookup(:test3))
|
||||
|
||||
assert_raises(RuntimeError) do
|
||||
@ss.lookup(:unlikely_name)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
require 'tc_log'
|
||||
require 'tc_string_store'
|
||||
require 'tc_schedule_file'
|
|
@ -1,42 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# This generates the index for the reports, including generation
|
||||
# times.
|
||||
|
||||
require 'log'
|
||||
require 'string-store'
|
||||
require 'reports'
|
||||
require 'erb'
|
||||
require 'report_templates'
|
||||
|
||||
include Reports
|
||||
|
||||
reports = ReportRegister.new
|
||||
|
||||
def safe_mtime(r)
|
||||
r.path.file? ? r.path.mtime.to_s : "not generated"
|
||||
end
|
||||
|
||||
template_store = TemplateStringStore.new
|
||||
|
||||
# FIXME: use generate_report() method
|
||||
erb = ERB.new(template_store.lookup("index.rhtml"))
|
||||
body = erb.result(binding)
|
||||
title = "Generation times"
|
||||
|
||||
erb = ERB.new(template_store.lookup("boiler_plate.rhtml"))
|
||||
txt = erb.result(binding)
|
||||
|
||||
Pathname.new("reports/index.html").open("w") do |f|
|
||||
f.puts txt
|
||||
end
|
||||
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Reads the schedule files given on the command line. Runs them and
|
||||
# generates the reports.
|
||||
|
||||
require 'schedule_file'
|
||||
require 'pathname'
|
||||
require 'reports'
|
||||
require 'erb'
|
||||
require 'report_templates'
|
||||
|
||||
include ReportTemplates
|
||||
|
||||
schedules = ARGV.map do |f|
|
||||
p = Pathname.new(f)
|
||||
Schedule.read(p.dirname, p)
|
||||
end
|
||||
|
||||
total_passed = 0
|
||||
total_failed = 0
|
||||
|
||||
# We need to make sure the lvm shared libs are in the LD_LIBRARY_PATH
|
||||
ENV['LD_LIBRARY_PATH'] = `pwd`.strip + "/libdm:" + (ENV['LD_LIBRARY_PATH'] || '')
|
||||
|
||||
schedules.each do |s|
|
||||
s.run
|
||||
|
||||
s.schedules.each do |t|
|
||||
if t.status.success?
|
||||
total_passed += 1
|
||||
else
|
||||
total_failed += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def mangle(txt)
|
||||
txt.gsub(/\s+/, '_')
|
||||
end
|
||||
|
||||
generate_report(:unit_test, binding)
|
||||
|
||||
# now we generate a detail report for each schedule
|
||||
schedules.each do |s|
|
||||
s.schedules.each do |t|
|
||||
generate_report(:unit_detail, binding, Pathname.new("reports/detail_#{mangle(t.desc)}.html"))
|
||||
end
|
||||
end
|
|
@ -1,77 +0,0 @@
|
|||
/* Styles for main page */
|
||||
#banner {
|
||||
background: #9c9;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
border-bottom: 2px solid;
|
||||
font: small-caps 20px/20px "Times New Roman", serif;
|
||||
color: #282;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#banner img {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#main {
|
||||
margin-left: 0em;
|
||||
padding-top: 4ex;
|
||||
padding-left: 2em;
|
||||
background: white;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font: 150% sans-serif;
|
||||
color: #226;
|
||||
border-bottom: 3px dotted #77d;
|
||||
}
|
||||
|
||||
body {
|
||||
font: normal 75% verdana,arial,helvetica;
|
||||
color:#000000;
|
||||
}
|
||||
|
||||
table tr td, table tr th {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
table.stripes tr th {
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
background: #a0a0a0;
|
||||
}
|
||||
|
||||
table.stripes tr td {
|
||||
background: #ccccc0;
|
||||
}
|
||||
|
||||
td.pass {
|
||||
color: green;
|
||||
}
|
||||
|
||||
td.fail {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#main {
|
||||
padding-left: 0em;
|
||||
}
|
||||
|
||||
#controls {
|
||||
float: left;
|
||||
padding-top: 1em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
padding-bottom: 1em;
|
||||
width: 14em;
|
||||
border-right: 2px solid;
|
||||
}
|
||||
|
||||
#body {
|
||||
margin-left: 16em;
|
||||
padding-top: 4ex;
|
||||
padding-left: 2em;
|
||||
background: white;
|
||||
border-left: 2px solid;
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "units.h"
|
||||
|
||||
static struct dm_pool *mem;
|
||||
|
||||
int config_init(void) {
|
||||
mem = dm_pool_create("config test", 1024);
|
||||
return mem == NULL;
|
||||
}
|
||||
|
||||
int config_fini(void) {
|
||||
dm_pool_destroy(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *conf =
|
||||
"id = \"yada-yada\"\n"
|
||||
"seqno = 15\n"
|
||||
"status = [\"READ\", \"WRITE\"]\n"
|
||||
"flags = []\n"
|
||||
"extent_size = 8192\n"
|
||||
"physical_volumes {\n"
|
||||
" pv0 {\n"
|
||||
" id = \"abcd-efgh\"\n"
|
||||
" }\n"
|
||||
" pv1 {\n"
|
||||
" id = \"bbcd-efgh\"\n"
|
||||
" }\n"
|
||||
" pv2 {\n"
|
||||
" id = \"cbcd-efgh\"\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
static const char *overlay =
|
||||
"id = \"yoda-soda\"\n"
|
||||
"flags = [\"FOO\"]\n"
|
||||
"physical_volumes {\n"
|
||||
" pv1 {\n"
|
||||
" id = \"hgfe-dcba\"\n"
|
||||
" }\n"
|
||||
" pv3 {\n"
|
||||
" id = \"dbcd-efgh\"\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
static void test_parse(void)
|
||||
{
|
||||
struct dm_config_tree *tree = dm_config_from_string(conf);
|
||||
const struct dm_config_value *value;
|
||||
|
||||
CU_ASSERT((long) tree);
|
||||
CU_ASSERT(dm_config_has_node(tree->root, "id"));
|
||||
CU_ASSERT(dm_config_has_node(tree->root, "physical_volumes"));
|
||||
CU_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0"));
|
||||
CU_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0/id"));
|
||||
|
||||
CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "id", "foo"), "yada-yada"));
|
||||
CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "idt", "foo"), "foo"));
|
||||
|
||||
CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/bb", "foo"), "foo"));
|
||||
CU_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/id", "foo"), "abcd-efgh"));
|
||||
|
||||
CU_ASSERT(!dm_config_get_uint32(tree->root, "id", NULL));
|
||||
CU_ASSERT(dm_config_get_uint32(tree->root, "extent_size", NULL));
|
||||
|
||||
/* FIXME: Currently everything parses as a list, even if it's not */
|
||||
// CU_ASSERT(!dm_config_get_list(tree->root, "id", NULL));
|
||||
// CU_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL));
|
||||
|
||||
CU_ASSERT(dm_config_get_list(tree->root, "flags", &value));
|
||||
CU_ASSERT(value->next == NULL); /* an empty list */
|
||||
CU_ASSERT(dm_config_get_list(tree->root, "status", &value));
|
||||
CU_ASSERT(value->next != NULL); /* a non-empty list */
|
||||
|
||||
dm_config_destroy(tree);
|
||||
}
|
||||
|
||||
static void test_clone(void)
|
||||
{
|
||||
struct dm_config_tree *tree = dm_config_from_string(conf);
|
||||
struct dm_config_node *n = dm_config_clone_node(tree, tree->root, 1);
|
||||
const struct dm_config_value *value;
|
||||
|
||||
/* Check that the nodes are actually distinct. */
|
||||
CU_ASSERT(n != tree->root);
|
||||
CU_ASSERT(n->sib != tree->root->sib);
|
||||
CU_ASSERT(dm_config_find_node(n, "physical_volumes") != NULL);
|
||||
CU_ASSERT(dm_config_find_node(tree->root, "physical_volumes") != NULL);
|
||||
CU_ASSERT(dm_config_find_node(n, "physical_volumes") != dm_config_find_node(tree->root, "physical_volumes"));
|
||||
|
||||
CU_ASSERT(dm_config_has_node(n, "id"));
|
||||
CU_ASSERT(dm_config_has_node(n, "physical_volumes"));
|
||||
CU_ASSERT(dm_config_has_node(n, "physical_volumes/pv0"));
|
||||
CU_ASSERT(dm_config_has_node(n, "physical_volumes/pv0/id"));
|
||||
|
||||
CU_ASSERT(!strcmp(dm_config_find_str(n, "id", "foo"), "yada-yada"));
|
||||
CU_ASSERT(!strcmp(dm_config_find_str(n, "idt", "foo"), "foo"));
|
||||
|
||||
CU_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/bb", "foo"), "foo"));
|
||||
CU_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/id", "foo"), "abcd-efgh"));
|
||||
|
||||
CU_ASSERT(!dm_config_get_uint32(n, "id", NULL));
|
||||
CU_ASSERT(dm_config_get_uint32(n, "extent_size", NULL));
|
||||
|
||||
/* FIXME: Currently everything parses as a list, even if it's not */
|
||||
// CU_ASSERT(!dm_config_get_list(tree->root, "id", NULL));
|
||||
// CU_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL));
|
||||
|
||||
CU_ASSERT(dm_config_get_list(n, "flags", &value));
|
||||
CU_ASSERT(value->next == NULL); /* an empty list */
|
||||
CU_ASSERT(dm_config_get_list(n, "status", &value));
|
||||
CU_ASSERT(value->next != NULL); /* a non-empty list */
|
||||