mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +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/vgs
|
||||||
test/lib/vgscan
|
test/lib/vgscan
|
||||||
test/lib/vgsplit
|
test/lib/vgsplit
|
||||||
|
|
||||||
|
unit-test/unit-test
|
||||||
|
@ -43,8 +43,7 @@ endif
|
|||||||
ifeq ($(MAKECMDGOALS),distclean)
|
ifeq ($(MAKECMDGOALS),distclean)
|
||||||
SUBDIRS = conf include man test scripts \
|
SUBDIRS = conf include man test scripts \
|
||||||
libdaemon lib tools daemons libdm \
|
libdaemon lib tools daemons libdm \
|
||||||
udev po liblvm python \
|
udev po liblvm python
|
||||||
unit-tests/datastruct unit-tests/mm unit-tests/regex
|
|
||||||
tools.distclean: test.distclean
|
tools.distclean: test.distclean
|
||||||
endif
|
endif
|
||||||
DISTCLEAN_DIRS += lcov_reports*
|
DISTCLEAN_DIRS += lcov_reports*
|
||||||
@ -97,7 +96,7 @@ endif
|
|||||||
DISTCLEAN_TARGETS += cscope.out
|
DISTCLEAN_TARGETS += cscope.out
|
||||||
CLEAN_DIRS += autom4te.cache
|
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 $(@)
|
$(MAKE) -C test $(@)
|
||||||
|
|
||||||
conf.generate man.generate: tools
|
conf.generate man.generate: tools
|
||||||
@ -212,7 +211,7 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ("$(TESTING)", "yes")
|
ifeq ("$(TESTING)", "yes")
|
||||||
include test/unit/Makefile
|
include unit-test/Makefile
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(shell which ctags),)
|
ifneq ($(shell which ctags),)
|
||||||
|
175
configure
vendored
175
configure
vendored
@ -707,9 +707,7 @@ FSADM
|
|||||||
ELDFLAGS
|
ELDFLAGS
|
||||||
DM_LIB_PATCHLEVEL
|
DM_LIB_PATCHLEVEL
|
||||||
DMEVENTD_PATH
|
DMEVENTD_PATH
|
||||||
AIO_LIBS
|
|
||||||
DL_LIBS
|
DL_LIBS
|
||||||
AIO
|
|
||||||
DEVMAPPER
|
DEVMAPPER
|
||||||
DEFAULT_USE_LVMLOCKD
|
DEFAULT_USE_LVMLOCKD
|
||||||
DEFAULT_USE_LVMPOLLD
|
DEFAULT_USE_LVMPOLLD
|
||||||
@ -783,8 +781,6 @@ LOCKD_SANLOCK_LIBS
|
|||||||
LOCKD_SANLOCK_CFLAGS
|
LOCKD_SANLOCK_CFLAGS
|
||||||
VALGRIND_LIBS
|
VALGRIND_LIBS
|
||||||
VALGRIND_CFLAGS
|
VALGRIND_CFLAGS
|
||||||
CUNIT_LIBS
|
|
||||||
CUNIT_CFLAGS
|
|
||||||
GENPNG
|
GENPNG
|
||||||
GENHTML
|
GENHTML
|
||||||
LCOV
|
LCOV
|
||||||
@ -957,7 +953,6 @@ enable_profiling
|
|||||||
enable_testing
|
enable_testing
|
||||||
enable_valgrind_pool
|
enable_valgrind_pool
|
||||||
enable_devmapper
|
enable_devmapper
|
||||||
enable_aio
|
|
||||||
enable_lvmetad
|
enable_lvmetad
|
||||||
enable_lvmpolld
|
enable_lvmpolld
|
||||||
enable_lvmlockd_sanlock
|
enable_lvmlockd_sanlock
|
||||||
@ -1047,8 +1042,6 @@ DLM_CFLAGS
|
|||||||
DLM_LIBS
|
DLM_LIBS
|
||||||
SACKPT_CFLAGS
|
SACKPT_CFLAGS
|
||||||
SACKPT_LIBS
|
SACKPT_LIBS
|
||||||
CUNIT_CFLAGS
|
|
||||||
CUNIT_LIBS
|
|
||||||
VALGRIND_CFLAGS
|
VALGRIND_CFLAGS
|
||||||
VALGRIND_LIBS
|
VALGRIND_LIBS
|
||||||
LOCKD_SANLOCK_CFLAGS
|
LOCKD_SANLOCK_CFLAGS
|
||||||
@ -1707,7 +1700,6 @@ Optional Features:
|
|||||||
--enable-testing enable testing targets in the makefile
|
--enable-testing enable testing targets in the makefile
|
||||||
--enable-valgrind-pool enable valgrind awareness of pools
|
--enable-valgrind-pool enable valgrind awareness of pools
|
||||||
--disable-devmapper disable LVM2 device-mapper interaction
|
--disable-devmapper disable LVM2 device-mapper interaction
|
||||||
--disable-aio disable asynchronous I/O
|
|
||||||
--enable-lvmetad enable the LVM Metadata Daemon
|
--enable-lvmetad enable the LVM Metadata Daemon
|
||||||
--enable-lvmpolld enable the LVM Polling Daemon
|
--enable-lvmpolld enable the LVM Polling Daemon
|
||||||
--enable-lvmlockd-sanlock
|
--enable-lvmlockd-sanlock
|
||||||
@ -1894,9 +1886,6 @@ Some influential environment variables:
|
|||||||
SACKPT_CFLAGS
|
SACKPT_CFLAGS
|
||||||
C compiler flags for SACKPT, overriding pkg-config
|
C compiler flags for SACKPT, overriding pkg-config
|
||||||
SACKPT_LIBS linker 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
|
VALGRIND_CFLAGS
|
||||||
C compiler flags for VALGRIND, overriding pkg-config
|
C compiler flags for VALGRIND, overriding pkg-config
|
||||||
VALGRIND_LIBS
|
VALGRIND_LIBS
|
||||||
@ -3195,7 +3184,6 @@ case "$host_os" in
|
|||||||
LDDEPS="$LDDEPS .export.sym"
|
LDDEPS="$LDDEPS .export.sym"
|
||||||
LIB_SUFFIX=so
|
LIB_SUFFIX=so
|
||||||
DEVMAPPER=yes
|
DEVMAPPER=yes
|
||||||
AIO=yes
|
|
||||||
BUILD_LVMETAD=no
|
BUILD_LVMETAD=no
|
||||||
BUILD_LVMPOLLD=no
|
BUILD_LVMPOLLD=no
|
||||||
LOCKDSANLOCK=no
|
LOCKDSANLOCK=no
|
||||||
@ -3215,7 +3203,6 @@ case "$host_os" in
|
|||||||
CLDNOWHOLEARCHIVE=
|
CLDNOWHOLEARCHIVE=
|
||||||
LIB_SUFFIX=dylib
|
LIB_SUFFIX=dylib
|
||||||
DEVMAPPER=yes
|
DEVMAPPER=yes
|
||||||
AIO=no
|
|
||||||
ODIRECT=no
|
ODIRECT=no
|
||||||
DM_IOCTLS=no
|
DM_IOCTLS=no
|
||||||
SELINUX=no
|
SELINUX=no
|
||||||
@ -11623,101 +11610,6 @@ fi
|
|||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TESTING" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TESTING" >&5
|
||||||
$as_echo "$TESTING" >&6; }
|
$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'
|
TESTSUITE_DATA='${datarootdir}/lvm2-testsuite'
|
||||||
# double eval needed ${datarootdir} -> ${prefix}/share -> real path
|
# double eval needed ${datarootdir} -> ${prefix}/share -> real path
|
||||||
@ -11844,67 +11736,6 @@ $as_echo "#define DEVMAPPER_SUPPORT 1" >>confdefs.h
|
|||||||
|
|
||||||
fi
|
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 "$as_me:${as_lineno-$LINENO}: checking whether to build LVMetaD" >&5
|
||||||
$as_echo_n "checking whether to build LVMetaD... " >&6; }
|
$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
|
cat >confcache <<\_ACEOF
|
||||||
# This file is a shell script that caches the results of configure
|
# 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" ;;
|
"scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
|
||||||
"test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
|
"test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
|
||||||
"test/api/Makefile") CONFIG_FILES="$CONFIG_FILES test/api/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" ;;
|
"tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
|
||||||
"udev/Makefile") CONFIG_FILES="$CONFIG_FILES udev/Makefile" ;;
|
"udev/Makefile") CONFIG_FILES="$CONFIG_FILES udev/Makefile" ;;
|
||||||
|
|
||||||
|
@ -1076,11 +1076,6 @@ AC_ARG_ENABLE(testing,
|
|||||||
TESTING=$enableval, TESTING=no)
|
TESTING=$enableval, TESTING=no)
|
||||||
AC_MSG_RESULT($TESTING)
|
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
|
dnl -- Set LVM2 testsuite data
|
||||||
TESTSUITE_DATA='${datarootdir}/lvm2-testsuite'
|
TESTSUITE_DATA='${datarootdir}/lvm2-testsuite'
|
||||||
@ -2251,7 +2246,7 @@ scripts/lvmdump.sh
|
|||||||
scripts/Makefile
|
scripts/Makefile
|
||||||
test/Makefile
|
test/Makefile
|
||||||
test/api/Makefile
|
test/api/Makefile
|
||||||
test/unit/Makefile
|
unit-test/Makefile
|
||||||
tools/Makefile
|
tools/Makefile
|
||||||
udev/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 */
|
|
||||||
|
|
||||||
dm_config_destroy(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_cascade(void)
|
|
||||||
{
|
|
||||||
struct dm_config_tree *t1 = dm_config_from_string(conf),
|
|
||||||
*t2 = dm_config_from_string(overlay),
|
|
||||||
*tree = dm_config_insert_cascaded_tree(t2, t1);
|
|
||||||
|
|
||||||
CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "id", "foo"), "yoda-soda"));
|
|
||||||
CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "idt", "foo"), "foo"));
|
|
||||||
|
|
||||||
CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv0/bb", "foo"), "foo"));
|
|
||||||
CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv1/id", "foo"), "hgfe-dcba"));
|
|
||||||
CU_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv3/id", "foo"), "dbcd-efgh"));
|
|
||||||
|
|
||||||
dm_config_destroy(t1);
|
|
||||||
dm_config_destroy(t2);
|
|
||||||
}
|
|
||||||
|
|
||||||
CU_TestInfo config_list[] = {
|
|
||||||
{ (char*)"parse", test_parse },
|
|
||||||
{ (char*)"clone", test_clone },
|
|
||||||
{ (char*)"cascade", test_cascade },
|
|
||||||
CU_TEST_INFO_NULL
|
|
||||||
};
|
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 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 dmstatus_init(void)
|
|
||||||
{
|
|
||||||
_mem = dm_pool_create("dmstatus test", 1024);
|
|
||||||
return (_mem == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int dmstatus_fini(void)
|
|
||||||
{
|
|
||||||
dm_pool_destroy(_mem);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _test_mirror_status(void)
|
|
||||||
{
|
|
||||||
struct dm_status_mirror *s = NULL;
|
|
||||||
|
|
||||||
CU_ASSERT(dm_get_status_mirror(_mem,
|
|
||||||
"2 253:1 253:2 80/81 1 AD 3 disk 253:0 A",
|
|
||||||
&s));
|
|
||||||
if (s) {
|
|
||||||
CU_ASSERT_EQUAL(s->total_regions, 81);
|
|
||||||
CU_ASSERT_EQUAL(s->insync_regions, 80);
|
|
||||||
CU_ASSERT_EQUAL(s->dev_count, 2);
|
|
||||||
CU_ASSERT_EQUAL(s->devs[0].health, 'A');
|
|
||||||
CU_ASSERT_EQUAL(s->devs[0].major, 253);
|
|
||||||
CU_ASSERT_EQUAL(s->devs[0].minor, 1);
|
|
||||||
CU_ASSERT_EQUAL(s->devs[1].health, 'D');
|
|
||||||
CU_ASSERT_EQUAL(s->devs[1].major, 253);
|
|
||||||
CU_ASSERT_EQUAL(s->devs[1].minor, 2);
|
|
||||||
CU_ASSERT_EQUAL(s->log_count, 1);
|
|
||||||
CU_ASSERT_EQUAL(s->logs[0].major, 253);
|
|
||||||
CU_ASSERT_EQUAL(s->logs[0].minor, 0);
|
|
||||||
CU_ASSERT_EQUAL(s->logs[0].health, 'A');
|
|
||||||
CU_ASSERT(!strcmp(s->log_type, "disk"));
|
|
||||||
}
|
|
||||||
|
|
||||||
CU_ASSERT(dm_get_status_mirror(_mem,
|
|
||||||
"4 253:1 253:2 253:3 253:4 10/10 1 ADFF 1 core",
|
|
||||||
&s));
|
|
||||||
if (s) {
|
|
||||||
CU_ASSERT_EQUAL(s->total_regions, 10);
|
|
||||||
CU_ASSERT_EQUAL(s->insync_regions, 10);
|
|
||||||
CU_ASSERT_EQUAL(s->dev_count, 4);
|
|
||||||
CU_ASSERT_EQUAL(s->devs[3].minor, 4);
|
|
||||||
CU_ASSERT_EQUAL(s->devs[3].health, 'F');
|
|
||||||
CU_ASSERT_EQUAL(s->log_count, 0);
|
|
||||||
CU_ASSERT(!strcmp(s->log_type, "core"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CU_TestInfo dmstatus_list[] = {
|
|
||||||
{ (char*)"mirror_status", _test_mirror_status },
|
|
||||||
CU_TEST_INFO_NULL
|
|
||||||
};
|
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
|
||||||
* Copyright (C) 2004-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"
|
|
||||||
|
|
||||||
#include "matcher_data.h"
|
|
||||||
|
|
||||||
static struct dm_pool *mem = NULL;
|
|
||||||
|
|
||||||
int regex_init(void) {
|
|
||||||
mem = dm_pool_create("bitset test", 1024);
|
|
||||||
return mem == NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int regex_fini(void) {
|
|
||||||
dm_pool_destroy(mem);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct dm_regex *make_scanner(const char **rx)
|
|
||||||
{
|
|
||||||
struct dm_regex *scanner;
|
|
||||||
int nrx = 0;
|
|
||||||
for (; rx[nrx]; ++nrx);
|
|
||||||
|
|
||||||
scanner = dm_regex_create(mem, rx, nrx);
|
|
||||||
CU_ASSERT_FATAL(scanner != NULL);
|
|
||||||
return scanner;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_fingerprints(void) {
|
|
||||||
struct dm_regex *scanner;
|
|
||||||
|
|
||||||
scanner = make_scanner(dev_patterns);
|
|
||||||
CU_ASSERT_EQUAL(dm_regex_fingerprint(scanner), 0x7f556c09);
|
|
||||||
|
|
||||||
scanner = make_scanner(random_patterns);
|
|
||||||
CU_ASSERT_EQUAL(dm_regex_fingerprint(scanner), 0x9f11076c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_matching(void) {
|
|
||||||
struct dm_regex *scanner;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
scanner = make_scanner(dev_patterns);
|
|
||||||
for (i = 0; devices[i].str; ++i)
|
|
||||||
CU_ASSERT_EQUAL(dm_regex_match(scanner, devices[i].str), devices[i].expected - 1);
|
|
||||||
|
|
||||||
scanner = make_scanner(nonprint_patterns);
|
|
||||||
for (i = 0; nonprint[i].str; ++i)
|
|
||||||
CU_ASSERT_EQUAL(dm_regex_match(scanner, nonprint[i].str), nonprint[i].expected - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
CU_TestInfo regex_list[] = {
|
|
||||||
{ (char*)"fingerprints", test_fingerprints },
|
|
||||||
{ (char*)"matching", test_matching },
|
|
||||||
CU_TEST_INFO_NULL
|
|
||||||
};
|
|
@ -1,39 +0,0 @@
|
|||||||
#include "units.h"
|
|
||||||
#include <CUnit/Basic.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* Setup SuiteInfo struct in a compatible way across different CUnit versions */
|
|
||||||
/* old version of CUnit has used char* for .pName, so using cast here */
|
|
||||||
#define USE(n) { \
|
|
||||||
.pName = (char*) #n, \
|
|
||||||
.pInitFunc = n##_init, \
|
|
||||||
.pCleanupFunc = n##_fini, \
|
|
||||||
.pTests = n##_list }
|
|
||||||
|
|
||||||
CU_SuiteInfo suites[] = {
|
|
||||||
USE(bcache),
|
|
||||||
USE(bitset),
|
|
||||||
USE(config),
|
|
||||||
USE(dmlist),
|
|
||||||
USE(dmstatus),
|
|
||||||
USE(regex),
|
|
||||||
USE(percent),
|
|
||||||
USE(string),
|
|
||||||
CU_SUITE_INFO_NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
if (CU_initialize_registry() != CUE_SUCCESS) {
|
|
||||||
printf("Initialization of Test Registry failed.\n");
|
|
||||||
return CU_get_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
CU_register_suites(suites);
|
|
||||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
|
||||||
CU_basic_run_tests();
|
|
||||||
CU_cleanup_registry();
|
|
||||||
|
|
||||||
return (CU_get_number_of_failures() != 0);
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2012 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"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static struct dm_pool *mem = NULL;
|
|
||||||
|
|
||||||
int string_init(void)
|
|
||||||
{
|
|
||||||
mem = dm_pool_create("string test", 1024);
|
|
||||||
|
|
||||||
return (mem == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int string_fini(void)
|
|
||||||
{
|
|
||||||
dm_pool_destroy(mem);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: Add more string unit tests here */
|
|
||||||
|
|
||||||
static void test_strncpy(void)
|
|
||||||
{
|
|
||||||
const char st[] = "1234567890";
|
|
||||||
char buf[sizeof(st)];
|
|
||||||
|
|
||||||
CU_ASSERT_EQUAL(dm_strncpy(buf, st, sizeof(buf)), 1);
|
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, st), 0);
|
|
||||||
|
|
||||||
CU_ASSERT_EQUAL(dm_strncpy(buf, st, sizeof(buf) - 1), 0);
|
|
||||||
CU_ASSERT_EQUAL(strlen(buf) + 1, sizeof(buf) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_asprint(void)
|
|
||||||
{
|
|
||||||
const char st0[] = "";
|
|
||||||
const char st1[] = "12345678901";
|
|
||||||
const char st2[] = "1234567890123456789012345678901234567890123456789012345678901234567";
|
|
||||||
char *buf;
|
|
||||||
int a;
|
|
||||||
|
|
||||||
a = dm_asprintf(&buf, "%s", st0);
|
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, st0), 0);
|
|
||||||
CU_ASSERT_EQUAL(a, sizeof(st0));
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
a = dm_asprintf(&buf, "%s", st1);
|
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, st1), 0);
|
|
||||||
CU_ASSERT_EQUAL(a, sizeof(st1));
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
a = dm_asprintf(&buf, "%s", st2);
|
|
||||||
CU_ASSERT_EQUAL(a, sizeof(st2));
|
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, st2), 0);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
CU_TestInfo string_list[] = {
|
|
||||||
{ (char*)"asprint", test_asprint },
|
|
||||||
{ (char*)"strncpy", test_strncpy },
|
|
||||||
CU_TEST_INFO_NULL
|
|
||||||
};
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015-2017 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _UNITS_H
|
|
||||||
#define _UNITS_H
|
|
||||||
|
|
||||||
#include "libdevmapper.h"
|
|
||||||
#include <CUnit/CUnit.h>
|
|
||||||
|
|
||||||
#define DECL(n) \
|
|
||||||
extern CU_TestInfo n ## _list[];\
|
|
||||||
int n ## _init(void); \
|
|
||||||
int n ## _fini(void);
|
|
||||||
|
|
||||||
DECL(bcache);
|
|
||||||
DECL(bitset);
|
|
||||||
DECL(config);
|
|
||||||
DECL(dmlist);
|
|
||||||
DECL(dmstatus);
|
|
||||||
DECL(regex);
|
|
||||||
DECL(percent);
|
|
||||||
DECL(string);
|
|
||||||
|
|
||||||
#endif
|
|
@ -11,29 +11,30 @@
|
|||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
UNIT_SOURCE=\
|
UNIT_SOURCE=\
|
||||||
test/unit/bcache_t.c \
|
unit-test/bcache_t.c \
|
||||||
|
unit-test/bitset_t.c \
|
||||||
|
unit-test/config_t.c \
|
||||||
# test/unit/run.c
|
unit-test/dmlist_t.c \
|
||||||
|
unit-test/dmstatus_t.c \
|
||||||
# test/unit/bitset_t.c\
|
unit-test/matcher_t.c \
|
||||||
# test/unit/config_t.c\
|
unit-test/framework.c \
|
||||||
# test/unit/dmlist_t.c\
|
unit-test/percent_t.c \
|
||||||
# test/unit/dmstatus_t.c\
|
unit-test/run.c \
|
||||||
# test/unit/matcher_t.c\
|
unit-test/string_t.c
|
||||||
# test/unit/percent_t.c\
|
|
||||||
# test/unit/string_t.c\
|
|
||||||
|
|
||||||
|
UNIT_DEPENDS=$(subst .c,.d,$(UNIT_SOURCE))
|
||||||
UNIT_OBJECTS=$(UNIT_SOURCE:%.c=%.o)
|
UNIT_OBJECTS=$(UNIT_SOURCE:%.c=%.o)
|
||||||
|
CLEAN_TARGETS+=$(UNIT_DEPENDS) $(UNIT_OBJECTS)
|
||||||
UNIT_LDLIBS += $(LVMINTERNAL_LIBS) -ldevmapper -laio
|
UNIT_LDLIBS += $(LVMINTERNAL_LIBS) -ldevmapper -laio
|
||||||
|
|
||||||
test/unit/run: $(UNIT_OBJECTS) libdm/libdevmapper.$(LIB_SUFFIX) lib/liblvm-internal.a
|
unit-test/unit-test: $(UNIT_OBJECTS) libdm/libdevmapper.$(LIB_SUFFIX) lib/liblvm-internal.a
|
||||||
@echo " [LD] $@"
|
@echo " [LD] $@"
|
||||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) -L$(top_builddir)/libdm \
|
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) -L$(top_builddir)/libdm \
|
||||||
-o $@ $(UNIT_OBJECTS) $(UNIT_LDLIBS)
|
-o $@ $(UNIT_OBJECTS) $(UNIT_LDLIBS)
|
||||||
|
|
||||||
.PHONEY: unit-test
|
.PHONEY: run-unit-test
|
||||||
unit-test: test/unit/run
|
run-unit-test: unit-test/unit-test
|
||||||
@echo Running unit tests
|
@echo Running unit tests
|
||||||
LD_LIBRARY_PATH=libdm test/unit/run
|
LD_LIBRARY_PATH=libdm unit-test/unit-test run
|
||||||
|
|
||||||
|
-include $(UNIT_DEPENDS)
|
@ -12,40 +12,17 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
#include "bcache.h"
|
#include "bcache.h"
|
||||||
|
#include "framework.h"
|
||||||
|
#include "units.h"
|
||||||
|
|
||||||
#define SHOW_MOCK_CALLS 0
|
#define SHOW_MOCK_CALLS 0
|
||||||
|
|
||||||
/*----------------------------------------------------------------
|
|
||||||
* Assertions
|
|
||||||
*--------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static jmp_buf _test_k;
|
|
||||||
#define TEST_FAILED 1
|
|
||||||
|
|
||||||
static void _fail(const char *fmt, ...)
|
|
||||||
__attribute__((format (printf, 1, 2)));
|
|
||||||
|
|
||||||
|
|
||||||
static void _fail(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vfprintf(stderr, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
|
|
||||||
longjmp(_test_k, TEST_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define T_ASSERT(e) if (!(e)) {_fail("assertion failed: '%s'", # e);}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------
|
/*----------------------------------------------------------------
|
||||||
* Mock engine
|
* Mock engine
|
||||||
*--------------------------------------------------------------*/
|
*--------------------------------------------------------------*/
|
||||||
@ -72,6 +49,8 @@ struct mock_call {
|
|||||||
enum dir d;
|
enum dir d;
|
||||||
int fd;
|
int fd;
|
||||||
block_address b;
|
block_address b;
|
||||||
|
bool issue_r;
|
||||||
|
bool wait_r;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mock_io {
|
struct mock_io {
|
||||||
@ -81,6 +60,7 @@ struct mock_io {
|
|||||||
sector_t se;
|
sector_t se;
|
||||||
void *data;
|
void *data;
|
||||||
void *context;
|
void *context;
|
||||||
|
bool r;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *_show_method(enum method m)
|
static const char *_show_method(enum method m)
|
||||||
@ -115,6 +95,8 @@ static void _expect_read(struct mock_engine *e, int fd, block_address b)
|
|||||||
mc->d = DIR_READ;
|
mc->d = DIR_READ;
|
||||||
mc->fd = fd;
|
mc->fd = fd;
|
||||||
mc->b = b;
|
mc->b = b;
|
||||||
|
mc->issue_r = true;
|
||||||
|
mc->wait_r = true;
|
||||||
dm_list_add(&e->expected_calls, &mc->list);
|
dm_list_add(&e->expected_calls, &mc->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +108,60 @@ static void _expect_write(struct mock_engine *e, int fd, block_address b)
|
|||||||
mc->d = DIR_WRITE;
|
mc->d = DIR_WRITE;
|
||||||
mc->fd = fd;
|
mc->fd = fd;
|
||||||
mc->b = b;
|
mc->b = b;
|
||||||
|
mc->issue_r = true;
|
||||||
|
mc->wait_r = true;
|
||||||
|
dm_list_add(&e->expected_calls, &mc->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _expect_read_bad_issue(struct mock_engine *e, int fd, block_address b)
|
||||||
|
{
|
||||||
|
struct mock_call *mc = malloc(sizeof(*mc));
|
||||||
|
mc->m = E_ISSUE;
|
||||||
|
mc->match_args = true;
|
||||||
|
mc->d = DIR_READ;
|
||||||
|
mc->fd = fd;
|
||||||
|
mc->b = b;
|
||||||
|
mc->issue_r = false;
|
||||||
|
mc->wait_r = true;
|
||||||
|
dm_list_add(&e->expected_calls, &mc->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _expect_write_bad_issue(struct mock_engine *e, int fd, block_address b)
|
||||||
|
{
|
||||||
|
struct mock_call *mc = malloc(sizeof(*mc));
|
||||||
|
mc->m = E_ISSUE;
|
||||||
|
mc->match_args = true;
|
||||||
|
mc->d = DIR_WRITE;
|
||||||
|
mc->fd = fd;
|
||||||
|
mc->b = b;
|
||||||
|
mc->issue_r = false;
|
||||||
|
mc->wait_r = true;
|
||||||
|
dm_list_add(&e->expected_calls, &mc->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _expect_read_bad_wait(struct mock_engine *e, int fd, block_address b)
|
||||||
|
{
|
||||||
|
struct mock_call *mc = malloc(sizeof(*mc));
|
||||||
|
mc->m = E_ISSUE;
|
||||||
|
mc->match_args = true;
|
||||||
|
mc->d = DIR_READ;
|
||||||
|
mc->fd = fd;
|
||||||
|
mc->b = b;
|
||||||
|
mc->issue_r = true;
|
||||||
|
mc->wait_r = false;
|
||||||
|
dm_list_add(&e->expected_calls, &mc->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _expect_write_bad_wait(struct mock_engine *e, int fd, block_address b)
|
||||||
|
{
|
||||||
|
struct mock_call *mc = malloc(sizeof(*mc));
|
||||||
|
mc->m = E_ISSUE;
|
||||||
|
mc->match_args = true;
|
||||||
|
mc->d = DIR_WRITE;
|
||||||
|
mc->fd = fd;
|
||||||
|
mc->b = b;
|
||||||
|
mc->issue_r = true;
|
||||||
|
mc->wait_r = false;
|
||||||
dm_list_add(&e->expected_calls, &mc->list);
|
dm_list_add(&e->expected_calls, &mc->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,13 +171,13 @@ static struct mock_call *_match_pop(struct mock_engine *e, enum method m)
|
|||||||
struct mock_call *mc;
|
struct mock_call *mc;
|
||||||
|
|
||||||
if (dm_list_empty(&e->expected_calls))
|
if (dm_list_empty(&e->expected_calls))
|
||||||
_fail("unexpected call to method %s\n", _show_method(m));
|
test_fail("unexpected call to method %s\n", _show_method(m));
|
||||||
|
|
||||||
mc = dm_list_item(e->expected_calls.n, struct mock_call);
|
mc = dm_list_item(e->expected_calls.n, struct mock_call);
|
||||||
dm_list_del(&mc->list);
|
dm_list_del(&mc->list);
|
||||||
|
|
||||||
if (mc->m != m)
|
if (mc->m != m)
|
||||||
_fail("expected %s, but got %s\n", _show_method(mc->m), _show_method(m));
|
test_fail("expected %s, but got %s\n", _show_method(mc->m), _show_method(m));
|
||||||
#if SHOW_MOCK_CALLS
|
#if SHOW_MOCK_CALLS
|
||||||
else
|
else
|
||||||
fprintf(stderr, "%s called (expected)\n", _show_method(m));
|
fprintf(stderr, "%s called (expected)\n", _show_method(m));
|
||||||
@ -185,6 +221,7 @@ static void _mock_destroy(struct io_engine *e)
|
|||||||
static bool _mock_issue(struct io_engine *e, enum dir d, int fd,
|
static bool _mock_issue(struct io_engine *e, enum dir d, int fd,
|
||||||
sector_t sb, sector_t se, void *data, void *context)
|
sector_t sb, sector_t se, void *data, void *context)
|
||||||
{
|
{
|
||||||
|
bool r, wait_r;
|
||||||
struct mock_io *io;
|
struct mock_io *io;
|
||||||
struct mock_call *mc;
|
struct mock_call *mc;
|
||||||
struct mock_engine *me = _to_mock(e);
|
struct mock_engine *me = _to_mock(e);
|
||||||
@ -196,8 +233,11 @@ static bool _mock_issue(struct io_engine *e, enum dir d, int fd,
|
|||||||
T_ASSERT(sb == mc->b * me->block_size);
|
T_ASSERT(sb == mc->b * me->block_size);
|
||||||
T_ASSERT(se == (mc->b + 1) * me->block_size);
|
T_ASSERT(se == (mc->b + 1) * me->block_size);
|
||||||
}
|
}
|
||||||
|
r = mc->issue_r;
|
||||||
|
wait_r = mc->wait_r;
|
||||||
free(mc);
|
free(mc);
|
||||||
|
|
||||||
|
if (r) {
|
||||||
io = malloc(sizeof(*io));
|
io = malloc(sizeof(*io));
|
||||||
if (!io)
|
if (!io)
|
||||||
abort();
|
abort();
|
||||||
@ -207,9 +247,12 @@ static bool _mock_issue(struct io_engine *e, enum dir d, int fd,
|
|||||||
io->se = se;
|
io->se = se;
|
||||||
io->data = data;
|
io->data = data;
|
||||||
io->context = context;
|
io->context = context;
|
||||||
|
io->r = wait_r;
|
||||||
|
|
||||||
dm_list_add(&me->issued_io, &io->list);
|
dm_list_add(&me->issued_io, &io->list);
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _mock_wait(struct io_engine *e, io_complete_fn fn)
|
static bool _mock_wait(struct io_engine *e, io_complete_fn fn)
|
||||||
@ -223,7 +266,9 @@ static bool _mock_wait(struct io_engine *e, io_complete_fn fn)
|
|||||||
T_ASSERT(!dm_list_empty(&me->issued_io));
|
T_ASSERT(!dm_list_empty(&me->issued_io));
|
||||||
io = dm_list_item(me->issued_io.n, struct mock_io);
|
io = dm_list_item(me->issued_io.n, struct mock_io);
|
||||||
dm_list_del(&io->list);
|
dm_list_del(&io->list);
|
||||||
fn(io->context, 0);
|
fn(io->context, io->r ? 0 : -EIO);
|
||||||
|
free(io);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,6 +408,7 @@ static void test_block_size_must_be_multiple_of_page_size(void *fixture)
|
|||||||
|
|
||||||
static void test_get_triggers_read(void *context)
|
static void test_get_triggers_read(void *context)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
struct fixture *f = context;
|
struct fixture *f = context;
|
||||||
|
|
||||||
int fd = 17; // arbitrary key
|
int fd = 17; // arbitrary key
|
||||||
@ -370,12 +416,13 @@ static void test_get_triggers_read(void *context)
|
|||||||
|
|
||||||
_expect_read(f->me, fd, 0);
|
_expect_read(f->me, fd, 0);
|
||||||
_expect(f->me, E_WAIT);
|
_expect(f->me, E_WAIT);
|
||||||
T_ASSERT(bcache_get(f->cache, fd, 0, 0, &b));
|
T_ASSERT(bcache_get(f->cache, fd, 0, 0, &b, &err));
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_repeated_reads_are_cached(void *context)
|
static void test_repeated_reads_are_cached(void *context)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
struct fixture *f = context;
|
struct fixture *f = context;
|
||||||
|
|
||||||
int fd = 17; // arbitrary key
|
int fd = 17; // arbitrary key
|
||||||
@ -385,7 +432,7 @@ static void test_repeated_reads_are_cached(void *context)
|
|||||||
_expect_read(f->me, fd, 0);
|
_expect_read(f->me, fd, 0);
|
||||||
_expect(f->me, E_WAIT);
|
_expect(f->me, E_WAIT);
|
||||||
for (i = 0; i < 100; i++) {
|
for (i = 0; i < 100; i++) {
|
||||||
T_ASSERT(bcache_get(f->cache, fd, 0, 0, &b));
|
T_ASSERT(bcache_get(f->cache, fd, 0, 0, &b, &err));
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,6 +441,7 @@ static void test_block_gets_evicted_with_many_reads(void *context)
|
|||||||
{
|
{
|
||||||
struct fixture *f = context;
|
struct fixture *f = context;
|
||||||
|
|
||||||
|
int err;
|
||||||
struct mock_engine *me = f->me;
|
struct mock_engine *me = f->me;
|
||||||
struct bcache *cache = f->cache;
|
struct bcache *cache = f->cache;
|
||||||
const unsigned nr_cache_blocks = 16;
|
const unsigned nr_cache_blocks = 16;
|
||||||
@ -405,14 +453,14 @@ static void test_block_gets_evicted_with_many_reads(void *context)
|
|||||||
for (i = 0; i < nr_cache_blocks; i++) {
|
for (i = 0; i < nr_cache_blocks; i++) {
|
||||||
_expect_read(me, fd, i);
|
_expect_read(me, fd, i);
|
||||||
_expect(me, E_WAIT);
|
_expect(me, E_WAIT);
|
||||||
T_ASSERT(bcache_get(cache, fd, i, 0, &b));
|
T_ASSERT(bcache_get(cache, fd, i, 0, &b, &err));
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not enough cache blocks to hold this one
|
// Not enough cache blocks to hold this one
|
||||||
_expect_read(me, fd, nr_cache_blocks);
|
_expect_read(me, fd, nr_cache_blocks);
|
||||||
_expect(me, E_WAIT);
|
_expect(me, E_WAIT);
|
||||||
T_ASSERT(bcache_get(cache, fd, nr_cache_blocks, 0, &b));
|
T_ASSERT(bcache_get(cache, fd, nr_cache_blocks, 0, &b, &err));
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
|
|
||||||
// Now if we run through we should find one block has been
|
// Now if we run through we should find one block has been
|
||||||
@ -421,7 +469,7 @@ static void test_block_gets_evicted_with_many_reads(void *context)
|
|||||||
_expect(me, E_ISSUE);
|
_expect(me, E_ISSUE);
|
||||||
_expect(me, E_WAIT);
|
_expect(me, E_WAIT);
|
||||||
for (i = nr_cache_blocks; i; i--) {
|
for (i = nr_cache_blocks; i; i--) {
|
||||||
T_ASSERT(bcache_get(cache, fd, i - 1, 0, &b));
|
T_ASSERT(bcache_get(cache, fd, i - 1, 0, &b, &err));
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,6 +481,7 @@ static void test_prefetch_issues_a_read(void *context)
|
|||||||
struct bcache *cache = f->cache;
|
struct bcache *cache = f->cache;
|
||||||
const unsigned nr_cache_blocks = 16;
|
const unsigned nr_cache_blocks = 16;
|
||||||
|
|
||||||
|
int err;
|
||||||
int fd = 17; // arbitrary key
|
int fd = 17; // arbitrary key
|
||||||
unsigned i;
|
unsigned i;
|
||||||
struct block *b;
|
struct block *b;
|
||||||
@ -446,7 +495,7 @@ static void test_prefetch_issues_a_read(void *context)
|
|||||||
|
|
||||||
for (i = 0; i < nr_cache_blocks; i++) {
|
for (i = 0; i < nr_cache_blocks; i++) {
|
||||||
_expect(me, E_WAIT);
|
_expect(me, E_WAIT);
|
||||||
T_ASSERT(bcache_get(cache, fd, i, 0, &b));
|
T_ASSERT(bcache_get(cache, fd, i, 0, &b, &err));
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,13 +528,14 @@ static void test_dirty_data_gets_written_back(void *context)
|
|||||||
struct mock_engine *me = f->me;
|
struct mock_engine *me = f->me;
|
||||||
struct bcache *cache = f->cache;
|
struct bcache *cache = f->cache;
|
||||||
|
|
||||||
|
int err;
|
||||||
int fd = 17; // arbitrary key
|
int fd = 17; // arbitrary key
|
||||||
struct block *b;
|
struct block *b;
|
||||||
|
|
||||||
// Expect the read
|
// Expect the read
|
||||||
_expect_read(me, fd, 0);
|
_expect_read(me, fd, 0);
|
||||||
_expect(me, E_WAIT);
|
_expect(me, E_WAIT);
|
||||||
T_ASSERT(bcache_get(cache, fd, 0, GF_DIRTY, &b));
|
T_ASSERT(bcache_get(cache, fd, 0, GF_DIRTY, &b, &err));
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
|
|
||||||
// Expect the write
|
// Expect the write
|
||||||
@ -499,11 +549,12 @@ static void test_zeroed_data_counts_as_dirty(void *context)
|
|||||||
struct mock_engine *me = f->me;
|
struct mock_engine *me = f->me;
|
||||||
struct bcache *cache = f->cache;
|
struct bcache *cache = f->cache;
|
||||||
|
|
||||||
|
int err;
|
||||||
int fd = 17; // arbitrary key
|
int fd = 17; // arbitrary key
|
||||||
struct block *b;
|
struct block *b;
|
||||||
|
|
||||||
// No read
|
// No read
|
||||||
T_ASSERT(bcache_get(cache, fd, 0, GF_ZERO, &b));
|
T_ASSERT(bcache_get(cache, fd, 0, GF_ZERO, &b, &err));
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
|
|
||||||
// Expect the write
|
// Expect the write
|
||||||
@ -518,17 +569,18 @@ static void test_flush_waits_for_all_dirty(void *context)
|
|||||||
struct bcache *cache = f->cache;
|
struct bcache *cache = f->cache;
|
||||||
|
|
||||||
const unsigned count = 16;
|
const unsigned count = 16;
|
||||||
|
int err;
|
||||||
int fd = 17; // arbitrary key
|
int fd = 17; // arbitrary key
|
||||||
unsigned i;
|
unsigned i;
|
||||||
struct block *b;
|
struct block *b;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if (i % 2) {
|
if (i % 2) {
|
||||||
T_ASSERT(bcache_get(cache, fd, i, GF_ZERO, &b));
|
T_ASSERT(bcache_get(cache, fd, i, GF_ZERO, &b, &err));
|
||||||
} else {
|
} else {
|
||||||
_expect_read(me, fd, i);
|
_expect_read(me, fd, i);
|
||||||
_expect(me, E_WAIT);
|
_expect(me, E_WAIT);
|
||||||
T_ASSERT(bcache_get(cache, fd, i, 0, &b));
|
T_ASSERT(bcache_get(cache, fd, i, 0, &b, &err));
|
||||||
}
|
}
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
}
|
}
|
||||||
@ -547,10 +599,11 @@ static void test_flush_waits_for_all_dirty(void *context)
|
|||||||
_no_outstanding_expectations(me);
|
_no_outstanding_expectations(me);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_multiple_files(void * context)
|
static void test_multiple_files(void *context)
|
||||||
{
|
{
|
||||||
static int _fds[] = {1, 128, 345, 678, 890};
|
static int _fds[] = {1, 128, 345, 678, 890};
|
||||||
|
|
||||||
|
int err;
|
||||||
struct fixture *f = context;
|
struct fixture *f = context;
|
||||||
struct mock_engine *me = f->me;
|
struct mock_engine *me = f->me;
|
||||||
struct bcache *cache = f->cache;
|
struct bcache *cache = f->cache;
|
||||||
@ -561,76 +614,170 @@ static void test_multiple_files(void * context)
|
|||||||
_expect_read(me, _fds[i], 0);
|
_expect_read(me, _fds[i], 0);
|
||||||
_expect(me, E_WAIT);
|
_expect(me, E_WAIT);
|
||||||
|
|
||||||
T_ASSERT(bcache_get(cache, _fds[i], 0, 0, &b));
|
T_ASSERT(bcache_get(cache, _fds[i], 0, 0, &b, &err));
|
||||||
bcache_put(b);
|
bcache_put(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_read_bad_issue(void *context)
|
||||||
|
{
|
||||||
|
struct fixture *f = context;
|
||||||
|
struct mock_engine *me = f->me;
|
||||||
|
struct bcache *cache = f->cache;
|
||||||
|
struct block *b;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
_expect_read_bad_issue(me, 17, 0);
|
||||||
|
T_ASSERT(!bcache_get(cache, 17, 0, 0, &b, &err));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_read_bad_issue_intermittent(void *context)
|
||||||
|
{
|
||||||
|
struct fixture *f = context;
|
||||||
|
struct mock_engine *me = f->me;
|
||||||
|
struct bcache *cache = f->cache;
|
||||||
|
struct block *b;
|
||||||
|
int fd = 17;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
_expect_read_bad_issue(me, fd, 0);
|
||||||
|
T_ASSERT(!bcache_get(cache, fd, 0, 0, &b, &err));
|
||||||
|
|
||||||
|
_expect_read(me, fd, 0);
|
||||||
|
_expect(me, E_WAIT);
|
||||||
|
T_ASSERT(bcache_get(cache, fd, 0, 0, &b, &err));
|
||||||
|
bcache_put(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_read_bad_wait(void *context)
|
||||||
|
{
|
||||||
|
struct fixture *f = context;
|
||||||
|
struct mock_engine *me = f->me;
|
||||||
|
struct bcache *cache = f->cache;
|
||||||
|
struct block *b;
|
||||||
|
int fd = 17;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
_expect_read_bad_wait(me, fd, 0);
|
||||||
|
_expect(me, E_WAIT);
|
||||||
|
T_ASSERT(!bcache_get(cache, fd, 0, 0, &b, &err));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_read_bad_wait_intermittent(void *context)
|
||||||
|
{
|
||||||
|
struct fixture *f = context;
|
||||||
|
struct mock_engine *me = f->me;
|
||||||
|
struct bcache *cache = f->cache;
|
||||||
|
struct block *b;
|
||||||
|
int fd = 17;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
_expect_read_bad_wait(me, fd, 0);
|
||||||
|
_expect(me, E_WAIT);
|
||||||
|
T_ASSERT(!bcache_get(cache, fd, 0, 0, &b, &err));
|
||||||
|
|
||||||
|
_expect_read(me, fd, 0);
|
||||||
|
_expect(me, E_WAIT);
|
||||||
|
T_ASSERT(bcache_get(cache, fd, 0, 0, &b, &err));
|
||||||
|
bcache_put(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_write_bad_issue_stops_flush(void *context)
|
||||||
|
{
|
||||||
|
struct fixture *f = context;
|
||||||
|
struct mock_engine *me = f->me;
|
||||||
|
struct bcache *cache = f->cache;
|
||||||
|
struct block *b;
|
||||||
|
int fd = 17;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
T_ASSERT(bcache_get(cache, fd, 0, GF_ZERO, &b, &err));
|
||||||
|
_expect_write_bad_issue(me, fd, 0);
|
||||||
|
bcache_put(b);
|
||||||
|
T_ASSERT(!bcache_flush(cache));
|
||||||
|
|
||||||
|
// we'll let it succeed the second time
|
||||||
|
_expect_write(me, fd, 0);
|
||||||
|
_expect(me, E_WAIT);
|
||||||
|
T_ASSERT(bcache_flush(cache));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_write_bad_io_stops_flush(void *context)
|
||||||
|
{
|
||||||
|
struct fixture *f = context;
|
||||||
|
struct mock_engine *me = f->me;
|
||||||
|
struct bcache *cache = f->cache;
|
||||||
|
struct block *b;
|
||||||
|
int fd = 17;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
T_ASSERT(bcache_get(cache, fd, 0, GF_ZERO, &b, &err));
|
||||||
|
_expect_write_bad_wait(me, fd, 0);
|
||||||
|
_expect(me, E_WAIT);
|
||||||
|
bcache_put(b);
|
||||||
|
T_ASSERT(!bcache_flush(cache));
|
||||||
|
|
||||||
|
// we'll let it succeed the second time
|
||||||
|
_expect_write(me, fd, 0);
|
||||||
|
_expect(me, E_WAIT);
|
||||||
|
T_ASSERT(bcache_flush(cache));
|
||||||
|
}
|
||||||
|
|
||||||
// Tests to be written
|
// Tests to be written
|
||||||
// Open multiple files and prove the blocks are coming from the correct file
|
|
||||||
// show invalidate works
|
// show invalidate works
|
||||||
// show invalidate_fd works
|
// show invalidate_fd works
|
||||||
// show writeback is working
|
// show writeback is working
|
||||||
// check zeroing
|
|
||||||
|
|
||||||
struct test_details {
|
/*----------------------------------------------------------------
|
||||||
const char *path;
|
* Top level
|
||||||
const char *desc;
|
*--------------------------------------------------------------*/
|
||||||
void (*fn)(void *);
|
#define T(path, desc, fn) register_test(ts, "/base/device/bcache/" path, desc, fn)
|
||||||
void *(*fixture_init)(void);
|
|
||||||
void (*fixture_exit)(void *);
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PATH "device/bcache/"
|
static struct test_suite *_small_tests(void)
|
||||||
#define TEST(path, name, fn) {PATH path, name, fn, NULL, NULL}
|
|
||||||
#define TEST_S(path, name, fn) {PATH path, name, fn, _small_fixture_init, _small_fixture_exit}
|
|
||||||
#define TEST_L(path, name, fn) {PATH path, name, fn, _large_fixture_init, _large_fixture_exit}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
static struct test_details _tests[] = {
|
struct test_suite *ts = test_suite_create(_small_fixture_init, _small_fixture_exit);
|
||||||
TEST("create-destroy", "simple create/destroy", test_create),
|
if (!ts) {
|
||||||
TEST("cache-blocks-positive", "nr cache blocks must be positive", test_nr_cache_blocks_must_be_positive),
|
fprintf(stderr, "out of memory\n");
|
||||||
TEST("block-size-positive", "block size must be positive", test_block_size_must_be_positive),
|
exit(1);
|
||||||
TEST("block-size-multiple-page", "block size must be a multiple of page size", test_block_size_must_be_multiple_of_page_size),
|
|
||||||
TEST_S("get-reads", "bcache_get() triggers read", test_get_triggers_read),
|
|
||||||
TEST_S("reads-cached", "repeated reads are cached", test_repeated_reads_are_cached),
|
|
||||||
TEST_S("blocks-get-evicted", "block get evicted with many reads", test_block_gets_evicted_with_many_reads),
|
|
||||||
TEST_S("prefetch-reads", "prefetch issues a read", test_prefetch_issues_a_read),
|
|
||||||
TEST_S("prefetch-never-waits", "too many prefetches does not trigger a wait", test_too_many_prefetches_does_not_trigger_a_wait),
|
|
||||||
TEST_S("writeback-occurs", "dirty data gets written back", test_dirty_data_gets_written_back),
|
|
||||||
TEST_S("zero-flag-dirties", "zeroed data counts as dirty", test_zeroed_data_counts_as_dirty),
|
|
||||||
TEST_L("flush waits for all dirty", "flush waits for all dirty", test_flush_waits_for_all_dirty),
|
|
||||||
TEST_S("read-multiple-files", "read from multiple files", test_multiple_files),
|
|
||||||
};
|
|
||||||
|
|
||||||
// We have to declare these as volatile because of the setjmp()
|
|
||||||
volatile unsigned i = 0, passed = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < DM_ARRAY_SIZE(_tests); i++) {
|
|
||||||
void *fixture;
|
|
||||||
struct test_details *t = _tests + i;
|
|
||||||
fprintf(stderr, "[RUN ] %s\n", t->path);
|
|
||||||
|
|
||||||
if (setjmp(_test_k))
|
|
||||||
fprintf(stderr, "[ FAIL] %s\n", t->path);
|
|
||||||
else {
|
|
||||||
if (t->fixture_init)
|
|
||||||
fixture = t->fixture_init();
|
|
||||||
else
|
|
||||||
fixture = NULL;
|
|
||||||
|
|
||||||
t->fn(fixture);
|
|
||||||
|
|
||||||
if (t->fixture_exit)
|
|
||||||
t->fixture_exit(fixture);
|
|
||||||
|
|
||||||
passed++;
|
|
||||||
fprintf(stderr, "[ OK] %s\n", t->path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "\n%u/%lu tests passed\n", passed, DM_ARRAY_SIZE(_tests));
|
T("create-destroy", "simple create/destroy", test_create);
|
||||||
|
T("cache-blocks-positive", "nr cache blocks must be positive", test_nr_cache_blocks_must_be_positive);
|
||||||
|
T("block-size-positive", "block size must be positive", test_block_size_must_be_positive);
|
||||||
|
T("block-size-multiple-page", "block size must be a multiple of page size", test_block_size_must_be_multiple_of_page_size);
|
||||||
|
T("get-reads", "bcache_get() triggers read", test_get_triggers_read);
|
||||||
|
T("reads-cached", "repeated reads are cached", test_repeated_reads_are_cached);
|
||||||
|
T("blocks-get-evicted", "block get evicted with many reads", test_block_gets_evicted_with_many_reads);
|
||||||
|
T("prefetch-reads", "prefetch issues a read", test_prefetch_issues_a_read);
|
||||||
|
T("prefetch-never-waits", "too many prefetches does not trigger a wait", test_too_many_prefetches_does_not_trigger_a_wait);
|
||||||
|
T("writeback-occurs", "dirty data gets written back", test_dirty_data_gets_written_back);
|
||||||
|
T("zero-flag-dirties", "zeroed data counts as dirty", test_zeroed_data_counts_as_dirty);
|
||||||
|
T("read-multiple-files", "read from multiple files", test_multiple_files);
|
||||||
|
T("read-bad-issue", "read fails if io engine unable to issue", test_read_bad_issue);
|
||||||
|
T("read-bad-issue-intermittent", "failed issue, followed by succes", test_read_bad_issue_intermittent);
|
||||||
|
T("read-bad-io", "read issued ok, but io fails", test_read_bad_wait);
|
||||||
|
T("read-bad-io-intermittent", "failed io, followed by success", test_read_bad_wait_intermittent);
|
||||||
|
T("write-bad-issue-stops-flush", "flush fails temporarily if any block fails to write", test_write_bad_issue_stops_flush);
|
||||||
|
T("write-bad-io-stops-flush", "flush fails temporarily if any block fails to write", test_write_bad_io_stops_flush);
|
||||||
|
|
||||||
return 0;
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct test_suite *_large_tests(void)
|
||||||
|
{
|
||||||
|
struct test_suite *ts = test_suite_create(_large_fixture_init, _large_fixture_exit);
|
||||||
|
if (!ts) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
T("flush-waits", "flush waits for all dirty", test_flush_waits_for_all_dirty);
|
||||||
|
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcache_tests(struct dm_list *all_tests)
|
||||||
|
{
|
||||||
|
dm_list_add(all_tests, &_small_tests()->list);
|
||||||
|
dm_list_add(all_tests, &_large_tests()->list);
|
||||||
}
|
}
|
@ -13,30 +13,36 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NR_BITS = 137
|
NR_BITS = 137
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dm_pool *mem;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
int bitset_init(void) {
|
return mem;
|
||||||
mem = dm_pool_create("bitset test", 1024);
|
|
||||||
return mem == NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bitset_fini(void) {
|
static void _mem_exit(void *mem)
|
||||||
dm_pool_destroy(mem);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_get_next(void)
|
|
||||||
{
|
{
|
||||||
|
dm_pool_destroy(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_get_next(void *fixture)
|
||||||
|
{
|
||||||
|
struct dm_pool *mem = fixture;
|
||||||
|
|
||||||
int i, j, last = 0, first;
|
int i, j, last = 0, first;
|
||||||
dm_bitset_t bs = dm_bitset_create(mem, NR_BITS);
|
dm_bitset_t bs = dm_bitset_create(mem, NR_BITS);
|
||||||
|
|
||||||
for (i = 0; i < NR_BITS; i++)
|
for (i = 0; i < NR_BITS; i++)
|
||||||
CU_ASSERT(!dm_bit(bs, i));
|
T_ASSERT(!dm_bit(bs, i));
|
||||||
|
|
||||||
for (i = 0, j = 1; i < NR_BITS; i += j, j++)
|
for (i = 0, j = 1; i < NR_BITS; i += j, j++)
|
||||||
dm_bit_set(bs, i);
|
dm_bit_set(bs, i);
|
||||||
@ -49,10 +55,10 @@ static void test_get_next(void)
|
|||||||
} else
|
} else
|
||||||
last = dm_bit_get_next(bs, last);
|
last = dm_bit_get_next(bs, last);
|
||||||
|
|
||||||
CU_ASSERT(last == i);
|
T_ASSERT(last == i);
|
||||||
}
|
}
|
||||||
|
|
||||||
CU_ASSERT(dm_bit_get_next(bs, last) == -1);
|
T_ASSERT(dm_bit_get_next(bs, last) == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bit_flip(dm_bitset_t bs, int bit)
|
static void bit_flip(dm_bitset_t bs, int bit)
|
||||||
@ -64,8 +70,9 @@ static void bit_flip(dm_bitset_t bs, int bit)
|
|||||||
dm_bit_set(bs, bit);
|
dm_bit_set(bs, bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_equal(void)
|
static void test_equal(void *fixture)
|
||||||
{
|
{
|
||||||
|
struct dm_pool *mem = fixture;
|
||||||
dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS);
|
dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS);
|
||||||
dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS);
|
dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS);
|
||||||
|
|
||||||
@ -75,21 +82,22 @@ static void test_equal(void)
|
|||||||
dm_bit_set(bs2, i);
|
dm_bit_set(bs2, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
CU_ASSERT(dm_bitset_equal(bs1, bs2));
|
T_ASSERT(dm_bitset_equal(bs1, bs2));
|
||||||
CU_ASSERT(dm_bitset_equal(bs2, bs1));
|
T_ASSERT(dm_bitset_equal(bs2, bs1));
|
||||||
|
|
||||||
for (i = 0; i < NR_BITS; i++) {
|
for (i = 0; i < NR_BITS; i++) {
|
||||||
bit_flip(bs1, i);
|
bit_flip(bs1, i);
|
||||||
CU_ASSERT(!dm_bitset_equal(bs1, bs2));
|
T_ASSERT(!dm_bitset_equal(bs1, bs2));
|
||||||
CU_ASSERT(!dm_bitset_equal(bs2, bs1));
|
T_ASSERT(!dm_bitset_equal(bs2, bs1));
|
||||||
|
|
||||||
CU_ASSERT(dm_bitset_equal(bs1, bs1)); /* comparing with self */
|
T_ASSERT(dm_bitset_equal(bs1, bs1)); /* comparing with self */
|
||||||
bit_flip(bs1, i);
|
bit_flip(bs1, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_and(void)
|
static void test_and(void *fixture)
|
||||||
{
|
{
|
||||||
|
struct dm_pool *mem = fixture;
|
||||||
dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS);
|
dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS);
|
||||||
dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS);
|
dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS);
|
||||||
dm_bitset_t bs3 = dm_bitset_create(mem, NR_BITS);
|
dm_bitset_t bs3 = dm_bitset_create(mem, NR_BITS);
|
||||||
@ -102,9 +110,9 @@ static void test_and(void)
|
|||||||
|
|
||||||
dm_bit_and(bs3, bs1, bs2);
|
dm_bit_and(bs3, bs1, bs2);
|
||||||
|
|
||||||
CU_ASSERT(dm_bitset_equal(bs1, bs2));
|
T_ASSERT(dm_bitset_equal(bs1, bs2));
|
||||||
CU_ASSERT(dm_bitset_equal(bs1, bs3));
|
T_ASSERT(dm_bitset_equal(bs1, bs3));
|
||||||
CU_ASSERT(dm_bitset_equal(bs2, bs3));
|
T_ASSERT(dm_bitset_equal(bs2, bs3));
|
||||||
|
|
||||||
dm_bit_clear_all(bs1);
|
dm_bit_clear_all(bs1);
|
||||||
dm_bit_clear_all(bs2);
|
dm_bit_clear_all(bs2);
|
||||||
@ -118,12 +126,23 @@ static void test_and(void)
|
|||||||
|
|
||||||
dm_bit_and(bs3, bs1, bs2);
|
dm_bit_and(bs3, bs1, bs2);
|
||||||
for (i = 0; i < NR_BITS; i++)
|
for (i = 0; i < NR_BITS; i++)
|
||||||
CU_ASSERT(!dm_bit(bs3, i));
|
T_ASSERT(!dm_bit(bs3, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
#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);
|
||||||
}
|
}
|
||||||
|
|
||||||
CU_TestInfo bitset_list[] = {
|
|
||||||
{ (char*)"get_next", test_get_next },
|
|
||||||
{ (char*)"equal", test_equal },
|
|
||||||
{ (char*)"and", test_and },
|
|
||||||
CU_TEST_INFO_NULL
|
|
||||||
};
|
|
167
unit-test/config_t.c
Normal file
167
unit-test/config_t.c
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
|
static void *_mem_init(void)
|
||||||
|
{
|
||||||
|
struct dm_pool *mem = dm_pool_create("config test", 1024);
|
||||||
|
if (!mem) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _mem_exit(void *mem)
|
||||||
|
{
|
||||||
|
dm_pool_destroy(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 *fixture)
|
||||||
|
{
|
||||||
|
struct dm_config_tree *tree = dm_config_from_string(conf);
|
||||||
|
const struct dm_config_value *value;
|
||||||
|
|
||||||
|
T_ASSERT((long) tree);
|
||||||
|
T_ASSERT(dm_config_has_node(tree->root, "id"));
|
||||||
|
T_ASSERT(dm_config_has_node(tree->root, "physical_volumes"));
|
||||||
|
T_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0"));
|
||||||
|
T_ASSERT(dm_config_has_node(tree->root, "physical_volumes/pv0/id"));
|
||||||
|
|
||||||
|
T_ASSERT(!strcmp(dm_config_find_str(tree->root, "id", "foo"), "yada-yada"));
|
||||||
|
T_ASSERT(!strcmp(dm_config_find_str(tree->root, "idt", "foo"), "foo"));
|
||||||
|
|
||||||
|
T_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/bb", "foo"), "foo"));
|
||||||
|
T_ASSERT(!strcmp(dm_config_find_str(tree->root, "physical_volumes/pv0/id", "foo"), "abcd-efgh"));
|
||||||
|
|
||||||
|
T_ASSERT(!dm_config_get_uint32(tree->root, "id", NULL));
|
||||||
|
T_ASSERT(dm_config_get_uint32(tree->root, "extent_size", NULL));
|
||||||
|
|
||||||
|
/* FIXME: Currently everything parses as a list, even if it's not */
|
||||||
|
// T_ASSERT(!dm_config_get_list(tree->root, "id", NULL));
|
||||||
|
// T_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL));
|
||||||
|
|
||||||
|
T_ASSERT(dm_config_get_list(tree->root, "flags", &value));
|
||||||
|
T_ASSERT(value->next == NULL); /* an empty list */
|
||||||
|
T_ASSERT(dm_config_get_list(tree->root, "status", &value));
|
||||||
|
T_ASSERT(value->next != NULL); /* a non-empty list */
|
||||||
|
|
||||||
|
dm_config_destroy(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_clone(void *fixture)
|
||||||
|
{
|
||||||
|
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. */
|
||||||
|
T_ASSERT(n != tree->root);
|
||||||
|
T_ASSERT(n->sib != tree->root->sib);
|
||||||
|
T_ASSERT(dm_config_find_node(n, "physical_volumes") != NULL);
|
||||||
|
T_ASSERT(dm_config_find_node(tree->root, "physical_volumes") != NULL);
|
||||||
|
T_ASSERT(dm_config_find_node(n, "physical_volumes") != dm_config_find_node(tree->root, "physical_volumes"));
|
||||||
|
|
||||||
|
T_ASSERT(dm_config_has_node(n, "id"));
|
||||||
|
T_ASSERT(dm_config_has_node(n, "physical_volumes"));
|
||||||
|
T_ASSERT(dm_config_has_node(n, "physical_volumes/pv0"));
|
||||||
|
T_ASSERT(dm_config_has_node(n, "physical_volumes/pv0/id"));
|
||||||
|
|
||||||
|
T_ASSERT(!strcmp(dm_config_find_str(n, "id", "foo"), "yada-yada"));
|
||||||
|
T_ASSERT(!strcmp(dm_config_find_str(n, "idt", "foo"), "foo"));
|
||||||
|
|
||||||
|
T_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/bb", "foo"), "foo"));
|
||||||
|
T_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/id", "foo"), "abcd-efgh"));
|
||||||
|
|
||||||
|
T_ASSERT(!dm_config_get_uint32(n, "id", NULL));
|
||||||
|
T_ASSERT(dm_config_get_uint32(n, "extent_size", NULL));
|
||||||
|
|
||||||
|
/* FIXME: Currently everything parses as a list, even if it's not */
|
||||||
|
// T_ASSERT(!dm_config_get_list(tree->root, "id", NULL));
|
||||||
|
// T_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL));
|
||||||
|
|
||||||
|
T_ASSERT(dm_config_get_list(n, "flags", &value));
|
||||||
|
T_ASSERT(value->next == NULL); /* an empty list */
|
||||||
|
T_ASSERT(dm_config_get_list(n, "status", &value));
|
||||||
|
T_ASSERT(value->next != NULL); /* a non-empty list */
|
||||||
|
|
||||||
|
dm_config_destroy(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_cascade(void *fixture)
|
||||||
|
{
|
||||||
|
struct dm_config_tree *t1 = dm_config_from_string(conf),
|
||||||
|
*t2 = dm_config_from_string(overlay),
|
||||||
|
*tree = dm_config_insert_cascaded_tree(t2, t1);
|
||||||
|
|
||||||
|
T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "id", "foo"), "yoda-soda"));
|
||||||
|
T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "idt", "foo"), "foo"));
|
||||||
|
|
||||||
|
T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv0/bb", "foo"), "foo"));
|
||||||
|
T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv1/id", "foo"), "hgfe-dcba"));
|
||||||
|
T_ASSERT(!strcmp(dm_config_tree_find_str(tree, "physical_volumes/pv3/id", "foo"), "dbcd-efgh"));
|
||||||
|
|
||||||
|
dm_config_destroy(t1);
|
||||||
|
dm_config_destroy(t2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define T(path, desc, fn) register_test(ts, "/metadata/config/" path, desc, fn)
|
||||||
|
|
||||||
|
void config_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("parse", "parsing various", test_parse);
|
||||||
|
T("clone", "duplicating a config tree", test_clone);
|
||||||
|
T("cascade", "cascade", test_cascade);
|
||||||
|
|
||||||
|
dm_list_add(all_tests, &ts->list);
|
||||||
|
};
|
@ -13,23 +13,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
int dmlist_init(void)
|
static void test_dmlist_splice(void *fixture)
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dmlist_fini(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_dmlist_splice(void)
|
|
||||||
{
|
{
|
||||||
|
unsigned i;
|
||||||
struct dm_list a[10];
|
struct dm_list a[10];
|
||||||
struct dm_list list1;
|
struct dm_list list1;
|
||||||
struct dm_list list2;
|
struct dm_list list2;
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
dm_list_init(&list1);
|
dm_list_init(&list1);
|
||||||
dm_list_init(&list2);
|
dm_list_init(&list2);
|
||||||
@ -38,12 +29,21 @@ static void test_dmlist_splice(void)
|
|||||||
dm_list_add(&list1, &a[i]);
|
dm_list_add(&list1, &a[i]);
|
||||||
|
|
||||||
dm_list_splice(&list2, &list1);
|
dm_list_splice(&list2, &list1);
|
||||||
CU_ASSERT_EQUAL(dm_list_size(&list1), 0);
|
T_ASSERT(dm_list_size(&list1) == 0);
|
||||||
CU_ASSERT_EQUAL(dm_list_size(&list2), 10);
|
T_ASSERT(dm_list_size(&list2) == 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
CU_TestInfo dmlist_list[] = {
|
#define T(path, desc, fn) register_test(ts, "/base/data-struct/list/" path, desc, fn)
|
||||||
{ (char*)"dmlist_splice", test_dmlist_splice },
|
|
||||||
//{ (char*)"dmlist", test_strncpy },
|
void dm_list_tests(struct dm_list *all_tests)
|
||||||
CU_TEST_INFO_NULL
|
{
|
||||||
};
|
struct test_suite *ts = test_suite_create(NULL, NULL);
|
||||||
|
if (!ts) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
T("splice", "joining lists together", test_dmlist_splice);
|
||||||
|
|
||||||
|
dm_list_add(all_tests, &ts->list);
|
||||||
|
}
|
84
unit-test/dmstatus_t.c
Normal file
84
unit-test/dmstatus_t.c
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 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"
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
|
static void *_mem_init(void)
|
||||||
|
{
|
||||||
|
struct dm_pool *mem = dm_pool_create("dmstatus test", 1024);
|
||||||
|
if (!mem) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _mem_exit(void *mem)
|
||||||
|
{
|
||||||
|
dm_pool_destroy(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _test_mirror_status(void *fixture)
|
||||||
|
{
|
||||||
|
struct dm_pool *mem = fixture;
|
||||||
|
struct dm_status_mirror *s = NULL;
|
||||||
|
|
||||||
|
T_ASSERT(dm_get_status_mirror(mem,
|
||||||
|
"2 253:1 253:2 80/81 1 AD 3 disk 253:0 A",
|
||||||
|
&s));
|
||||||
|
if (s) {
|
||||||
|
T_ASSERT_EQUAL(s->total_regions, 81);
|
||||||
|
T_ASSERT_EQUAL(s->insync_regions, 80);
|
||||||
|
T_ASSERT_EQUAL(s->dev_count, 2);
|
||||||
|
T_ASSERT_EQUAL(s->devs[0].health, 'A');
|
||||||
|
T_ASSERT_EQUAL(s->devs[0].major, 253);
|
||||||
|
T_ASSERT_EQUAL(s->devs[0].minor, 1);
|
||||||
|
T_ASSERT_EQUAL(s->devs[1].health, 'D');
|
||||||
|
T_ASSERT_EQUAL(s->devs[1].major, 253);
|
||||||
|
T_ASSERT_EQUAL(s->devs[1].minor, 2);
|
||||||
|
T_ASSERT_EQUAL(s->log_count, 1);
|
||||||
|
T_ASSERT_EQUAL(s->logs[0].major, 253);
|
||||||
|
T_ASSERT_EQUAL(s->logs[0].minor, 0);
|
||||||
|
T_ASSERT_EQUAL(s->logs[0].health, 'A');
|
||||||
|
T_ASSERT(!strcmp(s->log_type, "disk"));
|
||||||
|
}
|
||||||
|
|
||||||
|
T_ASSERT(dm_get_status_mirror(mem,
|
||||||
|
"4 253:1 253:2 253:3 253:4 10/10 1 ADFF 1 core",
|
||||||
|
&s));
|
||||||
|
if (s) {
|
||||||
|
T_ASSERT_EQUAL(s->total_regions, 10);
|
||||||
|
T_ASSERT_EQUAL(s->insync_regions, 10);
|
||||||
|
T_ASSERT_EQUAL(s->dev_count, 4);
|
||||||
|
T_ASSERT_EQUAL(s->devs[3].minor, 4);
|
||||||
|
T_ASSERT_EQUAL(s->devs[3].health, 'F');
|
||||||
|
T_ASSERT_EQUAL(s->log_count, 0);
|
||||||
|
T_ASSERT(!strcmp(s->log_type, "core"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_status_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
register_test(ts, "/dm/target/mirror/status", "parsing mirror status", _test_mirror_status);
|
||||||
|
dm_list_add(all_tests, &ts->list);
|
||||||
|
}
|
||||||
|
|
66
unit-test/framework.c
Normal file
66
unit-test/framework.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "framework.h"
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
* Assertions
|
||||||
|
*--------------------------------------------------------------*/
|
||||||
|
|
||||||
|
jmp_buf test_k;
|
||||||
|
#define TEST_FAILED 1
|
||||||
|
|
||||||
|
void test_fail(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
longjmp(test_k, TEST_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct test_suite *test_suite_create(void *(*fixture_init)(void),
|
||||||
|
void (*fixture_exit)(void *))
|
||||||
|
{
|
||||||
|
struct test_suite *ts = malloc(sizeof(*ts));
|
||||||
|
if (ts) {
|
||||||
|
ts->fixture_init = fixture_init;
|
||||||
|
ts->fixture_exit = fixture_exit;
|
||||||
|
dm_list_init(&ts->tests);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_suite_destroy(struct test_suite *ts)
|
||||||
|
{
|
||||||
|
struct test_details *td, *tmp;
|
||||||
|
|
||||||
|
dm_list_iterate_items_safe (td, tmp, &ts->tests) {
|
||||||
|
dm_list_del(&td->list);
|
||||||
|
free(td);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool register_test(struct test_suite *ts,
|
||||||
|
const char *path, const char *desc,
|
||||||
|
void (*fn)(void *))
|
||||||
|
{
|
||||||
|
struct test_details *t = malloc(sizeof(*t));
|
||||||
|
if (!t) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->parent = ts;
|
||||||
|
t->path = path;
|
||||||
|
t->desc = desc;
|
||||||
|
t->fn = fn;
|
||||||
|
dm_list_add(&ts->tests, &t->list);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
49
unit-test/framework.h
Normal file
49
unit-test/framework.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef TEST_UNIT_FRAMEWORK_H
|
||||||
|
#define TEST_UNIT_FRAMEWORK_H
|
||||||
|
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
|
||||||
|
// A test suite gathers a set of tests with a common fixture together.
|
||||||
|
struct test_suite {
|
||||||
|
struct dm_list list;
|
||||||
|
|
||||||
|
void *(*fixture_init)(void);
|
||||||
|
void (*fixture_exit)(void *);
|
||||||
|
struct dm_list tests;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_details {
|
||||||
|
struct test_suite *parent;
|
||||||
|
struct dm_list list;
|
||||||
|
|
||||||
|
const char *path;
|
||||||
|
const char *desc;
|
||||||
|
void (*fn)(void *);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_suite *test_suite_create(void *(*fixture_init)(void),
|
||||||
|
void (*fixture_exit)(void *));
|
||||||
|
void test_suite_destroy(struct test_suite *ts);
|
||||||
|
|
||||||
|
bool register_test(struct test_suite *ts,
|
||||||
|
const char *path, const char *desc, void (*fn)(void *));
|
||||||
|
|
||||||
|
void test_fail(const char *fmt, ...)
|
||||||
|
__attribute__((noreturn, format (printf, 1, 2)));
|
||||||
|
|
||||||
|
#define T_ASSERT(e) do {if (!(e)) {test_fail("assertion failed: '%s'", # e);} } while(0)
|
||||||
|
#define T_ASSERT_EQUAL(x, y) T_ASSERT((x) == (y))
|
||||||
|
#define T_ASSERT_NOT_EQUAL(x, y) T_ASSERT((x) != (y))
|
||||||
|
|
||||||
|
extern jmp_buf test_k;
|
||||||
|
#define TEST_FAILED 1
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif
|
89
unit-test/matcher_t.c
Normal file
89
unit-test/matcher_t.c
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004-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"
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
|
#include "matcher_data.h"
|
||||||
|
|
||||||
|
static void *_mem_init(void)
|
||||||
|
{
|
||||||
|
struct dm_pool *mem = dm_pool_create("bitset test", 1024);
|
||||||
|
if (!mem) {
|
||||||
|
fprintf(stderr, "out of memory");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _mem_exit(void *mem)
|
||||||
|
{
|
||||||
|
dm_pool_destroy(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dm_regex *make_scanner(struct dm_pool *mem, const char **rx)
|
||||||
|
{
|
||||||
|
struct dm_regex *scanner;
|
||||||
|
int nrx = 0;
|
||||||
|
for (; rx[nrx]; ++nrx);
|
||||||
|
|
||||||
|
scanner = dm_regex_create(mem, rx, nrx);
|
||||||
|
T_ASSERT(scanner != NULL);
|
||||||
|
return scanner;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_fingerprints(void *fixture)
|
||||||
|
{
|
||||||
|
struct dm_pool *mem = fixture;
|
||||||
|
struct dm_regex *scanner;
|
||||||
|
|
||||||
|
scanner = make_scanner(mem, dev_patterns);
|
||||||
|
T_ASSERT_EQUAL(dm_regex_fingerprint(scanner), 0x7f556c09);
|
||||||
|
|
||||||
|
scanner = make_scanner(mem, random_patterns);
|
||||||
|
T_ASSERT_EQUAL(dm_regex_fingerprint(scanner), 0x9f11076c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_matching(void *fixture)
|
||||||
|
{
|
||||||
|
struct dm_pool *mem = fixture;
|
||||||
|
struct dm_regex *scanner;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
scanner = make_scanner(mem, dev_patterns);
|
||||||
|
for (i = 0; devices[i].str; ++i)
|
||||||
|
T_ASSERT_EQUAL(dm_regex_match(scanner, devices[i].str), devices[i].expected - 1);
|
||||||
|
|
||||||
|
scanner = make_scanner(mem, nonprint_patterns);
|
||||||
|
for (i = 0; nonprint[i].str; ++i)
|
||||||
|
T_ASSERT_EQUAL(dm_regex_match(scanner, nonprint[i].str), nonprint[i].expected - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define T(path, desc, fn) register_test(ts, "/base/regex/" path, desc, fn)
|
||||||
|
|
||||||
|
void regex_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("fingerprints", "not sure", test_fingerprints);
|
||||||
|
T("matching", "test the matcher with a variety of regexes", test_matching);
|
||||||
|
|
||||||
|
dm_list_add(all_tests, &ts->list);
|
||||||
|
}
|
@ -13,21 +13,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
int percent_init(void)
|
static void test_percent_100(void *fixture)
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int percent_fini(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_percent_100(void)
|
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
@ -36,33 +27,33 @@ static void test_percent_100(void)
|
|||||||
dm_percent_t p1_100 = dm_make_percent(100000, 100000);
|
dm_percent_t p1_100 = dm_make_percent(100000, 100000);
|
||||||
dm_percent_t n_100 = dm_make_percent(999999, 1000000);
|
dm_percent_t n_100 = dm_make_percent(999999, 1000000);
|
||||||
|
|
||||||
CU_ASSERT_EQUAL(p_100, DM_PERCENT_100);
|
T_ASSERT_EQUAL(p_100, DM_PERCENT_100);
|
||||||
CU_ASSERT_EQUAL(p1_100, DM_PERCENT_100);
|
T_ASSERT_EQUAL(p1_100, DM_PERCENT_100);
|
||||||
CU_ASSERT_NOT_EQUAL(n_100, DM_PERCENT_100);
|
T_ASSERT_NOT_EQUAL(n_100, DM_PERCENT_100);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p_100));
|
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p_100));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "100.00"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "100.00"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p1_100));
|
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p1_100));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "100.00"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "100.00"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(n_100));
|
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(n_100));
|
||||||
CU_ASSERT_NOT_EQUAL(strcmp(buf, "99.99"), 0); /* Would like to gett */
|
T_ASSERT_NOT_EQUAL(strcmp(buf, "99.99"), 0); /* Would like to gett */
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_round_float(n_100, 2));
|
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_round_float(n_100, 2));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "99.99"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "99.99"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.3f", dm_percent_to_round_float(n_100, 3));
|
dm_snprintf(buf, sizeof(buf), "%.3f", dm_percent_to_round_float(n_100, 3));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "99.999"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "99.999"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.4f", dm_percent_to_round_float(n_100, 4));
|
dm_snprintf(buf, sizeof(buf), "%.4f", dm_percent_to_round_float(n_100, 4));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "99.9999"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "99.9999"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%d", (int)dm_percent_to_round_float(n_100, 0));
|
dm_snprintf(buf, sizeof(buf), "%d", (int)dm_percent_to_round_float(n_100, 0));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "99"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "99"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_percent_0(void)
|
static void test_percent_0(void *fixture)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
@ -71,31 +62,41 @@ static void test_percent_0(void)
|
|||||||
dm_percent_t p1_0 = dm_make_percent(0, 100000);
|
dm_percent_t p1_0 = dm_make_percent(0, 100000);
|
||||||
dm_percent_t n_0 = dm_make_percent(1, 1000000);
|
dm_percent_t n_0 = dm_make_percent(1, 1000000);
|
||||||
|
|
||||||
CU_ASSERT_EQUAL(p_0, DM_PERCENT_0);
|
T_ASSERT_EQUAL(p_0, DM_PERCENT_0);
|
||||||
CU_ASSERT_EQUAL(p1_0, DM_PERCENT_0);
|
T_ASSERT_EQUAL(p1_0, DM_PERCENT_0);
|
||||||
CU_ASSERT_NOT_EQUAL(n_0, DM_PERCENT_0);
|
T_ASSERT_NOT_EQUAL(n_0, DM_PERCENT_0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p_0));
|
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p_0));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "0.00"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "0.00"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p1_0));
|
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(p1_0));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "0.00"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "0.00"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(n_0));
|
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_float(n_0));
|
||||||
CU_ASSERT_NOT_EQUAL(strcmp(buf, "0.01"), 0);
|
T_ASSERT_NOT_EQUAL(strcmp(buf, "0.01"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_round_float(n_0, 2));
|
dm_snprintf(buf, sizeof(buf), "%.2f", dm_percent_to_round_float(n_0, 2));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "0.01"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "0.01"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%.3f", dm_percent_to_round_float(n_0, 3));
|
dm_snprintf(buf, sizeof(buf), "%.3f", dm_percent_to_round_float(n_0, 3));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "0.001"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "0.001"), 0);
|
||||||
|
|
||||||
dm_snprintf(buf, sizeof(buf), "%d", (int)dm_percent_to_round_float(n_0, 0));
|
dm_snprintf(buf, sizeof(buf), "%d", (int)dm_percent_to_round_float(n_0, 0));
|
||||||
CU_ASSERT_EQUAL(strcmp(buf, "1"), 0);
|
T_ASSERT_EQUAL(strcmp(buf, "1"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CU_TestInfo percent_list[] = {
|
#define T(path, desc, fn) register_test(ts, "/base/formatting/percent/" path, desc, fn)
|
||||||
{ (char*)"percent_100", test_percent_100 },
|
|
||||||
{ (char*)"percent_0", test_percent_0 },
|
void percent_tests(struct dm_list *all_tests)
|
||||||
CU_TEST_INFO_NULL
|
{
|
||||||
};
|
struct test_suite *ts = test_suite_create(NULL, NULL);
|
||||||
|
if (!ts) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
T("100", "Pretty printing of percentages near 100%", test_percent_100);
|
||||||
|
T("0", "Pretty printing of percentages near 0%", test_percent_0);
|
||||||
|
|
||||||
|
dm_list_add(all_tests, &ts->list);
|
||||||
|
}
|
309
unit-test/run.c
Normal file
309
unit-test/run.c
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
#include "units.h"
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
|
||||||
|
#define MAX_COMPONENTS 16
|
||||||
|
|
||||||
|
struct token {
|
||||||
|
const char *b, *e;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool _pop_component(const char *path, struct token *result)
|
||||||
|
{
|
||||||
|
const char *b, *e;
|
||||||
|
|
||||||
|
while (*path && *path == '/')
|
||||||
|
path++;
|
||||||
|
|
||||||
|
b = path;
|
||||||
|
while (*path && (*path != '/'))
|
||||||
|
path++;
|
||||||
|
e = path;
|
||||||
|
|
||||||
|
if (b == e)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
result->b = b;
|
||||||
|
result->e = e;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned _split_components(const char *path, struct token *toks, unsigned len)
|
||||||
|
{
|
||||||
|
unsigned count = 0;
|
||||||
|
struct token tok;
|
||||||
|
tok.e = path;
|
||||||
|
|
||||||
|
while (len && _pop_component(tok.e, &tok)) {
|
||||||
|
*toks = tok;
|
||||||
|
toks++;
|
||||||
|
count++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _indent(FILE *stream, unsigned count)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
fprintf(stream, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _print_token(FILE *stream, struct token *t)
|
||||||
|
{
|
||||||
|
const char *ptr;
|
||||||
|
|
||||||
|
for (ptr = t->b; ptr != t->e; ptr++)
|
||||||
|
fprintf(stream, "%c", *ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _char_cmp(char l, char r)
|
||||||
|
{
|
||||||
|
if (l < r)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
else if (r < l)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _tok_cmp(struct token *lhs, struct token *rhs)
|
||||||
|
{
|
||||||
|
const char *l = lhs->b, *le = lhs->e;
|
||||||
|
const char *r = rhs->b, *re = rhs->e;
|
||||||
|
|
||||||
|
while ((l != le) && (r != re) && (*l == *r)) {
|
||||||
|
l++;
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((l != le) && (r != re))
|
||||||
|
return _char_cmp(*l, *r);
|
||||||
|
|
||||||
|
else if (r != re)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
else if (l != le)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _print_path_delta(FILE *stream,
|
||||||
|
struct token *old, unsigned old_len,
|
||||||
|
struct token *new, unsigned new_len,
|
||||||
|
const char *desc)
|
||||||
|
{
|
||||||
|
unsigned i, common_prefix = 0, len, d;
|
||||||
|
unsigned max_prefix = old_len < new_len ? old_len : new_len;
|
||||||
|
|
||||||
|
for (i = 0; i < max_prefix; i++) {
|
||||||
|
if (_tok_cmp(old + i, new + i))
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
common_prefix++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < new_len; i++) {
|
||||||
|
_indent(stream, common_prefix);
|
||||||
|
_print_token(stream, new + i);
|
||||||
|
common_prefix++;
|
||||||
|
if (i < new_len - 1)
|
||||||
|
fprintf(stream, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
len = common_prefix * 2 + (new[new_len - 1].e - new[new_len - 1].b);
|
||||||
|
fprintf(stream, " ");
|
||||||
|
for (d = len; d < 60; d++)
|
||||||
|
fprintf(stream, ".");
|
||||||
|
fprintf(stream, " ");
|
||||||
|
fprintf(stream, "%s", desc);
|
||||||
|
fprintf(stream, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct token comp_t[MAX_COMPONENTS];
|
||||||
|
|
||||||
|
static void _list_tests(struct test_details **tests, unsigned nr)
|
||||||
|
{
|
||||||
|
unsigned i, current = 0, current_len, last_len = 0;
|
||||||
|
|
||||||
|
comp_t components[2];
|
||||||
|
|
||||||
|
for (i = 0; i < nr; i++) {
|
||||||
|
struct test_details *t = tests[i];
|
||||||
|
current_len = _split_components(t->path, components[current], MAX_COMPONENTS);
|
||||||
|
_print_path_delta(stderr, components[!current], last_len,
|
||||||
|
components[current], current_len, t->desc);
|
||||||
|
|
||||||
|
last_len = current_len;
|
||||||
|
current = !current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _destroy_tests(struct dm_list *suites)
|
||||||
|
{
|
||||||
|
struct test_suite *ts, *tmp;
|
||||||
|
|
||||||
|
dm_list_iterate_items_safe (ts, tmp, suites)
|
||||||
|
test_suite_destroy(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *red(bool c)
|
||||||
|
{
|
||||||
|
return c ? "\x1B[31m" : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *green(bool c)
|
||||||
|
{
|
||||||
|
return c ? "\x1B[32m" : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *normal(bool c)
|
||||||
|
{
|
||||||
|
return c ? "\x1B[0m" : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _run_test(struct test_details *t, bool use_colour, unsigned *passed, unsigned *total)
|
||||||
|
{
|
||||||
|
void *fixture;
|
||||||
|
struct test_suite *ts = t->parent;
|
||||||
|
fprintf(stderr, "[RUN ] %s\n", t->path);
|
||||||
|
|
||||||
|
(*total)++;
|
||||||
|
if (setjmp(test_k))
|
||||||
|
fprintf(stderr, "%s[ FAIL]%s %s\n", red(use_colour), normal(use_colour), t->path);
|
||||||
|
else {
|
||||||
|
if (ts->fixture_init)
|
||||||
|
fixture = ts->fixture_init();
|
||||||
|
else
|
||||||
|
fixture = NULL;
|
||||||
|
|
||||||
|
t->fn(fixture);
|
||||||
|
|
||||||
|
if (ts->fixture_exit)
|
||||||
|
ts->fixture_exit(fixture);
|
||||||
|
|
||||||
|
(*passed)++;
|
||||||
|
fprintf(stderr, "%s[ OK]%s\n", green(use_colour), normal(use_colour));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _run_tests(struct test_details **tests, unsigned nr)
|
||||||
|
{
|
||||||
|
bool use_colour = isatty(fileno(stderr));
|
||||||
|
unsigned i, passed = 0, total = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < nr; i++)
|
||||||
|
_run_test(tests[i], use_colour, &passed, &total);
|
||||||
|
|
||||||
|
fprintf(stderr, "\n%u/%u tests passed\n", passed, total);
|
||||||
|
|
||||||
|
return passed == total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: unit-test <list|run> [pattern]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _cmp_paths(const void *lhs, const void *rhs)
|
||||||
|
{
|
||||||
|
struct test_details *l = *((struct test_details **) lhs);
|
||||||
|
struct test_details *r = *((struct test_details **) rhs);
|
||||||
|
|
||||||
|
return strcmp(l->path, r->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned _filter(const char *pattern, struct test_details **tests, unsigned nr)
|
||||||
|
{
|
||||||
|
unsigned i, found = 0;
|
||||||
|
regex_t rx;
|
||||||
|
|
||||||
|
if (regcomp(&rx, pattern, 0)) {
|
||||||
|
fprintf(stderr, "couldn't compile regex '%s'\n", pattern);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nr; i++)
|
||||||
|
if (!regexec(&rx, tests[i]->path, 0, NULL, 0))
|
||||||
|
tests[found++] = tests[i];
|
||||||
|
|
||||||
|
regfree(&rx);
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
unsigned i, nr_tests;
|
||||||
|
struct test_suite *ts;
|
||||||
|
struct test_details *t, **t_array;
|
||||||
|
struct dm_list suites;
|
||||||
|
|
||||||
|
dm_list_init(&suites);
|
||||||
|
register_all_tests(&suites);
|
||||||
|
|
||||||
|
// count all tests
|
||||||
|
nr_tests = 0;
|
||||||
|
dm_list_iterate_items (ts, &suites)
|
||||||
|
dm_list_iterate_items (t, &ts->tests)
|
||||||
|
nr_tests++;
|
||||||
|
|
||||||
|
// stick them in an array
|
||||||
|
t_array = malloc(sizeof(*t_array) * nr_tests);
|
||||||
|
if (!t_array) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
dm_list_iterate_items (ts, &suites)
|
||||||
|
dm_list_iterate_items (t, &ts->tests)
|
||||||
|
t_array[i++] = t;
|
||||||
|
|
||||||
|
// filter
|
||||||
|
if (argc == 3)
|
||||||
|
nr_tests = _filter(argv[2], t_array, nr_tests);
|
||||||
|
|
||||||
|
// sort
|
||||||
|
qsort(t_array, nr_tests, sizeof(*t_array), _cmp_paths);
|
||||||
|
|
||||||
|
// run or list them
|
||||||
|
if (argc == 1)
|
||||||
|
r = !_run_tests(t_array, nr_tests);
|
||||||
|
else {
|
||||||
|
const char *cmd = argv[1];
|
||||||
|
if (!strcmp(cmd, "run"))
|
||||||
|
r = !_run_tests(t_array, nr_tests);
|
||||||
|
|
||||||
|
else if (!strcmp(cmd, "list")) {
|
||||||
|
_list_tests(t_array, nr_tests);
|
||||||
|
r = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_usage();
|
||||||
|
r = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(t_array);
|
||||||
|
_destroy_tests(&suites);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
91
unit-test/string_t.c
Normal file
91
unit-test/string_t.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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"
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int _mem_init(void)
|
||||||
|
{
|
||||||
|
struct dm_pool *mem = dm_pool_create("string test", 1024);
|
||||||
|
if (!mem) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _mem_exit(void *mem)
|
||||||
|
{
|
||||||
|
dm_pool_destroy(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Add more string unit tests here */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void test_strncpy(void *fixture)
|
||||||
|
{
|
||||||
|
const char st[] = "1234567890";
|
||||||
|
char buf[sizeof(st)];
|
||||||
|
|
||||||
|
T_ASSERT_EQUAL(dm_strncpy(buf, st, sizeof(buf)), 1);
|
||||||
|
T_ASSERT_EQUAL(strcmp(buf, st), 0);
|
||||||
|
|
||||||
|
T_ASSERT_EQUAL(dm_strncpy(buf, st, sizeof(buf) - 1), 0);
|
||||||
|
T_ASSERT_EQUAL(strlen(buf) + 1, sizeof(buf) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_asprint(void *fixture)
|
||||||
|
{
|
||||||
|
const char st0[] = "";
|
||||||
|
const char st1[] = "12345678901";
|
||||||
|
const char st2[] = "1234567890123456789012345678901234567890123456789012345678901234567";
|
||||||
|
char *buf;
|
||||||
|
int a;
|
||||||
|
|
||||||
|
a = dm_asprintf(&buf, "%s", st0);
|
||||||
|
T_ASSERT_EQUAL(strcmp(buf, st0), 0);
|
||||||
|
T_ASSERT_EQUAL(a, sizeof(st0));
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
a = dm_asprintf(&buf, "%s", st1);
|
||||||
|
T_ASSERT_EQUAL(strcmp(buf, st1), 0);
|
||||||
|
T_ASSERT_EQUAL(a, sizeof(st1));
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
a = dm_asprintf(&buf, "%s", st2);
|
||||||
|
T_ASSERT_EQUAL(a, sizeof(st2));
|
||||||
|
T_ASSERT_EQUAL(strcmp(buf, st2), 0);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define T(path, desc, fn) register_test(ts, "/base/data-struct/string/" path, desc, fn)
|
||||||
|
|
||||||
|
void string_tests(struct dm_list *all_tests)
|
||||||
|
{
|
||||||
|
struct test_suite *ts = test_suite_create(NULL, NULL);
|
||||||
|
if (!ts) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
T("asprint", "tests asprint", test_asprint);
|
||||||
|
T("strncpy", "tests string copying", test_strncpy);
|
||||||
|
|
||||||
|
dm_list_add(all_tests, &ts->list);
|
||||||
|
}
|
46
unit-test/units.h
Normal file
46
unit-test/units.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TEST_UNIT_UNITS_H
|
||||||
|
#define TEST_UNIT_UNITS_H
|
||||||
|
|
||||||
|
#include "framework.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
|
||||||
|
// Declare the function that adds tests suites here ...
|
||||||
|
void bcache_tests(struct dm_list *suites);
|
||||||
|
void bitset_tests(struct dm_list *suites);
|
||||||
|
void config_tests(struct dm_list *suites);
|
||||||
|
void dm_list_tests(struct dm_list *suites);
|
||||||
|
void dm_status_tests(struct dm_list *suites);
|
||||||
|
void regex_tests(struct dm_list *suites);
|
||||||
|
void percent_tests(struct dm_list *suites);
|
||||||
|
void string_tests(struct dm_list *suites);
|
||||||
|
|
||||||
|
// ... and call it in here.
|
||||||
|
static inline void register_all_tests(struct dm_list *suites)
|
||||||
|
{
|
||||||
|
bcache_tests(suites);
|
||||||
|
bitset_tests(suites);
|
||||||
|
config_tests(suites);
|
||||||
|
dm_list_tests(suites);
|
||||||
|
dm_status_tests(suites);
|
||||||
|
regex_tests(suites);
|
||||||
|
percent_tests(suites);
|
||||||
|
string_tests(suites);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user