arch_flags
blk_include
blk_nblock
blk_non_zero
blk_pool
blk_pool_lock
blk_pool_win
blk_recovery
blk_rw
blk_rw_mt
bttdevice
checksum
compat_incompat_features
ctl_prefault
daxio
ex_libpmem
ex_libpmemblk
ex_libpmemlog
ex_libpmemobj
ex_linkedlist
libpmempool_api
libpmempool_api_win
libpmempool_backup
libpmempool_bttdev
libpmempool_feature
libpmempool_include
libpmempool_map_flog
libpmempool_rm
libpmempool_rm_remote
libpmempool_rm_win
libpmempool_sync
libpmempool_sync_win
libpmempool_transform
libpmempool_transform_win
log_basic
log_include
log_pool
log_pool_lock
log_pool_win
log_recovery
log_walker
magic
obj_action
obj_basic_integration
obj_bucket
obj_check
obj_constructor
obj_ctl_alignment
obj_ctl_alloc_class
obj_ctl_alloc_class_config
obj_ctl_config
obj_ctl_debug
obj_ctl_heap_size
obj_ctl_stats
obj_cuckoo
obj_debug
obj_direct
obj_direct_volatile
obj_extend
obj_first_next
obj_fragmentation
obj_fragmentation2
obj_heap
obj_heap_interrupt
obj_heap_state
obj_include
obj_lane
obj_layout
obj_list
obj_list_insert
obj_list_macro
obj_list_move
obj_list_recovery
obj_list_remove
obj_list_valgrind
obj_locks
obj_many_size_allocs
obj_mem
obj_memblock
obj_memcheck
obj_memcheck_register
obj_memops
obj_oid_thread
obj_out_of_memory
obj_persist_count
obj_pmalloc_basic
obj_pmalloc_mt
obj_pmalloc_oom_mt
obj_pmalloc_rand_mt
obj_pmemcheck
obj_pool
obj_pool_lock
obj_pool_lookup
obj_pool_win
obj_ravl
obj_realloc
obj_recovery
obj_recreate
obj_reorder_basic
obj_root
obj_rpmem_basic_integration
obj_rpmem_heap_interrupt
obj_rpmem_heap_state
obj_sds
obj_strdup
obj_sync
obj_toid
obj_tx_add_range
obj_tx_add_range_direct
obj_tx_alloc
obj_tx_callbacks
obj_tx_flow
obj_tx_free
obj_tx_invalid
obj_tx_lock
obj_tx_locks
obj_tx_locks_abort
obj_tx_mt
obj_tx_realloc
obj_tx_strdup
obj_zones
out_err
out_err_mt
out_err_mt_win
out_err_win
pmem_deep_persist
pmem_has_auto_flush
pmem_has_auto_flush_win
pmem_include
pmem_is_pmem
pmem_is_pmem_posix
pmem_is_pmem_windows
pmem_map_file
pmem_map_file_win
pmem_memcpy
pmem_memmove
pmem_memset
pmem_movnt
pmem_movnt_align
pmem_unmap
pmem_valgr_simple
pmemobjcli
pmempool_check
pmempool_create
pmempool_dump
pmempool_feature
pmempool_feature_remote
pmempool_help
pmempool_info
pmempool_info_remote
pmempool_rm
pmempool_rm_remote
pmempool_sync
pmempool_sync_remote
pmempool_transform
pmempool_transform_remote
pmemspoil
pmreorder_simple
pmreorder_stack
remote_basic
remote_obj_basic
rpmem_addr
rpmem_addr_ext
rpmem_basic
rpmem_fip
rpmem_obc
rpmem_obc_int
rpmem_proto
rpmemd_config
rpmemd_db
rpmemd_dbg
rpmemd_log
rpmemd_obc
rpmemd_util
scope
set_funcs
signal_handle
sync-remotes
tools
traces
traces_custom_function
traces_pmem
unicode_api
unicode_match_script
unittest
util_badblock
util_cpuid
util_ctl
util_extent
util_file_create
util_file_open
util_is_absolute
util_is_poolset
util_is_zeroed
util_map_proc
util_parse_size
util_pool_hdr
util_poolset
util_poolset_foreach
util_poolset_parse
util_poolset_size
util_sds
util_uuid_generate
util_vec
util_vecq
vmem_aligned_alloc
vmem_calloc
vmem_check
vmem_check_allocations
vmem_check_version
vmem_create
vmem_create_error
vmem_create_in_region
vmem_create_win
vmem_custom_alloc
vmem_delete
vmem_malloc
vmem_malloc_usable_size
vmem_mix_allocations
vmem_multiple_pools
vmem_out_of_memory
vmem_pages_purging
vmem_realloc
vmem_realloc_inplace
vmem_stats
vmem_strdup
vmem_valgrind
vmem_valgrind_region
vmmalloc_calloc
vmmalloc_check_allocations
vmmalloc_dummy_funcs
vmmalloc_fork
vmmalloc_init
vmmalloc_malloc
vmmalloc_malloc_hooks
vmmalloc_malloc_usable_size
vmmalloc_memalign
vmmalloc_out_of_memory
vmmalloc_realloc
vmmalloc_valgrind
vmmalloc_valloc
win_common
win_getopt
win_lists
win_mmap
win_mmap_dtor
win_mmap_fixed
win_poolset_unmap
win_signal
.gitignore
Makefile
Makefile.inc
README
RUNTESTLIB.PS1
RUNTESTS.PS1
common_badblock.sh
config.sh.example
drd-libfabric.supp
drd-log.supp
freebsd.supp
helgrind-cxgb4.supp
helgrind-libfabric.supp
helgrind-log.supp
ld.supp
memcheck-dlopen.supp
memcheck-libibverbs.supp
memcheck-libunwind.supp
memcheck-stdcpp.supp
test_debug.props
test_release.props
testconfig.ps1.example
testconfig.sh.example
RUNTESTS
match
README
Persistent Memory Development Kit

This is src/test/README.

This directory contains the unit tests for the Persistent Memory Development Kit.

Unit tests require a config file, testconfig.sh, to exist in this directory.
That file describes the local machine configuration (where to find persistent
memory, for example) and must be created by hand in each repo as it makes no
sense to check in that configuration description to the main repo.

testconfig.sh.example provides more detail.  The script RUNTESTS, when run with
no arguments, will run all unit tests through all the combinations of fs-types
and build-types, running the "check" level test.


DETAILS ON HOW TO RUN UNIT TESTS

See the top-level README for instructions on building, installing, running
tests for the entire tree.  Here are some additional details on running tests.

Once the libraries are built, tests may be built from this directory using:
	$ make test

A testconfig.sh must exist to run these tests!
	$ cp testconfig.sh.example testconfig.sh
	$ ...edit testconfig.sh and modify as appropriate...

Tests may be run using the RUNTESTS script:
	$ RUNTESTS		(runs them all)
	$ RUNTESTS testname	(runs just the named test)

Each test script (named something like "TEST0") is potentially run multiple
times with a different set of environment variables so run the test with
different target file systems or different versions of the libraries.  To see
how RUNTESTS will run a test, use the -n option.  For example:

	$ RUNTESTS -n blk_nblock -s TEST0
	(in ./blk_nblock) TEST=check FS=none BUILD=debug ./TEST0
	(in ./blk_nblock) TEST=check FS=none BUILD=nondebug ./TEST0
	(in ./blk_nblock) TEST=check FS=none BUILD=static-debug ./TEST0
	(in ./blk_nblock) TEST=check FS=none BUILD=static-nondebug ./TEST0
	(in ./blk_nblock) TEST=check FS=pmem BUILD=debug ./TEST0
	(in ./blk_nblock) TEST=check FS=pmem BUILD=nondebug ./TEST0
	(in ./blk_nblock) TEST=check FS=pmem BUILD=static-debug ./TEST0
	(in ./blk_nblock) TEST=check FS=pmem BUILD=static-nondebug ./TEST0
	(in ./blk_nblock) TEST=check FS=non-pmem BUILD=debug ./TEST0
	(in ./blk_nblock) TEST=check FS=non-pmem BUILD=nondebug ./TEST0
	(in ./blk_nblock) TEST=check FS=non-pmem BUILD=static-debug ./TEST0
	(in ./blk_nblock) TEST=check FS=non-pmem BUILD=static-nondebug ./TEST0
	(in ./blk_nblock) TEST=check FS=any BUILD=debug ./TEST0
	(in ./blk_nblock) TEST=check FS=any BUILD=nondebug ./TEST0
	(in ./blk_nblock) TEST=check FS=any BUILD=static-debug ./TEST0
	(in ./blk_nblock) TEST=check FS=any BUILD=static-nondebug ./TEST0

Notice how the TEST0 script is run repeatedly with different settings for
the three environment variables TEST, FS, and BUILD, providing the test type,
file system type, and build type to test.

RUNTESTS takes options to limit what it runs.  The usage is:

 RUNTESTS [ -hnv ] [ -b build-type ] [ -t test-type ] [ -f fs-type ]
	    [ -o timeout ] [ -s test-file ] [ -k skip-dir ]
	    [ -m memcheck ] [-p pmemcheck ] [ -e helgrind ] [ -d drd ] [ -c ]
	    [ -q provider ] [ -r persistency-method ]
	    [tests...]

 Build types are: debug, nondebug, static-debug, static-nondebug, all (default)
 Test types are: check (default), short, medium, long, all
		 where: check = short + medium; all = short + medium + long
 File system types are: none, pmem, non-pmem, any, all (default)
 Timeout is: a floating point number with an optional suffix: 's' for seconds
		 (the default), 'm' for minutes, 'h' for hours or 'd' for days.
		 Default value is 3 minutes.
 Test file is: a name of the particular test script (test case).
		 all (default), TEST0, TEST1, ...
 Memcheck, helgrind, drd and pmemcheck modes are:
		 auto (default, enable/disable based on test requirements),
		 force-enable (enable when test does not require given valgrind tool,
		 but obey test's explicit tool disable)
 Providers are: verbs, sockets, all (default)
 Persistency methods are: GPSPM, APM, all (default)

For example:

	$ RUNTESTS -b debug blk_nblock -s TEST0
	blk_nblock/TEST0: SETUP (check/pmem/debug)
	blk_nblock/TEST0: START: blk_nblock
	blk_nblock/TEST0: PASS

Since the "-b debug" option was given, the RUNTESTS run above only executes
the test for the debug version of the library and skips the other variants.

Running the TEST* scripts directly is also common, especially when debugging
an issue.  Just running the script, like this:

	$ cd blk_nblock
	$ ./TEST0

will use default values for the environment, namely:

	TEST=check FS=any BUILD=debug

these defaults can be overridden on the command line:

	$ cd blk_nblock
	$ TEST=check FS=any BUILD=nondebug ./TEST0

The above example runs TEST0 with the nondebug library, just as using
RUNTESTS with "-b nondebug" would from the parent directory.

In addition to overriding TEST, FS, and BUILD environment variables, the
unit test framework also looks for several other variables:

	For tests that run a local program, insert the word "echo" in front
	of the program execution so the full command being run is displayed.
	This is useful to modify the command for debugging.

		$ ECHO=echo ./TEST0

	Insert the word "strace" in front of the local command execution:

		$ TRACE=strace ./TEST0

	TRACE is not supported for tests which are executed on remote nodes.

	Override the LD_LIBRARY_PATH provided by the unit test framework.  This
	is useful for running a test against another source tree or against the
	libraries installed on the system:

		$ TEST_LD_LIBRARY_PATH=/usr/lib ./TEST0

	Run test under Valgrind/memcheck:

		$ MEMCHECK=force-enable ./TEST0

	Display test run times:
		$ TM=1 ./TEST0


DETAILS ON HOW TO WRITE UNIT TESTS

A minimal unit test consists of a sub-directory here with an executable called
TEST0 in it that exits normally when the test passes.  Most tests, however,
source the file unittest/unittest.sh to use the utility functions for setting
up and checking tests.  Additionally, most unit tests build a local test
program and call it from the TEST* scripts.

In additional to TEST0, there can be as many TEST<num> scripts as desired, and
RUNTESTS will execute them in numeric order for each of the test runs it
executes.

There are two ways of setting test requirements:
	- using config.sh file located in a test sub-directory. It is the new and
	recommended method but it is still under development and does not cover all
	possible requirements. It is applied prior to the second method. If
	config.sh includes test requirements which are not met, the test will not be
	run at all. For details see config.sh.example.

	- using require_* utility functions. It is the old but still supported
	method. It can be used simultaneously with config.sh. Available require_*
	utility functions are described below.

If a test does not need any storage, the script uses this line:

	require_fs_type none

Similarly, if the test only makes sense for pmem or non-pmem:

	require_fs_type pmem
		or
	require_fs_type non-pmem

The above two are often combined to indicate the test should run once for pmem
and once for non-pmem:

	require_fs_type pmem non-pmem

If the test requires some storage, but does not care whether it's pmem or not:

	require_fs_type any

If both pmem and non-pmem are available, "any" means "pmem".

Similar to the above, tests can require a specific build types:

	require_build_type debug

Most tests are short "make check" tests, designed to run quickly when
smoke-checking a build.
Three test types are available: short, medium and long.
Each test script must use require_test_type to indicate to which group
of tests it belongs to.  For example, if it should only run during a long
test run, it can use this line:

	require_test_type long

Using the unittest library, the C programs run during unit testing get their
output and tracing information logged to various files.  These are named with
the test number embedded in them, so a script called TEST0 would commonly
produce:

	err0.log	log of stderr
	out0.log	log of stdout
	trace0.log	trace points from unittest library
	pmem0.log	trace from libpmem (PMEM_LOG_FILE points here)
	vmem0.log	trace from libvmem (VMEM_LOG_FILE points here)

Although the above log files are the common case, the TEST* scripts are free to
create any files.  It is recommended, however, that the script creates files
that are listed in .gitignore so they don't accidentally get committed to the
repo.

The TEST* scripts typically use the shell function "check" to check their
results.  That function calls the perl script "match" for any .match files
found.  For example, to check out0.log contains the expected output, the test
author creates a file called out0.log.match and commits that into the repo.
The match script provides several pattern-matching macros that allow for normal
variation in the test output:

	$(N)	an integer (i.e. one or more decimal digits)
	$(NC)	one or more decimal digits with optional comma separators
	$(FP)	a floating point number
	$(S)	ascii string
	$(X)	hex number
	$(W)	whitespace
	$(nW)	non-whitespace
	$(*)	any string
	$(DD)	output of a "dd" run
	$(OPT)	the entire line is optional
	$(OPX)	ends a contiguous list of $(OPT)...$(OPX) lines, at least
		one of which must match

The small C programs used for unit testing are designed to not worry about the
return values for things not under test.  This is done with the all-caps
versions of many common libc calls, for example:

	fd = OPEN(fname, O_RDRW);

The above call is just like calling open(2), expect the framework checks for
unexpected errors and halts the unit test if those happen.  The result is
usually a very short, compact unit test where most of the code is the
interesting code under test.  A full list of unit test macros is in
unittest/inittest.h.

The best way to create a new unit test is to start with an existing one.  The
test:

	blk_rw

makes an excellent starting point for new tests.  It illustrates the common
idioms used in the TEST* scripts, how the small C program is usually
command-line driven to create multiple cases, and the use of unit test macros
like START, OUT, FATAL, and DONE.  Every case is different, but a common
pattern for creating new unit tests is to follow steps like these:

	$ cp blk_rw new_test_name
	$ ...edit Makefile to add new_test_name to TEST list...
	$ cd new_test_name
	$ mv blk_rw.c to new_test_name.c
	$ ...edit .gitignore, README, Makefile, new_test_name.c...
	$ ...edit TEST0 to create first test case & get it working...
	$ ...add more TEST* scripts as appropriate...

When a "check" type test is run (the default), each test should try to limit
the real execution time to a couple minutes or less.  "short" and "long"
versions of the tests are encouraged, especially for stress testing.

PORTABILITY CONSIDERATIONS

unittest.sh defines a number of macros to support portability across POSIX
operating systems. See the Portability section of unittest.sh for details.

When a matching line count of an output file is required, use "$GREP -c" rather
than "$GREP | wc -l".

Use canonical ordering of program options and arguments, i.e., put all options
before any arguments. Not all operating systems support option reordering.