mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +03:00
ea34dad66f
See doc/unit-test.txt for details. Some bcache tests failing. Probably due to dct changing semantics, will fix in follow up patch.
258 lines
8.9 KiB
Plaintext
258 lines
8.9 KiB
Plaintext
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.
|
|
|