A big raft of changes to the unit-tests

This commit is contained in:
Joe Thornber 2013-01-09 20:24:11 +00:00
parent ab7124e441
commit 3e39e8bfeb
11 changed files with 238 additions and 296 deletions

View File

@ -55,14 +55,14 @@ CXX:=@CXX@
OBJECTS:=$(subst .cc,.o,$(SOURCE))
TOP_DIR:=@top_srcdir@
TOP_BUILDDIR:=@top_builddir@
CXXFLAGS+=-Wall -fno-strict-aliasing
CXXFLAGS+=-g -Wall -fno-strict-aliasing
CXXFLAGS+=@CXXOPTIMISE_FLAG@
CXXFLAGS+=@CXXDEBUG_FLAG@
INCLUDES+=-I$(TOP_BUILDDIR) -I$(TOP_DIR) -I$(TOP_DIR)/thin-provisioning
LIBS:=-lstdc++
LIBEXPAT:=-lexpat
INSTALL:=@INSTALL@
STRIP=
STRIP=strip
PREFIX:=@prefix@
BINDIR:=$(DESTDIR)$(PREFIX)/sbin
MANPATH:=$(DESTDIR)$(MANDIR)

View File

@ -172,7 +172,7 @@ namespace persistent_data {
buffer<BlockSize> const &data() const;
protected:
block_manager<BlockSize> const &bm_;
block_manager<BlockSize> const *bm_;
block_ptr block_;
unsigned *holders_;
};

View File

@ -154,7 +154,7 @@ block_manager<BlockSize>::block::flush()
template <uint32_t BlockSize>
block_manager<BlockSize>::read_ref::read_ref(block_manager<BlockSize> const &bm,
block_ptr b)
: bm_(bm),
: bm_(&bm),
block_(b),
holders_(new unsigned)
{
@ -175,13 +175,13 @@ block_manager<BlockSize>::read_ref::~read_ref()
{
if (!--(*holders_)) {
if (block_->bt_ == BT_SUPERBLOCK) {
bm_.flush();
bm_.cache_.put(block_);
bm_.flush();
bm_->flush();
bm_->cache_.put(block_);
bm_->flush();
} else
bm_.cache_.put(block_);
bm_->cache_.put(block_);
bm_.tracker_.unlock(block_->location_);
bm_->tracker_.unlock(block_->location_);
delete holders_;
}
}
@ -196,6 +196,8 @@ block_manager<BlockSize>::read_ref::operator =(read_ref const &rhs)
holders_ = rhs.holders_;
(*holders_)++;
}
return *this;
}
template <uint32_t BlockSize>

View File

@ -323,8 +323,10 @@ namespace {
index_entry ie = indexes_->find_ie(index);
bitmap bm(tm_, ie);
optional<unsigned> maybe_b = bm.find_free((index == begin_index) ? (begin % ENTRIES_PER_BLOCK) : 0,
(index == end_index - 1) ? (end % ENTRIES_PER_BLOCK) : ENTRIES_PER_BLOCK);
unsigned bit_begin = (index == begin_index) ? (begin % ENTRIES_PER_BLOCK) : 0;
unsigned bit_end = (index == end_index - 1) ? (end % ENTRIES_PER_BLOCK) : ENTRIES_PER_BLOCK;
optional<unsigned> maybe_b = bm.find_free(bit_begin, bit_end);
if (maybe_b) {
block_address b = *maybe_b;
indexes_->save_ie(index, bm.get_ie());

View File

@ -18,15 +18,13 @@
TEST_SOURCE=\
unit-tests/cache_t.cc \
unit-tests/block_t.cc
unit-tests/block_t.cc \
unit-tests/btree_t.cc \
unit-tests/endian_t.cc \
unit-tests/space_map_disk_t.cc \
unit-tests/transaction_manager_t.cc
# FIXME: reinstate
# unit-tests/btree_t.cc \
# unit-tests/endian_t.cc \
# unit-tests/run_list_t.cc \
# unit-tests/space_map_t.cc \
# unit-tests/space_map_disk_t.cc \
# unit-tests/transaction_manager_t.cc
# unit-tests/space_map_t.cc \
TEST_PROGRAMS=$(subst .cc,,$(TEST_SOURCE))

View File

@ -16,9 +16,9 @@
// with thin-provisioning-tools. If not, see
// <http://www.gnu.org/licenses/>.
#include "transaction_manager.h"
#include "space_map_core.h"
#include "btree.h"
#include "persistent-data/transaction_manager.h"
#include "persistent-data/space_map_core.h"
#include "persistent-data/btree.h"
#define BOOST_TEST_MODULE BTreeTests
#include <boost/test/included/unit_test.hpp>

View File

@ -16,8 +16,7 @@
// with thin-provisioning-tools. If not, see
// <http://www.gnu.org/licenses/>.
#include "space_map_disk.h"
#include "core_map.h"
#include "persistent-data/space_map_disk.h"
#define BOOST_TEST_MODULE EndianTests
#include <boost/test/included/unit_test.hpp>

View File

@ -16,7 +16,7 @@
// with thin-provisioning-tools. If not, see
// <http://www.gnu.org/licenses/>.
#include "run_list.h"
#include "persistent-data/run_list.h"
#define BOOST_TEST_MODULE RunListTests
#include <boost/test/included/unit_test.hpp>

View File

@ -16,8 +16,8 @@
// with thin-provisioning-tools. If not, see
// <http://www.gnu.org/licenses/>.
#include "space_map_disk.h"
#include "space_map_core.h"
#include "persistent-data/space_map_disk.h"
#include "persistent-data/space_map_core.h"
#define BOOST_TEST_MODULE SpaceMapDiskTests
#include <boost/test/included/unit_test.hpp>
@ -43,277 +43,209 @@ namespace {
return tm;
}
persistent_space_map::ptr
create_sm_disk() {
transaction_manager::ptr tm = create_tm();
return persistent_data::create_disk_sm(tm, NR_BLOCKS);
class sm_disk_creator {
public:
static persistent_space_map::ptr
create() {
transaction_manager::ptr tm = create_tm();
return persistent_data::create_disk_sm(tm, NR_BLOCKS);
}
static persistent_space_map::ptr
open(void *root) {
transaction_manager::ptr tm = create_tm();
return persistent_data::open_disk_sm(tm, root);
}
};
class sm_metadata_creator {
public:
static persistent_space_map::ptr
create() {
transaction_manager::ptr tm = create_tm();
return persistent_data::create_metadata_sm(tm, NR_BLOCKS);
}
static persistent_space_map::ptr
open(void *root) {
transaction_manager::ptr tm = create_tm();
return persistent_data::open_metadata_sm(tm, root);
}
};
//--------------------------------
void test_get_nr_blocks(space_map::ptr sm)
{
BOOST_CHECK_EQUAL(sm->get_nr_blocks(), NR_BLOCKS);
}
persistent_space_map::ptr
create_sm_metadata() {
transaction_manager::ptr tm = create_tm();
return persistent_data::create_metadata_sm(tm, NR_BLOCKS);
}
}
void test_get_nr_free(space_map::ptr sm)
{
BOOST_REQUIRE_EQUAL(sm->get_nr_free(), NR_BLOCKS);
//----------------------------------------------------------------
for (unsigned i = 0; i < NR_BLOCKS; i++) {
optional<block_address> mb = sm->new_block();
BOOST_REQUIRE(mb);
BOOST_REQUIRE_EQUAL(sm->get_nr_free(), NR_BLOCKS - i - 1);
}
void _test_get_nr_blocks(space_map::ptr sm)
{
BOOST_CHECK_EQUAL(sm->get_nr_blocks(), NR_BLOCKS);
}
void _test_get_nr_free(space_map::ptr sm)
{
BOOST_CHECK_EQUAL(sm->get_nr_free(), NR_BLOCKS);
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->new_block();
BOOST_CHECK_EQUAL(sm->get_nr_free(), NR_BLOCKS - i - 1);
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->dec(i);
BOOST_REQUIRE_EQUAL(sm->get_nr_free(), i + 1);
}
}
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->dec(i);
BOOST_CHECK_EQUAL(sm->get_nr_free(), i + 1);
}
}
void test_runs_out_of_space(space_map::ptr sm)
{
optional<block_address> mb;
void _test_throws_no_space(space_map::ptr sm)
{
for (unsigned i = 0; i < NR_BLOCKS; i++)
sm->new_block();
for (unsigned i = 0; i < NR_BLOCKS; i++)
mb = sm->new_block();
BOOST_CHECK_THROW(sm->new_block(), std::runtime_error);
}
void _test_inc_and_dec(space_map::ptr sm)
{
block_address b = 63;
for (unsigned i = 0; i < 50; i++) {
BOOST_CHECK_EQUAL(sm->get_count(b), i);
sm->inc(b);
mb = sm->new_block();
BOOST_REQUIRE(!mb);
}
for (unsigned i = 50; i > 0; i--) {
BOOST_CHECK_EQUAL(sm->get_count(b), i);
sm->dec(b);
}
}
void test_inc_and_dec(space_map::ptr sm)
{
block_address b = 63;
void _test_not_allocated_twice(space_map::ptr sm)
{
block_address b = sm->new_block();
for (unsigned i = 0; i < 50; i++) {
BOOST_REQUIRE_EQUAL(sm->get_count(b), i);
sm->inc(b);
}
try {
for (;;)
BOOST_CHECK(sm->new_block() != b);
} catch (...) {
}
}
void _test_set_count(space_map::ptr sm)
{
sm->set_count(43, 5);
BOOST_CHECK_EQUAL(sm->get_count(43), 5);
}
void _test_set_affects_nr_allocated(space_map::ptr sm)
{
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->set_count(i, 1);
BOOST_CHECK_EQUAL(sm->get_nr_free(), NR_BLOCKS - i - 1);
for (unsigned i = 50; i > 0; i--) {
BOOST_REQUIRE_EQUAL(sm->get_count(b), i);
sm->dec(b);
}
}
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->set_count(i, 0);
BOOST_CHECK_EQUAL(sm->get_nr_free(), i + 1);
void test_not_allocated_twice(space_map::ptr sm)
{
optional<block_address> mb = sm->new_block();
BOOST_REQUIRE(mb);
for (;;) {
boost::optional<block_address> b = sm->new_block();
if (!b)
break;
if (b)
BOOST_REQUIRE(*b != *mb);
}
}
}
// Ref counts below 3 gets stored as bitmaps, above 3 they go into a btree
// with uint32_t values. Worth checking this thoroughly, especially for
// the metadata format which may have complications due to recursion.
void _test_high_ref_counts(space_map::ptr sm)
{
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
sm->set_count(i, rand() % 6789);
sm->commit();
void test_set_count(space_map::ptr sm)
{
sm->set_count(43, 5);
BOOST_REQUIRE_EQUAL(sm->get_count(43), 5);
}
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->inc(i);
sm->inc(i);
if (i % 1000)
void test_set_affects_nr_allocated(space_map::ptr sm)
{
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->set_count(i, 1);
BOOST_REQUIRE_EQUAL(sm->get_nr_free(), NR_BLOCKS - i - 1);
}
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->set_count(i, 0);
BOOST_REQUIRE_EQUAL(sm->get_nr_free(), i + 1);
}
}
// Ref counts below 3 gets stored as bitmaps, above 3 they go into
// a btree with uint32_t values. Worth checking this thoroughly,
// especially for the metadata format which may have complications
// due to recursion.
void test_high_ref_counts(space_map::ptr sm)
{
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
sm->set_count(i, rand() % 6789);
sm->commit();
for (unsigned i = 0; i < NR_BLOCKS; i++) {
sm->inc(i);
sm->inc(i);
if (i % 1000)
sm->commit();
}
sm->commit();
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
BOOST_REQUIRE_EQUAL(sm->get_count(i), (rand() % 6789) + 2);
for (unsigned i = 0; i < NR_BLOCKS; i++)
sm->dec(i);
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
BOOST_REQUIRE_EQUAL(sm->get_count(i), (rand() % 6789) + 1);
}
template <typename SMCreator>
void test_sm_reopen()
{
unsigned char buffer[128];
{
persistent_space_map::ptr sm = SMCreator::create();
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++)
sm->inc(i);
sm->commit();
}
sm->commit();
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
BOOST_CHECK_EQUAL(sm->get_count(i), (rand() % 6789) + 2);
for (unsigned i = 0; i < NR_BLOCKS; i++)
sm->dec(i);
srand(1234);
for (unsigned i = 0; i < NR_BLOCKS; i++)
BOOST_CHECK_EQUAL(sm->get_count(i), (rand() % 6789) + 1);
}
//----------------------------------------------------------------
#if 0
BOOST_AUTO_TEST_CASE(reopen_an_sm)
{
space_map::ptr sm = create_sm_disk();
}
#endif
BOOST_AUTO_TEST_CASE(test_disk_get_nr_blocks)
{
space_map::ptr sm = create_sm_disk();
_test_get_nr_blocks(sm);
}
BOOST_AUTO_TEST_CASE(test_disk_get_nr_free)
{
space_map::ptr sm = create_sm_disk();
_test_get_nr_free(sm);
}
BOOST_AUTO_TEST_CASE(test_disk_throws_no_space)
{
space_map::ptr sm = create_sm_disk();
_test_throws_no_space(sm);
}
BOOST_AUTO_TEST_CASE(test_disk_inc_and_dec)
{
space_map::ptr sm = create_sm_disk();
_test_inc_and_dec(sm);
}
BOOST_AUTO_TEST_CASE(test_disk_not_allocated_twice)
{
space_map::ptr sm = create_sm_disk();
_test_not_allocated_twice(sm);
}
BOOST_AUTO_TEST_CASE(test_disk_set_count)
{
space_map::ptr sm = create_sm_disk();
_test_set_count(sm);
}
BOOST_AUTO_TEST_CASE(test_disk_set_affects_nr_allocated)
{
space_map::ptr sm = create_sm_disk();
_test_set_affects_nr_allocated(sm);
}
BOOST_AUTO_TEST_CASE(test_disk_high_ref_counts)
{
space_map::ptr sm = create_sm_disk();
_test_high_ref_counts(sm);
}
BOOST_AUTO_TEST_CASE(test_disk_reopen)
{
unsigned char buffer[128];
{
persistent_space_map::ptr sm = create_sm_disk();
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++) {
sm->inc(i);
BOOST_REQUIRE(sm->root_size() <= sizeof(buffer));
sm->copy_root(buffer, sizeof(buffer));
}
sm->commit();
BOOST_CHECK(sm->root_size() <= sizeof(buffer));
sm->copy_root(buffer, sizeof(buffer));
}
{
persistent_space_map::ptr sm = SMCreator::open(buffer);
{
transaction_manager::ptr tm = create_tm();
persistent_space_map::ptr sm = persistent_data::open_disk_sm(tm, buffer);
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++)
BOOST_CHECK_EQUAL(sm->get_count(i), 1);
}
}
//----------------------------------------------------------------
BOOST_AUTO_TEST_CASE(test_metadata_get_nr_blocks)
{
space_map::ptr sm = create_sm_metadata();
_test_get_nr_blocks(sm);
}
BOOST_AUTO_TEST_CASE(test_metadata_get_nr_free)
{
space_map::ptr sm = create_sm_metadata();
_test_get_nr_free(sm);
}
BOOST_AUTO_TEST_CASE(test_metadata_throws_no_space)
{
space_map::ptr sm = create_sm_metadata();
_test_throws_no_space(sm);
}
BOOST_AUTO_TEST_CASE(test_metadata_inc_and_dec)
{
space_map::ptr sm = create_sm_metadata();
_test_inc_and_dec(sm);
}
BOOST_AUTO_TEST_CASE(test_metadata_not_allocated_twice)
{
space_map::ptr sm = create_sm_metadata();
_test_not_allocated_twice(sm);
}
BOOST_AUTO_TEST_CASE(test_metadata_set_count)
{
space_map::ptr sm = create_sm_metadata();
_test_set_count(sm);
}
BOOST_AUTO_TEST_CASE(test_metadata_set_affects_nr_allocated)
{
space_map::ptr sm = create_sm_metadata();
_test_set_affects_nr_allocated(sm);
}
BOOST_AUTO_TEST_CASE(test_metadata_high_ref_counts)
{
space_map::ptr sm = create_sm_metadata();
_test_high_ref_counts(sm);
}
BOOST_AUTO_TEST_CASE(test_metadata_reopen)
{
unsigned char buffer[128];
{
persistent_space_map::ptr sm = create_sm_metadata();
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++) {
sm->inc(i);
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++)
BOOST_REQUIRE_EQUAL(sm->get_count(i), 1);
}
sm->commit();
BOOST_CHECK(sm->root_size() <= sizeof(buffer));
sm->copy_root(buffer, sizeof(buffer));
}
typedef void (*sm_test)(space_map::ptr);
template <typename SMCreator, unsigned NTests>
void do_tests(sm_test (&tests)[NTests])
{
transaction_manager::ptr tm = create_tm();
persistent_space_map::ptr sm = persistent_data::open_metadata_sm(tm, buffer);
for (unsigned i = 0, step = 1; i < NR_BLOCKS; i += step, step++)
BOOST_CHECK_EQUAL(sm->get_count(i), 1);
for (unsigned t = 0; t < NTests; t++) {
space_map::ptr sm = SMCreator::create();
tests[t](sm);
}
}
sm_test space_map_tests[] = {
test_get_nr_blocks,
test_get_nr_free,
test_runs_out_of_space,
test_inc_and_dec,
test_not_allocated_twice,
test_set_count,
test_set_affects_nr_allocated,
test_high_ref_counts
};
}
//----------------------------------------------------------------
BOOST_AUTO_TEST_CASE(test_sm_disk)
{
do_tests<sm_disk_creator>(space_map_tests);
test_sm_reopen<sm_disk_creator>();
}
BOOST_AUTO_TEST_CASE(test_sm_metadata)
{
do_tests<sm_metadata_creator>(space_map_tests);
test_sm_reopen<sm_metadata_creator>();
}
//----------------------------------------------------------------

View File

@ -16,8 +16,7 @@
// with thin-provisioning-tools. If not, see
// <http://www.gnu.org/licenses/>.
#include "space_map.h"
#include "core_map.h"
#include "persistent-data/space_map.h"
#define BOOST_TEST_MODULE SpaceMapTests
#include <boost/test/included/unit_test.hpp>

View File

@ -16,8 +16,8 @@
// with thin-provisioning-tools. If not, see
// <http://www.gnu.org/licenses/>.
#include "transaction_manager.h"
#include "core_map.h"
#include "persistent-data/transaction_manager.h"
#include "persistent-data/space_map_core.h"
#define BOOST_TEST_MODULE TransactionManagerTests
#include <boost/test/included/unit_test.hpp>
@ -29,37 +29,47 @@ using namespace persistent_data;
//----------------------------------------------------------------
namespace {
unsigned const MAX_HELD_LOCKS = 16;
block_address const NR_BLOCKS = 1024;
transaction_manager::ptr
create_tm() {
block_manager<>::ptr bm(new block_manager<>("./test.data", NR_BLOCKS));
block_manager<>::ptr bm(new block_manager<>("./test.data", NR_BLOCKS, MAX_HELD_LOCKS, true));
space_map::ptr sm(new core_map(NR_BLOCKS));
transaction_manager::ptr tm(new transaction_manager(bm, sm));
tm->get_sm()->inc(0);
return tm;
}
typedef block_manager<>::validator::ptr validator_ptr;
validator_ptr noop_validator() {
return block_manager<>::validator::ptr(
new block_manager<>::noop_validator);
}
typedef block_manager<>::write_ref write_ref;
}
//----------------------------------------------------------------
BOOST_AUTO_TEST_CASE(commit_succeeds)
{
auto tm = create_tm();
tm->begin(0);
transaction_manager::ptr tm = create_tm();
tm->begin(0, block_manager<>::validator::ptr(new block_manager<>::noop_validator));
}
BOOST_AUTO_TEST_CASE(shadowing)
{
auto tm = create_tm();
auto superblock = tm->begin(0);
transaction_manager::ptr tm = create_tm();
block_manager<>::write_ref superblock = tm->begin(0, noop_validator());
auto sm = tm->get_sm();
space_map::ptr sm = tm->get_sm();
sm->inc(1);
block_address b;
{
auto p = tm->shadow(1);
pair<write_ref, bool> p = tm->shadow(1, noop_validator());
b = p.first.get_location();
BOOST_CHECK(b != 1);
BOOST_CHECK(!p.second);
@ -67,7 +77,7 @@ BOOST_AUTO_TEST_CASE(shadowing)
}
{
auto p = tm->shadow(b);
pair<write_ref, bool> p = tm->shadow(b, noop_validator());
BOOST_CHECK(p.first.get_location() == b);
BOOST_CHECK(!p.second);
}
@ -75,7 +85,7 @@ BOOST_AUTO_TEST_CASE(shadowing)
sm->inc(b);
{
auto p = tm->shadow(b);
pair<write_ref, bool> p = tm->shadow(b, noop_validator());
BOOST_CHECK(p.first.get_location() != b);
BOOST_CHECK(p.second);
}
@ -83,25 +93,25 @@ BOOST_AUTO_TEST_CASE(shadowing)
BOOST_AUTO_TEST_CASE(multiple_shadowing)
{
auto tm = create_tm();
auto superblock = tm->begin(0);
transaction_manager::ptr tm = create_tm();
write_ref superblock = tm->begin(0, noop_validator());
auto sm = tm->get_sm();
space_map::ptr sm = tm->get_sm();
sm->set_count(1, 3);
auto p = tm->shadow(1);
auto b = p.first.get_location();
pair<write_ref, bool> p = tm->shadow(1, noop_validator());
block_address b = p.first.get_location();
BOOST_CHECK(b != 1);
BOOST_CHECK(p.second);
p = tm->shadow(1);
auto b2 = p.first.get_location();
p = tm->shadow(1, noop_validator());
block_address b2 = p.first.get_location();
BOOST_CHECK(b2 != 1);
BOOST_CHECK(b2 != b);
BOOST_CHECK(p.second);
p = tm->shadow(1);
auto b3 = p.first.get_location();
p = tm->shadow(1, noop_validator());
block_address b3 = p.first.get_location();
BOOST_CHECK(b3 != b2);
BOOST_CHECK(b3 != b);
BOOST_CHECK(b3 != 1);
@ -110,8 +120,8 @@ BOOST_AUTO_TEST_CASE(multiple_shadowing)
BOOST_AUTO_TEST_CASE(shadow_free_block_fails)
{
auto tm = create_tm();
auto superblock = tm->begin(0);
BOOST_CHECK_THROW(tm->shadow(1), runtime_error);
transaction_manager::ptr tm = create_tm();
write_ref superblock = tm->begin(0, noop_validator());
BOOST_CHECK_THROW(tm->shadow(1, noop_validator()), runtime_error);
}