Written test cases for DataNodeView

This commit is contained in:
Sebastian Messmer 2014-12-10 17:26:49 +01:00
parent b33cf908fa
commit 85b100ac9d
2 changed files with 141 additions and 6 deletions

View File

@ -8,13 +8,16 @@
#include "fspp/utils/macros.h"
#include <memory>
#include <cassert>
namespace blobstore {
namespace onblocks {
class DataNodeView {
public:
DataNodeView(std::unique_ptr<blockstore::Block> block): _block(std::move(block)) {}
DataNodeView(std::unique_ptr<blockstore::Block> block): _block(std::move(block)) {
assert(_block->size() == BLOCKSIZE_BYTES);
}
virtual ~DataNodeView() {}
DataNodeView(DataNodeView &&rhs) = default;
@ -73,18 +76,16 @@ public:
return const_cast<Entry*>(const_cast<const DataNodeView*>(this)->DataEnd<Entry>());
}
protected:
private:
template<int offset, class Type>
const Type *GetOffset() const {
return (Type*)(((const int8_t*)_block->data())+offset);
}
private:
DISALLOW_COPY_AND_ASSIGN(DataNodeView);
std::unique_ptr<blockstore::Block> _block;
DISALLOW_COPY_AND_ASSIGN(DataNodeView);
};
}

View File

@ -0,0 +1,134 @@
#include <gtest/gtest.h>
#include "blockstore/implementations/inmemory/InMemoryBlockStore.h"
#include "blockstore/implementations/inmemory/InMemoryBlock.h"
#include "blobstore/implementations/onblocks/BlobStoreOnBlocks.h"
#include "blobstore/implementations/onblocks/impl/DataNodeView.h"
#include "test/testutils/DataBlockFixture.h"
using ::testing::Test;
using ::testing::WithParamInterface;
using ::testing::Values;
using std::unique_ptr;
using std::make_unique;
using std::string;
using blockstore::BlockStore;
using blockstore::inmemory::InMemoryBlockStore;
using namespace blobstore;
using namespace blobstore::onblocks;
class DataNodeViewTest: public Test {
public:
unique_ptr<BlockStore> blockStore = make_unique<InMemoryBlockStore>();
};
TEST_F(DataNodeViewTest, MagicNumberIsStored) {
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
{
DataNodeView view(std::move(block.block));
*view.MagicNumber() = 0x3F;
}
DataNodeView view(blockStore->load(block.key));
EXPECT_EQ(0x3F, *view.MagicNumber());
}
class DataNodeViewSizeTest: public DataNodeViewTest, public WithParamInterface<uint32_t> {
};
INSTANTIATE_TEST_CASE_P(DataNodeViewSizeTest, DataNodeViewSizeTest, Values(0, 50, 64, 1024, 1024*1024*1024));
TEST_P(DataNodeViewSizeTest, SizeIsStored) {
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
{
DataNodeView view(std::move(block.block));
*view.Size() = GetParam();
}
DataNodeView view(blockStore->load(block.key));
EXPECT_EQ(GetParam(), *view.Size());
}
TEST_F(DataNodeViewTest, DataIsStored) {
DataBlockFixture randomData(DataNodeView::DATASIZE_BYTES);
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
{
DataNodeView view(std::move(block.block));
std::memcpy(view.DataBegin<uint8_t>(), randomData.data(), DataNodeView::DATASIZE_BYTES);
}
DataNodeView view(blockStore->load(block.key));
EXPECT_EQ(0, std::memcmp(view.DataBegin<uint8_t>(), randomData.data(), DataNodeView::DATASIZE_BYTES));
}
TEST_F(DataNodeViewTest, HeaderAndBodyDontOverlap) {
DataBlockFixture randomData(DataNodeView::DATASIZE_BYTES);
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
{
DataNodeView view(std::move(block.block));
*view.MagicNumber() = 0xAA;
*view.Size() = 1000000000u;
std::memcpy(view.DataBegin<uint8_t>(), randomData.data(), DataNodeView::DATASIZE_BYTES);
}
DataNodeView view(blockStore->load(block.key));
EXPECT_EQ(0xAA, *view.MagicNumber());
EXPECT_EQ(1000000000u, *view.Size());
EXPECT_EQ(0, std::memcmp(view.DataBegin<uint8_t>(), randomData.data(), DataNodeView::DATASIZE_BYTES));
}
TEST_F(DataNodeViewTest, DataBeginWorksWithOneByteEntries) {
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
uint8_t *blockBegin = (uint8_t*)block.block->data();
DataNodeView view(std::move(block.block));
EXPECT_EQ(blockBegin+view.HEADERSIZE_BYTES, view.DataBegin<uint8_t>());
}
TEST_F(DataNodeViewTest, DataBeginWorksWithEightByteEntries) {
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
uint8_t *blockBegin = (uint8_t*)block.block->data();
DataNodeView view(std::move(block.block));
EXPECT_EQ(blockBegin+view.HEADERSIZE_BYTES, (uint8_t*)view.DataBegin<uint64_t>());
}
TEST_F(DataNodeViewTest, DataEndWorksWithOneByteEntries) {
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
uint8_t *blockBegin = (uint8_t*)block.block->data();
DataNodeView view(std::move(block.block));
EXPECT_EQ(blockBegin+view.BLOCKSIZE_BYTES, view.DataEnd<uint8_t>());
}
TEST_F(DataNodeViewTest, DataEndWorksWithEightByteEntries) {
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
uint8_t *blockBegin = (uint8_t*)block.block->data();
DataNodeView view(std::move(block.block));
EXPECT_EQ(blockBegin+view.BLOCKSIZE_BYTES, (uint8_t*)view.DataEnd<uint64_t>());
}
struct SizedDataEntry {
uint8_t data[6];
};
BOOST_STATIC_ASSERT_MSG(DataNodeView::DATASIZE_BYTES % sizeof(SizedDataEntry) != 0,
"This test case only makes sense, if the data entries don't fill up the whole space. "
"There should be some space left at the end that is not used, because it isn't enough space for a full entry. "
"If this static assertion fails, please use a different size for SizedDataEntry.");
TEST_F(DataNodeViewTest, DataBeginWorksWithStructEntries) {
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
uint8_t *blockBegin = (uint8_t*)block.block->data();
DataNodeView view(std::move(block.block));
EXPECT_EQ(blockBegin+view.HEADERSIZE_BYTES, (uint8_t*)view.DataBegin<SizedDataEntry>());
}
TEST_F(DataNodeViewTest, DataEndWorksWithStructByteEntries) {
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
uint8_t *blockBegin = (uint8_t*)block.block->data();
DataNodeView view(std::move(block.block));
unsigned int numFittingEntries = view.DATASIZE_BYTES / sizeof(SizedDataEntry);
uint8_t *dataEnd = (uint8_t*)view.DataEnd<SizedDataEntry>();
EXPECT_EQ(blockBegin+view.HEADERSIZE_BYTES + numFittingEntries * sizeof(SizedDataEntry), dataEnd);
EXPECT_LT(dataEnd, blockBegin + view.BLOCKSIZE_BYTES);
}