Remove c style casts and unaligned memory accesses
This commit is contained in:
parent
e736d249f2
commit
f439bf9d0f
@ -115,7 +115,7 @@ void BlobOnBlocks::_read(void *target, uint64_t offset, uint64_t count) const {
|
|||||||
auto onExistingLeaf = [target, offset, count] (uint64_t indexOfFirstLeafByte, LeafHandle leaf, uint32_t leafDataOffset, uint32_t leafDataSize) {
|
auto onExistingLeaf = [target, offset, count] (uint64_t indexOfFirstLeafByte, LeafHandle leaf, uint32_t leafDataOffset, uint32_t leafDataSize) {
|
||||||
ASSERT(indexOfFirstLeafByte+leafDataOffset>=offset && indexOfFirstLeafByte-offset+leafDataOffset <= count && indexOfFirstLeafByte-offset+leafDataOffset+leafDataSize <= count, "Writing to target out of bounds");
|
ASSERT(indexOfFirstLeafByte+leafDataOffset>=offset && indexOfFirstLeafByte-offset+leafDataOffset <= count && indexOfFirstLeafByte-offset+leafDataOffset+leafDataSize <= count, "Writing to target out of bounds");
|
||||||
//TODO Simplify formula, make it easier to understand
|
//TODO Simplify formula, make it easier to understand
|
||||||
leaf.node()->read((uint8_t*)target + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset, leafDataSize);
|
leaf.node()->read(static_cast<uint8_t*>(target) + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset, leafDataSize);
|
||||||
};
|
};
|
||||||
auto onCreateLeaf = [] (uint64_t /*beginByte*/, uint32_t /*count*/) -> Data {
|
auto onCreateLeaf = [] (uint64_t /*beginByte*/, uint32_t /*count*/) -> Data {
|
||||||
ASSERT(false, "Reading shouldn't create new leaves.");
|
ASSERT(false, "Reading shouldn't create new leaves.");
|
||||||
@ -128,11 +128,11 @@ void BlobOnBlocks::write(const void *source, uint64_t offset, uint64_t count) {
|
|||||||
ASSERT(indexOfFirstLeafByte+leafDataOffset>=offset && indexOfFirstLeafByte-offset+leafDataOffset <= count && indexOfFirstLeafByte-offset+leafDataOffset+leafDataSize <= count, "Reading from source out of bounds");
|
ASSERT(indexOfFirstLeafByte+leafDataOffset>=offset && indexOfFirstLeafByte-offset+leafDataOffset <= count && indexOfFirstLeafByte-offset+leafDataOffset+leafDataSize <= count, "Reading from source out of bounds");
|
||||||
if (leafDataOffset == 0 && leafDataSize == leaf.nodeStore()->layout().maxBytesPerLeaf()) {
|
if (leafDataOffset == 0 && leafDataSize == leaf.nodeStore()->layout().maxBytesPerLeaf()) {
|
||||||
Data leafData(leafDataSize);
|
Data leafData(leafDataSize);
|
||||||
std::memcpy(leafData.data(), (uint8_t*)source + indexOfFirstLeafByte - offset, leafDataSize);
|
std::memcpy(leafData.data(), static_cast<const uint8_t*>(source) + indexOfFirstLeafByte - offset, leafDataSize);
|
||||||
leaf.nodeStore()->overwriteLeaf(leaf.blockId(), std::move(leafData));
|
leaf.nodeStore()->overwriteLeaf(leaf.blockId(), std::move(leafData));
|
||||||
} else {
|
} else {
|
||||||
//TODO Simplify formula, make it easier to understand
|
//TODO Simplify formula, make it easier to understand
|
||||||
leaf.node()->write((uint8_t *) source + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset,
|
leaf.node()->write(static_cast<const uint8_t*>(source) + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset,
|
||||||
leafDataSize);
|
leafDataSize);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -140,7 +140,7 @@ void BlobOnBlocks::write(const void *source, uint64_t offset, uint64_t count) {
|
|||||||
ASSERT(beginByte >= offset && beginByte-offset <= count && beginByte-offset+numBytes <= count, "Reading from source out of bounds");
|
ASSERT(beginByte >= offset && beginByte-offset <= count && beginByte-offset+numBytes <= count, "Reading from source out of bounds");
|
||||||
Data result(numBytes);
|
Data result(numBytes);
|
||||||
//TODO Simplify formula, make it easier to understand
|
//TODO Simplify formula, make it easier to understand
|
||||||
std::memcpy(result.data(), (uint8_t*)source + beginByte - offset, numBytes);
|
std::memcpy(result.data(), static_cast<const uint8_t*>(source) + beginByte - offset, numBytes);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
_traverseLeaves(offset, count, onExistingLeaf, onCreateLeaf);
|
_traverseLeaves(offset, count, onExistingLeaf, onCreateLeaf);
|
||||||
|
@ -43,7 +43,8 @@ Data DataInnerNode::_serializeChildren(const vector<BlockId> &children) {
|
|||||||
Data data(sizeof(ChildEntry) * children.size());
|
Data data(sizeof(ChildEntry) * children.size());
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
for (const BlockId &child : children) {
|
for (const BlockId &child : children) {
|
||||||
reinterpret_cast<ChildEntry*>(data.data())[i++].setBlockId(child);
|
child.ToBinary(data.dataOffset(i * BlockId::BINARY_LENGTH));
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -52,49 +53,34 @@ uint32_t DataInnerNode::numChildren() const {
|
|||||||
return node().Size();
|
return node().Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
DataInnerNode::ChildEntry *DataInnerNode::ChildrenBegin() {
|
DataInnerNode::ChildEntry DataInnerNode::readChild(unsigned int index) const {
|
||||||
return const_cast<ChildEntry*>(const_cast<const DataInnerNode*>(this)->ChildrenBegin());
|
|
||||||
}
|
|
||||||
|
|
||||||
const DataInnerNode::ChildEntry *DataInnerNode::ChildrenBegin() const {
|
|
||||||
return node().DataBegin<ChildEntry>();
|
|
||||||
}
|
|
||||||
|
|
||||||
DataInnerNode::ChildEntry *DataInnerNode::ChildrenEnd() {
|
|
||||||
return const_cast<ChildEntry*>(const_cast<const DataInnerNode*>(this)->ChildrenEnd());
|
|
||||||
}
|
|
||||||
|
|
||||||
const DataInnerNode::ChildEntry *DataInnerNode::ChildrenEnd() const {
|
|
||||||
return ChildrenBegin() + node().Size();
|
|
||||||
}
|
|
||||||
|
|
||||||
DataInnerNode::ChildEntry *DataInnerNode::LastChild() {
|
|
||||||
return const_cast<ChildEntry*>(const_cast<const DataInnerNode*>(this)->LastChild());
|
|
||||||
}
|
|
||||||
|
|
||||||
const DataInnerNode::ChildEntry *DataInnerNode::LastChild() const {
|
|
||||||
return getChild(numChildren()-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
DataInnerNode::ChildEntry *DataInnerNode::getChild(unsigned int index) {
|
|
||||||
return const_cast<ChildEntry*>(const_cast<const DataInnerNode*>(this)->getChild(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
const DataInnerNode::ChildEntry *DataInnerNode::getChild(unsigned int index) const {
|
|
||||||
ASSERT(index < numChildren(), "Accessing child out of range");
|
ASSERT(index < numChildren(), "Accessing child out of range");
|
||||||
return ChildrenBegin()+index;
|
return ChildEntry(BlockId::FromBinary(static_cast<const uint8_t*>(node().data()) + index * sizeof(ChildEntry)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataInnerNode::_writeChild(unsigned int index, const ChildEntry& child) {
|
||||||
|
ASSERT(index < numChildren(), "Accessing child out of range");
|
||||||
|
node().write(child.blockId().data().data(), index * sizeof(ChildEntry), sizeof(ChildEntry));
|
||||||
|
}
|
||||||
|
|
||||||
|
DataInnerNode::ChildEntry DataInnerNode::readLastChild() const {
|
||||||
|
return readChild(numChildren() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataInnerNode::_writeLastChild(const ChildEntry& child) {
|
||||||
|
_writeChild(numChildren() - 1, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataInnerNode::addChild(const DataNode &child) {
|
void DataInnerNode::addChild(const DataNode &child) {
|
||||||
ASSERT(numChildren() < maxStoreableChildren(), "Adding more children than we can store");
|
ASSERT(numChildren() < maxStoreableChildren(), "Adding more children than we can store");
|
||||||
ASSERT(child.depth() == depth()-1, "The child that should be added has wrong depth");
|
ASSERT(child.depth() == depth()-1, "The child that should be added has wrong depth");
|
||||||
node().setSize(node().Size()+1);
|
node().setSize(node().Size()+1);
|
||||||
LastChild()->setBlockId(child.blockId());
|
_writeLastChild(ChildEntry(child.blockId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataInnerNode::removeLastChild() {
|
void DataInnerNode::removeLastChild() {
|
||||||
ASSERT(node().Size() > 1, "There is no child to remove");
|
ASSERT(node().Size() > 1, "There is no child to remove");
|
||||||
LastChild()->setBlockId(BlockId::Null());
|
_writeLastChild(ChildEntry(BlockId::Null()));
|
||||||
node().setSize(node().Size()-1);
|
node().setSize(node().Size()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,15 +14,15 @@ public:
|
|||||||
static cpputils::unique_ref<DataInnerNode> InitializeNewNode(cpputils::unique_ref<blockstore::Block> block, const DataNodeLayout &layout, uint8_t depth, const std::vector<blockstore::BlockId> &children);
|
static cpputils::unique_ref<DataInnerNode> InitializeNewNode(cpputils::unique_ref<blockstore::Block> block, const DataNodeLayout &layout, uint8_t depth, const std::vector<blockstore::BlockId> &children);
|
||||||
static cpputils::unique_ref<DataInnerNode> CreateNewNode(blockstore::BlockStore *blockStore, const DataNodeLayout &layout, uint8_t depth, const std::vector<blockstore::BlockId> &children);
|
static cpputils::unique_ref<DataInnerNode> CreateNewNode(blockstore::BlockStore *blockStore, const DataNodeLayout &layout, uint8_t depth, const std::vector<blockstore::BlockId> &children);
|
||||||
|
|
||||||
|
using ChildEntry = DataInnerNode_ChildEntry;
|
||||||
|
|
||||||
DataInnerNode(DataNodeView block);
|
DataInnerNode(DataNodeView block);
|
||||||
~DataInnerNode();
|
~DataInnerNode();
|
||||||
|
|
||||||
using ChildEntry = DataInnerNode_ChildEntry;
|
|
||||||
|
|
||||||
uint32_t maxStoreableChildren() const;
|
uint32_t maxStoreableChildren() const;
|
||||||
|
|
||||||
ChildEntry *getChild(unsigned int index);
|
ChildEntry readChild(unsigned int index) const;
|
||||||
const ChildEntry *getChild(unsigned int index) const;
|
ChildEntry readLastChild() const;
|
||||||
|
|
||||||
uint32_t numChildren() const;
|
uint32_t numChildren() const;
|
||||||
|
|
||||||
@ -30,16 +30,9 @@ public:
|
|||||||
|
|
||||||
void removeLastChild();
|
void removeLastChild();
|
||||||
|
|
||||||
ChildEntry *LastChild();
|
|
||||||
const ChildEntry *LastChild() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _writeChild(unsigned int index, const ChildEntry& child);
|
||||||
ChildEntry *ChildrenBegin();
|
void _writeLastChild(const ChildEntry& child);
|
||||||
ChildEntry *ChildrenEnd();
|
|
||||||
const ChildEntry *ChildrenBegin() const;
|
|
||||||
const ChildEntry *ChildrenEnd() const;
|
|
||||||
|
|
||||||
static cpputils::Data _serializeChildren(const std::vector<blockstore::BlockId> &children);
|
static cpputils::Data _serializeChildren(const std::vector<blockstore::BlockId> &children);
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(DataInnerNode);
|
DISALLOW_COPY_AND_ASSIGN(DataInnerNode);
|
||||||
|
@ -10,17 +10,19 @@ namespace datanodestore{
|
|||||||
|
|
||||||
struct DataInnerNode_ChildEntry final {
|
struct DataInnerNode_ChildEntry final {
|
||||||
public:
|
public:
|
||||||
blockstore::BlockId blockId() const {
|
DataInnerNode_ChildEntry(const blockstore::BlockId &blockId): _blockId(blockId) {}
|
||||||
return blockstore::BlockId::FromBinary(_blockIdData);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void setBlockId(const blockstore::BlockId &blockId) {
|
|
||||||
blockId.ToBinary(_blockIdData);
|
|
||||||
}
|
|
||||||
friend class DataInnerNode;
|
|
||||||
uint8_t _blockIdData[blockstore::BlockId::BINARY_LENGTH];
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(DataInnerNode_ChildEntry);
|
const blockstore::BlockId& blockId() const {
|
||||||
|
return _blockId;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataInnerNode_ChildEntry(const DataInnerNode_ChildEntry&) = delete;
|
||||||
|
DataInnerNode_ChildEntry& operator=(const DataInnerNode_ChildEntry&) = delete;
|
||||||
|
DataInnerNode_ChildEntry(DataInnerNode_ChildEntry&&) = default;
|
||||||
|
DataInnerNode_ChildEntry& operator=(DataInnerNode_ChildEntry&&) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
blockstore::BlockId _blockId;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ unique_ref<DataLeafNode> DataLeafNode::OverwriteNode(BlockStore *blockStore, con
|
|||||||
|
|
||||||
void DataLeafNode::read(void *target, uint64_t offset, uint64_t size) const {
|
void DataLeafNode::read(void *target, uint64_t offset, uint64_t size) const {
|
||||||
ASSERT(offset <= node().Size() && offset + size <= node().Size(), "Read out of valid area"); // Also check offset, because the addition could lead to overflows
|
ASSERT(offset <= node().Size() && offset + size <= node().Size(), "Read out of valid area"); // Also check offset, because the addition could lead to overflows
|
||||||
std::memcpy(target, (uint8_t*)node().data() + offset, size);
|
std::memcpy(target, static_cast<const uint8_t*>(node().data()) + offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataLeafNode::write(const void *source, uint64_t offset, uint64_t size) {
|
void DataLeafNode::write(const void *source, uint64_t offset, uint64_t size) {
|
||||||
|
@ -99,7 +99,7 @@ void DataNodeStore::removeSubtree(unique_ref<DataNode> node) {
|
|||||||
auto inner = dynamic_pointer_move<DataInnerNode>(node);
|
auto inner = dynamic_pointer_move<DataInnerNode>(node);
|
||||||
ASSERT(inner != none, "Is neither a leaf nor an inner node");
|
ASSERT(inner != none, "Is neither a leaf nor an inner node");
|
||||||
for (uint32_t i = 0; i < (*inner)->numChildren(); ++i) {
|
for (uint32_t i = 0; i < (*inner)->numChildren(); ++i) {
|
||||||
removeSubtree((*inner)->depth()-1, (*inner)->getChild(i)->blockId());
|
removeSubtree((*inner)->depth()-1, (*inner)->readChild(i).blockId());
|
||||||
}
|
}
|
||||||
remove(std::move(*inner));
|
remove(std::move(*inner));
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ void DataNodeStore::removeSubtree(uint8_t depth, const BlockId &blockId) {
|
|||||||
ASSERT(inner != none, "Is not an inner node, but depth was not zero");
|
ASSERT(inner != none, "Is not an inner node, but depth was not zero");
|
||||||
ASSERT((*inner)->depth() == depth, "Wrong depth given");
|
ASSERT((*inner)->depth() == depth, "Wrong depth given");
|
||||||
for (uint32_t i = 0; i < (*inner)->numChildren(); ++i) {
|
for (uint32_t i = 0; i < (*inner)->numChildren(); ++i) {
|
||||||
removeSubtree(depth-1, (*inner)->getChild(i)->blockId());
|
removeSubtree(depth-1, (*inner)->readChild(i).blockId());
|
||||||
}
|
}
|
||||||
remove(std::move(*inner));
|
remove(std::move(*inner));
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ public:
|
|||||||
DataNodeView(DataNodeView &&rhs) = default;
|
DataNodeView(DataNodeView &&rhs) = default;
|
||||||
|
|
||||||
uint16_t FormatVersion() const {
|
uint16_t FormatVersion() const {
|
||||||
return *((uint8_t*)_block->data()+DataNodeLayout::FORMAT_VERSION_OFFSET_BYTES);
|
return cpputils::deserializeWithOffset<uint16_t>(_block->data(), DataNodeLayout::FORMAT_VERSION_OFFSET_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFormatVersion(uint16_t value) {
|
void setFormatVersion(uint16_t value) {
|
||||||
@ -99,7 +99,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Depth() const {
|
uint8_t Depth() const {
|
||||||
return *((uint8_t*)_block->data()+DataNodeLayout::DEPTH_OFFSET_BYTES);
|
return cpputils::deserializeWithOffset<uint8_t>(_block->data(), DataNodeLayout::DEPTH_OFFSET_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDepth(uint8_t value) {
|
void setDepth(uint8_t value) {
|
||||||
@ -107,7 +107,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Size() const {
|
uint32_t Size() const {
|
||||||
return *(uint32_t*)((uint8_t*)_block->data()+DataNodeLayout::SIZE_OFFSET_BYTES);
|
return cpputils::deserializeWithOffset<uint32_t>(_block->data(), DataNodeLayout::SIZE_OFFSET_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSize(uint32_t value) {
|
void setSize(uint32_t value) {
|
||||||
@ -115,24 +115,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const void *data() const {
|
const void *data() const {
|
||||||
return (uint8_t*)_block->data() + DataNodeLayout::HEADERSIZE_BYTES;
|
return static_cast<const uint8_t*>(_block->data()) + DataNodeLayout::HEADERSIZE_BYTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const void *source, uint64_t offset, uint64_t size) {
|
void write(const void *source, uint64_t offset, uint64_t size) {
|
||||||
_block->write(source, offset + DataNodeLayout::HEADERSIZE_BYTES, size);
|
_block->write(source, offset + DataNodeLayout::HEADERSIZE_BYTES, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Entry>
|
|
||||||
const Entry *DataBegin() const {
|
|
||||||
return GetOffset<DataNodeLayout::HEADERSIZE_BYTES, Entry>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Entry>
|
|
||||||
const Entry *DataEnd() const {
|
|
||||||
const unsigned int NUM_ENTRIES = layout().datasizeBytes() / sizeof(Entry);
|
|
||||||
return DataBegin<Entry>() + NUM_ENTRIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataNodeLayout layout() const {
|
DataNodeLayout layout() const {
|
||||||
return DataNodeLayout(_block->size());
|
return DataNodeLayout(_block->size());
|
||||||
}
|
}
|
||||||
@ -154,16 +143,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<int offset, class Type>
|
|
||||||
const Type *GetOffset() const {
|
|
||||||
return (Type*)(((const int8_t*)_block->data())+offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cpputils::Data _serialize(const DataNodeLayout &layout, uint16_t formatVersion, uint8_t depth, uint32_t size, cpputils::Data data) {
|
static cpputils::Data _serialize(const DataNodeLayout &layout, uint16_t formatVersion, uint8_t depth, uint32_t size, cpputils::Data data) {
|
||||||
cpputils::Data result(layout.blocksizeBytes());
|
cpputils::Data result(layout.blocksizeBytes());
|
||||||
*((uint16_t*)result.dataOffset(layout.FORMAT_VERSION_OFFSET_BYTES)) = formatVersion;
|
cpputils::serialize<uint16_t>(result.dataOffset(layout.FORMAT_VERSION_OFFSET_BYTES), formatVersion);
|
||||||
*((uint8_t*)result.dataOffset(layout.DEPTH_OFFSET_BYTES)) = depth;
|
cpputils::serialize<uint8_t>(result.dataOffset(layout.DEPTH_OFFSET_BYTES), depth);
|
||||||
*((uint32_t*)result.dataOffset(layout.SIZE_OFFSET_BYTES)) = size;
|
cpputils::serialize<uint32_t>(result.dataOffset(layout.SIZE_OFFSET_BYTES), size);
|
||||||
std::memcpy(result.dataOffset(layout.HEADERSIZE_BYTES), data.data(), data.size());
|
std::memcpy(result.dataOffset(layout.HEADERSIZE_BYTES), data.data(), data.size());
|
||||||
std::memset(result.dataOffset(layout.HEADERSIZE_BYTES+data.size()), 0, layout.datasizeBytes()-data.size());
|
std::memset(result.dataOffset(layout.HEADERSIZE_BYTES+data.size()), 0, layout.datasizeBytes()-data.size());
|
||||||
return result;
|
return result;
|
||||||
|
@ -82,8 +82,8 @@ uint32_t DataTree::_computeNumLeaves(const DataNode &node) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const DataInnerNode &inner = dynamic_cast<const DataInnerNode&>(node);
|
const DataInnerNode &inner = dynamic_cast<const DataInnerNode&>(node);
|
||||||
uint64_t numLeavesInLeftChildren = (uint64_t)(inner.numChildren()-1) * leavesPerFullChild(inner);
|
uint64_t numLeavesInLeftChildren = static_cast<uint64_t>(inner.numChildren()-1) * leavesPerFullChild(inner);
|
||||||
auto lastChild = _nodeStore->load(inner.LastChild()->blockId());
|
auto lastChild = _nodeStore->load(inner.readLastChild().blockId());
|
||||||
ASSERT(lastChild != none, "Couldn't load last child");
|
ASSERT(lastChild != none, "Couldn't load last child");
|
||||||
uint64_t numLeavesInRightChild = _computeNumLeaves(**lastChild);
|
uint64_t numLeavesInRightChild = _computeNumLeaves(**lastChild);
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ void DataTree::_traverseLeaves(uint32_t beginIndex, uint32_t endIndex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DataTree::leavesPerFullChild(const DataInnerNode &root) const {
|
uint32_t DataTree::leavesPerFullChild(const DataInnerNode &root) const {
|
||||||
return utils::intPow(_nodeStore->layout().maxChildrenPerInnerNode(), (uint64_t)root.depth()-1);
|
return utils::intPow(_nodeStore->layout().maxChildrenPerInnerNode(), static_cast<uint64_t>(root.depth())-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DataTree::numStoredBytes() const {
|
uint64_t DataTree::numStoredBytes() const {
|
||||||
@ -132,7 +132,7 @@ uint64_t DataTree::_numStoredBytes(const DataNode &root) const {
|
|||||||
|
|
||||||
const DataInnerNode &inner = dynamic_cast<const DataInnerNode&>(root);
|
const DataInnerNode &inner = dynamic_cast<const DataInnerNode&>(root);
|
||||||
uint64_t numBytesInLeftChildren = (inner.numChildren()-1) * leavesPerFullChild(inner) * _nodeStore->layout().maxBytesPerLeaf();
|
uint64_t numBytesInLeftChildren = (inner.numChildren()-1) * leavesPerFullChild(inner) * _nodeStore->layout().maxBytesPerLeaf();
|
||||||
auto lastChild = _nodeStore->load(inner.LastChild()->blockId());
|
auto lastChild = _nodeStore->load(inner.readLastChild().blockId());
|
||||||
ASSERT(lastChild != none, "Couldn't load last child");
|
ASSERT(lastChild != none, "Couldn't load last child");
|
||||||
uint64_t numBytesInRightChild = _numStoredBytes(**lastChild);
|
uint64_t numBytesInRightChild = _numStoredBytes(**lastChild);
|
||||||
|
|
||||||
@ -159,14 +159,14 @@ void DataTree::resizeNumBytes(uint64_t newNumBytes) {
|
|||||||
auto onBacktrackFromSubtree = [this, newNumLeaves, maxChildrenPerInnerNode] (DataInnerNode* node) {
|
auto onBacktrackFromSubtree = [this, newNumLeaves, maxChildrenPerInnerNode] (DataInnerNode* node) {
|
||||||
// This is only called for the right border nodes of the new tree.
|
// This is only called for the right border nodes of the new tree.
|
||||||
// When growing size, the following is a no-op. When shrinking, we're deleting the children that aren't needed anymore.
|
// When growing size, the following is a no-op. When shrinking, we're deleting the children that aren't needed anymore.
|
||||||
uint32_t maxLeavesPerChild = utils::intPow((uint64_t)maxChildrenPerInnerNode, ((uint64_t)node->depth()-1));
|
uint32_t maxLeavesPerChild = utils::intPow(static_cast<uint64_t>(maxChildrenPerInnerNode), (static_cast<uint64_t>(node->depth())-1));
|
||||||
uint32_t neededNodesOnChildLevel = utils::ceilDivision(newNumLeaves, maxLeavesPerChild);
|
uint32_t neededNodesOnChildLevel = utils::ceilDivision(newNumLeaves, maxLeavesPerChild);
|
||||||
uint32_t neededSiblings = utils::ceilDivision(neededNodesOnChildLevel, maxChildrenPerInnerNode);
|
uint32_t neededSiblings = utils::ceilDivision(neededNodesOnChildLevel, maxChildrenPerInnerNode);
|
||||||
uint32_t neededChildrenForRightBorderNode = neededNodesOnChildLevel - (neededSiblings-1) * maxChildrenPerInnerNode;
|
uint32_t neededChildrenForRightBorderNode = neededNodesOnChildLevel - (neededSiblings-1) * maxChildrenPerInnerNode;
|
||||||
ASSERT(neededChildrenForRightBorderNode <= node->numChildren(), "Node has too few children");
|
ASSERT(neededChildrenForRightBorderNode <= node->numChildren(), "Node has too few children");
|
||||||
// All children to the right of the new right-border-node are removed including their subtree.
|
// All children to the right of the new right-border-node are removed including their subtree.
|
||||||
while(node->numChildren() > neededChildrenForRightBorderNode) {
|
while(node->numChildren() > neededChildrenForRightBorderNode) {
|
||||||
_nodeStore->removeSubtree(node->depth()-1, node->LastChild()->blockId());
|
_nodeStore->removeSubtree(node->depth()-1, node->readLastChild().blockId());
|
||||||
node->removeLastChild();
|
node->removeLastChild();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -122,7 +122,7 @@ namespace blobstore {
|
|||||||
// we still have to descend to the last old child to fill it with leaves and grow the last old leaf.
|
// we still have to descend to the last old child to fill it with leaves and grow the last old leaf.
|
||||||
if (isLeftBorderOfTraversal && beginChild >= numChildren) {
|
if (isLeftBorderOfTraversal && beginChild >= numChildren) {
|
||||||
ASSERT(numChildren > 0, "Node doesn't have children.");
|
ASSERT(numChildren > 0, "Node doesn't have children.");
|
||||||
auto childBlockId = root->getChild(numChildren-1)->blockId();
|
auto childBlockId = root->readLastChild().blockId();
|
||||||
uint32_t childOffset = (numChildren-1) * leavesPerChild;
|
uint32_t childOffset = (numChildren-1) * leavesPerChild;
|
||||||
_traverseExistingSubtree(childBlockId, root->depth()-1, leavesPerChild, leavesPerChild, childOffset, true, false, true,
|
_traverseExistingSubtree(childBlockId, root->depth()-1, leavesPerChild, leavesPerChild, childOffset, true, false, true,
|
||||||
[] (uint32_t /*index*/, bool /*isRightBorderNode*/, LeafHandle /*leaf*/) {ASSERT(false, "We don't actually traverse any leaves.");},
|
[] (uint32_t /*index*/, bool /*isRightBorderNode*/, LeafHandle /*leaf*/) {ASSERT(false, "We don't actually traverse any leaves.");},
|
||||||
@ -132,7 +132,7 @@ namespace blobstore {
|
|||||||
|
|
||||||
// Traverse existing children
|
// Traverse existing children
|
||||||
for (uint32_t childIndex = beginChild; childIndex < std::min(endChild, numChildren); ++childIndex) {
|
for (uint32_t childIndex = beginChild; childIndex < std::min(endChild, numChildren); ++childIndex) {
|
||||||
auto childBlockId = root->getChild(childIndex)->blockId();
|
auto childBlockId = root->readChild(childIndex).blockId();
|
||||||
uint32_t childOffset = childIndex * leavesPerChild;
|
uint32_t childOffset = childIndex * leavesPerChild;
|
||||||
uint32_t localBeginIndex = utils::maxZeroSubtraction(beginIndex, childOffset);
|
uint32_t localBeginIndex = utils::maxZeroSubtraction(beginIndex, childOffset);
|
||||||
uint32_t localEndIndex = std::min(leavesPerChild, endIndex - childOffset);
|
uint32_t localEndIndex = std::min(leavesPerChild, endIndex - childOffset);
|
||||||
@ -169,7 +169,7 @@ namespace blobstore {
|
|||||||
return _nodeStore->createNewLeafNode(leafCreator(leafOffset));
|
return _nodeStore->createNewLeafNode(leafCreator(leafOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t minNeededDepth = utils::ceilLog(_nodeStore->layout().maxChildrenPerInnerNode(), (uint64_t)endIndex);
|
uint8_t minNeededDepth = utils::ceilLog(_nodeStore->layout().maxChildrenPerInnerNode(), static_cast<uint64_t>(endIndex));
|
||||||
ASSERT(depth >= minNeededDepth, "Given tree depth doesn't fit given number of leaves to create.");
|
ASSERT(depth >= minNeededDepth, "Given tree depth doesn't fit given number of leaves to create.");
|
||||||
uint32_t leavesPerChild = _maxLeavesForTreeDepth(depth-1);
|
uint32_t leavesPerChild = _maxLeavesForTreeDepth(depth-1);
|
||||||
uint32_t beginChild = beginIndex/leavesPerChild;
|
uint32_t beginChild = beginIndex/leavesPerChild;
|
||||||
@ -208,7 +208,7 @@ namespace blobstore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t LeafTraverser::_maxLeavesForTreeDepth(uint8_t depth) const {
|
uint32_t LeafTraverser::_maxLeavesForTreeDepth(uint8_t depth) const {
|
||||||
return utils::intPow(_nodeStore->layout().maxChildrenPerInnerNode(), (uint64_t)depth);
|
return utils::intPow(_nodeStore->layout().maxChildrenPerInnerNode(), static_cast<uint64_t>(depth));
|
||||||
}
|
}
|
||||||
|
|
||||||
function<Data (uint32_t index)> LeafTraverser::_createMaxSizeLeaf() const {
|
function<Data (uint32_t index)> LeafTraverser::_createMaxSizeLeaf() const {
|
||||||
@ -221,7 +221,7 @@ namespace blobstore {
|
|||||||
unique_ref<DataNode> LeafTraverser::_whileRootHasOnlyOneChildReplaceRootWithItsChild(unique_ref<DataNode> root) {
|
unique_ref<DataNode> LeafTraverser::_whileRootHasOnlyOneChildReplaceRootWithItsChild(unique_ref<DataNode> root) {
|
||||||
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
||||||
if (inner != nullptr && inner->numChildren() == 1) {
|
if (inner != nullptr && inner->numChildren() == 1) {
|
||||||
auto newRoot = _whileRootHasOnlyOneChildRemoveRootReturnChild(inner->getChild(0)->blockId());
|
auto newRoot = _whileRootHasOnlyOneChildRemoveRootReturnChild(inner->readChild(0).blockId());
|
||||||
auto result = _nodeStore->overwriteNodeWith(std::move(root), *newRoot);
|
auto result = _nodeStore->overwriteNodeWith(std::move(root), *newRoot);
|
||||||
_nodeStore->remove(std::move(newRoot));
|
_nodeStore->remove(std::move(newRoot));
|
||||||
return result;
|
return result;
|
||||||
@ -237,7 +237,7 @@ namespace blobstore {
|
|||||||
if (inner == none) {
|
if (inner == none) {
|
||||||
return std::move(*current);
|
return std::move(*current);
|
||||||
} else if ((*inner)->numChildren() == 1) {
|
} else if ((*inner)->numChildren() == 1) {
|
||||||
auto result = _whileRootHasOnlyOneChildRemoveRootReturnChild((*inner)->getChild(0)->blockId());
|
auto result = _whileRootHasOnlyOneChildRemoveRootReturnChild((*inner)->readChild(0).blockId());
|
||||||
_nodeStore->remove(std::move(*inner));
|
_nodeStore->remove(std::move(*inner));
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
|
@ -23,7 +23,7 @@ namespace datatreestore {
|
|||||||
namespace algorithms {
|
namespace algorithms {
|
||||||
|
|
||||||
optional<unique_ref<DataInnerNode>> getLastChildAsInnerNode(DataNodeStore *nodeStore, const DataInnerNode &node) {
|
optional<unique_ref<DataInnerNode>> getLastChildAsInnerNode(DataNodeStore *nodeStore, const DataInnerNode &node) {
|
||||||
BlockId blockId = node.LastChild()->blockId();
|
BlockId blockId = node.readLastChild().blockId();
|
||||||
auto lastChild = nodeStore->load(blockId);
|
auto lastChild = nodeStore->load(blockId);
|
||||||
ASSERT(lastChild != none, "Couldn't load last child");
|
ASSERT(lastChild != none, "Couldn't load last child");
|
||||||
return dynamic_pointer_move<DataInnerNode>(*lastChild);
|
return dynamic_pointer_move<DataInnerNode>(*lastChild);
|
||||||
|
@ -33,7 +33,7 @@ inline INT_TYPE maxZeroSubtraction(INT_TYPE minuend, INT_TYPE subtrahend) {
|
|||||||
|
|
||||||
template<typename INT_TYPE>
|
template<typename INT_TYPE>
|
||||||
inline INT_TYPE ceilLog(INT_TYPE base, INT_TYPE value) {
|
inline INT_TYPE ceilLog(INT_TYPE base, INT_TYPE value) {
|
||||||
return std::ceil((long double)std::log(value)/(long double)std::log(base));
|
return std::ceil(static_cast<long double>(std::log(value))/static_cast<long double>(std::log(base)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public:
|
|||||||
CacheEntry(CacheEntry&& rhs) noexcept: _lastAccess(std::move(rhs._lastAccess)), _value(std::move(rhs._value)) {}
|
CacheEntry(CacheEntry&& rhs) noexcept: _lastAccess(std::move(rhs._lastAccess)), _value(std::move(rhs._value)) {}
|
||||||
|
|
||||||
double ageSeconds() const {
|
double ageSeconds() const {
|
||||||
return ((double)(currentTime() - _lastAccess).total_nanoseconds()) / ((double)1000000000);
|
return static_cast<double>((currentTime() - _lastAccess).total_nanoseconds()) / static_cast<double>(1000000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value releaseValue() {
|
Value releaseValue() {
|
||||||
|
@ -9,7 +9,7 @@ namespace caching {
|
|||||||
|
|
||||||
PeriodicTask::PeriodicTask(function<void ()> task, double intervalSec) :
|
PeriodicTask::PeriodicTask(function<void ()> task, double intervalSec) :
|
||||||
_task(task),
|
_task(task),
|
||||||
_interval((uint64_t)(UINT64_C(1000000000) * intervalSec)),
|
_interval(static_cast<uint64_t>(UINT64_C(1000000000) * intervalSec)),
|
||||||
_thread(std::bind(&PeriodicTask::_loopIteration, this)) {
|
_thread(std::bind(&PeriodicTask::_loopIteration, this)) {
|
||||||
_thread.start();
|
_thread.start();
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ cpputils::unique_ref<CompressedBlock<Compressor>> CompressedBlock<Compressor>::O
|
|||||||
|
|
||||||
template<class Compressor>
|
template<class Compressor>
|
||||||
cpputils::unique_ref<CompressedBlock<Compressor>> CompressedBlock<Compressor>::Decompress(cpputils::unique_ref<Block> baseBlock) {
|
cpputils::unique_ref<CompressedBlock<Compressor>> CompressedBlock<Compressor>::Decompress(cpputils::unique_ref<Block> baseBlock) {
|
||||||
cpputils::Data decompressed = Compressor::Decompress((CryptoPP::byte*)baseBlock->data(), baseBlock->size());
|
cpputils::Data decompressed = Compressor::Decompress(baseBlock->data(), baseBlock->size());
|
||||||
return cpputils::make_unique_ref<CompressedBlock<Compressor>>(std::move(baseBlock), std::move(decompressed));
|
return cpputils::make_unique_ref<CompressedBlock<Compressor>>(std::move(baseBlock), std::move(decompressed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ const void *CompressedBlock<Compressor>::data() const {
|
|||||||
|
|
||||||
template<class Compressor>
|
template<class Compressor>
|
||||||
void CompressedBlock<Compressor>::write(const void *source, uint64_t offset, uint64_t size) {
|
void CompressedBlock<Compressor>::write(const void *source, uint64_t offset, uint64_t size) {
|
||||||
std::memcpy((uint8_t*)_decompressedData.dataOffset(offset), source, size);
|
std::memcpy(_decompressedData.dataOffset(offset), source, size);
|
||||||
_dataChanged = true;
|
_dataChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,20 +9,20 @@ namespace blockstore {
|
|||||||
|
|
||||||
Data Gzip::Compress(const Data &data) {
|
Data Gzip::Compress(const Data &data) {
|
||||||
CryptoPP::Gzip zipper;
|
CryptoPP::Gzip zipper;
|
||||||
zipper.Put((CryptoPP::byte *) data.data(), data.size());
|
zipper.Put(static_cast<const CryptoPP::byte *>(data.data()), data.size());
|
||||||
zipper.MessageEnd();
|
zipper.MessageEnd();
|
||||||
Data compressed(zipper.MaxRetrievable());
|
Data compressed(zipper.MaxRetrievable());
|
||||||
zipper.Get((CryptoPP::byte *) compressed.data(), compressed.size());
|
zipper.Get(static_cast<CryptoPP::byte *>(compressed.data()), compressed.size());
|
||||||
return compressed;
|
return compressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Data Gzip::Decompress(const void *data, size_t size) {
|
Data Gzip::Decompress(const void *data, size_t size) {
|
||||||
//TODO Change interface to taking cpputils::Data objects (needs changing blockstore so we can read their "class Data", because this is called from CompressedBlock::Decompress()).
|
//TODO Change interface to taking cpputils::Data objects (needs changing blockstore so we can read their "class Data", because this is called from CompressedBlock::Decompress()).
|
||||||
CryptoPP::Gunzip zipper;
|
CryptoPP::Gunzip zipper;
|
||||||
zipper.Put((CryptoPP::byte *) data, size);
|
zipper.Put(static_cast<const CryptoPP::byte *>(data), size);
|
||||||
zipper.MessageEnd();
|
zipper.MessageEnd();
|
||||||
Data decompressed(zipper.MaxRetrievable());
|
Data decompressed(zipper.MaxRetrievable());
|
||||||
zipper.Get((CryptoPP::byte *) decompressed.data(), decompressed.size());
|
zipper.Get(static_cast<CryptoPP::byte *>(decompressed.data()), decompressed.size());
|
||||||
return decompressed;
|
return decompressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ namespace blockstore {
|
|||||||
|
|
||||||
Data RunLengthEncoding::Compress(const Data &data) {
|
Data RunLengthEncoding::Compress(const Data &data) {
|
||||||
ostringstream compressed;
|
ostringstream compressed;
|
||||||
uint8_t *current = (uint8_t*)data.data();
|
const uint8_t *current = static_cast<const uint8_t*>(data.data());
|
||||||
uint8_t *end = (uint8_t*)data.data()+data.size();
|
const uint8_t *end = static_cast<const uint8_t*>(data.data())+data.size();
|
||||||
while (current < end) {
|
while (current < end) {
|
||||||
_encodeArbitraryWords(¤t, end, &compressed);
|
_encodeArbitraryWords(¤t, end, &compressed);
|
||||||
ASSERT(current <= end, "Overflow");
|
ASSERT(current <= end, "Overflow");
|
||||||
@ -32,25 +32,25 @@ namespace blockstore {
|
|||||||
return _extractData(&compressed);
|
return _extractData(&compressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunLengthEncoding::_encodeArbitraryWords(uint8_t **current, uint8_t* end, ostringstream *output) {
|
void RunLengthEncoding::_encodeArbitraryWords(const uint8_t **current, const uint8_t* end, ostringstream *output) {
|
||||||
uint16_t size = _arbitraryRunLength(*current, end);
|
uint16_t size = _arbitraryRunLength(*current, end);
|
||||||
output->write((const char*)&size, sizeof(uint16_t));
|
output->write(reinterpret_cast<const char*>(&size), sizeof(uint16_t));
|
||||||
output->write((const char*)*current, size);
|
output->write(reinterpret_cast<const char*>(*current), size);
|
||||||
*current += size;
|
*current += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t RunLengthEncoding::_arbitraryRunLength(uint8_t *start, uint8_t* end) {
|
uint16_t RunLengthEncoding::_arbitraryRunLength(const uint8_t *start, const uint8_t* end) {
|
||||||
// Each stopping of an arbitrary bytes run costs us 5 byte, because we have to store the length
|
// Each stopping of an arbitrary bytes run costs us 5 byte, because we have to store the length
|
||||||
// for the identical bytes run (2 byte), the identical byte itself (1 byte) and the length for the next arbitrary bytes run (2 byte).
|
// for the identical bytes run (2 byte), the identical byte itself (1 byte) and the length for the next arbitrary bytes run (2 byte).
|
||||||
// So to get an advantage from stopping an arbitrary bytes run, at least 6 bytes have to be identical.
|
// So to get an advantage from stopping an arbitrary bytes run, at least 6 bytes have to be identical.
|
||||||
|
|
||||||
// realEnd avoids an overflow of the 16bit counter
|
// realEnd avoids an overflow of the 16bit counter
|
||||||
uint8_t *realEnd = std::min(end, start + std::numeric_limits<uint16_t>::max());
|
const uint8_t *realEnd = std::min(end, start + std::numeric_limits<uint16_t>::max());
|
||||||
|
|
||||||
// Count the number of identical bytes and return if it finds a run of more than 6 identical bytes.
|
// Count the number of identical bytes and return if it finds a run of more than 6 identical bytes.
|
||||||
uint8_t lastByte = *start + 1; // Something different from the first byte
|
uint8_t lastByte = *start + 1; // Something different from the first byte
|
||||||
uint8_t numIdenticalBytes = 1;
|
uint8_t numIdenticalBytes = 1;
|
||||||
for(uint8_t *current = start; current != realEnd; ++current) {
|
for(const uint8_t *current = start; current != realEnd; ++current) {
|
||||||
if (*current == lastByte) {
|
if (*current == lastByte) {
|
||||||
++numIdenticalBytes;
|
++numIdenticalBytes;
|
||||||
if (numIdenticalBytes == 6) {
|
if (numIdenticalBytes == 6) {
|
||||||
@ -65,16 +65,16 @@ namespace blockstore {
|
|||||||
return realEnd-start;
|
return realEnd-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunLengthEncoding::_encodeIdenticalWords(uint8_t **current, uint8_t* end, ostringstream *output) {
|
void RunLengthEncoding::_encodeIdenticalWords(const uint8_t **current, const uint8_t* end, ostringstream *output) {
|
||||||
uint16_t size = _countIdenticalBytes(*current, end);
|
uint16_t size = _countIdenticalBytes(*current, end);
|
||||||
output->write((const char*)&size, sizeof(uint16_t));
|
output->write(reinterpret_cast<const char*>(&size), sizeof(uint16_t));
|
||||||
output->write((const char*)*current, 1);
|
output->write(reinterpret_cast<const char*>(*current), 1);
|
||||||
*current += size;
|
*current += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t RunLengthEncoding::_countIdenticalBytes(uint8_t *start, uint8_t *end) {
|
uint16_t RunLengthEncoding::_countIdenticalBytes(const uint8_t *start, const uint8_t *end) {
|
||||||
uint8_t *realEnd = std::min(end, start + std::numeric_limits<uint16_t>::max()); // This prevents overflow of the 16bit counter
|
const uint8_t *realEnd = std::min(end, start + std::numeric_limits<uint16_t>::max()); // This prevents overflow of the 16bit counter
|
||||||
for (uint8_t *current = start+1; current != realEnd; ++current) {
|
for (const uint8_t *current = start+1; current != realEnd; ++current) {
|
||||||
if (*current != *start) {
|
if (*current != *start) {
|
||||||
return current-start;
|
return current-start;
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ namespace blockstore {
|
|||||||
|
|
||||||
Data RunLengthEncoding::Decompress(const void *data, size_t size) {
|
Data RunLengthEncoding::Decompress(const void *data, size_t size) {
|
||||||
istringstream stream;
|
istringstream stream;
|
||||||
_parseData((uint8_t*)data, size, &stream);
|
_parseData(static_cast<const uint8_t*>(data), size, &stream);
|
||||||
ostringstream decompressed;
|
ostringstream decompressed;
|
||||||
while(_hasData(&stream)) {
|
while(_hasData(&stream)) {
|
||||||
_decodeArbitraryWords(&stream, &decompressed);
|
_decodeArbitraryWords(&stream, &decompressed);
|
||||||
@ -110,29 +110,29 @@ namespace blockstore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RunLengthEncoding::_parseData(const uint8_t *data, size_t size, istringstream *result) {
|
void RunLengthEncoding::_parseData(const uint8_t *data, size_t size, istringstream *result) {
|
||||||
result->str(string((const char*)data, size));
|
result->str(string(reinterpret_cast<const char*>(data), size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunLengthEncoding::_decodeArbitraryWords(istringstream *stream, ostringstream *decompressed) {
|
void RunLengthEncoding::_decodeArbitraryWords(istringstream *stream, ostringstream *decompressed) {
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
stream->read((char*)&size, sizeof(uint16_t));
|
stream->read(reinterpret_cast<char*>(&size), sizeof(uint16_t));
|
||||||
ASSERT(stream->good(), "Premature end of stream");
|
ASSERT(stream->good(), "Premature end of stream");
|
||||||
Data run(size);
|
Data run(size);
|
||||||
stream->read((char*)run.data(), size);
|
stream->read(static_cast<char*>(run.data()), size);
|
||||||
ASSERT(stream->good(), "Premature end of stream");
|
ASSERT(stream->good(), "Premature end of stream");
|
||||||
decompressed->write((const char*)run.data(), run.size());
|
decompressed->write(static_cast<const char*>(run.data()), run.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunLengthEncoding::_decodeIdenticalWords(istringstream *stream, ostringstream *decompressed) {
|
void RunLengthEncoding::_decodeIdenticalWords(istringstream *stream, ostringstream *decompressed) {
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
stream->read((char*)&size, sizeof(uint16_t));
|
stream->read(reinterpret_cast<char*>(&size), sizeof(uint16_t));
|
||||||
ASSERT(stream->good(), "Premature end of stream");
|
ASSERT(stream->good(), "Premature end of stream");
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
stream->read((char*)&value, 1);
|
stream->read(reinterpret_cast<char*>(&value), 1);
|
||||||
ASSERT(stream->good(), "Premature end of stream");
|
ASSERT(stream->good(), "Premature end of stream");
|
||||||
Data run(size);
|
Data run(size);
|
||||||
std::memset(run.data(), value, run.size());
|
std::memset(run.data(), value, run.size());
|
||||||
decompressed->write((const char*)run.data(), run.size());
|
decompressed->write(static_cast<const char*>(run.data()), run.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,10 @@ namespace blockstore {
|
|||||||
static cpputils::Data Decompress(const void *data, size_t size);
|
static cpputils::Data Decompress(const void *data, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void _encodeArbitraryWords(uint8_t **current, uint8_t* end, std::ostringstream *output);
|
static void _encodeArbitraryWords(const uint8_t **current, const uint8_t* end, std::ostringstream *output);
|
||||||
static uint16_t _arbitraryRunLength(uint8_t *start, uint8_t* end);
|
static uint16_t _arbitraryRunLength(const uint8_t *start, const uint8_t* end);
|
||||||
static void _encodeIdenticalWords(uint8_t **current, uint8_t* end, std::ostringstream *output);
|
static void _encodeIdenticalWords(const uint8_t **current, const uint8_t* end, std::ostringstream *output);
|
||||||
static uint16_t _countIdenticalBytes(uint8_t *start, uint8_t *end);
|
static uint16_t _countIdenticalBytes(const uint8_t *start, const uint8_t *end);
|
||||||
static bool _hasData(std::istringstream *stream);
|
static bool _hasData(std::istringstream *stream);
|
||||||
static cpputils::Data _extractData(std::ostringstream *stream);
|
static cpputils::Data _extractData(std::ostringstream *stream);
|
||||||
static void _parseData(const uint8_t *data, size_t size, std::istringstream *result);
|
static void _parseData(const uint8_t *data, size_t size, std::istringstream *result);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "cpp-utils/crypto/cryptopp_byte.h"
|
#include "cpp-utils/crypto/cryptopp_byte.h"
|
||||||
#include <cpp-utils/macros.h>
|
#include <cpp-utils/macros.h>
|
||||||
#include <cpp-utils/crypto/symmetric/Cipher.h>
|
#include <cpp-utils/crypto/symmetric/Cipher.h>
|
||||||
|
#include <cpp-utils/data/SerializationHelper.h>
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace encrypted {
|
namespace encrypted {
|
||||||
@ -122,14 +123,14 @@ inline void EncryptedBlockStore2<Cipher>::forEachBlock(std::function<void (const
|
|||||||
|
|
||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
inline cpputils::Data EncryptedBlockStore2<Cipher>::_encrypt(const cpputils::Data &data) const {
|
inline cpputils::Data EncryptedBlockStore2<Cipher>::_encrypt(const cpputils::Data &data) const {
|
||||||
cpputils::Data encrypted = Cipher::encrypt((CryptoPP::byte*)data.data(), data.size(), _encKey);
|
cpputils::Data encrypted = Cipher::encrypt(static_cast<const CryptoPP::byte*>(data.data()), data.size(), _encKey);
|
||||||
return _prependFormatHeaderToData(encrypted);
|
return _prependFormatHeaderToData(encrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
inline boost::optional<cpputils::Data> EncryptedBlockStore2<Cipher>::_tryDecrypt(const BlockId &blockId, const cpputils::Data &data) const {
|
inline boost::optional<cpputils::Data> EncryptedBlockStore2<Cipher>::_tryDecrypt(const BlockId &blockId, const cpputils::Data &data) const {
|
||||||
_checkFormatHeader(data);
|
_checkFormatHeader(data);
|
||||||
boost::optional<cpputils::Data> decrypted = Cipher::decrypt((CryptoPP::byte*)data.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.size() - sizeof(FORMAT_VERSION_HEADER), _encKey);
|
boost::optional<cpputils::Data> decrypted = Cipher::decrypt(static_cast<const CryptoPP::byte*>(data.dataOffset(sizeof(FORMAT_VERSION_HEADER))), data.size() - sizeof(FORMAT_VERSION_HEADER), _encKey);
|
||||||
if (decrypted == boost::none) {
|
if (decrypted == boost::none) {
|
||||||
// TODO Log warning
|
// TODO Log warning
|
||||||
return boost::none;
|
return boost::none;
|
||||||
@ -164,7 +165,7 @@ inline bool EncryptedBlockStore2<Cipher>::_blockIdHeaderIsCorrect(const BlockId
|
|||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
inline cpputils::Data EncryptedBlockStore2<Cipher>::_prependFormatHeaderToData(const cpputils::Data &data) {
|
inline cpputils::Data EncryptedBlockStore2<Cipher>::_prependFormatHeaderToData(const cpputils::Data &data) {
|
||||||
cpputils::Data dataWithHeader(sizeof(FORMAT_VERSION_HEADER) + data.size());
|
cpputils::Data dataWithHeader(sizeof(FORMAT_VERSION_HEADER) + data.size());
|
||||||
std::memcpy(dataWithHeader.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER));
|
cpputils::serialize<uint16_t>(dataWithHeader.dataOffset(0), FORMAT_VERSION_HEADER);
|
||||||
std::memcpy(dataWithHeader.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.data(), data.size());
|
std::memcpy(dataWithHeader.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.data(), data.size());
|
||||||
return dataWithHeader;
|
return dataWithHeader;
|
||||||
}
|
}
|
||||||
@ -184,7 +185,7 @@ inline void EncryptedBlockStore2<Cipher>::_checkFormatHeader(const cpputils::Dat
|
|||||||
|
|
||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
uint16_t EncryptedBlockStore2<Cipher>::_readFormatHeader(const cpputils::Data &data) {
|
uint16_t EncryptedBlockStore2<Cipher>::_readFormatHeader(const cpputils::Data &data) {
|
||||||
return *reinterpret_cast<decltype(FORMAT_VERSION_HEADER)*>(data.data());
|
return cpputils::deserialize<uint16_t>(data.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#include <blockstore/interface/BlockStore2.h>
|
#include <blockstore/interface/BlockStore2.h>
|
||||||
#include "IntegrityBlockStore2.h"
|
#include "IntegrityBlockStore2.h"
|
||||||
#include "KnownBlockVersions.h"
|
#include "KnownBlockVersions.h"
|
||||||
|
#include <cpp-utils/data/SerializationHelper.h>
|
||||||
|
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
|
using cpputils::serialize;
|
||||||
|
using cpputils::deserialize;
|
||||||
using std::string;
|
using std::string;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
@ -25,11 +28,11 @@ constexpr unsigned int IntegrityBlockStore2::HEADER_LENGTH;
|
|||||||
Data IntegrityBlockStore2::_prependHeaderToData(const BlockId& blockId, uint32_t myClientId, uint64_t version, const Data &data) {
|
Data IntegrityBlockStore2::_prependHeaderToData(const BlockId& blockId, uint32_t myClientId, uint64_t version, const Data &data) {
|
||||||
static_assert(HEADER_LENGTH == sizeof(FORMAT_VERSION_HEADER) + BlockId::BINARY_LENGTH + sizeof(myClientId) + sizeof(version), "Wrong header length");
|
static_assert(HEADER_LENGTH == sizeof(FORMAT_VERSION_HEADER) + BlockId::BINARY_LENGTH + sizeof(myClientId) + sizeof(version), "Wrong header length");
|
||||||
Data result(data.size() + HEADER_LENGTH);
|
Data result(data.size() + HEADER_LENGTH);
|
||||||
std::memcpy(result.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER));
|
serialize<uint16_t>(result.dataOffset(0), FORMAT_VERSION_HEADER);
|
||||||
std::memcpy(result.dataOffset(ID_HEADER_OFFSET), blockId.data().data(), BlockId::BINARY_LENGTH);
|
blockId.ToBinary(result.dataOffset(ID_HEADER_OFFSET));
|
||||||
std::memcpy(result.dataOffset(CLIENTID_HEADER_OFFSET), &myClientId, sizeof(myClientId));
|
serialize<uint32_t>(result.dataOffset(CLIENTID_HEADER_OFFSET), myClientId);
|
||||||
std::memcpy(result.dataOffset(VERSION_HEADER_OFFSET), &version, sizeof(version));
|
serialize<uint64_t>(result.dataOffset(VERSION_HEADER_OFFSET), version);
|
||||||
std::memcpy((uint8_t*)result.dataOffset(HEADER_LENGTH), data.data(), data.size());
|
std::memcpy(result.dataOffset(HEADER_LENGTH), data.data(), data.size());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,13 +65,11 @@ void IntegrityBlockStore2::_checkIdHeader(const BlockId &expectedBlockId, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t IntegrityBlockStore2::_readFormatHeader(const Data &data) {
|
uint16_t IntegrityBlockStore2::_readFormatHeader(const Data &data) {
|
||||||
return *reinterpret_cast<decltype(FORMAT_VERSION_HEADER)*>(data.data());
|
return deserialize<uint16_t>(data.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IntegrityBlockStore2::_readClientId(const Data &data) {
|
uint32_t IntegrityBlockStore2::_readClientId(const Data &data) {
|
||||||
uint32_t clientId;
|
return deserialize<uint32_t>(data.dataOffset(CLIENTID_HEADER_OFFSET));
|
||||||
std::memcpy(&clientId, data.dataOffset(CLIENTID_HEADER_OFFSET), sizeof(clientId));
|
|
||||||
return clientId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockId IntegrityBlockStore2::_readBlockId(const Data &data) {
|
BlockId IntegrityBlockStore2::_readBlockId(const Data &data) {
|
||||||
@ -76,9 +77,7 @@ BlockId IntegrityBlockStore2::_readBlockId(const Data &data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t IntegrityBlockStore2::_readVersion(const Data &data) {
|
uint64_t IntegrityBlockStore2::_readVersion(const Data &data) {
|
||||||
uint64_t version;
|
return deserialize<uint64_t>(data.dataOffset(VERSION_HEADER_OFFSET));
|
||||||
std::memcpy(&version, data.dataOffset(VERSION_HEADER_OFFSET), sizeof(version));
|
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Data IntegrityBlockStore2::_removeHeader(const Data &data) {
|
Data IntegrityBlockStore2::_removeHeader(const Data &data) {
|
||||||
@ -146,8 +145,8 @@ optional<Data> IntegrityBlockStore2::load(const BlockId &blockId) const {
|
|||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
Data IntegrityBlockStore2::_migrateBlock(const BlockId &blockId, const Data &data) {
|
Data IntegrityBlockStore2::_migrateBlock(const BlockId &blockId, const Data &data) {
|
||||||
Data migrated(data.size() + BlockId::BINARY_LENGTH);
|
Data migrated(data.size() + BlockId::BINARY_LENGTH);
|
||||||
std::memcpy(migrated.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER));
|
serialize<uint16_t>(migrated.dataOffset(0), FORMAT_VERSION_HEADER);
|
||||||
std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET), blockId.data().data(), BlockId::BINARY_LENGTH);
|
blockId.ToBinary(migrated.dataOffset(ID_HEADER_OFFSET));
|
||||||
std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET + BlockId::BINARY_LENGTH), data.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.size() - sizeof(FORMAT_VERSION_HEADER));
|
std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET + BlockId::BINARY_LENGTH), data.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.size() - sizeof(FORMAT_VERSION_HEADER));
|
||||||
ASSERT(migrated.size() == sizeof(FORMAT_VERSION_HEADER) + BlockId::BINARY_LENGTH + (data.size() - sizeof(FORMAT_VERSION_HEADER)), "Wrong offset computation");
|
ASSERT(migrated.size() == sizeof(FORMAT_VERSION_HEADER) + BlockId::BINARY_LENGTH + (data.size() - sizeof(FORMAT_VERSION_HEADER)), "Wrong offset computation");
|
||||||
return migrated;
|
return migrated;
|
||||||
|
@ -48,12 +48,12 @@ LowToHighLevelBlock::~LowToHighLevelBlock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const void *LowToHighLevelBlock::data() const {
|
const void *LowToHighLevelBlock::data() const {
|
||||||
return (uint8_t*)_data.data();
|
return _data.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LowToHighLevelBlock::write(const void *source, uint64_t offset, uint64_t count) {
|
void LowToHighLevelBlock::write(const void *source, uint64_t offset, uint64_t count) {
|
||||||
ASSERT(offset <= size() && offset + count <= size(), "Write outside of valid area"); //Also check offset < size() because of possible overflow in the addition
|
ASSERT(offset <= size() && offset + count <= size(), "Write outside of valid area"); //Also check offset < size() because of possible overflow in the addition
|
||||||
std::memcpy((uint8_t*)_data.data()+offset, source, count);
|
std::memcpy(_data.dataOffset(offset), source, count);
|
||||||
_dataChanged = true;
|
_dataChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ const void *FakeBlock::data() const {
|
|||||||
|
|
||||||
void FakeBlock::write(const void *source, uint64_t offset, uint64_t size) {
|
void FakeBlock::write(const void *source, uint64_t offset, uint64_t size) {
|
||||||
ASSERT(offset <= _data->size() && offset + size <= _data->size(), "Write outside of valid area"); //Also check offset < _data->size() because of possible overflow in the addition
|
ASSERT(offset <= _data->size() && offset + size <= _data->size(), "Write outside of valid area"); //Also check offset < _data->size() because of possible overflow in the addition
|
||||||
std::memcpy((uint8_t*)_data->data()+offset, source, size);
|
std::memcpy(_data->dataOffset(offset), source, size);
|
||||||
_dataChanged = true;
|
_dataChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <cpp-utils/data/FixedSizeData.h>
|
#include <cpp-utils/data/FixedSizeData.h>
|
||||||
#include <cpp-utils/random/Random.h>
|
#include <cpp-utils/random/Random.h>
|
||||||
|
#include <cpp-utils/data/SerializationHelper.h>
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ inline bool operator!=(const IdWrapper<Tag>& lhs, const IdWrapper<Tag>& rhs) {
|
|||||||
template <> struct hash<IdWrapper> { \
|
template <> struct hash<IdWrapper> { \
|
||||||
size_t operator()(const IdWrapper &idWrapper) const { \
|
size_t operator()(const IdWrapper &idWrapper) const { \
|
||||||
/*Ids are random, so it is enough to use the first few bytes as a hash */ \
|
/*Ids are random, so it is enough to use the first few bytes as a hash */ \
|
||||||
return *(size_t*)(idWrapper.id_.data()); \
|
return cpputils::deserialize<size_t>(idWrapper.id_.data()); \
|
||||||
} \
|
} \
|
||||||
}; \
|
}; \
|
||||||
/*Allow using IdWrapper in std::map / std::set */ \
|
/*Allow using IdWrapper in std::map / std::set */ \
|
||||||
|
@ -31,6 +31,7 @@ set(SOURCES
|
|||||||
random/RandomDataBuffer.cpp
|
random/RandomDataBuffer.cpp
|
||||||
random/RandomGenerator.cpp
|
random/RandomGenerator.cpp
|
||||||
lock/LockPool.cpp
|
lock/LockPool.cpp
|
||||||
|
data/SerializationHelper.cpp
|
||||||
data/Serializer.cpp
|
data/Serializer.cpp
|
||||||
data/Deserializer.cpp
|
data/Deserializer.cpp
|
||||||
data/DataFixture.cpp
|
data/DataFixture.cpp
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <cpp-utils/data/SerializationHelper.h>
|
||||||
#include "RandomPadding.h"
|
#include "RandomPadding.h"
|
||||||
#include "../logging/logging.h"
|
#include "../logging/logging.h"
|
||||||
#include "../random/Random.h"
|
#include "../random/Random.h"
|
||||||
@ -14,21 +15,20 @@ namespace cpputils {
|
|||||||
Data randomData = Random::PseudoRandom().get(targetSize-sizeof(size)-size);
|
Data randomData = Random::PseudoRandom().get(targetSize-sizeof(size)-size);
|
||||||
ASSERT(sizeof(size) + size + randomData.size() == targetSize, "Calculated size of randomData incorrectly");
|
ASSERT(sizeof(size) + size + randomData.size() == targetSize, "Calculated size of randomData incorrectly");
|
||||||
Data result(targetSize);
|
Data result(targetSize);
|
||||||
std::memcpy(reinterpret_cast<char*>(result.data()), &size, sizeof(size));
|
serialize<uint32_t>(result.data(), size);
|
||||||
std::memcpy(reinterpret_cast<char*>(result.dataOffset(sizeof(size))), reinterpret_cast<const char*>(data.data()), size);
|
std::memcpy(result.dataOffset(sizeof(size)), data.data(), size);
|
||||||
std::memcpy(reinterpret_cast<char*>(result.dataOffset(sizeof(size)+size)), reinterpret_cast<const char*>(randomData.data()), randomData.size());
|
std::memcpy(result.dataOffset(sizeof(size)+size), randomData.data(), randomData.size());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<Data> RandomPadding::remove(const Data &data) {
|
optional<Data> RandomPadding::remove(const Data &data) {
|
||||||
uint32_t size;
|
uint32_t size = deserialize<uint32_t>(data.data());
|
||||||
std::memcpy(&size, reinterpret_cast<const char*>(data.data()), sizeof(size));
|
|
||||||
if(sizeof(size) + size >= data.size()) {
|
if(sizeof(size) + size >= data.size()) {
|
||||||
LOG(ERROR, "Config file is invalid: Invalid padding.");
|
LOG(ERROR, "Config file is invalid: Invalid padding.");
|
||||||
return boost::none;
|
return boost::none;
|
||||||
};
|
};
|
||||||
Data result(size);
|
Data result(size);
|
||||||
std::memcpy(reinterpret_cast<char*>(result.data()), reinterpret_cast<const char*>(data.dataOffset(sizeof(size))), size);
|
std::memcpy(result.data(), data.dataOffset(sizeof(size)), size);
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,11 @@ namespace hash {
|
|||||||
|
|
||||||
Hash hash(const Data& data, Salt salt) {
|
Hash hash(const Data& data, Salt salt) {
|
||||||
SHA512 hasher; // NOLINT (workaround for clang-warning in libcrypto++)
|
SHA512 hasher; // NOLINT (workaround for clang-warning in libcrypto++)
|
||||||
hasher.Update((CryptoPP::byte*)salt.data(), Salt::BINARY_LENGTH);
|
hasher.Update(static_cast<const CryptoPP::byte*>(salt.data()), Salt::BINARY_LENGTH);
|
||||||
hasher.Update((CryptoPP::byte*)data.data(), data.size());
|
hasher.Update(static_cast<const CryptoPP::byte*>(data.data()), data.size());
|
||||||
|
|
||||||
Digest digest = Digest::Null();
|
Digest digest = Digest::Null();
|
||||||
hasher.Final((CryptoPP::byte*)digest.data());
|
hasher.Final(static_cast<CryptoPP::byte*>(digest.data()));
|
||||||
|
|
||||||
return Hash{
|
return Hash{
|
||||||
.digest = digest,
|
.digest = digest,
|
||||||
|
@ -24,7 +24,7 @@ namespace cpputils {
|
|||||||
void SCrypt::derive(void *destination, size_t size, const string &password) {
|
void SCrypt::derive(void *destination, size_t size, const string &password) {
|
||||||
_checkCallOnlyOnce();
|
_checkCallOnlyOnce();
|
||||||
int errorcode = crypto_scrypt(reinterpret_cast<const uint8_t*>(password.c_str()), password.size(),
|
int errorcode = crypto_scrypt(reinterpret_cast<const uint8_t*>(password.c_str()), password.size(),
|
||||||
reinterpret_cast<const uint8_t*>(_config.salt().data()), _config.salt().size(),
|
static_cast<const uint8_t*>(_config.salt().data()), _config.salt().size(),
|
||||||
_config.N(), _config.r(), _config.p(),
|
_config.N(), _config.r(), _config.p(),
|
||||||
static_cast<uint8_t*>(destination), size);
|
static_cast<uint8_t*>(destination), size);
|
||||||
if (errorcode != 0) {
|
if (errorcode != 0) {
|
||||||
|
@ -36,10 +36,10 @@ private:
|
|||||||
template<typename BlockCipher, unsigned int KeySize>
|
template<typename BlockCipher, unsigned int KeySize>
|
||||||
Data CFB_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
Data CFB_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
||||||
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
|
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
|
||||||
auto encryption = typename CryptoPP::CFB_Mode<BlockCipher>::Encryption((CryptoPP::byte*)encKey.data(), encKey.BINARY_LENGTH, iv.data());
|
auto encryption = typename CryptoPP::CFB_Mode<BlockCipher>::Encryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, iv.data());
|
||||||
Data ciphertext(ciphertextSize(plaintextSize));
|
Data ciphertext(ciphertextSize(plaintextSize));
|
||||||
std::memcpy(ciphertext.data(), iv.data(), IV_SIZE);
|
iv.ToBinary(ciphertext.data());
|
||||||
encryption.ProcessData((CryptoPP::byte*)ciphertext.data() + IV_SIZE, plaintext, plaintextSize);
|
encryption.ProcessData(static_cast<CryptoPP::byte*>(ciphertext.data()) + IV_SIZE, plaintext, plaintextSize);
|
||||||
return ciphertext;
|
return ciphertext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,9 +51,9 @@ boost::optional<Data> CFB_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::
|
|||||||
|
|
||||||
const CryptoPP::byte *ciphertextIV = ciphertext;
|
const CryptoPP::byte *ciphertextIV = ciphertext;
|
||||||
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
|
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
|
||||||
auto decryption = typename CryptoPP::CFB_Mode<BlockCipher>::Decryption((CryptoPP::byte*)encKey.data(), encKey.BINARY_LENGTH, ciphertextIV);
|
auto decryption = typename CryptoPP::CFB_Mode<BlockCipher>::Decryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, ciphertextIV);
|
||||||
Data plaintext(plaintextSize(ciphertextSize));
|
Data plaintext(plaintextSize(ciphertextSize));
|
||||||
decryption.ProcessData((CryptoPP::byte*)plaintext.data(), ciphertextData, plaintext.size());
|
decryption.ProcessData(static_cast<CryptoPP::byte*>(plaintext.data()), ciphertextData, plaintext.size());
|
||||||
return std::move(plaintext);
|
return std::move(plaintext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ public:
|
|||||||
same_type(UINT32_C(0), X::ciphertextSize(UINT32_C(5)));
|
same_type(UINT32_C(0), X::ciphertextSize(UINT32_C(5)));
|
||||||
same_type(UINT32_C(0), X::plaintextSize(UINT32_C(5)));
|
same_type(UINT32_C(0), X::plaintextSize(UINT32_C(5)));
|
||||||
typename X::EncryptionKey key = X::EncryptionKey::CreateKey(Random::OSRandom());
|
typename X::EncryptionKey key = X::EncryptionKey::CreateKey(Random::OSRandom());
|
||||||
same_type(Data(0), X::encrypt((uint8_t*)nullptr, UINT32_C(0), key));
|
same_type(Data(0), X::encrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key));
|
||||||
same_type(boost::optional<Data>(Data(0)), X::decrypt((uint8_t*)nullptr, UINT32_C(0), key));
|
same_type(boost::optional<Data>(Data(0)), X::decrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key));
|
||||||
string name = X::NAME;
|
string name = X::NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,13 +37,13 @@ template<typename BlockCipher, unsigned int KeySize>
|
|||||||
Data GCM_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
Data GCM_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
||||||
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
|
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
|
||||||
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Encryption encryption;
|
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Encryption encryption;
|
||||||
encryption.SetKeyWithIV((CryptoPP::byte*)encKey.data(), encKey.BINARY_LENGTH, iv.data(), IV_SIZE);
|
encryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, iv.data(), IV_SIZE);
|
||||||
Data ciphertext(ciphertextSize(plaintextSize));
|
Data ciphertext(ciphertextSize(plaintextSize));
|
||||||
|
|
||||||
std::memcpy(ciphertext.data(), iv.data(), IV_SIZE);
|
iv.ToBinary(ciphertext.data());
|
||||||
CryptoPP::ArraySource(plaintext, plaintextSize, true,
|
CryptoPP::ArraySource(plaintext, plaintextSize, true,
|
||||||
new CryptoPP::AuthenticatedEncryptionFilter(encryption,
|
new CryptoPP::AuthenticatedEncryptionFilter(encryption,
|
||||||
new CryptoPP::ArraySink((CryptoPP::byte*)ciphertext.data() + IV_SIZE, ciphertext.size() - IV_SIZE),
|
new CryptoPP::ArraySink(static_cast<CryptoPP::byte*>(ciphertext.data()) + IV_SIZE, ciphertext.size() - IV_SIZE),
|
||||||
false, TAG_SIZE
|
false, TAG_SIZE
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -59,13 +59,13 @@ boost::optional<Data> GCM_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::
|
|||||||
const CryptoPP::byte *ciphertextIV = ciphertext;
|
const CryptoPP::byte *ciphertextIV = ciphertext;
|
||||||
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
|
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
|
||||||
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Decryption decryption;
|
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Decryption decryption;
|
||||||
decryption.SetKeyWithIV((CryptoPP::byte*)encKey.data(), encKey.BINARY_LENGTH, ciphertextIV, IV_SIZE);
|
decryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, ciphertextIV, IV_SIZE);
|
||||||
Data plaintext(plaintextSize(ciphertextSize));
|
Data plaintext(plaintextSize(ciphertextSize));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CryptoPP::ArraySource((CryptoPP::byte*)ciphertextData, ciphertextSize - IV_SIZE, true,
|
CryptoPP::ArraySource(static_cast<const CryptoPP::byte*>(ciphertextData), ciphertextSize - IV_SIZE, true,
|
||||||
new CryptoPP::AuthenticatedDecryptionFilter(decryption,
|
new CryptoPP::AuthenticatedDecryptionFilter(decryption,
|
||||||
new CryptoPP::ArraySink((CryptoPP::byte*)plaintext.data(), plaintext.size()),
|
new CryptoPP::ArraySink(static_cast<CryptoPP::byte*>(plaintext.data()), plaintext.size()),
|
||||||
CryptoPP::AuthenticatedDecryptionFilter::DEFAULT_FLAGS, TAG_SIZE
|
CryptoPP::AuthenticatedDecryptionFilter::DEFAULT_FLAGS, TAG_SIZE
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -8,19 +8,20 @@
|
|||||||
#include "cpp-utils/data/Data.h"
|
#include "cpp-utils/data/Data.h"
|
||||||
#include "cpp-utils/random/RandomGenerator.h"
|
#include "cpp-utils/random/RandomGenerator.h"
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <cpp-utils/data/SerializationHelper.h>
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
|
|
||||||
struct FakeKey {
|
struct FakeKey {
|
||||||
static FakeKey FromBinary(const void *data) {
|
static FakeKey FromBinary(const void *data) {
|
||||||
return FakeKey{*(uint64_t *) data};
|
return FakeKey{deserialize<uint64_t>(data)};
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr unsigned int BINARY_LENGTH = sizeof(uint64_t);
|
static constexpr unsigned int BINARY_LENGTH = sizeof(uint64_t);
|
||||||
|
|
||||||
static FakeKey CreateKey(RandomGenerator &randomGenerator) {
|
static FakeKey CreateKey(RandomGenerator &randomGenerator) {
|
||||||
auto data = randomGenerator.getFixedSize<sizeof(uint64_t)>();
|
auto data = randomGenerator.getFixedSize<sizeof(uint64_t)>();
|
||||||
return FakeKey{*((uint64_t *) data.data())};
|
return FromBinary(data.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
@ -54,14 +55,14 @@ namespace cpputils {
|
|||||||
|
|
||||||
//Add a random IV
|
//Add a random IV
|
||||||
uint64_t iv = std::uniform_int_distribution<uint64_t>()(random_);
|
uint64_t iv = std::uniform_int_distribution<uint64_t>()(random_);
|
||||||
std::memcpy(result.data(), &iv, sizeof(uint64_t));
|
serialize<uint64_t>(result.data(), iv);
|
||||||
|
|
||||||
//Use xor chiffre on plaintext
|
//Use xor chiffre on plaintext
|
||||||
_xor((CryptoPP::byte *) result.data() + sizeof(uint64_t), plaintext, plaintextSize, encKey.value ^ iv);
|
_xor(static_cast<CryptoPP::byte*>(result.dataOffset(sizeof(uint64_t))), plaintext, plaintextSize, encKey.value ^ iv);
|
||||||
|
|
||||||
//Add checksum information
|
//Add checksum information
|
||||||
uint64_t checksum = _checksum((CryptoPP::byte *) result.data(), encKey, plaintextSize + sizeof(uint64_t));
|
uint64_t checksum = _checksum(static_cast<const CryptoPP::byte*>(result.data()), encKey, plaintextSize + sizeof(uint64_t));
|
||||||
std::memcpy((CryptoPP::byte *) result.data() + plaintextSize + sizeof(uint64_t), &checksum, sizeof(uint64_t));
|
serialize<uint64_t>(result.dataOffset(plaintextSize + sizeof(uint64_t)), checksum);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -75,45 +76,35 @@ namespace cpputils {
|
|||||||
|
|
||||||
//Check checksum
|
//Check checksum
|
||||||
uint64_t expectedParity = _checksum(ciphertext, encKey, plaintextSize(ciphertextSize) + sizeof(uint64_t));
|
uint64_t expectedParity = _checksum(ciphertext, encKey, plaintextSize(ciphertextSize) + sizeof(uint64_t));
|
||||||
uint64_t actualParity = *(uint64_t * )(ciphertext + plaintextSize(ciphertextSize) + sizeof(uint64_t));
|
uint64_t actualParity = deserialize<uint64_t>(ciphertext + plaintextSize(ciphertextSize) + sizeof(uint64_t));
|
||||||
if (expectedParity != actualParity) {
|
if (expectedParity != actualParity) {
|
||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Decrypt xor chiffre from ciphertext
|
//Decrypt xor chiffre from ciphertext
|
||||||
uint64_t iv = *(uint64_t *) ciphertext;
|
uint64_t iv = deserialize<uint64_t>(ciphertext);
|
||||||
Data result(plaintextSize(ciphertextSize));
|
Data result(plaintextSize(ciphertextSize));
|
||||||
_xor((CryptoPP::byte *) result.data(), ciphertext + sizeof(uint64_t), plaintextSize(ciphertextSize), encKey.value ^ iv);
|
_xor(static_cast<CryptoPP::byte *>(result.data()), ciphertext + sizeof(uint64_t), plaintextSize(ciphertextSize), encKey.value ^ iv);
|
||||||
|
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr const char *NAME = "FakeAuthenticatedCipher";
|
static constexpr const char *NAME = "FakeAuthenticatedCipher";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uint64_t _checksum(const CryptoPP::byte *data, FakeKey encKey, unsigned int size) {
|
static uint64_t _checksum(const CryptoPP::byte *data, FakeKey encKey, std::size_t size) {
|
||||||
uint64_t checksum = 34343435 * encKey.value; // some init value
|
uint64_t checksum = 34343435 * encKey.value; // some init value
|
||||||
const uint64_t *intData = reinterpret_cast<const uint64_t *>(data);
|
|
||||||
unsigned int intSize = size / sizeof(uint64_t);
|
for (unsigned int i = 0; i < size; ++i) {
|
||||||
for (unsigned int i = 0; i < intSize; ++i) {
|
checksum ^= (static_cast<uint64_t>(data[i]) << (56 - 8 * (i%8)));
|
||||||
checksum = ((uint64_t)checksum) + intData[i];
|
|
||||||
}
|
|
||||||
unsigned int remainingBytes = size - sizeof(uint64_t) * intSize;
|
|
||||||
for (unsigned int i = 0; i < remainingBytes; ++i) {
|
|
||||||
checksum = ((uint64_t)checksum) + (data[8 * intSize + i] << (56 - 8 * i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return checksum;
|
return checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _xor(CryptoPP::byte *dst, const CryptoPP::byte *src, unsigned int size, uint64_t key) {
|
static void _xor(CryptoPP::byte *dst, const CryptoPP::byte *src, unsigned int size, uint64_t key) {
|
||||||
const uint64_t *srcIntData = reinterpret_cast<const uint64_t *>(src);
|
for (unsigned int i = 0; i < size; ++i) {
|
||||||
uint64_t *dstIntData = reinterpret_cast<uint64_t *>(dst);
|
dst[i] = src[i] ^ ((key >> (56 - 8*(i%8))) & 0xFF);
|
||||||
unsigned int intSize = size / sizeof(uint64_t);
|
|
||||||
for (unsigned int i = 0; i < intSize; ++i) {
|
|
||||||
dstIntData[i] = srcIntData[i] ^ key;
|
|
||||||
}
|
|
||||||
unsigned int remainingBytes = size - sizeof(uint64_t) * intSize;
|
|
||||||
for (unsigned int i = 0; i < remainingBytes; ++i) {
|
|
||||||
dst[8 * intSize + i] = src[8 * intSize + i] ^ ((key >> (56 - 8*i)) & 0xFF);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ Data Data::FromString(const std::string &data) {
|
|||||||
Data result(data.size() / 2);
|
Data result(data.size() / 2);
|
||||||
CryptoPP::StringSource(data, true,
|
CryptoPP::StringSource(data, true,
|
||||||
new CryptoPP::HexDecoder(
|
new CryptoPP::HexDecoder(
|
||||||
new CryptoPP::ArraySink((CryptoPP::byte*)result._data, result.size())
|
new CryptoPP::ArraySink(static_cast<CryptoPP::byte*>(result._data), result.size())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
@ -57,7 +57,7 @@ Data Data::FromString(const std::string &data) {
|
|||||||
|
|
||||||
std::string Data::ToString() const {
|
std::string Data::ToString() const {
|
||||||
std::string result;
|
std::string result;
|
||||||
CryptoPP::ArraySource((CryptoPP::byte*)_data, _size, true,
|
CryptoPP::ArraySource(static_cast<const CryptoPP::byte*>(_data), _size, true,
|
||||||
new CryptoPP::HexEncoder(
|
new CryptoPP::HexEncoder(
|
||||||
new CryptoPP::StringSink(result)
|
new CryptoPP::StringSink(result)
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "DataFixture.h"
|
#include "DataFixture.h"
|
||||||
|
#include "SerializationHelper.h"
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
Data DataFixture::generate(size_t size, long long int seed) {
|
Data DataFixture::generate(size_t size, long long int seed) {
|
||||||
@ -8,7 +9,7 @@ namespace cpputils {
|
|||||||
//MMIX linear congruential generator
|
//MMIX linear congruential generator
|
||||||
val *= 6364136223846793005L;
|
val *= 6364136223846793005L;
|
||||||
val += 1442695040888963407;
|
val += 1442695040888963407;
|
||||||
reinterpret_cast<long long int*>(result.data())[i] = val;
|
serialize<long long int>(result.dataOffset(i*sizeof(long long int)), val);
|
||||||
}
|
}
|
||||||
uint64_t alreadyWritten = (size/sizeof(long long int))*sizeof(long long int);
|
uint64_t alreadyWritten = (size/sizeof(long long int))*sizeof(long long int);
|
||||||
val *= 6364136223846793005L;
|
val *= 6364136223846793005L;
|
||||||
@ -16,7 +17,7 @@ namespace cpputils {
|
|||||||
char *remainingBytes = reinterpret_cast<char*>(&val);
|
char *remainingBytes = reinterpret_cast<char*>(&val);
|
||||||
//Fill remaining bytes
|
//Fill remaining bytes
|
||||||
for(size_t i=0; i<size-alreadyWritten; ++i) {
|
for(size_t i=0; i<size-alreadyWritten; ++i) {
|
||||||
reinterpret_cast<char*>(result.data())[alreadyWritten + i] = remainingBytes[i];
|
serialize<char>(result.dataOffset(alreadyWritten + i), remainingBytes[i]);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "../macros.h"
|
#include "../macros.h"
|
||||||
#include "../assert/assert.h"
|
#include "../assert/assert.h"
|
||||||
#include "FixedSizeData.h"
|
#include "FixedSizeData.h"
|
||||||
|
#include "SerializationHelper.h"
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
class Deserializer final {
|
class Deserializer final {
|
||||||
@ -79,7 +80,7 @@ namespace cpputils {
|
|||||||
if (_pos + sizeof(DataType) > _source->size()) {
|
if (_pos + sizeof(DataType) > _source->size()) {
|
||||||
throw std::runtime_error("Deserialization failed - size overflow");
|
throw std::runtime_error("Deserialization failed - size overflow");
|
||||||
}
|
}
|
||||||
DataType result = *reinterpret_cast<const DataType*>(_source->dataOffset(_pos));
|
DataType result = deserialize<DataType>(_source->dataOffset(_pos));
|
||||||
_pos += sizeof(DataType);
|
_pos += sizeof(DataType);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -122,7 +123,7 @@ namespace cpputils {
|
|||||||
throw std::runtime_error("Deserialization failed - missing nullbyte for string termination");
|
throw std::runtime_error("Deserialization failed - missing nullbyte for string termination");
|
||||||
}
|
}
|
||||||
uint64_t size = static_cast<const uint8_t*>(nullbytepos) - static_cast<const uint8_t*>(_source->dataOffset(_pos));
|
uint64_t size = static_cast<const uint8_t*>(nullbytepos) - static_cast<const uint8_t*>(_source->dataOffset(_pos));
|
||||||
std::string result(reinterpret_cast<const char*>(_source->dataOffset(_pos)), size);
|
std::string result(static_cast<const char*>(_source->dataOffset(_pos)), size);
|
||||||
_pos += size + 1;
|
_pos += size + 1;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
1
src/cpp-utils/data/SerializationHelper.cpp
Normal file
1
src/cpp-utils/data/SerializationHelper.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "SerializationHelper.h"
|
78
src/cpp-utils/data/SerializationHelper.h
Normal file
78
src/cpp-utils/data/SerializationHelper.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef MESSMER_CPPUTILS_DATA_SERIALIZATIONHELPER_H
|
||||||
|
#define MESSMER_CPPUTILS_DATA_SERIALIZATIONHELPER_H
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace cpputils {
|
||||||
|
|
||||||
|
namespace details {
|
||||||
|
|
||||||
|
constexpr bool greater_than(size_t lhs, size_t rhs) {
|
||||||
|
return lhs > rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class DataType, class Enable = void> struct serialize;
|
||||||
|
|
||||||
|
// Specialize for 1-byte types for faster performance with direct pointer access (no memcpy).
|
||||||
|
template<class DataType>
|
||||||
|
struct serialize<DataType, typename std::enable_if<sizeof(DataType) == 1>::type> final {
|
||||||
|
static_assert(std::is_pod<DataType>::value, "Can only serialize PODs");
|
||||||
|
static void call(void *dst, const DataType &obj) {
|
||||||
|
*static_cast<DataType *>(dst) = obj;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialize for larger types with memcpy because unaligned data accesses through pointers are undefined behavior.
|
||||||
|
template<class DataType>
|
||||||
|
struct serialize<DataType, typename std::enable_if<greater_than(sizeof(DataType), 1)>::type> final {
|
||||||
|
static_assert(std::is_pod<DataType>::value, "Can only serialize PODs");
|
||||||
|
static void call(void *dst, const DataType &obj) {
|
||||||
|
std::memcpy(dst, &obj, sizeof(DataType));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class DataType, class Enable = void> struct deserialize;
|
||||||
|
|
||||||
|
// Specialize for 1-byte types for faster performance with direct pointer access (no memcpy).
|
||||||
|
template<class DataType>
|
||||||
|
struct deserialize<DataType, typename std::enable_if<sizeof(DataType) == 1>::type> final {
|
||||||
|
static_assert(std::is_pod<DataType>::value, "Can only serialize PODs");
|
||||||
|
static DataType call(const void *src) {
|
||||||
|
return *static_cast<const DataType *>(src);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialize for larger types with memcpy because unaligned data accesses through pointers are undefined behavior.
|
||||||
|
template<class DataType>
|
||||||
|
struct deserialize<DataType, typename std::enable_if<greater_than(sizeof(DataType), 1)>::type> final {
|
||||||
|
static_assert(std::is_pod<DataType>::value, "Can only deserialize PODs");
|
||||||
|
static DataType call(const void *src) {
|
||||||
|
typename std::remove_const<DataType>::type result{};
|
||||||
|
std::memcpy(&result, src, sizeof(DataType));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class DataType>
|
||||||
|
inline void serialize(void *dst, const DataType& obj) {
|
||||||
|
return details::serialize<DataType>::call(dst, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class DataType>
|
||||||
|
inline DataType deserialize(const void *src) {
|
||||||
|
return details::deserialize<DataType>::call(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class DataType>
|
||||||
|
inline DataType deserializeWithOffset(const void* src, size_t offset) {
|
||||||
|
return deserialize<DataType>(static_cast<const uint8_t*>(src) + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -7,6 +7,7 @@
|
|||||||
#include "../macros.h"
|
#include "../macros.h"
|
||||||
#include "../assert/assert.h"
|
#include "../assert/assert.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "SerializationHelper.h"
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
//TODO Test Serializer/Deserializer
|
//TODO Test Serializer/Deserializer
|
||||||
@ -83,11 +84,10 @@ namespace cpputils {
|
|||||||
|
|
||||||
template<typename DataType>
|
template<typename DataType>
|
||||||
inline void Serializer::_write(DataType obj) {
|
inline void Serializer::_write(DataType obj) {
|
||||||
static_assert(std::is_pod<DataType>::value, "Can only serialize PODs");
|
|
||||||
if (_pos + sizeof(DataType) > _result.size()) {
|
if (_pos + sizeof(DataType) > _result.size()) {
|
||||||
throw std::runtime_error("Serialization failed - size overflow");
|
throw std::runtime_error("Serialization failed - size overflow");
|
||||||
}
|
}
|
||||||
*reinterpret_cast<DataType*>(_result.dataOffset(_pos)) = obj;
|
serialize<DataType>(_result.dataOffset(_pos), obj);
|
||||||
_pos += sizeof(DataType);
|
_pos += sizeof(DataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ using std::ostringstream;
|
|||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
|
|
||||||
size_t CurlHttpClient::write_data(void *ptr, size_t size, size_t nmemb, ostringstream *stream) {
|
size_t CurlHttpClient::write_data(void *ptr, size_t size, size_t nmemb, ostringstream *stream) {
|
||||||
stream->write((const char *) ptr, size * nmemb);
|
stream->write(static_cast<const char *>(ptr), size * nmemb);
|
||||||
return size * nmemb;
|
return size * nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ namespace cpputils {
|
|||||||
inline OSRandomGenerator::OSRandomGenerator() {}
|
inline OSRandomGenerator::OSRandomGenerator() {}
|
||||||
|
|
||||||
inline void OSRandomGenerator::_get(void *target, size_t bytes) {
|
inline void OSRandomGenerator::_get(void *target, size_t bytes) {
|
||||||
CryptoPP::OS_GenerateRandomBlock(true, (CryptoPP::byte*)target, bytes);
|
CryptoPP::OS_GenerateRandomBlock(true, static_cast<CryptoPP::byte*>(target), bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ void DirBlob::statChildWithSizeAlreadySet(const BlockId &blockId, struct ::stat
|
|||||||
result->st_mtim = child.lastModificationTime();
|
result->st_mtim = child.lastModificationTime();
|
||||||
result->st_ctim = child.lastMetadataChangeTime();
|
result->st_ctim = child.lastMetadataChangeTime();
|
||||||
//TODO Move ceilDivision to general utils which can be used by cryfs as well
|
//TODO Move ceilDivision to general utils which can be used by cryfs as well
|
||||||
result->st_blocks = blobstore::onblocks::utils::ceilDivision(result->st_size, (off_t)512);
|
result->st_blocks = blobstore::onblocks::utils::ceilDivision(result->st_size, static_cast<off_t>(512));
|
||||||
result->st_blksize = _fsBlobStore->virtualBlocksizeBytes();
|
result->st_blksize = _fsBlobStore->virtualBlocksizeBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
#include <cpp-utils/data/SerializationHelper.h>
|
||||||
#include "DirEntry.h"
|
#include "DirEntry.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::string;
|
using std::string;
|
||||||
@ -6,6 +8,64 @@ using blockstore::BlockId;
|
|||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
namespace fsblobstore {
|
namespace fsblobstore {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template<typename DataType>
|
||||||
|
size_t _serialize(void* dst, const DataType& obj) {
|
||||||
|
cpputils::serialize<DataType>(dst, obj);
|
||||||
|
return sizeof(DataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DataType>
|
||||||
|
DataType _deserialize(const char** src) {
|
||||||
|
DataType result = cpputils::deserialize<DataType>(*src);
|
||||||
|
*src += sizeof(DataType);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t _serializedTimeValueSize() {
|
||||||
|
return sizeof(uint64_t) + sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int _serializeTimeValue(uint8_t *dest, timespec value) {
|
||||||
|
unsigned int offset = 0;
|
||||||
|
offset += _serialize<uint64_t>(dest + offset, value.tv_sec);
|
||||||
|
offset += _serialize<uint32_t>(dest + offset, value.tv_nsec);
|
||||||
|
ASSERT(offset == _serializedTimeValueSize(), "serialized to wrong size");
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
timespec _deserializeTimeValue(const char **pos) {
|
||||||
|
timespec value{};
|
||||||
|
value.tv_sec = _deserialize<uint64_t>(pos);
|
||||||
|
value.tv_nsec = _deserialize<uint32_t>(pos);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int _serializeString(uint8_t *dest, const string &value) {
|
||||||
|
std::memcpy(dest, value.c_str(), value.size()+1);
|
||||||
|
return value.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string _deserializeString(const char **pos) {
|
||||||
|
size_t length = strlen(*pos);
|
||||||
|
string value(*pos, length);
|
||||||
|
*pos += length + 1;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int _serializeBlockId(uint8_t *dest, const BlockId &blockId) {
|
||||||
|
blockId.ToBinary(dest);
|
||||||
|
return blockId.BINARY_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockId _deserializeBlockId(const char **pos) {
|
||||||
|
BlockId blockId = BlockId::FromBinary(*pos);
|
||||||
|
*pos += BlockId::BINARY_LENGTH;
|
||||||
|
return blockId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DirEntry::serialize(uint8_t *dest) const {
|
void DirEntry::serialize(uint8_t *dest) const {
|
||||||
ASSERT(
|
ASSERT(
|
||||||
((_type == fspp::Dir::EntryType::FILE) && S_ISREG(_mode) && !S_ISDIR(_mode) && !S_ISLNK(_mode)) ||
|
((_type == fspp::Dir::EntryType::FILE) && S_ISREG(_mode) && !S_ISDIR(_mode) && !S_ISLNK(_mode)) ||
|
||||||
@ -15,10 +75,10 @@ namespace cryfs {
|
|||||||
_mode & S_IFDIR) + ", " + std::to_string(_mode & S_IFLNK) + ", " + std::to_string(static_cast<uint8_t>(_type))
|
_mode & S_IFDIR) + ", " + std::to_string(_mode & S_IFLNK) + ", " + std::to_string(static_cast<uint8_t>(_type))
|
||||||
);
|
);
|
||||||
unsigned int offset = 0;
|
unsigned int offset = 0;
|
||||||
offset += _serializeUint8(dest + offset, static_cast<uint8_t>(_type));
|
offset += _serialize<uint8_t>(dest + offset, static_cast<uint8_t>(_type));
|
||||||
offset += _serializeUint32(dest + offset, _mode);
|
offset += _serialize<uint32_t>(dest + offset, _mode);
|
||||||
offset += _serializeUint32(dest + offset, _uid);
|
offset += _serialize<uint32_t>(dest + offset, _uid);
|
||||||
offset += _serializeUint32(dest + offset, _gid);
|
offset += _serialize<uint32_t>(dest + offset, _gid);
|
||||||
offset += _serializeTimeValue(dest + offset, _lastAccessTime);
|
offset += _serializeTimeValue(dest + offset, _lastAccessTime);
|
||||||
offset += _serializeTimeValue(dest + offset, _lastModificationTime);
|
offset += _serializeTimeValue(dest + offset, _lastModificationTime);
|
||||||
offset += _serializeTimeValue(dest + offset, _lastMetadataChangeTime);
|
offset += _serializeTimeValue(dest + offset, _lastMetadataChangeTime);
|
||||||
@ -28,10 +88,10 @@ namespace cryfs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *DirEntry::deserializeAndAddToVector(const char *pos, vector<DirEntry> *result) {
|
const char *DirEntry::deserializeAndAddToVector(const char *pos, vector<DirEntry> *result) {
|
||||||
fspp::Dir::EntryType type = static_cast<fspp::Dir::EntryType>(_deserializeUint8(&pos));
|
fspp::Dir::EntryType type = static_cast<fspp::Dir::EntryType>(_deserialize<uint8_t>(&pos));
|
||||||
mode_t mode = _deserializeUint32(&pos);
|
mode_t mode = _deserialize<uint32_t>(&pos);
|
||||||
uid_t uid = _deserializeUint32(&pos);
|
uid_t uid = _deserialize<uint32_t>(&pos);
|
||||||
gid_t gid = _deserializeUint32(&pos);
|
gid_t gid = _deserialize<uint32_t>(&pos);
|
||||||
timespec lastAccessTime = _deserializeTimeValue(&pos);
|
timespec lastAccessTime = _deserializeTimeValue(&pos);
|
||||||
timespec lastModificationTime = _deserializeTimeValue(&pos);
|
timespec lastModificationTime = _deserializeTimeValue(&pos);
|
||||||
timespec lastMetadataChangeTime = _deserializeTimeValue(&pos);
|
timespec lastMetadataChangeTime = _deserializeTimeValue(&pos);
|
||||||
@ -42,74 +102,6 @@ namespace cryfs {
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DirEntry::_serializeTimeValue(uint8_t *dest, timespec value) {
|
|
||||||
unsigned int offset = 0;
|
|
||||||
*reinterpret_cast<uint64_t*>(dest+offset) = value.tv_sec;
|
|
||||||
offset += sizeof(uint64_t);
|
|
||||||
*reinterpret_cast<uint32_t*>(dest+offset) = value.tv_nsec;
|
|
||||||
offset += sizeof(uint32_t);
|
|
||||||
ASSERT(offset == _serializedTimeValueSize(), "serialized to wrong size");
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t DirEntry::_serializedTimeValueSize() {
|
|
||||||
return sizeof(uint64_t) + sizeof(uint32_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
timespec DirEntry::_deserializeTimeValue(const char **pos) {
|
|
||||||
timespec value{};
|
|
||||||
value.tv_sec = *(uint64_t*)(*pos);
|
|
||||||
*pos += sizeof(uint64_t);
|
|
||||||
value.tv_nsec = *(uint32_t*)(*pos);
|
|
||||||
*pos += sizeof(uint32_t);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int DirEntry::_serializeUint8(uint8_t *dest, uint8_t value) {
|
|
||||||
*reinterpret_cast<uint8_t*>(dest) = value;
|
|
||||||
return sizeof(uint8_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t DirEntry::_deserializeUint8(const char **pos) {
|
|
||||||
uint8_t value = *(uint8_t*)(*pos);
|
|
||||||
*pos += sizeof(uint8_t);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int DirEntry::_serializeUint32(uint8_t *dest, uint32_t value) {
|
|
||||||
*reinterpret_cast<uint32_t*>(dest) = value;
|
|
||||||
return sizeof(uint32_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t DirEntry::_deserializeUint32(const char **pos) {
|
|
||||||
uint32_t value = *(uint32_t*)(*pos);
|
|
||||||
*pos += sizeof(uint32_t);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int DirEntry::_serializeString(uint8_t *dest, const string &value) {
|
|
||||||
std::memcpy(dest, value.c_str(), value.size()+1);
|
|
||||||
return value.size() + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string DirEntry::_deserializeString(const char **pos) {
|
|
||||||
size_t length = strlen(*pos);
|
|
||||||
string value(*pos, length);
|
|
||||||
*pos += length + 1;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int DirEntry::_serializeBlockId(uint8_t *dest, const BlockId &blockId) {
|
|
||||||
blockId.ToBinary(dest);
|
|
||||||
return blockId.BINARY_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockId DirEntry::_deserializeBlockId(const char **pos) {
|
|
||||||
BlockId blockId = BlockId::FromBinary(*pos);
|
|
||||||
*pos += BlockId::BINARY_LENGTH;
|
|
||||||
return blockId;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t DirEntry::serializedSize() const {
|
size_t DirEntry::serializedSize() const {
|
||||||
return 1 + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + 3*_serializedTimeValueSize() + (
|
return 1 + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + 3*_serializedTimeValueSize() + (
|
||||||
_name.size() + 1) + _blockId.BINARY_LENGTH;
|
_name.size() + 1) + _blockId.BINARY_LENGTH;
|
||||||
|
@ -46,17 +46,6 @@ namespace cryfs {
|
|||||||
timespec lastMetadataChangeTime() const;
|
timespec lastMetadataChangeTime() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static size_t _serializedTimeValueSize();
|
|
||||||
static unsigned int _serializeTimeValue(uint8_t *dest, timespec value);
|
|
||||||
static unsigned int _serializeUint8(uint8_t *dest, uint8_t value);
|
|
||||||
static unsigned int _serializeUint32(uint8_t *dest, uint32_t value);
|
|
||||||
static unsigned int _serializeString(uint8_t *dest, const std::string &value);
|
|
||||||
static unsigned int _serializeBlockId(uint8_t *dest, const blockstore::BlockId &value);
|
|
||||||
static timespec _deserializeTimeValue(const char **pos);
|
|
||||||
static uint8_t _deserializeUint8(const char **pos);
|
|
||||||
static uint32_t _deserializeUint32(const char **pos);
|
|
||||||
static std::string _deserializeString(const char **pos);
|
|
||||||
static blockstore::BlockId _deserializeBlockId(const char **pos);
|
|
||||||
|
|
||||||
void _updateLastMetadataChangeTime();
|
void _updateLastMetadataChangeTime();
|
||||||
|
|
||||||
|
@ -211,11 +211,11 @@ void DirEntryList::setMode(const BlockId &blockId, mode_t mode) {
|
|||||||
bool DirEntryList::setUidGid(const BlockId &blockId, uid_t uid, gid_t gid) {
|
bool DirEntryList::setUidGid(const BlockId &blockId, uid_t uid, gid_t gid) {
|
||||||
auto found = _findById(blockId);
|
auto found = _findById(blockId);
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
if (uid != (uid_t)-1) {
|
if (uid != static_cast<uid_t>(-1)) {
|
||||||
found->setUid(uid);
|
found->setUid(uid);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (gid != (gid_t)-1) {
|
if (gid != static_cast<gid_t>(-1)) {
|
||||||
found->setGid(gid);
|
found->setGid(gid);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ namespace {
|
|||||||
uint32_t _generateClientId() {
|
uint32_t _generateClientId() {
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
do {
|
do {
|
||||||
result = *reinterpret_cast<uint32_t*>(Random::PseudoRandom().getFixedSize<sizeof(uint32_t)>().data());
|
result = cpputils::deserialize<uint32_t>(Random::PseudoRandom().getFixedSize<sizeof(uint32_t)>().data());
|
||||||
} while(result == KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK); // Safety check - CLIENT_ID_FOR_DELETED_BLOCK shouldn't be used by any valid client.
|
} while(result == KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK); // Safety check - CLIENT_ID_FOR_DELETED_BLOCK shouldn't be used by any valid client.
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public:
|
|||||||
void Test_Chmod(fspp::File *file, fspp::Node *node) {
|
void Test_Chmod(fspp::File *file, fspp::Node *node) {
|
||||||
node->chmod(S_IFREG | S_IRUSR | S_IWOTH);
|
node->chmod(S_IFREG | S_IRUSR | S_IWOTH);
|
||||||
this->IN_STAT(file, node, [] (struct stat st){
|
this->IN_STAT(file, node, [] (struct stat st){
|
||||||
EXPECT_EQ((mode_t)(S_IFREG | S_IRUSR | S_IWOTH), st.st_mode);
|
EXPECT_EQ(static_cast<mode_t>(S_IFREG | S_IRUSR | S_IWOTH), st.st_mode);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ public:
|
|||||||
|
|
||||||
void EXPECT_SIZE(uint64_t expectedSize, fspp::OpenFile *openFile) {
|
void EXPECT_SIZE(uint64_t expectedSize, fspp::OpenFile *openFile) {
|
||||||
IN_STAT(openFile, [expectedSize] (struct stat st) {
|
IN_STAT(openFile, [expectedSize] (struct stat st) {
|
||||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
EXPECT_EQ(expectedSize, static_cast<uint64_t>(st.st_size));
|
||||||
});
|
});
|
||||||
|
|
||||||
EXPECT_NUMBYTES_READABLE(expectedSize, openFile);
|
EXPECT_NUMBYTES_READABLE(expectedSize, openFile);
|
||||||
@ -26,7 +26,7 @@ public:
|
|||||||
//Try to read one byte more than the expected size
|
//Try to read one byte more than the expected size
|
||||||
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
||||||
//and check that it only read the expected size (but also not less)
|
//and check that it only read the expected size (but also not less)
|
||||||
EXPECT_EQ(expectedSize, (uint64_t)readBytes);
|
EXPECT_EQ(expectedSize, static_cast<uint64_t>(readBytes));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public:
|
|||||||
|
|
||||||
void EXPECT_SIZE(uint64_t expectedSize, fspp::File *file, fspp::Node *node) {
|
void EXPECT_SIZE(uint64_t expectedSize, fspp::File *file, fspp::Node *node) {
|
||||||
IN_STAT(file, node, [expectedSize] (struct stat st) {
|
IN_STAT(file, node, [expectedSize] (struct stat st) {
|
||||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
EXPECT_EQ(expectedSize, static_cast<uint64_t>(st.st_size));
|
||||||
});
|
});
|
||||||
|
|
||||||
EXPECT_NUMBYTES_READABLE(expectedSize, file);
|
EXPECT_NUMBYTES_READABLE(expectedSize, file);
|
||||||
@ -50,7 +50,7 @@ public:
|
|||||||
//Try to read one byte more than the expected size
|
//Try to read one byte more than the expected size
|
||||||
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
||||||
//and check that it only read the expected size (but also not less)
|
//and check that it only read the expected size (but also not less)
|
||||||
EXPECT_EQ(expectedSize, (uint64_t)readBytes);
|
EXPECT_EQ(expectedSize, static_cast<uint64_t>(readBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_ATIME_EQ(struct timespec expected, struct stat st) {
|
void EXPECT_ATIME_EQ(struct timespec expected, struct stat st) {
|
||||||
|
@ -17,7 +17,7 @@ public:
|
|||||||
|
|
||||||
void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) {
|
void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) {
|
||||||
IN_STAT(node, [expectedSize] (struct stat st) {
|
IN_STAT(node, [expectedSize] (struct stat st) {
|
||||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
EXPECT_EQ(expectedSize, static_cast<uint64_t>(st.st_size));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -16,7 +16,7 @@ namespace bf = boost::filesystem;
|
|||||||
using namespace cpputils::logging;
|
using namespace cpputils::logging;
|
||||||
using namespace fspp::fuse;
|
using namespace fspp::fuse;
|
||||||
|
|
||||||
#define FUSE_OBJ ((Fuse *) fuse_get_context()->private_data)
|
#define FUSE_OBJ (static_cast<Fuse *>(fuse_get_context()->private_data))
|
||||||
|
|
||||||
// Remove the following line, if you don't want to output each fuse operation on the console
|
// Remove the following line, if you don't want to output each fuse operation on the console
|
||||||
//#define FSPP_LOG 1
|
//#define FSPP_LOG 1
|
||||||
@ -236,7 +236,7 @@ void Fuse::run(const bf::path &mountdir, const vector<string> &fuseOptions) {
|
|||||||
|
|
||||||
_argv = _build_argv(mountdir, fuseOptions);
|
_argv = _build_argv(mountdir, fuseOptions);
|
||||||
|
|
||||||
fuse_main(_argv.size(), _argv.data(), operations(), (void*)this);
|
fuse_main(_argv.size(), _argv.data(), operations(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<char *> Fuse::_build_argv(const bf::path &mountdir, const vector<string> &fuseOptions) {
|
vector<char *> Fuse::_build_argv(const bf::path &mountdir, const vector<string> &fuseOptions) {
|
||||||
|
@ -68,7 +68,7 @@ set<BlockId> _getBlockstoreUnaccountedBlocks(const CryConfig &config) {
|
|||||||
auto innerNode = dynamic_pointer_move<DataInnerNode>(*node);
|
auto innerNode = dynamic_pointer_move<DataInnerNode>(*node);
|
||||||
if (innerNode != none) {
|
if (innerNode != none) {
|
||||||
for (uint32_t childIndex = 0; childIndex < (*innerNode)->numChildren(); ++childIndex) {
|
for (uint32_t childIndex = 0; childIndex < (*innerNode)->numChildren(); ++childIndex) {
|
||||||
auto child = (*innerNode)->getChild(childIndex)->blockId();
|
auto child = (*innerNode)->readChild(childIndex).blockId();
|
||||||
unaccountedBlocks.erase(child);
|
unaccountedBlocks.erase(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ public:
|
|||||||
Data end(GetParam().blobsize - count - start);
|
Data end(GetParam().blobsize - count - start);
|
||||||
|
|
||||||
std::memcpy(begin.data(), expected.data(), start);
|
std::memcpy(begin.data(), expected.data(), start);
|
||||||
std::memcpy(end.data(), (uint8_t*)expected.data()+start+count, end.size());
|
std::memcpy(end.data(), expected.dataOffset(start+count), end.size());
|
||||||
|
|
||||||
EXPECT_DATA_READS_AS(begin, blob, 0, start);
|
EXPECT_DATA_READS_AS(begin, blob, 0, start);
|
||||||
EXPECT_DATA_READS_AS(end, blob, start + count, end.size());
|
EXPECT_DATA_READS_AS(end, blob, start + count, end.size());
|
||||||
@ -152,7 +152,7 @@ TEST_P(BlobReadWriteDataTest, WriteWholeAndReadPart) {
|
|||||||
blob->write(this->backgroundData.data(), 0, GetParam().blobsize);
|
blob->write(this->backgroundData.data(), 0, GetParam().blobsize);
|
||||||
Data read(GetParam().count);
|
Data read(GetParam().count);
|
||||||
blob->read(read.data(), GetParam().offset, GetParam().count);
|
blob->read(read.data(), GetParam().offset, GetParam().count);
|
||||||
EXPECT_EQ(0, std::memcmp(read.data(), (uint8_t*)this->backgroundData.data()+GetParam().offset, GetParam().count));
|
EXPECT_EQ(0, std::memcmp(read.data(), this->backgroundData.dataOffset(GetParam().offset), GetParam().count));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(BlobReadWriteDataTest, WritePartAndReadWhole) {
|
TEST_P(BlobReadWriteDataTest, WritePartAndReadWhole) {
|
||||||
@ -161,6 +161,6 @@ TEST_P(BlobReadWriteDataTest, WritePartAndReadWhole) {
|
|||||||
blob->write(this->foregroundData.data(), GetParam().offset, GetParam().count);
|
blob->write(this->foregroundData.data(), GetParam().offset, GetParam().count);
|
||||||
Data read = readBlob(*blob);
|
Data read = readBlob(*blob);
|
||||||
EXPECT_EQ(0, std::memcmp(read.data(), this->backgroundData.data(), GetParam().offset));
|
EXPECT_EQ(0, std::memcmp(read.data(), this->backgroundData.data(), GetParam().offset));
|
||||||
EXPECT_EQ(0, std::memcmp((uint8_t*)read.data()+GetParam().offset, this->foregroundData.data(), GetParam().count));
|
EXPECT_EQ(0, std::memcmp(read.dataOffset(GetParam().offset), this->foregroundData.data(), GetParam().count));
|
||||||
EXPECT_EQ(0, std::memcmp((uint8_t*)read.data()+GetParam().offset+GetParam().count, (uint8_t*)this->backgroundData.data()+GetParam().offset+GetParam().count, GetParam().blobsize-GetParam().count-GetParam().offset));
|
EXPECT_EQ(0, std::memcmp(read.dataOffset(GetParam().offset+GetParam().count), this->backgroundData.dataOffset(GetParam().offset+GetParam().count), GetParam().blobsize-GetParam().count-GetParam().offset));
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ TEST_F(BlobSizeDataTest, DataStaysIntactWhenGrowing) {
|
|||||||
blob->write(randomData.data(), 0, MEDIUM_SIZE);
|
blob->write(randomData.data(), 0, MEDIUM_SIZE);
|
||||||
blob->resize(LARGE_SIZE);
|
blob->resize(LARGE_SIZE);
|
||||||
EXPECT_EQ(0, std::memcmp(readBlob(*blob).data(), randomData.data(), MEDIUM_SIZE));
|
EXPECT_EQ(0, std::memcmp(readBlob(*blob).data(), randomData.data(), MEDIUM_SIZE));
|
||||||
EXPECT_EQ(0, std::memcmp((uint8_t*)readBlob(*blob).data() + MEDIUM_SIZE, ZEROES.data(), LARGE_SIZE-MEDIUM_SIZE));
|
EXPECT_EQ(0, std::memcmp(readBlob(*blob).dataOffset(MEDIUM_SIZE), ZEROES.data(), LARGE_SIZE-MEDIUM_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlobSizeDataTest, DataStaysIntactWhenShrinking) {
|
TEST_F(BlobSizeDataTest, DataStaysIntactWhenShrinking) {
|
||||||
@ -168,5 +168,5 @@ TEST_F(BlobSizeDataTest, ChangedAreaIsZeroedOutWhenShrinkingAndRegrowing) {
|
|||||||
blob->resize(MEDIUM_SIZE);
|
blob->resize(MEDIUM_SIZE);
|
||||||
blob->resize(LARGE_SIZE);
|
blob->resize(LARGE_SIZE);
|
||||||
EXPECT_EQ(0, std::memcmp(readBlob(*blob).data(), randomData.data(), MEDIUM_SIZE));
|
EXPECT_EQ(0, std::memcmp(readBlob(*blob).data(), randomData.data(), MEDIUM_SIZE));
|
||||||
EXPECT_EQ(0, std::memcmp((uint8_t*)readBlob(*blob).data() + MEDIUM_SIZE, ZEROES.data(), LARGE_SIZE-MEDIUM_SIZE));
|
EXPECT_EQ(0, std::memcmp(readBlob(*blob).dataOffset(MEDIUM_SIZE), ZEROES.data(), LARGE_SIZE-MEDIUM_SIZE));
|
||||||
}
|
}
|
||||||
|
@ -25,13 +25,13 @@ TEST_F(BlobStoreTest, BlobIsNotLoadableAfterDeletion_DeleteDirectly) {
|
|||||||
auto blob = blobStore->create();
|
auto blob = blobStore->create();
|
||||||
BlockId blockId = blob->blockId();
|
BlockId blockId = blob->blockId();
|
||||||
blobStore->remove(std::move(blob));
|
blobStore->remove(std::move(blob));
|
||||||
EXPECT_FALSE((bool)blobStore->load(blockId));
|
EXPECT_FALSE(static_cast<bool>(blobStore->load(blockId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlobStoreTest, BlobIsNotLoadableAfterDeletion_DeleteByKey) {
|
TEST_F(BlobStoreTest, BlobIsNotLoadableAfterDeletion_DeleteByKey) {
|
||||||
auto blockId = blobStore->create()->blockId();
|
auto blockId = blobStore->create()->blockId();
|
||||||
blobStore->remove(blockId);
|
blobStore->remove(blockId);
|
||||||
EXPECT_FALSE((bool)blobStore->load(blockId));
|
EXPECT_FALSE(static_cast<bool>(blobStore->load(blockId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlobStoreTest, BlobIsNotLoadableAfterDeletion_DeleteAfterLoading) {
|
TEST_F(BlobStoreTest, BlobIsNotLoadableAfterDeletion_DeleteAfterLoading) {
|
||||||
@ -39,5 +39,5 @@ TEST_F(BlobStoreTest, BlobIsNotLoadableAfterDeletion_DeleteAfterLoading) {
|
|||||||
BlockId blockId = blob->blockId();
|
BlockId blockId = blob->blockId();
|
||||||
reset(std::move(blob));
|
reset(std::move(blob));
|
||||||
blobStore->remove(loadBlob(blockId));
|
blobStore->remove(loadBlob(blockId));
|
||||||
EXPECT_FALSE((bool)blobStore->load(blockId));
|
EXPECT_FALSE(static_cast<bool>(blobStore->load(blockId)));
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ TEST_F(DataInnerNodeTest, InitializesCorrectly) {
|
|||||||
auto node = DataInnerNode::CreateNewNode(blockStore, nodeStore->layout(), 1, {leaf->blockId()});
|
auto node = DataInnerNode::CreateNewNode(blockStore, nodeStore->layout(), 1, {leaf->blockId()});
|
||||||
|
|
||||||
EXPECT_EQ(1u, node->numChildren());
|
EXPECT_EQ(1u, node->numChildren());
|
||||||
EXPECT_EQ(leaf->blockId(), node->getChild(0)->blockId());
|
EXPECT_EQ(leaf->blockId(), node->readChild(0).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, ReinitializesCorrectly) {
|
TEST_F(DataInnerNodeTest, ReinitializesCorrectly) {
|
||||||
@ -132,22 +132,22 @@ TEST_F(DataInnerNodeTest, ReinitializesCorrectly) {
|
|||||||
auto node = DataInnerNode::InitializeNewNode(blockStore->load(blockId).value(), nodeStore->layout(), 1, {leaf->blockId()});
|
auto node = DataInnerNode::InitializeNewNode(blockStore->load(blockId).value(), nodeStore->layout(), 1, {leaf->blockId()});
|
||||||
|
|
||||||
EXPECT_EQ(1u, node->numChildren());
|
EXPECT_EQ(1u, node->numChildren());
|
||||||
EXPECT_EQ(leaf->blockId(), node->getChild(0)->blockId());
|
EXPECT_EQ(leaf->blockId(), node->readChild(0).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, IsCorrectlyInitializedAfterLoading) {
|
TEST_F(DataInnerNodeTest, IsCorrectlyInitializedAfterLoading) {
|
||||||
auto loaded = CreateAndLoadNewInnerNode(*leaf);
|
auto loaded = CreateAndLoadNewInnerNode(*leaf);
|
||||||
|
|
||||||
EXPECT_EQ(1u, loaded->numChildren());
|
EXPECT_EQ(1u, loaded->numChildren());
|
||||||
EXPECT_EQ(leaf->blockId(), loaded->getChild(0)->blockId());
|
EXPECT_EQ(leaf->blockId(), loaded->readChild(0).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, AddingASecondLeaf) {
|
TEST_F(DataInnerNodeTest, AddingASecondLeaf) {
|
||||||
BlockId leaf2_blockId = AddALeafTo(node.get());
|
BlockId leaf2_blockId = AddALeafTo(node.get());
|
||||||
|
|
||||||
EXPECT_EQ(2u, node->numChildren());
|
EXPECT_EQ(2u, node->numChildren());
|
||||||
EXPECT_EQ(leaf->blockId(), node->getChild(0)->blockId());
|
EXPECT_EQ(leaf->blockId(), node->readChild(0).blockId());
|
||||||
EXPECT_EQ(leaf2_blockId, node->getChild(1)->blockId());
|
EXPECT_EQ(leaf2_blockId, node->readChild(1).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, AddingASecondLeafAndReload) {
|
TEST_F(DataInnerNodeTest, AddingASecondLeafAndReload) {
|
||||||
@ -155,8 +155,8 @@ TEST_F(DataInnerNodeTest, AddingASecondLeafAndReload) {
|
|||||||
auto loaded = CreateAndLoadNewInnerNode(1, {leaf->blockId(), leaf2->blockId()});
|
auto loaded = CreateAndLoadNewInnerNode(1, {leaf->blockId(), leaf2->blockId()});
|
||||||
|
|
||||||
EXPECT_EQ(2u, loaded->numChildren());
|
EXPECT_EQ(2u, loaded->numChildren());
|
||||||
EXPECT_EQ(leaf->blockId(), loaded->getChild(0)->blockId());
|
EXPECT_EQ(leaf->blockId(), loaded->readChild(0).blockId());
|
||||||
EXPECT_EQ(leaf2->blockId(), loaded->getChild(1)->blockId());
|
EXPECT_EQ(leaf2->blockId(), loaded->readChild(1).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, BuildingAThreeLevelTree) {
|
TEST_F(DataInnerNodeTest, BuildingAThreeLevelTree) {
|
||||||
@ -164,8 +164,8 @@ TEST_F(DataInnerNodeTest, BuildingAThreeLevelTree) {
|
|||||||
auto parent = CreateNewInnerNode(node->depth()+1, {node->blockId(), node2->blockId()});
|
auto parent = CreateNewInnerNode(node->depth()+1, {node->blockId(), node2->blockId()});
|
||||||
|
|
||||||
EXPECT_EQ(2u, parent->numChildren());
|
EXPECT_EQ(2u, parent->numChildren());
|
||||||
EXPECT_EQ(node->blockId(), parent->getChild(0)->blockId());
|
EXPECT_EQ(node->blockId(), parent->readChild(0).blockId());
|
||||||
EXPECT_EQ(node2->blockId(), parent->getChild(1)->blockId());
|
EXPECT_EQ(node2->blockId(), parent->readChild(1).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, BuildingAThreeLevelTreeAndReload) {
|
TEST_F(DataInnerNodeTest, BuildingAThreeLevelTreeAndReload) {
|
||||||
@ -173,8 +173,8 @@ TEST_F(DataInnerNodeTest, BuildingAThreeLevelTreeAndReload) {
|
|||||||
auto parent = CreateAndLoadNewInnerNode(node->depth()+1, {node->blockId(), node2->blockId()});
|
auto parent = CreateAndLoadNewInnerNode(node->depth()+1, {node->blockId(), node2->blockId()});
|
||||||
|
|
||||||
EXPECT_EQ(2u, parent->numChildren());
|
EXPECT_EQ(2u, parent->numChildren());
|
||||||
EXPECT_EQ(node->blockId(), parent->getChild(0)->blockId());
|
EXPECT_EQ(node->blockId(), parent->readChild(0).blockId());
|
||||||
EXPECT_EQ(node2->blockId(), parent->getChild(1)->blockId());
|
EXPECT_EQ(node2->blockId(), parent->readChild(1).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, ConvertToInternalNode) {
|
TEST_F(DataInnerNodeTest, ConvertToInternalNode) {
|
||||||
@ -183,7 +183,7 @@ TEST_F(DataInnerNodeTest, ConvertToInternalNode) {
|
|||||||
unique_ref<DataInnerNode> converted = DataNode::convertToNewInnerNode(std::move(node), nodeStore->layout(), *child);
|
unique_ref<DataInnerNode> converted = DataNode::convertToNewInnerNode(std::move(node), nodeStore->layout(), *child);
|
||||||
|
|
||||||
EXPECT_EQ(1u, converted->numChildren());
|
EXPECT_EQ(1u, converted->numChildren());
|
||||||
EXPECT_EQ(child->blockId(), converted->getChild(0)->blockId());
|
EXPECT_EQ(child->blockId(), converted->readChild(0).blockId());
|
||||||
EXPECT_EQ(node_blockId, converted->blockId());
|
EXPECT_EQ(node_blockId, converted->blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ TEST_F(DataInnerNodeTest, ConvertToInternalNodeZeroesOutChildrenRegion) {
|
|||||||
BlockId blockId = CreateNodeWithDataConvertItToInnerNodeAndReturnKey();
|
BlockId blockId = CreateNodeWithDataConvertItToInnerNodeAndReturnKey();
|
||||||
|
|
||||||
auto block = blockStore->load(blockId).value();
|
auto block = blockStore->load(blockId).value();
|
||||||
EXPECT_EQ(0, std::memcmp(ZEROES.data(), (uint8_t*)block->data()+DataNodeLayout::HEADERSIZE_BYTES+sizeof(DataInnerNode::ChildEntry), nodeStore->layout().maxBytesPerLeaf()-sizeof(DataInnerNode::ChildEntry)));
|
EXPECT_EQ(0, std::memcmp(ZEROES.data(), static_cast<const uint8_t*>(block->data())+DataNodeLayout::HEADERSIZE_BYTES+sizeof(DataInnerNode::ChildEntry), nodeStore->layout().maxBytesPerLeaf()-sizeof(DataInnerNode::ChildEntry)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, CopyingCreatesNewNode) {
|
TEST_F(DataInnerNodeTest, CopyingCreatesNewNode) {
|
||||||
@ -203,7 +203,7 @@ TEST_F(DataInnerNodeTest, CopyInnerNodeWithOneChild) {
|
|||||||
auto copied = CopyInnerNode(*node);
|
auto copied = CopyInnerNode(*node);
|
||||||
|
|
||||||
EXPECT_EQ(node->numChildren(), copied->numChildren());
|
EXPECT_EQ(node->numChildren(), copied->numChildren());
|
||||||
EXPECT_EQ(node->getChild(0)->blockId(), copied->getChild(0)->blockId());
|
EXPECT_EQ(node->readChild(0).blockId(), copied->readChild(0).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, CopyInnerNodeWithTwoChildren) {
|
TEST_F(DataInnerNodeTest, CopyInnerNodeWithTwoChildren) {
|
||||||
@ -211,21 +211,21 @@ TEST_F(DataInnerNodeTest, CopyInnerNodeWithTwoChildren) {
|
|||||||
auto copied = CopyInnerNode(*node);
|
auto copied = CopyInnerNode(*node);
|
||||||
|
|
||||||
EXPECT_EQ(node->numChildren(), copied->numChildren());
|
EXPECT_EQ(node->numChildren(), copied->numChildren());
|
||||||
EXPECT_EQ(node->getChild(0)->blockId(), copied->getChild(0)->blockId());
|
EXPECT_EQ(node->readChild(0).blockId(), copied->readChild(0).blockId());
|
||||||
EXPECT_EQ(node->getChild(1)->blockId(), copied->getChild(1)->blockId());
|
EXPECT_EQ(node->readChild(1).blockId(), copied->readChild(1).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, LastChildWhenOneChild) {
|
TEST_F(DataInnerNodeTest, LastChildWhenOneChild) {
|
||||||
EXPECT_EQ(leaf->blockId(), node->LastChild()->blockId());
|
EXPECT_EQ(leaf->blockId(), node->readLastChild().blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, LastChildWhenTwoChildren) {
|
TEST_F(DataInnerNodeTest, LastChildWhenTwoChildren) {
|
||||||
BlockId blockId = AddALeafTo(node.get());
|
BlockId blockId = AddALeafTo(node.get());
|
||||||
EXPECT_EQ(blockId, node->LastChild()->blockId());
|
EXPECT_EQ(blockId, node->readLastChild().blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataInnerNodeTest, LastChildWhenThreeChildren) {
|
TEST_F(DataInnerNodeTest, LastChildWhenThreeChildren) {
|
||||||
AddALeafTo(node.get());
|
AddALeafTo(node.get());
|
||||||
BlockId blockId = AddALeafTo(node.get());
|
BlockId blockId = AddALeafTo(node.get());
|
||||||
EXPECT_EQ(blockId, node->LastChild()->blockId());
|
EXPECT_EQ(blockId, node->readLastChild().blockId());
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ using cpputils::unique_ref;
|
|||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
using std::string;
|
using std::string;
|
||||||
using cpputils::DataFixture;
|
using cpputils::DataFixture;
|
||||||
|
using cpputils::deserialize;
|
||||||
|
|
||||||
//TODO Split into multiple files
|
//TODO Split into multiple files
|
||||||
|
|
||||||
@ -186,7 +187,7 @@ TEST_F(DataLeafNodeTest, SpaceGetsZeroFilledWhenShrinkingAndRegrowing) {
|
|||||||
leaf->resize(randomData.size());
|
leaf->resize(randomData.size());
|
||||||
|
|
||||||
//Check that the space was filled with zeroes
|
//Check that the space was filled with zeroes
|
||||||
EXPECT_EQ(0, std::memcmp(ZEROES.data(), ((uint8_t*)loadData(*leaf).data())+smaller_size, 100));
|
EXPECT_EQ(0, std::memcmp(ZEROES.data(), static_cast<const uint8_t*>(loadData(*leaf).data())+smaller_size, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataLeafNodeTest, DataGetsZeroFilledWhenShrinking) {
|
TEST_F(DataLeafNodeTest, DataGetsZeroFilledWhenShrinking) {
|
||||||
@ -195,14 +196,14 @@ TEST_F(DataLeafNodeTest, DataGetsZeroFilledWhenShrinking) {
|
|||||||
{
|
{
|
||||||
//At first, we expect there to be random data in the underlying data block
|
//At first, we expect there to be random data in the underlying data block
|
||||||
auto block = blockStore->load(blockId).value();
|
auto block = blockStore->load(blockId).value();
|
||||||
EXPECT_EQ(0, std::memcmp((char*)randomData.data()+smaller_size, (uint8_t*)block->data()+DataNodeLayout::HEADERSIZE_BYTES+smaller_size, 100));
|
EXPECT_EQ(0, std::memcmp(randomData.dataOffset(smaller_size), static_cast<const uint8_t*>(block->data())+DataNodeLayout::HEADERSIZE_BYTES+smaller_size, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
//After shrinking, we expect there to be zeroes in the underlying data block
|
//After shrinking, we expect there to be zeroes in the underlying data block
|
||||||
ResizeLeaf(blockId, smaller_size);
|
ResizeLeaf(blockId, smaller_size);
|
||||||
{
|
{
|
||||||
auto block = blockStore->load(blockId).value();
|
auto block = blockStore->load(blockId).value();
|
||||||
EXPECT_EQ(0, std::memcmp(ZEROES.data(), (uint8_t*)block->data()+DataNodeLayout::HEADERSIZE_BYTES+smaller_size, 100));
|
EXPECT_EQ(0, std::memcmp(ZEROES.data(), static_cast<const uint8_t*>(block->data())+DataNodeLayout::HEADERSIZE_BYTES+smaller_size, 100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +222,7 @@ TEST_F(DataLeafNodeTest, ConvertToInternalNode) {
|
|||||||
unique_ref<DataInnerNode> converted = DataNode::convertToNewInnerNode(std::move(leaf), LAYOUT, *child);
|
unique_ref<DataInnerNode> converted = DataNode::convertToNewInnerNode(std::move(leaf), LAYOUT, *child);
|
||||||
|
|
||||||
EXPECT_EQ(1u, converted->numChildren());
|
EXPECT_EQ(1u, converted->numChildren());
|
||||||
EXPECT_EQ(child->blockId(), converted->getChild(0)->blockId());
|
EXPECT_EQ(child->blockId(), converted->readChild(0).blockId());
|
||||||
EXPECT_EQ(leaf_blockId, converted->blockId());
|
EXPECT_EQ(leaf_blockId, converted->blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +230,7 @@ TEST_F(DataLeafNodeTest, ConvertToInternalNodeZeroesOutChildrenRegion) {
|
|||||||
BlockId blockId = CreateLeafWithDataConvertItToInnerNodeAndReturnKey();
|
BlockId blockId = CreateLeafWithDataConvertItToInnerNodeAndReturnKey();
|
||||||
|
|
||||||
auto block = blockStore->load(blockId).value();
|
auto block = blockStore->load(blockId).value();
|
||||||
EXPECT_EQ(0, std::memcmp(ZEROES.data(), (uint8_t*)block->data()+DataNodeLayout::HEADERSIZE_BYTES+sizeof(DataInnerNode::ChildEntry), nodeStore->layout().maxBytesPerLeaf()-sizeof(DataInnerNode::ChildEntry)));
|
EXPECT_EQ(0, std::memcmp(ZEROES.data(), static_cast<const uint8_t*>(block->data())+DataNodeLayout::HEADERSIZE_BYTES+sizeof(DataInnerNode::ChildEntry), nodeStore->layout().maxBytesPerLeaf()-sizeof(DataInnerNode::ChildEntry)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataLeafNodeTest, CopyingCreatesANewLeaf) {
|
TEST_F(DataLeafNodeTest, CopyingCreatesANewLeaf) {
|
||||||
@ -250,10 +251,10 @@ TEST_F(DataLeafNodeTest, CopyDataLeaf) {
|
|||||||
EXPECT_EQ(0, std::memcmp(loadData(*leaf).data(), loadData(*copied).data(), leaf->numBytes()));
|
EXPECT_EQ(0, std::memcmp(loadData(*leaf).data(), loadData(*copied).data(), leaf->numBytes()));
|
||||||
|
|
||||||
//Test that they have different data regions (changing the original one doesn't change the copy)
|
//Test that they have different data regions (changing the original one doesn't change the copy)
|
||||||
char data = '\0';
|
uint8_t data = 0;
|
||||||
leaf->write(&data, 0, 1);
|
leaf->write(&data, 0, 1);
|
||||||
EXPECT_EQ(data, *(char*)loadData(*leaf).data());
|
EXPECT_EQ(data, deserialize<uint8_t>(loadData(*leaf).data()));
|
||||||
EXPECT_NE(data, *(char*)loadData(*copied).data());
|
EXPECT_NE(data, deserialize<uint8_t>(loadData(*copied).data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -292,7 +293,7 @@ public:
|
|||||||
Data end(GetParam().leafsize - count - start);
|
Data end(GetParam().leafsize - count - start);
|
||||||
|
|
||||||
std::memcpy(begin.data(), expected.data(), start);
|
std::memcpy(begin.data(), expected.data(), start);
|
||||||
std::memcpy(end.data(), (uint8_t*)expected.data()+start+count, end.size());
|
std::memcpy(end.data(), expected.dataOffset(start+count), end.size());
|
||||||
|
|
||||||
EXPECT_DATA_READS_AS(begin, leaf, 0, start);
|
EXPECT_DATA_READS_AS(begin, leaf, 0, start);
|
||||||
EXPECT_DATA_READS_AS(end, leaf, start + count, end.size());
|
EXPECT_DATA_READS_AS(end, leaf, start + count, end.size());
|
||||||
|
@ -92,7 +92,7 @@ TEST_F(DataNodeStoreTest, CreatedInnerNodeIsInitialized) {
|
|||||||
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
auto leaf = nodeStore->createNewLeafNode(Data(0));
|
||||||
auto node = nodeStore->createNewInnerNode(1, {leaf->blockId()});
|
auto node = nodeStore->createNewInnerNode(1, {leaf->blockId()});
|
||||||
EXPECT_EQ(1u, node->numChildren());
|
EXPECT_EQ(1u, node->numChildren());
|
||||||
EXPECT_EQ(leaf->blockId(), node->getChild(0)->blockId());
|
EXPECT_EQ(leaf->blockId(), node->readChild(0).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataNodeStoreTest, CreatedLeafNodeIsInitialized) {
|
TEST_F(DataNodeStoreTest, CreatedLeafNodeIsInitialized) {
|
||||||
|
@ -87,64 +87,12 @@ TEST_F(DataNodeViewTest, HeaderAndBodyDontOverlap) {
|
|||||||
EXPECT_EQ(0, std::memcmp(view.data(), randomData.data(), DATASIZE_BYTES));
|
EXPECT_EQ(0, std::memcmp(view.data(), randomData.data(), DATASIZE_BYTES));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataNodeViewTest, DataBeginWorksWithOneByteEntries) {
|
TEST_F(DataNodeViewTest, Data) {
|
||||||
auto block = blockStore->create(Data(BLOCKSIZE_BYTES));
|
auto block = blockStore->create(Data(BLOCKSIZE_BYTES));
|
||||||
uint8_t *blockBegin = (uint8_t*)block->data();
|
const uint8_t *blockBegin = static_cast<const uint8_t*>(block->data());
|
||||||
DataNodeView view(std::move(block));
|
DataNodeView view(std::move(block));
|
||||||
|
|
||||||
EXPECT_EQ(blockBegin+DataNodeLayout::HEADERSIZE_BYTES, view.DataBegin<uint8_t>());
|
EXPECT_EQ(blockBegin+DataNodeLayout::HEADERSIZE_BYTES, static_cast<const uint8_t*>(view.data()));
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(DataNodeViewTest, DataBeginWorksWithEightByteEntries) {
|
|
||||||
auto block = blockStore->create(Data(BLOCKSIZE_BYTES));
|
|
||||||
uint8_t *blockBegin = (uint8_t*)block->data();
|
|
||||||
DataNodeView view(std::move(block));
|
|
||||||
|
|
||||||
EXPECT_EQ(blockBegin+DataNodeLayout::HEADERSIZE_BYTES, (uint8_t*)view.DataBegin<uint64_t>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(DataNodeViewTest, DataEndWorksWithOneByteEntries) {
|
|
||||||
auto block = blockStore->create(Data(BLOCKSIZE_BYTES));
|
|
||||||
uint8_t *blockBegin = (uint8_t*)block->data();
|
|
||||||
DataNodeView view(std::move(block));
|
|
||||||
|
|
||||||
EXPECT_EQ(blockBegin+BLOCKSIZE_BYTES, view.DataEnd<uint8_t>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(DataNodeViewTest, DataEndWorksWithEightByteEntries) {
|
|
||||||
auto block = blockStore->create(Data(BLOCKSIZE_BYTES));
|
|
||||||
uint8_t *blockBegin = (uint8_t*)block->data();
|
|
||||||
DataNodeView view(std::move(block));
|
|
||||||
|
|
||||||
EXPECT_EQ(blockBegin+BLOCKSIZE_BYTES, (uint8_t*)view.DataEnd<uint64_t>());
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SizedDataEntry {
|
|
||||||
uint8_t data[6];
|
|
||||||
};
|
|
||||||
BOOST_STATIC_ASSERT_MSG(DataNodeViewTest::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(Data(BLOCKSIZE_BYTES));
|
|
||||||
uint8_t *blockBegin = (uint8_t*)block->data();
|
|
||||||
DataNodeView view(std::move(block));
|
|
||||||
|
|
||||||
EXPECT_EQ(blockBegin+DataNodeLayout::HEADERSIZE_BYTES, (uint8_t*)view.DataBegin<SizedDataEntry>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(DataNodeViewTest, DataEndWorksWithStructByteEntries) {
|
|
||||||
auto block = blockStore->create(Data(BLOCKSIZE_BYTES));
|
|
||||||
uint8_t *blockBegin = (uint8_t*)block->data();
|
|
||||||
DataNodeView view(std::move(block));
|
|
||||||
|
|
||||||
unsigned int numFittingEntries = DATASIZE_BYTES / sizeof(SizedDataEntry);
|
|
||||||
|
|
||||||
uint8_t *dataEnd = (uint8_t*)view.DataEnd<SizedDataEntry>();
|
|
||||||
EXPECT_EQ(blockBegin+DataNodeLayout::HEADERSIZE_BYTES + numFittingEntries * sizeof(SizedDataEntry), dataEnd);
|
|
||||||
EXPECT_LT(dataEnd, blockBegin + BLOCKSIZE_BYTES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO Test that header fields (and data) are also stored over reloads
|
//TODO Test that header fields (and data) are also stored over reloads
|
||||||
|
@ -19,7 +19,7 @@ TEST_F(DataTreeTest_NumStoredBytes, CreatedTreeIsEmpty) {
|
|||||||
class DataTreeTest_NumStoredBytes_P: public DataTreeTest_NumStoredBytes, public WithParamInterface<uint32_t> {};
|
class DataTreeTest_NumStoredBytes_P: public DataTreeTest_NumStoredBytes, public WithParamInterface<uint32_t> {};
|
||||||
INSTANTIATE_TEST_CASE_P(EmptyLastLeaf, DataTreeTest_NumStoredBytes_P, Values(0u));
|
INSTANTIATE_TEST_CASE_P(EmptyLastLeaf, DataTreeTest_NumStoredBytes_P, Values(0u));
|
||||||
INSTANTIATE_TEST_CASE_P(HalfFullLastLeaf, DataTreeTest_NumStoredBytes_P, Values(5u, 10u));
|
INSTANTIATE_TEST_CASE_P(HalfFullLastLeaf, DataTreeTest_NumStoredBytes_P, Values(5u, 10u));
|
||||||
INSTANTIATE_TEST_CASE_P(FullLastLeaf, DataTreeTest_NumStoredBytes_P, Values((uint32_t)DataNodeLayout(DataTreeTest_NumStoredBytes::BLOCKSIZE_BYTES).maxBytesPerLeaf()));
|
INSTANTIATE_TEST_CASE_P(FullLastLeaf, DataTreeTest_NumStoredBytes_P, Values(static_cast<uint32_t>(DataNodeLayout(DataTreeTest_NumStoredBytes::BLOCKSIZE_BYTES).maxBytesPerLeaf())));
|
||||||
|
|
||||||
TEST_P(DataTreeTest_NumStoredBytes_P, SingleLeaf) {
|
TEST_P(DataTreeTest_NumStoredBytes_P, SingleLeaf) {
|
||||||
BlockId blockId = CreateLeafWithSize(GetParam())->blockId();
|
BlockId blockId = CreateLeafWithSize(GetParam())->blockId();
|
||||||
|
@ -70,9 +70,9 @@ public:
|
|||||||
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
||||||
if (inner != nullptr) {
|
if (inner != nullptr) {
|
||||||
for (uint32_t i = 0; i < inner->numChildren()-1; ++i) {
|
for (uint32_t i = 0; i < inner->numChildren()-1; ++i) {
|
||||||
EXPECT_IS_MAXDATA_TREE(inner->getChild(i)->blockId());
|
EXPECT_IS_MAXDATA_TREE(inner->readChild(i).blockId());
|
||||||
}
|
}
|
||||||
EXPECT_IS_LEFTMAXDATA_TREE(inner->LastChild()->blockId());
|
EXPECT_IS_LEFTMAXDATA_TREE(inner->readLastChild().blockId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ public:
|
|||||||
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
||||||
if (inner != nullptr) {
|
if (inner != nullptr) {
|
||||||
for (uint32_t i = 0; i < inner->numChildren(); ++i) {
|
for (uint32_t i = 0; i < inner->numChildren(); ++i) {
|
||||||
EXPECT_IS_MAXDATA_TREE(inner->getChild(i)->blockId());
|
EXPECT_IS_MAXDATA_TREE(inner->readChild(i).blockId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DataLeafNode *leaf = dynamic_cast<DataLeafNode*>(root.get());
|
DataLeafNode *leaf = dynamic_cast<DataLeafNode*>(root.get());
|
||||||
@ -122,7 +122,7 @@ public:
|
|||||||
return std::move(*leaf);
|
return std::move(*leaf);
|
||||||
}
|
}
|
||||||
auto inner = dynamic_pointer_move<DataInnerNode>(root).value();
|
auto inner = dynamic_pointer_move<DataInnerNode>(root).value();
|
||||||
return LastLeaf(inner->LastChild()->blockId());
|
return LastLeaf(inner->readLastChild().blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t oldLastLeafSize;
|
uint32_t oldLastLeafSize;
|
||||||
@ -208,7 +208,7 @@ TEST_P(DataTreeTest_ResizeByTraversing_P, KeyDoesntChange) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(DataTreeTest_ResizeByTraversing_P, DataStaysIntact) {
|
TEST_P(DataTreeTest_ResizeByTraversing_P, DataStaysIntact) {
|
||||||
uint32_t oldNumberOfLeaves = std::max(UINT64_C(1), ceilDivision(tree->numStoredBytes(), (uint64_t)nodeStore->layout().maxBytesPerLeaf()));
|
uint32_t oldNumberOfLeaves = std::max(UINT64_C(1), ceilDivision(tree->numStoredBytes(), static_cast<uint64_t>(nodeStore->layout().maxBytesPerLeaf())));
|
||||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Unchanged);
|
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Unchanged);
|
||||||
BlockId blockId = tree->blockId();
|
BlockId blockId = tree->blockId();
|
||||||
cpputils::destruct(std::move(tree));
|
cpputils::destruct(std::move(tree));
|
||||||
|
@ -69,9 +69,9 @@ public:
|
|||||||
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
||||||
if (inner != nullptr) {
|
if (inner != nullptr) {
|
||||||
for (uint32_t i = 0; i < inner->numChildren()-1; ++i) {
|
for (uint32_t i = 0; i < inner->numChildren()-1; ++i) {
|
||||||
EXPECT_IS_MAXDATA_TREE(inner->getChild(i)->blockId());
|
EXPECT_IS_MAXDATA_TREE(inner->readChild(i).blockId());
|
||||||
}
|
}
|
||||||
EXPECT_IS_LEFTMAXDATA_TREE(inner->LastChild()->blockId());
|
EXPECT_IS_LEFTMAXDATA_TREE(inner->readLastChild().blockId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ public:
|
|||||||
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
|
||||||
if (inner != nullptr) {
|
if (inner != nullptr) {
|
||||||
for (uint32_t i = 0; i < inner->numChildren(); ++i) {
|
for (uint32_t i = 0; i < inner->numChildren(); ++i) {
|
||||||
EXPECT_IS_MAXDATA_TREE(inner->getChild(i)->blockId());
|
EXPECT_IS_MAXDATA_TREE(inner->readChild(i).blockId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DataLeafNode *leaf = dynamic_cast<DataLeafNode*>(root.get());
|
DataLeafNode *leaf = dynamic_cast<DataLeafNode*>(root.get());
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
return std::move(*leaf);
|
return std::move(*leaf);
|
||||||
}
|
}
|
||||||
auto inner = dynamic_pointer_move<DataInnerNode>(root).value();
|
auto inner = dynamic_pointer_move<DataInnerNode>(root).value();
|
||||||
return LastLeaf(inner->LastChild()->blockId());
|
return LastLeaf(inner->readLastChild().blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t oldLastLeafSize;
|
uint32_t oldLastLeafSize;
|
||||||
@ -208,7 +208,7 @@ TEST_P(DataTreeTest_ResizeNumBytes_P, KeyDoesntChange) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(DataTreeTest_ResizeNumBytes_P, DataStaysIntact) {
|
TEST_P(DataTreeTest_ResizeNumBytes_P, DataStaysIntact) {
|
||||||
uint32_t oldNumberOfLeaves = std::max(UINT64_C(1), ceilDivision(tree->numStoredBytes(), (uint64_t)nodeStore->layout().maxBytesPerLeaf()));
|
uint32_t oldNumberOfLeaves = std::max(UINT64_C(1), ceilDivision(tree->numStoredBytes(), static_cast<uint64_t>(nodeStore->layout().maxBytesPerLeaf())));
|
||||||
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Unchanged);
|
TwoLevelDataFixture data(nodeStore, TwoLevelDataFixture::SizePolicy::Unchanged);
|
||||||
BlockId blockId = tree->blockId();
|
BlockId blockId = tree->blockId();
|
||||||
cpputils::destruct(std::move(tree));
|
cpputils::destruct(std::move(tree));
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
|
|
||||||
void EXPECT_TRAVERSE_ALL_CHILDREN_OF(const DataInnerNode &node, bool isRightBorderNode, uint32_t firstLeafIndex) {
|
void EXPECT_TRAVERSE_ALL_CHILDREN_OF(const DataInnerNode &node, bool isRightBorderNode, uint32_t firstLeafIndex) {
|
||||||
for (unsigned int i = 0; i < node.numChildren(); ++i) {
|
for (unsigned int i = 0; i < node.numChildren(); ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(node.getChild(i)->blockId(), isRightBorderNode && i == node.numChildren()-1, firstLeafIndex+i);
|
EXPECT_TRAVERSE_LEAF(node.readChild(i).blockId(), isRightBorderNode && i == node.numChildren()-1, firstLeafIndex+i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,21 +106,21 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseNothingInSingleLeafTree2) {
|
|||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstLeafOfFullTwolevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstLeafOfFullTwolevelTree) {
|
||||||
auto root = CreateFullTwoLevel();
|
auto root = CreateFullTwoLevel();
|
||||||
EXPECT_TRAVERSE_LEAF(root->getChild(0)->blockId(), false, 0);
|
EXPECT_TRAVERSE_LEAF(root->readChild(0).blockId(), false, 0);
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, 1);
|
TraverseLeaves(root.get(), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddleLeafOfFullTwolevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddleLeafOfFullTwolevelTree) {
|
||||||
auto root = CreateFullTwoLevel();
|
auto root = CreateFullTwoLevel();
|
||||||
EXPECT_TRAVERSE_LEAF(root->getChild(5)->blockId(), false, 5);
|
EXPECT_TRAVERSE_LEAF(root->readChild(5).blockId(), false, 5);
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 5, 6);
|
TraverseLeaves(root.get(), 5, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastLeafOfFullTwolevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastLeafOfFullTwolevelTree) {
|
||||||
auto root = CreateFullTwoLevel();
|
auto root = CreateFullTwoLevel();
|
||||||
EXPECT_TRAVERSE_LEAF(root->getChild(nodeStore->layout().maxChildrenPerInnerNode()-1)->blockId(), true, nodeStore->layout().maxChildrenPerInnerNode()-1);
|
EXPECT_TRAVERSE_LEAF(root->readChild(nodeStore->layout().maxChildrenPerInnerNode()-1).blockId(), true, nodeStore->layout().maxChildrenPerInnerNode()-1);
|
||||||
|
|
||||||
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode()-1, nodeStore->layout().maxChildrenPerInnerNode());
|
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode()-1, nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
@ -141,21 +141,21 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseNothingInFullTwolevelTree2) {
|
|||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstLeafOfThreeLevelMinDataTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstLeafOfThreeLevelMinDataTree) {
|
||||||
auto root = CreateThreeLevelMinData();
|
auto root = CreateThreeLevelMinData();
|
||||||
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->getChild(0)->blockId())->getChild(0)->blockId(), false, 0);
|
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->readChild(0).blockId())->readChild(0).blockId(), false, 0);
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, 1);
|
TraverseLeaves(root.get(), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddleLeafOfThreeLevelMinDataTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddleLeafOfThreeLevelMinDataTree) {
|
||||||
auto root = CreateThreeLevelMinData();
|
auto root = CreateThreeLevelMinData();
|
||||||
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->getChild(0)->blockId())->getChild(5)->blockId(), false, 5);
|
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->readChild(0).blockId())->readChild(5).blockId(), false, 5);
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 5, 6);
|
TraverseLeaves(root.get(), 5, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastLeafOfThreeLevelMinDataTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastLeafOfThreeLevelMinDataTree) {
|
||||||
auto root = CreateThreeLevelMinData();
|
auto root = CreateThreeLevelMinData();
|
||||||
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->getChild(1)->blockId())->getChild(0)->blockId(), true, nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->readChild(1).blockId())->readChild(0).blockId(), true, nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
|
|
||||||
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode(), nodeStore->layout().maxChildrenPerInnerNode()+1);
|
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode(), nodeStore->layout().maxChildrenPerInnerNode()+1);
|
||||||
}
|
}
|
||||||
@ -169,15 +169,15 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseAllLeavesOfFullTwolevelTree) {
|
|||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseAllLeavesOfThreelevelMinDataTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseAllLeavesOfThreelevelMinDataTree) {
|
||||||
auto root = CreateThreeLevelMinData();
|
auto root = CreateThreeLevelMinData();
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->getChild(0)->blockId()), false, 0);
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->readChild(0).blockId()), false, 0);
|
||||||
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->getChild(1)->blockId())->getChild(0)->blockId(), true, nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->readChild(1).blockId())->readChild(0).blockId(), true, nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, nodeStore->layout().maxChildrenPerInnerNode()+1);
|
TraverseLeaves(root.get(), 0, nodeStore->layout().maxChildrenPerInnerNode()+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstChildOfThreelevelMinDataTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstChildOfThreelevelMinDataTree) {
|
||||||
auto root = CreateThreeLevelMinData();
|
auto root = CreateThreeLevelMinData();
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->getChild(0)->blockId()), false, 0);
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->readChild(0).blockId()), false, 0);
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, nodeStore->layout().maxChildrenPerInnerNode());
|
TraverseLeaves(root.get(), 0, nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstChildOfThreelevelMinDataTree) {
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstPartOfFullTwolevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstPartOfFullTwolevelTree) {
|
||||||
auto root = CreateFullTwoLevel();
|
auto root = CreateFullTwoLevel();
|
||||||
for (unsigned int i = 0; i < 5; ++i) {
|
for (unsigned int i = 0; i < 5; ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(root->getChild(i)->blockId(), false, i);
|
EXPECT_TRAVERSE_LEAF(root->readChild(i).blockId(), false, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, 5);
|
TraverseLeaves(root.get(), 0, 5);
|
||||||
@ -194,7 +194,7 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstPartOfFullTwolevelTree) {
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseInnerPartOfFullTwolevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseInnerPartOfFullTwolevelTree) {
|
||||||
auto root = CreateFullTwoLevel();
|
auto root = CreateFullTwoLevel();
|
||||||
for (unsigned int i = 5; i < 10; ++i) {
|
for (unsigned int i = 5; i < 10; ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(root->getChild(i)->blockId(), false, i);
|
EXPECT_TRAVERSE_LEAF(root->readChild(i).blockId(), false, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 5, 10);
|
TraverseLeaves(root.get(), 5, 10);
|
||||||
@ -203,7 +203,7 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseInnerPartOfFullTwolevelTree) {
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastPartOfFullTwolevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastPartOfFullTwolevelTree) {
|
||||||
auto root = CreateFullTwoLevel();
|
auto root = CreateFullTwoLevel();
|
||||||
for (unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
for (unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(root->getChild(i)->blockId(), i==nodeStore->layout().maxChildrenPerInnerNode()-1, i);
|
EXPECT_TRAVERSE_LEAF(root->readChild(i).blockId(), i==nodeStore->layout().maxChildrenPerInnerNode()-1, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 5, nodeStore->layout().maxChildrenPerInnerNode());
|
TraverseLeaves(root.get(), 5, nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
@ -211,9 +211,9 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseLastPartOfFullTwolevelTree) {
|
|||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstPartOfThreelevelMinDataTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstPartOfThreelevelMinDataTree) {
|
||||||
auto root = CreateThreeLevelMinData();
|
auto root = CreateThreeLevelMinData();
|
||||||
auto node = LoadInnerNode(root->getChild(0)->blockId());
|
auto node = LoadInnerNode(root->readChild(0).blockId());
|
||||||
for (unsigned int i = 0; i < 5; ++i) {
|
for (unsigned int i = 0; i < 5; ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(node->getChild(i)->blockId(), false, i);
|
EXPECT_TRAVERSE_LEAF(node->readChild(i).blockId(), false, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, 5);
|
TraverseLeaves(root.get(), 0, 5);
|
||||||
@ -221,9 +221,9 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstPartOfThreelevelMinDataTree) {
|
|||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseInnerPartOfThreelevelMinDataTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseInnerPartOfThreelevelMinDataTree) {
|
||||||
auto root = CreateThreeLevelMinData();
|
auto root = CreateThreeLevelMinData();
|
||||||
auto node = LoadInnerNode(root->getChild(0)->blockId());
|
auto node = LoadInnerNode(root->readChild(0).blockId());
|
||||||
for (unsigned int i = 5; i < 10; ++i) {
|
for (unsigned int i = 5; i < 10; ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(node->getChild(i)->blockId(), false, i);
|
EXPECT_TRAVERSE_LEAF(node->readChild(i).blockId(), false, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 5, 10);
|
TraverseLeaves(root.get(), 5, 10);
|
||||||
@ -231,18 +231,18 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseInnerPartOfThreelevelMinDataTree) {
|
|||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastPartOfThreelevelMinDataTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastPartOfThreelevelMinDataTree) {
|
||||||
auto root = CreateThreeLevelMinData();
|
auto root = CreateThreeLevelMinData();
|
||||||
auto node = LoadInnerNode(root->getChild(0)->blockId());
|
auto node = LoadInnerNode(root->readChild(0).blockId());
|
||||||
for (unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
for (unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(node->getChild(i)->blockId(), false, i);
|
EXPECT_TRAVERSE_LEAF(node->readChild(i).blockId(), false, i);
|
||||||
}
|
}
|
||||||
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->getChild(1)->blockId())->getChild(0)->blockId(), true, nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->readChild(1).blockId())->readChild(0).blockId(), true, nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 5, nodeStore->layout().maxChildrenPerInnerNode()+1);
|
TraverseLeaves(root.get(), 5, nodeStore->layout().maxChildrenPerInnerNode()+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstLeafOfThreelevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstLeafOfThreelevelTree) {
|
||||||
auto root = CreateThreeLevel();
|
auto root = CreateThreeLevel();
|
||||||
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->getChild(0)->blockId())->getChild(0)->blockId(), false, 0);
|
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->readChild(0).blockId())->readChild(0).blockId(), false, 0);
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, 1);
|
TraverseLeaves(root.get(), 0, 1);
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstLeafOfThreelevelTree) {
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastLeafOfThreelevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastLeafOfThreelevelTree) {
|
||||||
auto root = CreateThreeLevel();
|
auto root = CreateThreeLevel();
|
||||||
uint32_t numLeaves = nodeStore->layout().maxChildrenPerInnerNode() * 5 + 3;
|
uint32_t numLeaves = nodeStore->layout().maxChildrenPerInnerNode() * 5 + 3;
|
||||||
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->LastChild()->blockId())->LastChild()->blockId(), true, numLeaves-1);
|
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->readLastChild().blockId())->readLastChild().blockId(), true, numLeaves-1);
|
||||||
|
|
||||||
TraverseLeaves(root.get(), numLeaves-1, numLeaves);
|
TraverseLeaves(root.get(), numLeaves-1, numLeaves);
|
||||||
}
|
}
|
||||||
@ -258,7 +258,7 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseLastLeafOfThreelevelTree) {
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddleLeafOfThreelevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddleLeafOfThreelevelTree) {
|
||||||
auto root = CreateThreeLevel();
|
auto root = CreateThreeLevel();
|
||||||
uint32_t wantedLeafIndex = nodeStore->layout().maxChildrenPerInnerNode() * 2 + 5;
|
uint32_t wantedLeafIndex = nodeStore->layout().maxChildrenPerInnerNode() * 2 + 5;
|
||||||
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->getChild(2)->blockId())->getChild(5)->blockId(), false, wantedLeafIndex);
|
EXPECT_TRAVERSE_LEAF(LoadInnerNode(root->readChild(2).blockId())->readChild(5).blockId(), false, wantedLeafIndex);
|
||||||
|
|
||||||
TraverseLeaves(root.get(), wantedLeafIndex, wantedLeafIndex+1);
|
TraverseLeaves(root.get(), wantedLeafIndex, wantedLeafIndex+1);
|
||||||
}
|
}
|
||||||
@ -267,12 +267,12 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstPartOfThreelevelTree) {
|
|||||||
auto root = CreateThreeLevel();
|
auto root = CreateThreeLevel();
|
||||||
//Traverse all leaves in the first two children of the root
|
//Traverse all leaves in the first two children of the root
|
||||||
for(unsigned int i = 0; i < 2; ++i) {
|
for(unsigned int i = 0; i < 2; ++i) {
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->getChild(i)->blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->readChild(i).blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
//Traverse some of the leaves in the third child of the root
|
//Traverse some of the leaves in the third child of the root
|
||||||
auto child = LoadInnerNode(root->getChild(2)->blockId());
|
auto child = LoadInnerNode(root->readChild(2).blockId());
|
||||||
for(unsigned int i = 0; i < 5; ++i) {
|
for(unsigned int i = 0; i < 5; ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(child->getChild(i)->blockId(), false, 2 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
EXPECT_TRAVERSE_LEAF(child->readChild(i).blockId(), false, 2 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, 2 * nodeStore->layout().maxChildrenPerInnerNode() + 5);
|
TraverseLeaves(root.get(), 0, 2 * nodeStore->layout().maxChildrenPerInnerNode() + 5);
|
||||||
@ -281,18 +281,18 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseFirstPartOfThreelevelTree) {
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddlePartOfThreelevelTree_OnlyFullChildren) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddlePartOfThreelevelTree_OnlyFullChildren) {
|
||||||
auto root = CreateThreeLevel();
|
auto root = CreateThreeLevel();
|
||||||
//Traverse some of the leaves in the second child of the root
|
//Traverse some of the leaves in the second child of the root
|
||||||
auto child = LoadInnerNode(root->getChild(1)->blockId());
|
auto child = LoadInnerNode(root->readChild(1).blockId());
|
||||||
for(unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
for(unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(child->getChild(i)->blockId(), false, nodeStore->layout().maxChildrenPerInnerNode() + i);
|
EXPECT_TRAVERSE_LEAF(child->readChild(i).blockId(), false, nodeStore->layout().maxChildrenPerInnerNode() + i);
|
||||||
}
|
}
|
||||||
//Traverse all leaves in the third and fourth child of the root
|
//Traverse all leaves in the third and fourth child of the root
|
||||||
for(unsigned int i = 2; i < 4; ++i) {
|
for(unsigned int i = 2; i < 4; ++i) {
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->getChild(i)->blockId()),false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->readChild(i).blockId()),false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
//Traverse some of the leaves in the fifth child of the root
|
//Traverse some of the leaves in the fifth child of the root
|
||||||
child = LoadInnerNode(root->getChild(4)->blockId());
|
child = LoadInnerNode(root->readChild(4).blockId());
|
||||||
for(unsigned int i = 0; i < 5; ++i) {
|
for(unsigned int i = 0; i < 5; ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(child->getChild(i)->blockId(), false, 4 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
EXPECT_TRAVERSE_LEAF(child->readChild(i).blockId(), false, 4 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode() + 5, 4 * nodeStore->layout().maxChildrenPerInnerNode() + 5);
|
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode() + 5, 4 * nodeStore->layout().maxChildrenPerInnerNode() + 5);
|
||||||
@ -301,18 +301,18 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddlePartOfThreelevelTree_OnlyFullC
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddlePartOfThreelevelTree_AlsoLastNonfullChild) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddlePartOfThreelevelTree_AlsoLastNonfullChild) {
|
||||||
auto root = CreateThreeLevel();
|
auto root = CreateThreeLevel();
|
||||||
//Traverse some of the leaves in the second child of the root
|
//Traverse some of the leaves in the second child of the root
|
||||||
auto child = LoadInnerNode(root->getChild(1)->blockId());
|
auto child = LoadInnerNode(root->readChild(1).blockId());
|
||||||
for(unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
for(unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(child->getChild(i)->blockId(), false, nodeStore->layout().maxChildrenPerInnerNode() + i);
|
EXPECT_TRAVERSE_LEAF(child->readChild(i).blockId(), false, nodeStore->layout().maxChildrenPerInnerNode() + i);
|
||||||
}
|
}
|
||||||
//Traverse all leaves in the third, fourth and fifth child of the root
|
//Traverse all leaves in the third, fourth and fifth child of the root
|
||||||
for(unsigned int i = 2; i < 5; ++i) {
|
for(unsigned int i = 2; i < 5; ++i) {
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->getChild(i)->blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->readChild(i).blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
//Traverse some of the leaves in the sixth child of the root
|
//Traverse some of the leaves in the sixth child of the root
|
||||||
child = LoadInnerNode(root->getChild(5)->blockId());
|
child = LoadInnerNode(root->readChild(5).blockId());
|
||||||
for(unsigned int i = 0; i < 2; ++i) {
|
for(unsigned int i = 0; i < 2; ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(child->getChild(i)->blockId(), false, 5 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
EXPECT_TRAVERSE_LEAF(child->readChild(i).blockId(), false, 5 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode() + 5, 5 * nodeStore->layout().maxChildrenPerInnerNode() + 2);
|
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode() + 5, 5 * nodeStore->layout().maxChildrenPerInnerNode() + 2);
|
||||||
@ -321,18 +321,18 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddlePartOfThreelevelTree_AlsoLastN
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastPartOfThreelevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseLastPartOfThreelevelTree) {
|
||||||
auto root = CreateThreeLevel();
|
auto root = CreateThreeLevel();
|
||||||
//Traverse some of the leaves in the second child of the root
|
//Traverse some of the leaves in the second child of the root
|
||||||
auto child = LoadInnerNode(root->getChild(1)->blockId());
|
auto child = LoadInnerNode(root->readChild(1).blockId());
|
||||||
for(unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
for(unsigned int i = 5; i < nodeStore->layout().maxChildrenPerInnerNode(); ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(child->getChild(i)->blockId(), false, nodeStore->layout().maxChildrenPerInnerNode() + i);
|
EXPECT_TRAVERSE_LEAF(child->readChild(i).blockId(), false, nodeStore->layout().maxChildrenPerInnerNode() + i);
|
||||||
}
|
}
|
||||||
//Traverse all leaves in the third, fourth and fifth child of the root
|
//Traverse all leaves in the third, fourth and fifth child of the root
|
||||||
for(unsigned int i = 2; i < 5; ++i) {
|
for(unsigned int i = 2; i < 5; ++i) {
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->getChild(i)->blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->readChild(i).blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
//Traverse all of the leaves in the sixth child of the root
|
//Traverse all of the leaves in the sixth child of the root
|
||||||
child = LoadInnerNode(root->getChild(5)->blockId());
|
child = LoadInnerNode(root->readChild(5).blockId());
|
||||||
for(unsigned int i = 0; i < child->numChildren(); ++i) {
|
for(unsigned int i = 0; i < child->numChildren(); ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(child->getChild(i)->blockId(), i == child->numChildren()-1, 5 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
EXPECT_TRAVERSE_LEAF(child->readChild(i).blockId(), i == child->numChildren()-1, 5 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode() + 5, 5 * nodeStore->layout().maxChildrenPerInnerNode() + child->numChildren());
|
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode() + 5, 5 * nodeStore->layout().maxChildrenPerInnerNode() + child->numChildren());
|
||||||
@ -342,12 +342,12 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseAllLeavesOfThreelevelTree) {
|
|||||||
auto root = CreateThreeLevel();
|
auto root = CreateThreeLevel();
|
||||||
//Traverse all leaves in the third, fourth and fifth child of the root
|
//Traverse all leaves in the third, fourth and fifth child of the root
|
||||||
for(unsigned int i = 0; i < 5; ++i) {
|
for(unsigned int i = 0; i < 5; ++i) {
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->getChild(i)->blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(root->readChild(i).blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
//Traverse all of the leaves in the sixth child of the root
|
//Traverse all of the leaves in the sixth child of the root
|
||||||
auto child = LoadInnerNode(root->getChild(5)->blockId());
|
auto child = LoadInnerNode(root->readChild(5).blockId());
|
||||||
for(unsigned int i = 0; i < child->numChildren(); ++i) {
|
for(unsigned int i = 0; i < child->numChildren(); ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(child->getChild(i)->blockId(), i==child->numChildren()-1, 5 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
EXPECT_TRAVERSE_LEAF(child->readChild(i).blockId(), i==child->numChildren()-1, 5 * nodeStore->layout().maxChildrenPerInnerNode() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, 5 * nodeStore->layout().maxChildrenPerInnerNode() + child->numChildren());
|
TraverseLeaves(root.get(), 0, 5 * nodeStore->layout().maxChildrenPerInnerNode() + child->numChildren());
|
||||||
@ -356,19 +356,19 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseAllLeavesOfThreelevelTree) {
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseAllLeavesOfFourLevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseAllLeavesOfFourLevelTree) {
|
||||||
auto root = CreateFourLevel();
|
auto root = CreateFourLevel();
|
||||||
//Traverse all leaves of the full threelevel tree in the first child
|
//Traverse all leaves of the full threelevel tree in the first child
|
||||||
auto firstChild = LoadInnerNode(root->getChild(0)->blockId());
|
auto firstChild = LoadInnerNode(root->readChild(0).blockId());
|
||||||
for(unsigned int i = 0; i < firstChild->numChildren(); ++i) {
|
for(unsigned int i = 0; i < firstChild->numChildren(); ++i) {
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(firstChild->getChild(i)->blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(firstChild->readChild(i).blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
//Traverse all leaves of the full threelevel tree in the second child
|
//Traverse all leaves of the full threelevel tree in the second child
|
||||||
auto secondChild = LoadInnerNode(root->getChild(1)->blockId());
|
auto secondChild = LoadInnerNode(root->readChild(1).blockId());
|
||||||
for(unsigned int i = 0; i < secondChild->numChildren(); ++i) {
|
for(unsigned int i = 0; i < secondChild->numChildren(); ++i) {
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(secondChild->getChild(i)->blockId()), false, (nodeStore->layout().maxChildrenPerInnerNode() + i) * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(secondChild->readChild(i).blockId()), false, (nodeStore->layout().maxChildrenPerInnerNode() + i) * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
//Traverse all leaves of the non-full threelevel tree in the third child
|
//Traverse all leaves of the non-full threelevel tree in the third child
|
||||||
auto thirdChild = LoadInnerNode(root->getChild(2)->blockId());
|
auto thirdChild = LoadInnerNode(root->readChild(2).blockId());
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(thirdChild->getChild(0)->blockId()), false, 2 * nodeStore->layout().maxChildrenPerInnerNode() * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(thirdChild->readChild(0).blockId()), false, 2 * nodeStore->layout().maxChildrenPerInnerNode() * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
EXPECT_TRAVERSE_LEAF(LoadInnerNode(thirdChild->getChild(1)->blockId())->getChild(0)->blockId(), true, 2 * nodeStore->layout().maxChildrenPerInnerNode() * nodeStore->layout().maxChildrenPerInnerNode() + nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_LEAF(LoadInnerNode(thirdChild->readChild(1).blockId())->readChild(0).blockId(), true, 2 * nodeStore->layout().maxChildrenPerInnerNode() * nodeStore->layout().maxChildrenPerInnerNode() + nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
|
|
||||||
TraverseLeaves(root.get(), 0, 2*nodeStore->layout().maxChildrenPerInnerNode()*nodeStore->layout().maxChildrenPerInnerNode() + nodeStore->layout().maxChildrenPerInnerNode() + 1);
|
TraverseLeaves(root.get(), 0, 2*nodeStore->layout().maxChildrenPerInnerNode()*nodeStore->layout().maxChildrenPerInnerNode() + nodeStore->layout().maxChildrenPerInnerNode() + 1);
|
||||||
}
|
}
|
||||||
@ -376,24 +376,24 @@ TEST_F(DataTreeTest_TraverseLeaves, TraverseAllLeavesOfFourLevelTree) {
|
|||||||
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddlePartOfFourLevelTree) {
|
TEST_F(DataTreeTest_TraverseLeaves, TraverseMiddlePartOfFourLevelTree) {
|
||||||
auto root = CreateFourLevel();
|
auto root = CreateFourLevel();
|
||||||
//Traverse some leaves of the full threelevel tree in the first child
|
//Traverse some leaves of the full threelevel tree in the first child
|
||||||
auto firstChild = LoadInnerNode(root->getChild(0)->blockId());
|
auto firstChild = LoadInnerNode(root->readChild(0).blockId());
|
||||||
auto secondChildOfFirstChild = LoadInnerNode(firstChild->getChild(1)->blockId());
|
auto secondChildOfFirstChild = LoadInnerNode(firstChild->readChild(1).blockId());
|
||||||
for(unsigned int i = 5; i < secondChildOfFirstChild->numChildren(); ++i) {
|
for(unsigned int i = 5; i < secondChildOfFirstChild->numChildren(); ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(secondChildOfFirstChild->getChild(i)->blockId(), false, nodeStore->layout().maxChildrenPerInnerNode()+i);
|
EXPECT_TRAVERSE_LEAF(secondChildOfFirstChild->readChild(i).blockId(), false, nodeStore->layout().maxChildrenPerInnerNode()+i);
|
||||||
}
|
}
|
||||||
for(unsigned int i = 2; i < firstChild->numChildren(); ++i) {
|
for(unsigned int i = 2; i < firstChild->numChildren(); ++i) {
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(firstChild->getChild(i)->blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(firstChild->readChild(i).blockId()), false, i * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
//Traverse all leaves of the full threelevel tree in the second child
|
//Traverse all leaves of the full threelevel tree in the second child
|
||||||
auto secondChild = LoadInnerNode(root->getChild(1)->blockId());
|
auto secondChild = LoadInnerNode(root->readChild(1).blockId());
|
||||||
for(unsigned int i = 0; i < secondChild->numChildren(); ++i) {
|
for(unsigned int i = 0; i < secondChild->numChildren(); ++i) {
|
||||||
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(secondChild->getChild(i)->blockId()), false, (nodeStore->layout().maxChildrenPerInnerNode() + i) * nodeStore->layout().maxChildrenPerInnerNode());
|
EXPECT_TRAVERSE_ALL_CHILDREN_OF(*LoadInnerNode(secondChild->readChild(i).blockId()), false, (nodeStore->layout().maxChildrenPerInnerNode() + i) * nodeStore->layout().maxChildrenPerInnerNode());
|
||||||
}
|
}
|
||||||
//Traverse some leaves of the non-full threelevel tree in the third child
|
//Traverse some leaves of the non-full threelevel tree in the third child
|
||||||
auto thirdChild = LoadInnerNode(root->getChild(2)->blockId());
|
auto thirdChild = LoadInnerNode(root->readChild(2).blockId());
|
||||||
auto firstChildOfThirdChild = LoadInnerNode(thirdChild->getChild(0)->blockId());
|
auto firstChildOfThirdChild = LoadInnerNode(thirdChild->readChild(0).blockId());
|
||||||
for(unsigned int i = 0; i < firstChildOfThirdChild->numChildren()-1; ++i) {
|
for(unsigned int i = 0; i < firstChildOfThirdChild->numChildren()-1; ++i) {
|
||||||
EXPECT_TRAVERSE_LEAF(firstChildOfThirdChild->getChild(i)->blockId(), false, 2 * nodeStore->layout().maxChildrenPerInnerNode()*nodeStore->layout().maxChildrenPerInnerNode()+i);
|
EXPECT_TRAVERSE_LEAF(firstChildOfThirdChild->readChild(i).blockId(), false, 2 * nodeStore->layout().maxChildrenPerInnerNode()*nodeStore->layout().maxChildrenPerInnerNode()+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode()+5, 2*nodeStore->layout().maxChildrenPerInnerNode()*nodeStore->layout().maxChildrenPerInnerNode() + nodeStore->layout().maxChildrenPerInnerNode() -1);
|
TraverseLeaves(root.get(), nodeStore->layout().maxChildrenPerInnerNode()+5, 2*nodeStore->layout().maxChildrenPerInnerNode()*nodeStore->layout().maxChildrenPerInnerNode() + nodeStore->layout().maxChildrenPerInnerNode() -1);
|
||||||
|
@ -66,7 +66,7 @@ public:
|
|||||||
|
|
||||||
TestData CreateFullThreeLevelTree() {
|
TestData CreateFullThreeLevelTree() {
|
||||||
auto root = CreateFullThreeLevel();
|
auto root = CreateFullThreeLevel();
|
||||||
return TestData{root->blockId(), root->LastChild()->blockId()};
|
return TestData{root->blockId(), root->readLastChild().blockId()};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,9 +137,9 @@ unique_ref<DataInnerNode> DataTreeTest::CreateTwoLeafWithSecondLeafSize(uint32_t
|
|||||||
unique_ref<DataInnerNode> DataTreeTest::CreateFullTwoLevelWithLastLeafSize(uint32_t size) {
|
unique_ref<DataInnerNode> DataTreeTest::CreateFullTwoLevelWithLastLeafSize(uint32_t size) {
|
||||||
auto root = CreateFullTwoLevel();
|
auto root = CreateFullTwoLevel();
|
||||||
for (uint32_t i = 0; i < root->numChildren()-1; ++i) {
|
for (uint32_t i = 0; i < root->numChildren()-1; ++i) {
|
||||||
LoadLeafNode(root->getChild(i)->blockId())->resize(nodeStore->layout().maxBytesPerLeaf());
|
LoadLeafNode(root->readChild(i).blockId())->resize(nodeStore->layout().maxBytesPerLeaf());
|
||||||
}
|
}
|
||||||
LoadLeafNode(root->LastChild()->blockId())->resize(size);
|
LoadLeafNode(root->readLastChild().blockId())->resize(size);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,12 +176,12 @@ unique_ref<DataInnerNode> DataTreeTest::CreateThreeLevelWithThreeChildrenAndLast
|
|||||||
unique_ref<DataInnerNode> DataTreeTest::CreateFullThreeLevelWithLastLeafSize(uint32_t size) {
|
unique_ref<DataInnerNode> DataTreeTest::CreateFullThreeLevelWithLastLeafSize(uint32_t size) {
|
||||||
auto root = CreateFullThreeLevel();
|
auto root = CreateFullThreeLevel();
|
||||||
for (uint32_t i = 0; i < root->numChildren(); ++i) {
|
for (uint32_t i = 0; i < root->numChildren(); ++i) {
|
||||||
auto node = LoadInnerNode(root->getChild(i)->blockId());
|
auto node = LoadInnerNode(root->readChild(i).blockId());
|
||||||
for (uint32_t j = 0; j < node->numChildren(); ++j) {
|
for (uint32_t j = 0; j < node->numChildren(); ++j) {
|
||||||
LoadLeafNode(node->getChild(j)->blockId())->resize(nodeStore->layout().maxBytesPerLeaf());
|
LoadLeafNode(node->readChild(j).blockId())->resize(nodeStore->layout().maxBytesPerLeaf());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LoadLeafNode(LoadInnerNode(root->LastChild()->blockId())->LastChild()->blockId())->resize(size);
|
LoadLeafNode(LoadInnerNode(root->readLastChild().blockId())->readLastChild().blockId())->resize(size);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,14 +205,14 @@ void DataTreeTest::EXPECT_IS_INNER_NODE(const BlockId &blockId) {
|
|||||||
void DataTreeTest::EXPECT_IS_TWONODE_CHAIN(const BlockId &blockId) {
|
void DataTreeTest::EXPECT_IS_TWONODE_CHAIN(const BlockId &blockId) {
|
||||||
auto node = LoadInnerNode(blockId);
|
auto node = LoadInnerNode(blockId);
|
||||||
EXPECT_EQ(1u, node->numChildren());
|
EXPECT_EQ(1u, node->numChildren());
|
||||||
EXPECT_IS_LEAF_NODE(node->getChild(0)->blockId());
|
EXPECT_IS_LEAF_NODE(node->readChild(0).blockId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataTreeTest::EXPECT_IS_FULL_TWOLEVEL_TREE(const BlockId &blockId) {
|
void DataTreeTest::EXPECT_IS_FULL_TWOLEVEL_TREE(const BlockId &blockId) {
|
||||||
auto node = LoadInnerNode(blockId);
|
auto node = LoadInnerNode(blockId);
|
||||||
EXPECT_EQ(nodeStore->layout().maxChildrenPerInnerNode(), node->numChildren());
|
EXPECT_EQ(nodeStore->layout().maxChildrenPerInnerNode(), node->numChildren());
|
||||||
for (unsigned int i = 0; i < node->numChildren(); ++i) {
|
for (unsigned int i = 0; i < node->numChildren(); ++i) {
|
||||||
EXPECT_IS_LEAF_NODE(node->getChild(i)->blockId());
|
EXPECT_IS_LEAF_NODE(node->readChild(i).blockId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,10 +220,10 @@ void DataTreeTest::EXPECT_IS_FULL_THREELEVEL_TREE(const BlockId &blockId) {
|
|||||||
auto root = LoadInnerNode(blockId);
|
auto root = LoadInnerNode(blockId);
|
||||||
EXPECT_EQ(nodeStore->layout().maxChildrenPerInnerNode(), root->numChildren());
|
EXPECT_EQ(nodeStore->layout().maxChildrenPerInnerNode(), root->numChildren());
|
||||||
for (unsigned int i = 0; i < root->numChildren(); ++i) {
|
for (unsigned int i = 0; i < root->numChildren(); ++i) {
|
||||||
auto node = LoadInnerNode(root->getChild(i)->blockId());
|
auto node = LoadInnerNode(root->readChild(i).blockId());
|
||||||
EXPECT_EQ(nodeStore->layout().maxChildrenPerInnerNode(), node->numChildren());
|
EXPECT_EQ(nodeStore->layout().maxChildrenPerInnerNode(), node->numChildren());
|
||||||
for (unsigned int j = 0; j < node->numChildren(); ++j) {
|
for (unsigned int j = 0; j < node->numChildren(); ++j) {
|
||||||
EXPECT_IS_LEAF_NODE(node->getChild(j)->blockId());
|
EXPECT_IS_LEAF_NODE(node->readChild(j).blockId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ void DataTreeTest::CHECK_DEPTH(int depth, const BlockId &blockId) {
|
|||||||
auto node = LoadInnerNode(blockId);
|
auto node = LoadInnerNode(blockId);
|
||||||
EXPECT_EQ(depth, node->depth());
|
EXPECT_EQ(depth, node->depth());
|
||||||
for (uint32_t i = 0; i < node->numChildren(); ++i) {
|
for (uint32_t i = 0; i < node->numChildren(); ++i) {
|
||||||
CHECK_DEPTH(depth-1, node->getChild(i)->blockId());
|
CHECK_DEPTH(depth-1, node->readChild(i).blockId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ public:
|
|||||||
EXPECT_EQ(_data.size(), leaf.numBytes());
|
EXPECT_EQ(_data.size(), leaf.numBytes());
|
||||||
EXPECT_EQ(0, std::memcmp(_data.data(), loadData(leaf).data(), _data.size()));
|
EXPECT_EQ(0, std::memcmp(_data.data(), loadData(leaf).data(), _data.size()));
|
||||||
} else {
|
} else {
|
||||||
EXPECT_LE(onlyCheckNumBytes, (int)leaf.numBytes());
|
EXPECT_LE(onlyCheckNumBytes, static_cast<int>(leaf.numBytes()));
|
||||||
EXPECT_EQ(0, std::memcmp(_data.data(), loadData(leaf).data(), onlyCheckNumBytes));
|
EXPECT_EQ(0, std::memcmp(_data.data(), loadData(leaf).data(), onlyCheckNumBytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ private:
|
|||||||
auto inner = dynamic_cast<blobstore::onblocks::datanodestore::DataInnerNode*>(node);
|
auto inner = dynamic_cast<blobstore::onblocks::datanodestore::DataInnerNode*>(node);
|
||||||
int leafIndex = firstLeafIndex;
|
int leafIndex = firstLeafIndex;
|
||||||
for (uint32_t i = 0; i < inner->numChildren(); ++i) {
|
for (uint32_t i = 0; i < inner->numChildren(); ++i) {
|
||||||
auto child = _dataNodeStore->load(inner->getChild(i)->blockId()).value();
|
auto child = _dataNodeStore->load(inner->readChild(i).blockId()).value();
|
||||||
leafIndex = ForEachLeaf(child.get(), leafIndex, endLeafIndex, action);
|
leafIndex = ForEachLeaf(child.get(), leafIndex, endLeafIndex, action);
|
||||||
}
|
}
|
||||||
return leafIndex;
|
return leafIndex;
|
||||||
|
@ -16,7 +16,7 @@ public:
|
|||||||
|
|
||||||
cpputils::unique_ref<blobstore::Blob> loadBlob(const blockstore::BlockId &blockId) {
|
cpputils::unique_ref<blobstore::Blob> loadBlob(const blockstore::BlockId &blockId) {
|
||||||
auto loaded = blobStore->load(blockId);
|
auto loaded = blobStore->load(blockId);
|
||||||
EXPECT_TRUE((bool)loaded);
|
EXPECT_TRUE(static_cast<bool>(loaded));
|
||||||
return std::move(*loaded);
|
return std::move(*loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,5 +84,5 @@ TEST_F(CeilDivisionTest, DivideLargeByItself) {
|
|||||||
TEST_F(CeilDivisionTest, 64bit) {
|
TEST_F(CeilDivisionTest, 64bit) {
|
||||||
uint64_t base = UINT64_C(1024)*1024*1024*1024;
|
uint64_t base = UINT64_C(1024)*1024*1024*1024;
|
||||||
EXPECT_GT(base, std::numeric_limits<uint32_t>::max());
|
EXPECT_GT(base, std::numeric_limits<uint32_t>::max());
|
||||||
EXPECT_EQ(base/1024, ceilDivision(base, (uint64_t)1024));
|
EXPECT_EQ(base/1024, ceilDivision(base, UINT64_C(1024)));
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ TEST_F(CeilLogTest, Log3_4) {
|
|||||||
TEST_F(CeilLogTest, 64bit) {
|
TEST_F(CeilLogTest, 64bit) {
|
||||||
uint64_t value = UINT64_C(1024)*1024*1024*1024;
|
uint64_t value = UINT64_C(1024)*1024*1024*1024;
|
||||||
EXPECT_GT(value, std::numeric_limits<uint32_t>::max());
|
EXPECT_GT(value, std::numeric_limits<uint32_t>::max());
|
||||||
EXPECT_EQ(4u, ceilLog((uint64_t)1024, value));
|
EXPECT_EQ(4u, ceilLog(UINT64_C(1024), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,5 +73,5 @@ TEST_F(IntPowTest, ArbitraryNumbers3) {
|
|||||||
TEST_F(IntPowTest, 64bit) {
|
TEST_F(IntPowTest, 64bit) {
|
||||||
uint64_t value = UINT64_C(1024)*1024*1024*1024;
|
uint64_t value = UINT64_C(1024)*1024*1024*1024;
|
||||||
EXPECT_GT(value, std::numeric_limits<uint32_t>::max());
|
EXPECT_GT(value, std::numeric_limits<uint32_t>::max());
|
||||||
EXPECT_EQ(value*value*value, intPow(value, (uint64_t)3));
|
EXPECT_EQ(value*value*value, intPow(value, UINT64_C(3)));
|
||||||
}
|
}
|
@ -47,7 +47,7 @@ TEST_F(CacheTest_PushAndPop, FullCache) {
|
|||||||
push(i, 2*i);
|
push(i, 2*i);
|
||||||
}
|
}
|
||||||
for(unsigned int i = 0; i < MAX_ENTRIES; ++i) {
|
for(unsigned int i = 0; i < MAX_ENTRIES; ++i) {
|
||||||
EXPECT_EQ((signed int)(2*i), pop(i).value());
|
EXPECT_EQ(static_cast<signed int>(2*i), pop(i).value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ TEST_F(CacheTest_PushAndPop, FullCache_PushNonOrdered_PopOrdered) {
|
|||||||
push(i, 2*i);
|
push(i, 2*i);
|
||||||
}
|
}
|
||||||
for(unsigned int i = 0; i < MAX_ENTRIES; ++i) {
|
for(unsigned int i = 0; i < MAX_ENTRIES; ++i) {
|
||||||
EXPECT_EQ((signed int)(2*i), pop(i).value());
|
EXPECT_EQ(static_cast<signed int>(2*i), pop(i).value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,10 +68,10 @@ TEST_F(CacheTest_PushAndPop, FullCache_PushOrdered_PopNonOrdered) {
|
|||||||
push(i, 2*i);
|
push(i, 2*i);
|
||||||
}
|
}
|
||||||
for(unsigned int i = 1; i < MAX_ENTRIES; i += 2) {
|
for(unsigned int i = 1; i < MAX_ENTRIES; i += 2) {
|
||||||
EXPECT_EQ((signed int)(2*i), pop(i).value());
|
EXPECT_EQ(static_cast<signed int>(2*i), pop(i).value());
|
||||||
}
|
}
|
||||||
for(unsigned int i = 0; i < MAX_ENTRIES; i += 2) {
|
for(unsigned int i = 0; i < MAX_ENTRIES; i += 2) {
|
||||||
EXPECT_EQ((signed int)(2*i), pop(i).value());
|
EXPECT_EQ(static_cast<signed int>(2*i), pop(i).value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,10 +99,10 @@ TEST_F(CacheTest_PushAndPop, FullCache_PushNonOrdered_PopNonOrdered) {
|
|||||||
push(i, 2*i);
|
push(i, 2*i);
|
||||||
}
|
}
|
||||||
for(int i = roundDownToOdd(MAX_ENTRIES-1); i >= 0; i -= 2) {
|
for(int i = roundDownToOdd(MAX_ENTRIES-1); i >= 0; i -= 2) {
|
||||||
EXPECT_EQ((signed int)(2*i), pop(i).value());
|
EXPECT_EQ(static_cast<signed int>(2*i), pop(i).value());
|
||||||
}
|
}
|
||||||
for(unsigned int i = 0; i < MAX_ENTRIES; i += 2) {
|
for(unsigned int i = 0; i < MAX_ENTRIES; i += 2) {
|
||||||
EXPECT_EQ((signed int)(2*i), pop(i).value());
|
EXPECT_EQ(static_cast<signed int>(2*i), pop(i).value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ TEST_F(CacheTest_PushAndPop, MoreThanFullCache) {
|
|||||||
EXPECT_EQ(boost::none, pop(1));
|
EXPECT_EQ(boost::none, pop(1));
|
||||||
//Check the other elements are still there
|
//Check the other elements are still there
|
||||||
for(unsigned int i = 2; i < MAX_ENTRIES + 2; ++i) {
|
for(unsigned int i = 2; i < MAX_ENTRIES + 2; ++i) {
|
||||||
EXPECT_EQ((signed int)(2*i), pop(i).value());
|
EXPECT_EQ(static_cast<signed int>(2*i), pop(i).value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public:
|
|||||||
|
|
||||||
void ModifyBaseBlock(const blockstore::BlockId &blockId) {
|
void ModifyBaseBlock(const blockstore::BlockId &blockId) {
|
||||||
auto block = baseBlockStore->load(blockId).value();
|
auto block = baseBlockStore->load(blockId).value();
|
||||||
byte* middle_byte = ((CryptoPP::byte*)block.data()) + 10;
|
byte* middle_byte = static_cast<CryptoPP::byte*>(block.data()) + 10;
|
||||||
*middle_byte = *middle_byte + 1;
|
*middle_byte = *middle_byte + 1;
|
||||||
baseBlockStore->store(blockId, block);
|
baseBlockStore->store(blockId, block);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ using cpputils::Data;
|
|||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
using cpputils::TempFile;
|
using cpputils::TempFile;
|
||||||
|
using cpputils::serialize;
|
||||||
|
using cpputils::deserialize;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
@ -66,7 +68,7 @@ public:
|
|||||||
|
|
||||||
void modifyBlock(const blockstore::BlockId &blockId) {
|
void modifyBlock(const blockstore::BlockId &blockId) {
|
||||||
auto block = blockStore->load(blockId).value();
|
auto block = blockStore->load(blockId).value();
|
||||||
byte* first_byte = (byte*)block.data();
|
byte* first_byte = static_cast<byte*>(block.data());
|
||||||
*first_byte = *first_byte + 1;
|
*first_byte = *first_byte + 1;
|
||||||
blockStore->store(blockId, block);
|
blockStore->store(blockId, block);
|
||||||
}
|
}
|
||||||
@ -77,23 +79,26 @@ public:
|
|||||||
|
|
||||||
void decreaseVersionNumber(const blockstore::BlockId &blockId) {
|
void decreaseVersionNumber(const blockstore::BlockId &blockId) {
|
||||||
auto baseBlock = baseBlockStore->load(blockId).value();
|
auto baseBlock = baseBlockStore->load(blockId).value();
|
||||||
uint64_t* version = (uint64_t*)((uint8_t*)baseBlock.data()+IntegrityBlockStore2::VERSION_HEADER_OFFSET);
|
void* versionPtr = static_cast<uint8_t*>(baseBlock.data()) + IntegrityBlockStore2::VERSION_HEADER_OFFSET;
|
||||||
ASSERT(*version > 1, "Can't decrease the lowest allowed version number");
|
uint64_t version = deserialize<uint64_t>(versionPtr);
|
||||||
*version -= 1;
|
ASSERT(version > 1, "Can't decrease the lowest allowed version number");
|
||||||
|
serialize<uint64_t>(versionPtr, version-1);
|
||||||
baseBlockStore->store(blockId, baseBlock);
|
baseBlockStore->store(blockId, baseBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void increaseVersionNumber(const blockstore::BlockId &blockId) {
|
void increaseVersionNumber(const blockstore::BlockId &blockId) {
|
||||||
auto baseBlock = baseBlockStore->load(blockId).value();
|
auto baseBlock = baseBlockStore->load(blockId).value();
|
||||||
uint64_t* version = (uint64_t*)((uint8_t*)baseBlock.data()+IntegrityBlockStore2::VERSION_HEADER_OFFSET);
|
void* versionPtr = static_cast<uint8_t*>(baseBlock.data()) + IntegrityBlockStore2::VERSION_HEADER_OFFSET;
|
||||||
*version += 1;
|
uint64_t version = deserialize<uint64_t>(versionPtr);
|
||||||
|
serialize<uint64_t>(versionPtr, version+1);
|
||||||
baseBlockStore->store(blockId, baseBlock);
|
baseBlockStore->store(blockId, baseBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeClientId(const blockstore::BlockId &blockId) {
|
void changeClientId(const blockstore::BlockId &blockId) {
|
||||||
auto baseBlock = baseBlockStore->load(blockId).value();
|
auto baseBlock = baseBlockStore->load(blockId).value();
|
||||||
uint32_t* clientId = (uint32_t*)((uint8_t*)baseBlock.data()+IntegrityBlockStore2::CLIENTID_HEADER_OFFSET);
|
void* clientIdPtr = static_cast<uint8_t*>(baseBlock.data()) + IntegrityBlockStore2::CLIENTID_HEADER_OFFSET;
|
||||||
*clientId += 1;
|
uint64_t clientId = deserialize<uint64_t>(clientIdPtr);
|
||||||
|
serialize<uint64_t>(clientIdPtr, clientId+1);
|
||||||
baseBlockStore->store(blockId, baseBlock);
|
baseBlockStore->store(blockId, baseBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ private:
|
|||||||
|
|
||||||
void EXPECT_DATA_READS_AS(const cpputils::Data &expected, const blockstore::Block &block, off_t offset, size_t count) {
|
void EXPECT_DATA_READS_AS(const cpputils::Data &expected, const blockstore::Block &block, off_t offset, size_t count) {
|
||||||
cpputils::Data read(count);
|
cpputils::Data read(count);
|
||||||
std::memcpy(read.data(), (uint8_t*)block.data() + offset, count);
|
std::memcpy(read.data(), static_cast<const uint8_t*>(block.data()) + offset, count);
|
||||||
EXPECT_EQ(expected, read);
|
EXPECT_EQ(expected, read);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ private:
|
|||||||
cpputils::Data end(testData.blocksize - count - start);
|
cpputils::Data end(testData.blocksize - count - start);
|
||||||
|
|
||||||
std::memcpy(begin.data(), expected.data(), start);
|
std::memcpy(begin.data(), expected.data(), start);
|
||||||
std::memcpy(end.data(), (uint8_t*)expected.data()+start+count, end.size());
|
std::memcpy(end.data(), expected.dataOffset(start+count), end.size());
|
||||||
|
|
||||||
EXPECT_DATA_READS_AS(begin, block, 0, start);
|
EXPECT_DATA_READS_AS(begin, block, 0, start);
|
||||||
EXPECT_DATA_READS_AS(end, block, start + count, end.size());
|
EXPECT_DATA_READS_AS(end, block, start + count, end.size());
|
||||||
|
@ -34,6 +34,7 @@ set(SOURCES
|
|||||||
data/DataFixtureTest.cpp
|
data/DataFixtureTest.cpp
|
||||||
data/DataTest.cpp
|
data/DataTest.cpp
|
||||||
data/FixedSizeDataIncludeTest.cpp
|
data/FixedSizeDataIncludeTest.cpp
|
||||||
|
data/SerializationHelperTest.cpp
|
||||||
data/DataIncludeTest.cpp
|
data/DataIncludeTest.cpp
|
||||||
logging/LoggingLevelTest.cpp
|
logging/LoggingLevelTest.cpp
|
||||||
logging/LoggerTest.cpp
|
logging/LoggerTest.cpp
|
||||||
|
@ -40,16 +40,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExpectDoesntDecrypt(const Data &ciphertext) {
|
void ExpectDoesntDecrypt(const Data &ciphertext) {
|
||||||
auto decrypted = Cipher::decrypt((CryptoPP::byte*)ciphertext.data(), ciphertext.size(), this->encKey);
|
auto decrypted = Cipher::decrypt(static_cast<const CryptoPP::byte*>(ciphertext.data()), ciphertext.size(), this->encKey);
|
||||||
EXPECT_FALSE(decrypted);
|
EXPECT_FALSE(decrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
Data Encrypt(const Data &plaintext) {
|
Data Encrypt(const Data &plaintext) {
|
||||||
return Cipher::encrypt((CryptoPP::byte*)plaintext.data(), plaintext.size(), this->encKey);
|
return Cipher::encrypt(static_cast<const CryptoPP::byte*>(plaintext.data()), plaintext.size(), this->encKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
Data Decrypt(const Data &ciphertext) {
|
Data Decrypt(const Data &ciphertext) {
|
||||||
return Cipher::decrypt((CryptoPP::byte*)ciphertext.data(), ciphertext.size(), this->encKey).value();
|
return Cipher::decrypt(static_cast<const CryptoPP::byte*>(ciphertext.data()), ciphertext.size(), this->encKey).value();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Data CreateZeroes(unsigned int size) {
|
static Data CreateZeroes(unsigned int size) {
|
||||||
@ -149,49 +149,57 @@ TYPED_TEST_CASE_P(AuthenticatedCipherTest);
|
|||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, ModifyFirstByte_Zeroes_Size1) {
|
TYPED_TEST_P(AuthenticatedCipherTest, ModifyFirstByte_Zeroes_Size1) {
|
||||||
Data ciphertext = this->Encrypt(this->zeroes1);
|
Data ciphertext = this->Encrypt(this->zeroes1);
|
||||||
*(CryptoPP::byte*)ciphertext.data() = *(CryptoPP::byte*)ciphertext.data() + 1;
|
void* firstByte = ciphertext.data();
|
||||||
|
serialize<CryptoPP::byte>(firstByte, deserialize<CryptoPP::byte>(firstByte) + 1);
|
||||||
this->ExpectDoesntDecrypt(ciphertext);
|
this->ExpectDoesntDecrypt(ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, ModifyFirstByte_Data_Size1) {
|
TYPED_TEST_P(AuthenticatedCipherTest, ModifyFirstByte_Data_Size1) {
|
||||||
Data ciphertext = this->Encrypt(this->plaintext1);
|
Data ciphertext = this->Encrypt(this->plaintext1);
|
||||||
*(CryptoPP::byte*)ciphertext.data() = *(CryptoPP::byte*)ciphertext.data() + 1;
|
void* firstByte = ciphertext.data();
|
||||||
|
serialize<CryptoPP::byte>(firstByte, deserialize<CryptoPP::byte>(firstByte) + 1);
|
||||||
this->ExpectDoesntDecrypt(ciphertext);
|
this->ExpectDoesntDecrypt(ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, ModifyFirstByte_Zeroes) {
|
TYPED_TEST_P(AuthenticatedCipherTest, ModifyFirstByte_Zeroes) {
|
||||||
Data ciphertext = this->Encrypt(this->zeroes2);
|
Data ciphertext = this->Encrypt(this->zeroes2);
|
||||||
*(CryptoPP::byte*)ciphertext.data() = *(CryptoPP::byte*)ciphertext.data() + 1;
|
void* firstByte = ciphertext.data();
|
||||||
|
serialize<CryptoPP::byte>(firstByte, deserialize<CryptoPP::byte>(firstByte) + 1);
|
||||||
this->ExpectDoesntDecrypt(ciphertext);
|
this->ExpectDoesntDecrypt(ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, ModifyFirstByte_Data) {
|
TYPED_TEST_P(AuthenticatedCipherTest, ModifyFirstByte_Data) {
|
||||||
Data ciphertext = this->Encrypt(this->plaintext2);
|
Data ciphertext = this->Encrypt(this->plaintext2);
|
||||||
*(CryptoPP::byte*)ciphertext.data() = *(CryptoPP::byte*)ciphertext.data() + 1;
|
void* firstByte = ciphertext.data();
|
||||||
|
serialize<CryptoPP::byte>(firstByte, deserialize<CryptoPP::byte>(firstByte) + 1);
|
||||||
this->ExpectDoesntDecrypt(ciphertext);
|
this->ExpectDoesntDecrypt(ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, ModifyLastByte_Zeroes) {
|
TYPED_TEST_P(AuthenticatedCipherTest, ModifyLastByte_Zeroes) {
|
||||||
Data ciphertext = this->Encrypt(this->zeroes2);
|
Data ciphertext = this->Encrypt(this->zeroes2);
|
||||||
((CryptoPP::byte*)ciphertext.data())[ciphertext.size() - 1] = ((CryptoPP::byte*)ciphertext.data())[ciphertext.size() - 1] + 1;
|
void* lastByte = ciphertext.dataOffset(ciphertext.size() - 1);
|
||||||
|
serialize<CryptoPP::byte>(lastByte, deserialize<CryptoPP::byte>(lastByte) + 1);
|
||||||
this->ExpectDoesntDecrypt(ciphertext);
|
this->ExpectDoesntDecrypt(ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, ModifyLastByte_Data) {
|
TYPED_TEST_P(AuthenticatedCipherTest, ModifyLastByte_Data) {
|
||||||
Data ciphertext = this->Encrypt(this->plaintext2);
|
Data ciphertext = this->Encrypt(this->plaintext2);
|
||||||
((CryptoPP::byte*)ciphertext.data())[ciphertext.size() - 1] = ((CryptoPP::byte*)ciphertext.data())[ciphertext.size() - 1] + 1;
|
void* lastByte = ciphertext.dataOffset(ciphertext.size() - 1);
|
||||||
|
serialize<CryptoPP::byte>(lastByte, deserialize<CryptoPP::byte>(lastByte) + 1);
|
||||||
this->ExpectDoesntDecrypt(ciphertext);
|
this->ExpectDoesntDecrypt(ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, ModifyMiddleByte_Zeroes) {
|
TYPED_TEST_P(AuthenticatedCipherTest, ModifyMiddleByte_Zeroes) {
|
||||||
Data ciphertext = this->Encrypt(this->zeroes2);
|
Data ciphertext = this->Encrypt(this->zeroes2);
|
||||||
((CryptoPP::byte*)ciphertext.data())[ciphertext.size()/2] = ((CryptoPP::byte*)ciphertext.data())[ciphertext.size()/2] + 1;
|
void* middleByte = ciphertext.dataOffset(ciphertext.size()/2);
|
||||||
|
serialize<CryptoPP::byte>(middleByte, deserialize<CryptoPP::byte>(middleByte) + 1);
|
||||||
this->ExpectDoesntDecrypt(ciphertext);
|
this->ExpectDoesntDecrypt(ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, ModifyMiddleByte_Data) {
|
TYPED_TEST_P(AuthenticatedCipherTest, ModifyMiddleByte_Data) {
|
||||||
Data ciphertext = this->Encrypt(this->plaintext2);
|
Data ciphertext = this->Encrypt(this->plaintext2);
|
||||||
((CryptoPP::byte*)ciphertext.data())[ciphertext.size()/2] = ((CryptoPP::byte*)ciphertext.data())[ciphertext.size()/2] + 1;
|
void* middleByte = ciphertext.dataOffset(ciphertext.size()/2);
|
||||||
|
serialize<CryptoPP::byte>(middleByte, deserialize<CryptoPP::byte>(middleByte) + 1);
|
||||||
this->ExpectDoesntDecrypt(ciphertext);
|
this->ExpectDoesntDecrypt(ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "cpp-utils/data/DataFixture.h"
|
#include "cpp-utils/data/DataFixture.h"
|
||||||
#include "cpp-utils/data/Data.h"
|
#include "cpp-utils/data/Data.h"
|
||||||
|
#include "cpp-utils/data/SerializationHelper.h"
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "cpp-utils/tempfile/TempFile.h"
|
#include "cpp-utils/tempfile/TempFile.h"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -24,7 +24,7 @@ class DataTest: public Test {
|
|||||||
public:
|
public:
|
||||||
bool DataIsZeroes(const Data &data) {
|
bool DataIsZeroes(const Data &data) {
|
||||||
for (size_t i = 0; i != data.size(); ++ i) {
|
for (size_t i = 0; i != data.size(); ++ i) {
|
||||||
if (((char*)data.data())[i] != 0) {
|
if (deserialize<uint8_t>(data.dataOffset(i)) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ public:
|
|||||||
|
|
||||||
static void StoreData(const Data &data, const bf::path &filepath) {
|
static void StoreData(const Data &data, const bf::path &filepath) {
|
||||||
ofstream file(filepath.c_str(), std::ios::binary | std::ios::trunc);
|
ofstream file(filepath.c_str(), std::ios::binary | std::ios::trunc);
|
||||||
file.write((char*)data.data(), data.size());
|
file.write(static_cast<const char*>(data.data()), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EXPECT_STORED_FILE_DATA_CORRECT(const Data &data, const bf::path &filepath) {
|
static void EXPECT_STORED_FILE_DATA_CORRECT(const Data &data, const bf::path &filepath) {
|
||||||
@ -118,7 +118,7 @@ TEST_P(DataTestWithSizeParam, Copy) {
|
|||||||
TEST_F(DataTest, ChangingCopyDoesntChangeOriginal) {
|
TEST_F(DataTest, ChangingCopyDoesntChangeOriginal) {
|
||||||
Data original = DataFixture::generate(1024);
|
Data original = DataFixture::generate(1024);
|
||||||
Data copy = original.copy();
|
Data copy = original.copy();
|
||||||
((uint8_t*)copy.data())[0] = ((uint8_t*)copy.data())[0] + 1;
|
serialize<uint8_t>(copy.data(), deserialize<uint8_t>(copy.data()) + 1);
|
||||||
EXPECT_EQ(DataFixture::generate(1024), original);
|
EXPECT_EQ(DataFixture::generate(1024), original);
|
||||||
EXPECT_NE(copy, original);
|
EXPECT_NE(copy, original);
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ TEST_F(DataTest, Inequality_DifferentSize) {
|
|||||||
TEST_F(DataTest, Inequality_DifferentFirstByte) {
|
TEST_F(DataTest, Inequality_DifferentFirstByte) {
|
||||||
Data data1 = DataFixture::generate(1024);
|
Data data1 = DataFixture::generate(1024);
|
||||||
Data data2 = DataFixture::generate(1024);
|
Data data2 = DataFixture::generate(1024);
|
||||||
((uint8_t*)data2.data())[0] = ((uint8_t*)data2.data())[0] + 1;
|
serialize<uint8_t>(data2.data(), deserialize<uint8_t>(data2.data()) + 1);
|
||||||
EXPECT_FALSE(data1 == data2);
|
EXPECT_FALSE(data1 == data2);
|
||||||
EXPECT_TRUE(data1 != data2);
|
EXPECT_TRUE(data1 != data2);
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ TEST_F(DataTest, Inequality_DifferentFirstByte) {
|
|||||||
TEST_F(DataTest, Inequality_DifferentMiddleByte) {
|
TEST_F(DataTest, Inequality_DifferentMiddleByte) {
|
||||||
Data data1 = DataFixture::generate(1024);
|
Data data1 = DataFixture::generate(1024);
|
||||||
Data data2 = DataFixture::generate(1024);
|
Data data2 = DataFixture::generate(1024);
|
||||||
((uint8_t*)data2.data())[500] = ((uint8_t*)data2.data())[500] + 1;
|
serialize<uint8_t>(data2.dataOffset(500), deserialize<uint8_t>(data2.dataOffset(500)) + 1);
|
||||||
EXPECT_FALSE(data1 == data2);
|
EXPECT_FALSE(data1 == data2);
|
||||||
EXPECT_TRUE(data1 != data2);
|
EXPECT_TRUE(data1 != data2);
|
||||||
}
|
}
|
||||||
@ -187,7 +187,7 @@ TEST_F(DataTest, Inequality_DifferentMiddleByte) {
|
|||||||
TEST_F(DataTest, Inequality_DifferentLastByte) {
|
TEST_F(DataTest, Inequality_DifferentLastByte) {
|
||||||
Data data1 = DataFixture::generate(1024);
|
Data data1 = DataFixture::generate(1024);
|
||||||
Data data2 = DataFixture::generate(1024);
|
Data data2 = DataFixture::generate(1024);
|
||||||
((uint8_t*)data2.data())[1023] = ((uint8_t*)data2.data())[1023] + 1;
|
serialize<uint8_t>(data2.dataOffset(1023), deserialize<uint8_t>(data2.dataOffset(1023)) + 1);
|
||||||
EXPECT_FALSE(data1 == data2);
|
EXPECT_FALSE(data1 == data2);
|
||||||
EXPECT_TRUE(data1 != data2);
|
EXPECT_TRUE(data1 != data2);
|
||||||
}
|
}
|
||||||
|
@ -89,19 +89,19 @@ const Data FixedSizeDataTestWithBinaryParam::VALUE2(DataFixture::generate(SIZE,
|
|||||||
INSTANTIATE_TEST_CASE_P(FixedSizeDataTestWithBinaryParam, FixedSizeDataTestWithBinaryParam, Values(&FixedSizeDataTestWithBinaryParam::VALUE1, &FixedSizeDataTestWithBinaryParam::VALUE2));
|
INSTANTIATE_TEST_CASE_P(FixedSizeDataTestWithBinaryParam, FixedSizeDataTestWithBinaryParam, Values(&FixedSizeDataTestWithBinaryParam::VALUE1, &FixedSizeDataTestWithBinaryParam::VALUE2));
|
||||||
|
|
||||||
TEST_P(FixedSizeDataTestWithBinaryParam, FromBinary) {
|
TEST_P(FixedSizeDataTestWithBinaryParam, FromBinary) {
|
||||||
FixedSizeData<SIZE> data = FixedSizeData<SIZE>::FromBinary((uint8_t*)GetParam()->data());
|
FixedSizeData<SIZE> data = FixedSizeData<SIZE>::FromBinary(GetParam()->data());
|
||||||
EXPECT_DATA_EQ(*GetParam(), data);
|
EXPECT_DATA_EQ(*GetParam(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(FixedSizeDataTestWithBinaryParam, FromAndToBinary) {
|
TEST_P(FixedSizeDataTestWithBinaryParam, FromAndToBinary) {
|
||||||
FixedSizeData<SIZE> data = FixedSizeData<SIZE>::FromBinary((uint8_t*)GetParam()->data());
|
FixedSizeData<SIZE> data = FixedSizeData<SIZE>::FromBinary(GetParam()->data());
|
||||||
Data output(FixedSizeData<SIZE>::BINARY_LENGTH);
|
Data output(FixedSizeData<SIZE>::BINARY_LENGTH);
|
||||||
data.ToBinary(output.data());
|
data.ToBinary(output.data());
|
||||||
EXPECT_EQ(*GetParam(), output);
|
EXPECT_EQ(*GetParam(), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(FixedSizeDataTestWithBinaryParam, ToAndFromBinary) {
|
TEST_P(FixedSizeDataTestWithBinaryParam, ToAndFromBinary) {
|
||||||
FixedSizeData<SIZE> data = FixedSizeData<SIZE>::FromBinary((uint8_t*)GetParam()->data());
|
FixedSizeData<SIZE> data = FixedSizeData<SIZE>::FromBinary(GetParam()->data());
|
||||||
Data stored(FixedSizeData<SIZE>::BINARY_LENGTH);
|
Data stored(FixedSizeData<SIZE>::BINARY_LENGTH);
|
||||||
data.ToBinary(stored.data());
|
data.ToBinary(stored.data());
|
||||||
FixedSizeData<SIZE> loaded = FixedSizeData<SIZE>::FromBinary(stored.data());
|
FixedSizeData<SIZE> loaded = FixedSizeData<SIZE>::FromBinary(stored.data());
|
||||||
|
205
test/cpp-utils/data/SerializationHelperTest.cpp
Normal file
205
test/cpp-utils/data/SerializationHelperTest.cpp
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <cpp-utils/data/SerializationHelper.h>
|
||||||
|
#include <cpp-utils/data/Data.h>
|
||||||
|
|
||||||
|
using cpputils::serialize;
|
||||||
|
using cpputils::deserialize;
|
||||||
|
using cpputils::deserializeWithOffset;
|
||||||
|
using cpputils::Data;
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, uint8) {
|
||||||
|
Data data(1);
|
||||||
|
serialize<uint8_t>(data.data(), 5u);
|
||||||
|
EXPECT_EQ(5u, deserialize<uint8_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int8_positive) {
|
||||||
|
Data data(1);
|
||||||
|
serialize<int8_t>(data.data(), 5);
|
||||||
|
EXPECT_EQ(5, deserialize<int8_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int8_negative) {
|
||||||
|
Data data(1);
|
||||||
|
serialize<int8_t>(data.data(), -5);
|
||||||
|
EXPECT_EQ(-5, deserialize<int8_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, uint16_aligned) {
|
||||||
|
Data data(2);
|
||||||
|
serialize<uint16_t>(data.data(), 1000u);
|
||||||
|
EXPECT_EQ(1000u, deserialize<uint16_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, uint16_unaligned) {
|
||||||
|
Data data(3);
|
||||||
|
serialize<uint16_t>(data.dataOffset(1), 1000u);
|
||||||
|
EXPECT_EQ(1000u, deserialize<uint16_t>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int16_postive_aligned) {
|
||||||
|
Data data(2);
|
||||||
|
serialize<int16_t>(data.data(), 1000);
|
||||||
|
EXPECT_EQ(1000, deserialize<int16_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int16_positive_unaligned) {
|
||||||
|
Data data(3);
|
||||||
|
serialize<int16_t>(data.dataOffset(1), 1000);
|
||||||
|
EXPECT_EQ(1000, deserialize<int16_t>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int16_negative_aligned) {
|
||||||
|
Data data(2);
|
||||||
|
serialize<int16_t>(data.data(), -1000);
|
||||||
|
EXPECT_EQ(-1000, deserialize<int16_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int16_negative_unaligned) {
|
||||||
|
Data data(3);
|
||||||
|
serialize<int16_t>(data.dataOffset(1), -1000);
|
||||||
|
EXPECT_EQ(-1000, deserialize<int16_t>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, uint32_aligned) {
|
||||||
|
Data data(4);
|
||||||
|
serialize<uint32_t>(data.data(), 100000u);
|
||||||
|
EXPECT_EQ(100000u, deserialize<uint32_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, uint32_unaligned) {
|
||||||
|
Data data(5);
|
||||||
|
serialize<uint32_t>(data.dataOffset(1), 100000u);
|
||||||
|
EXPECT_EQ(100000u, deserialize<uint32_t>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int32_positive_aligned) {
|
||||||
|
Data data(4);
|
||||||
|
serialize<int32_t>(data.data(), 100000);
|
||||||
|
EXPECT_EQ(100000, deserialize<int32_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int32_positive_unaligned) {
|
||||||
|
Data data(5);
|
||||||
|
serialize<int32_t>(data.dataOffset(1), 100000);
|
||||||
|
EXPECT_EQ(100000, deserialize<int32_t>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int32_negative_aligned) {
|
||||||
|
Data data(4);
|
||||||
|
serialize<int32_t>(data.data(), -100000);
|
||||||
|
EXPECT_EQ(-100000, deserialize<int32_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int32_negative_unaligned) {
|
||||||
|
Data data(5);
|
||||||
|
serialize<int32_t>(data.dataOffset(1), -100000);
|
||||||
|
EXPECT_EQ(-100000, deserialize<int32_t>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, uint64_aligned) {
|
||||||
|
Data data(8);
|
||||||
|
serialize<uint64_t>(data.data(), 10000000000u);
|
||||||
|
EXPECT_EQ(10000000000u, deserialize<uint64_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, uint64_unaligned) {
|
||||||
|
Data data(9);
|
||||||
|
serialize<uint64_t>(data.dataOffset(1), 10000000000u);
|
||||||
|
EXPECT_EQ(10000000000u, deserialize<uint64_t>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int64_positive_aligned) {
|
||||||
|
Data data(8);
|
||||||
|
serialize<int64_t>(data.data(), 10000000000);
|
||||||
|
EXPECT_EQ(10000000000, deserialize<int64_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int64_positive_unaligned) {
|
||||||
|
Data data(9);
|
||||||
|
serialize<int64_t>(data.dataOffset(1), 10000000000);
|
||||||
|
EXPECT_EQ(10000000000, deserialize<int64_t>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int64_negative_aligned) {
|
||||||
|
Data data(8);
|
||||||
|
serialize<int64_t>(data.data(), -10000000000);
|
||||||
|
EXPECT_EQ(-10000000000, deserialize<int64_t>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, int64_negative_unaligned) {
|
||||||
|
Data data(9);
|
||||||
|
serialize<int64_t>(data.dataOffset(1), -10000000000);
|
||||||
|
EXPECT_EQ(-10000000000, deserialize<int64_t>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, float_aligned) {
|
||||||
|
Data data(sizeof(float));
|
||||||
|
serialize<float>(data.data(), 3.1415f);
|
||||||
|
EXPECT_EQ(3.1415f, deserialize<float>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, float_unaligned) {
|
||||||
|
Data data(sizeof(float) + 1);
|
||||||
|
serialize<float>(data.dataOffset(1), 3.1415f);
|
||||||
|
EXPECT_EQ(3.1415f, deserialize<float>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, double_aligned) {
|
||||||
|
Data data(sizeof(double));
|
||||||
|
serialize<double>(data.data(), 3.1415);
|
||||||
|
EXPECT_EQ(3.1415, deserialize<double>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, double_unaligned) {
|
||||||
|
Data data(sizeof(double) + 1);
|
||||||
|
serialize<double>(data.dataOffset(1), 3.1415);
|
||||||
|
EXPECT_EQ(3.1415, deserialize<double>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct DataStructure final {
|
||||||
|
uint64_t v1;
|
||||||
|
uint32_t v2;
|
||||||
|
uint16_t v3;
|
||||||
|
uint8_t v4;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const DataStructure &lhs, const DataStructure &rhs) {
|
||||||
|
return lhs.v1 == rhs.v1 && lhs.v2 == rhs.v2 && lhs.v3 == rhs.v3 && lhs.v4 == rhs.v4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, struct_aligned) {
|
||||||
|
Data data(sizeof(DataStructure));
|
||||||
|
const DataStructure fixture {10000000000u, 100000u, 1000u, 5u};
|
||||||
|
serialize<DataStructure>(data.data(), fixture);
|
||||||
|
EXPECT_EQ(fixture, deserialize<DataStructure>(data.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, struct_unaligned) {
|
||||||
|
Data data(sizeof(DataStructure) + 1);
|
||||||
|
const DataStructure fixture {10000000000u, 100000u, 1000u, 5u};
|
||||||
|
serialize<DataStructure>(data.dataOffset(1), fixture);
|
||||||
|
EXPECT_EQ(fixture, deserialize<DataStructure>(data.dataOffset(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct OneByteStruct final {
|
||||||
|
uint8_t v;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(OneByteStruct) == 1, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, onebytestruct) {
|
||||||
|
Data data(1);
|
||||||
|
OneByteStruct fixture {5};
|
||||||
|
serialize<OneByteStruct>(data.data(), fixture);
|
||||||
|
EXPECT_EQ(fixture.v, deserialize<OneByteStruct>(data.data()).v);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SerializationHelperTest, deserializeWithOffset) {
|
||||||
|
Data data(5);
|
||||||
|
serialize<uint16_t>(data.dataOffset(1), 1000);
|
||||||
|
EXPECT_EQ(1000, deserializeWithOffset<uint16_t>(data.data(), 1));
|
||||||
|
}
|
@ -115,7 +115,7 @@ TEST_F(OptionalOwnershipPointerTest, DoesntCrashWhenDestructingNullptr1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(OptionalOwnershipPointerTest, DoesntCrashWhenDestructingNullptrWithoutOwnership) {
|
TEST_F(OptionalOwnershipPointerTest, DoesntCrashWhenDestructingNullptrWithoutOwnership) {
|
||||||
optional_ownership_ptr<TestObject> ptr = WithoutOwnership((TestObject*)nullptr);
|
optional_ownership_ptr<TestObject> ptr = WithoutOwnership(static_cast<TestObject*>(nullptr));
|
||||||
UNUSED(ptr);
|
UNUSED(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,36 +91,36 @@ TEST(MakeUniqueRefTest, CanAssignToBaseClassSharedPtr) {
|
|||||||
|
|
||||||
TEST(NullcheckTest, givenUniquePtrToInt_withNullptr_whenNullcheckCalled_thenReturnsNone) {
|
TEST(NullcheckTest, givenUniquePtrToInt_withNullptr_whenNullcheckCalled_thenReturnsNone) {
|
||||||
boost::optional<unique_ref<int>> var = nullcheck(std::unique_ptr<int>(nullptr));
|
boost::optional<unique_ref<int>> var = nullcheck(std::unique_ptr<int>(nullptr));
|
||||||
EXPECT_FALSE((bool)var);
|
EXPECT_FALSE(static_cast<bool>(var));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(NullcheckTest, givenUniquePtrToObject_withNullptr_whenNullcheckCalled_thenReturnsNone) {
|
TEST(NullcheckTest, givenUniquePtrToObject_withNullptr_whenNullcheckCalled_thenReturnsNone) {
|
||||||
boost::optional<unique_ref<SomeClass0Parameters>> var = nullcheck(std::unique_ptr<SomeClass0Parameters>(nullptr));
|
boost::optional<unique_ref<SomeClass0Parameters>> var = nullcheck(std::unique_ptr<SomeClass0Parameters>(nullptr));
|
||||||
EXPECT_FALSE((bool)var);
|
EXPECT_FALSE(static_cast<bool>(var));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(NullcheckTest, givenUniquePtrToInt_withNonNullptr_whenNullcheckCalled_thenReturnsUniqueRef) {
|
TEST(NullcheckTest, givenUniquePtrToInt_withNonNullptr_whenNullcheckCalled_thenReturnsUniqueRef) {
|
||||||
boost::optional<unique_ref<int>> var = nullcheck(std::make_unique<int>(3));
|
boost::optional<unique_ref<int>> var = nullcheck(std::make_unique<int>(3));
|
||||||
EXPECT_TRUE((bool)var);
|
EXPECT_TRUE(static_cast<bool>(var));
|
||||||
EXPECT_EQ(3, **var);
|
EXPECT_EQ(3, **var);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(NullcheckTest, givenUniquePtrToObject_withNonNullptr_whenNullcheckCalled_thenReturnsUniqueRef) {
|
TEST(NullcheckTest, givenUniquePtrToObject_withNonNullptr_whenNullcheckCalled_thenReturnsUniqueRef) {
|
||||||
boost::optional<unique_ref<SomeClass0Parameters>> var = nullcheck(std::make_unique<SomeClass0Parameters>());
|
boost::optional<unique_ref<SomeClass0Parameters>> var = nullcheck(std::make_unique<SomeClass0Parameters>());
|
||||||
EXPECT_TRUE((bool)var);
|
EXPECT_TRUE(static_cast<bool>(var));
|
||||||
//Check that the type is correct
|
//Check that the type is correct
|
||||||
EXPECT_EQ(var->get(), dynamic_cast<SomeClass0Parameters*>(var->get()));
|
EXPECT_EQ(var->get(), dynamic_cast<SomeClass0Parameters*>(var->get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(NullcheckTest, givenUniquePtrToObjectWith1Parameter_withNonNullptr_whenNullcheckCalled_thenReturnsUniqueRef) {
|
TEST(NullcheckTest, givenUniquePtrToObjectWith1Parameter_withNonNullptr_whenNullcheckCalled_thenReturnsUniqueRef) {
|
||||||
boost::optional<unique_ref<SomeClass1Parameter>> var = nullcheck(std::make_unique<SomeClass1Parameter>(5));
|
boost::optional<unique_ref<SomeClass1Parameter>> var = nullcheck(std::make_unique<SomeClass1Parameter>(5));
|
||||||
EXPECT_TRUE((bool)var);
|
EXPECT_TRUE(static_cast<bool>(var));
|
||||||
EXPECT_EQ(5, (*var)->param);
|
EXPECT_EQ(5, (*var)->param);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(NullcheckTest, givenUniquePtrToObjectWith2Parameters_withNonNullptr_whenNullcheckCalled_thenReturnsUniqueRef) {
|
TEST(NullcheckTest, givenUniquePtrToObjectWith2Parameters_withNonNullptr_whenNullcheckCalled_thenReturnsUniqueRef) {
|
||||||
boost::optional<unique_ref<SomeClass2Parameters>> var = nullcheck(std::make_unique<SomeClass2Parameters>(7,2));
|
boost::optional<unique_ref<SomeClass2Parameters>> var = nullcheck(std::make_unique<SomeClass2Parameters>(7,2));
|
||||||
EXPECT_TRUE((bool)var);
|
EXPECT_TRUE(static_cast<bool>(var));
|
||||||
EXPECT_EQ(7, (*var)->param1);
|
EXPECT_EQ(7, (*var)->param1);
|
||||||
EXPECT_EQ(2, (*var)->param2);
|
EXPECT_EQ(2, (*var)->param2);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ private:
|
|||||||
Data result(hex.size()/2);
|
Data result(hex.size()/2);
|
||||||
CryptoPP::StringSource(hex, true,
|
CryptoPP::StringSource(hex, true,
|
||||||
new CryptoPP::HexDecoder(
|
new CryptoPP::HexDecoder(
|
||||||
new CryptoPP::ArraySink((CryptoPP::byte*)result.data(), result.size())
|
new CryptoPP::ArraySink(static_cast<CryptoPP::byte*>(result.data()), result.size())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
|
@ -13,6 +13,8 @@ using cpputils::AES128_CFB;
|
|||||||
using cpputils::AES256_GCM;
|
using cpputils::AES256_GCM;
|
||||||
using cpputils::Twofish256_GCM;
|
using cpputils::Twofish256_GCM;
|
||||||
using cpputils::Twofish128_CFB;
|
using cpputils::Twofish128_CFB;
|
||||||
|
using cpputils::serialize;
|
||||||
|
using cpputils::deserialize;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
using namespace cryfs;
|
using namespace cryfs;
|
||||||
|
|
||||||
@ -102,7 +104,7 @@ TEST_F(CryConfigEncryptorTest, EncryptAndDecrypt_EmptyData) {
|
|||||||
TEST_F(CryConfigEncryptorTest, InvalidCiphertext) {
|
TEST_F(CryConfigEncryptorTest, InvalidCiphertext) {
|
||||||
auto encryptor = makeEncryptor();
|
auto encryptor = makeEncryptor();
|
||||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
||||||
*(char*)encrypted.data() = *(char*)encrypted.data()+1; //Modify ciphertext
|
serialize<uint8_t>(encrypted.data(), deserialize<uint8_t>(encrypted.data()) + 1); //Modify ciphertext
|
||||||
auto decrypted = encryptor->decrypt(encrypted);
|
auto decrypted = encryptor->decrypt(encrypted);
|
||||||
EXPECT_EQ(none, decrypted);
|
EXPECT_EQ(none, decrypted);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ using cpputils::make_unique_ref;
|
|||||||
using cpputils::AES256_GCM;
|
using cpputils::AES256_GCM;
|
||||||
using cpputils::AES256_CFB;
|
using cpputils::AES256_CFB;
|
||||||
using cpputils::Twofish128_CFB;
|
using cpputils::Twofish128_CFB;
|
||||||
|
using cpputils::serialize;
|
||||||
|
using cpputils::deserialize;
|
||||||
using namespace cryfs;
|
using namespace cryfs;
|
||||||
|
|
||||||
// This is needed for google test
|
// This is needed for google test
|
||||||
@ -63,7 +65,7 @@ TEST_F(ConcreteInnerEncryptorTest, DoesntDecryptWithWrongCipherName) {
|
|||||||
TEST_F(ConcreteInnerEncryptorTest, InvalidCiphertext) {
|
TEST_F(ConcreteInnerEncryptorTest, InvalidCiphertext) {
|
||||||
auto encryptor = makeInnerEncryptor<AES256_GCM>();
|
auto encryptor = makeInnerEncryptor<AES256_GCM>();
|
||||||
InnerConfig encrypted = encryptor->encrypt(DataFixture::generate(200));
|
InnerConfig encrypted = encryptor->encrypt(DataFixture::generate(200));
|
||||||
*(char*)encrypted.encryptedConfig.data() = *(char*)encrypted.encryptedConfig.data()+1; //Modify ciphertext
|
serialize<uint8_t>(encrypted.encryptedConfig.data(), deserialize<uint8_t>(encrypted.encryptedConfig.data()) + 1); //Modify ciphertext
|
||||||
auto decrypted = encryptor->decrypt(encrypted);
|
auto decrypted = encryptor->decrypt(encrypted);
|
||||||
EXPECT_EQ(none, decrypted);
|
EXPECT_EQ(none, decrypted);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ using cpputils::Data;
|
|||||||
using cpputils::DataFixture;
|
using cpputils::DataFixture;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
|
using cpputils::serialize;
|
||||||
|
using cpputils::deserialize;
|
||||||
using namespace cryfs;
|
using namespace cryfs;
|
||||||
|
|
||||||
// This is needed for google test
|
// This is needed for google test
|
||||||
@ -48,7 +50,7 @@ TEST_F(OuterEncryptorTest, EncryptAndDecrypt_EmptyData) {
|
|||||||
TEST_F(OuterEncryptorTest, InvalidCiphertext) {
|
TEST_F(OuterEncryptorTest, InvalidCiphertext) {
|
||||||
auto encryptor = makeOuterEncryptor();
|
auto encryptor = makeOuterEncryptor();
|
||||||
OuterConfig encrypted = encryptor->encrypt(DataFixture::generate(200));
|
OuterConfig encrypted = encryptor->encrypt(DataFixture::generate(200));
|
||||||
*(char*)encrypted.encryptedInnerConfig.data() = *(char*)encrypted.encryptedInnerConfig.data()+1; //Modify ciphertext
|
serialize<uint8_t>(encrypted.encryptedInnerConfig.data(), deserialize<uint8_t>(encrypted.encryptedInnerConfig.data()) + 1); //Modify ciphertext
|
||||||
auto decrypted = encryptor->decrypt(encrypted);
|
auto decrypted = encryptor->decrypt(encrypted);
|
||||||
EXPECT_EQ(none, decrypted);
|
EXPECT_EQ(none, decrypted);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
|
|
||||||
::testing::Action<size_t(int, void*, size_t, off_t)> ReturnSuccessfulReadRegardingSize(size_t filesize) {
|
::testing::Action<size_t(int, void*, size_t, off_t)> ReturnSuccessfulReadRegardingSize(size_t filesize) {
|
||||||
return ::testing::Invoke([filesize](int, void *, size_t count, off_t offset) {
|
return ::testing::Invoke([filesize](int, void *, size_t count, off_t offset) {
|
||||||
size_t ableToReadCount = std::min(count, (size_t)(filesize - offset));
|
size_t ableToReadCount = std::min(count, static_cast<size_t>(filesize - offset));
|
||||||
return ableToReadCount;
|
return ableToReadCount;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -19,25 +19,25 @@
|
|||||||
RETURNTYPE NAME(const boost::filesystem::path &path) override { \
|
RETURNTYPE NAME(const boost::filesystem::path &path) override { \
|
||||||
return NAME(path.c_str()); \
|
return NAME(path.c_str()); \
|
||||||
} \
|
} \
|
||||||
MOCK_METHOD1(NAME, RETURNTYPE(const char*)); \
|
MOCK_METHOD1(NAME, RETURNTYPE(const char*)) \
|
||||||
|
|
||||||
#define MOCK_PATH_METHOD2(NAME, RETURNTYPE, PARAM1) \
|
#define MOCK_PATH_METHOD2(NAME, RETURNTYPE, PARAM1) \
|
||||||
RETURNTYPE NAME(const boost::filesystem::path &path, PARAM1 param1) override { \
|
RETURNTYPE NAME(const boost::filesystem::path &path, PARAM1 param1) override { \
|
||||||
return NAME(path.c_str(), param1); \
|
return NAME(path.c_str(), param1); \
|
||||||
} \
|
} \
|
||||||
MOCK_METHOD2(NAME, RETURNTYPE(const char*, PARAM1)); \
|
MOCK_METHOD2(NAME, RETURNTYPE(const char*, PARAM1)) \
|
||||||
|
|
||||||
#define MOCK_PATH_METHOD3(NAME, RETURNTYPE, PARAM1, PARAM2) \
|
#define MOCK_PATH_METHOD3(NAME, RETURNTYPE, PARAM1, PARAM2) \
|
||||||
RETURNTYPE NAME(const boost::filesystem::path &path, PARAM1 p1, PARAM2 p2) override { \
|
RETURNTYPE NAME(const boost::filesystem::path &path, PARAM1 p1, PARAM2 p2) override { \
|
||||||
return NAME(path.c_str(), p1, p2); \
|
return NAME(path.c_str(), p1, p2); \
|
||||||
} \
|
} \
|
||||||
MOCK_METHOD3(NAME, RETURNTYPE(const char*, PARAM1, PARAM2)); \
|
MOCK_METHOD3(NAME, RETURNTYPE(const char*, PARAM1, PARAM2)) \
|
||||||
|
|
||||||
#define MOCK_PATH_METHOD4(NAME, RETURNTYPE, PARAM1, PARAM2, PARAM3) \
|
#define MOCK_PATH_METHOD4(NAME, RETURNTYPE, PARAM1, PARAM2, PARAM3) \
|
||||||
RETURNTYPE NAME(const boost::filesystem::path &path, PARAM1 p1, PARAM2 p2, PARAM3 p3) override { \
|
RETURNTYPE NAME(const boost::filesystem::path &path, PARAM1 p1, PARAM2 p2, PARAM3 p3) override { \
|
||||||
return NAME(path.c_str(), p1, p2, p3); \
|
return NAME(path.c_str(), p1, p2, p3); \
|
||||||
} \
|
} \
|
||||||
MOCK_METHOD4(NAME, RETURNTYPE(const char*, PARAM1, PARAM2, PARAM3)); \
|
MOCK_METHOD4(NAME, RETURNTYPE(const char*, PARAM1, PARAM2, PARAM3)) \
|
||||||
|
|
||||||
class MockFilesystem: public fspp::fuse::Filesystem {
|
class MockFilesystem: public fspp::fuse::Filesystem {
|
||||||
public:
|
public:
|
||||||
|
@ -9,8 +9,8 @@ InMemoryFile::~InMemoryFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int InMemoryFile::read(void *buf, size_t count, off_t offset) const {
|
int InMemoryFile::read(void *buf, size_t count, off_t offset) const {
|
||||||
size_t realCount = std::min(count, (size_t)(_data.size() - offset));
|
size_t realCount = std::min(count, static_cast<size_t>(_data.size() - offset));
|
||||||
std::memcpy(buf, (uint8_t*)_data.data() + offset, realCount);
|
std::memcpy(buf, _data.dataOffset(offset), realCount);
|
||||||
return realCount;
|
return realCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ const void *InMemoryFile::data() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool InMemoryFile::fileContentEquals(const Data &expected, off_t offset) const {
|
bool InMemoryFile::fileContentEquals(const Data &expected, off_t offset) const {
|
||||||
return 0 == std::memcmp((uint8_t*)expected.data(), (uint8_t*)_data.data() + offset, expected.size());
|
return 0 == std::memcmp(expected.data(), _data.dataOffset(offset), expected.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t InMemoryFile::size() const {
|
size_t InMemoryFile::size() const {
|
||||||
@ -32,7 +32,7 @@ WriteableInMemoryFile::WriteableInMemoryFile(Data data): InMemoryFile(std::move(
|
|||||||
void WriteableInMemoryFile::write(const void *buf, size_t count, off_t offset) {
|
void WriteableInMemoryFile::write(const void *buf, size_t count, off_t offset) {
|
||||||
_extendFileSizeIfNecessary(count + offset);
|
_extendFileSizeIfNecessary(count + offset);
|
||||||
|
|
||||||
std::memcpy((uint8_t*)_data.data() + offset, buf, count);
|
std::memcpy(_data.dataOffset(offset), buf, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteableInMemoryFile::_extendFileSizeIfNecessary(size_t size) {
|
void WriteableInMemoryFile::_extendFileSizeIfNecessary(size_t size) {
|
||||||
@ -52,5 +52,5 @@ bool WriteableInMemoryFile::sizeUnchanged() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WriteableInMemoryFile::regionUnchanged(off_t offset, size_t count) const {
|
bool WriteableInMemoryFile::regionUnchanged(off_t offset, size_t count) const {
|
||||||
return 0 == std::memcmp((uint8_t*)_data.data() + offset, (uint8_t*)_originalData.data() + offset, count);
|
return 0 == std::memcmp(_data.dataOffset(offset), _originalData.dataOffset(offset), count);
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ endif()
|
|||||||
#################################################
|
#################################################
|
||||||
function(target_enable_style_warnings TARGET)
|
function(target_enable_style_warnings TARGET)
|
||||||
# Enable compiler options
|
# Enable compiler options
|
||||||
target_compile_options(${TARGET} PRIVATE -Wall -Wextra)
|
target_compile_options(${TARGET} PRIVATE -Wall -Wextra -Wold-style-cast -Wcast-align) # TODO consider -Wpedantic -Wchkp -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -Wno-variadic-macros -Wno-parentheses -fdiagnostics-show-option -Wconversion and others?
|
||||||
|
|
||||||
# Enable clang-tidy
|
# Enable clang-tidy
|
||||||
#set_target_properties(
|
#set_target_properties(
|
||||||
|
Loading…
Reference in New Issue
Block a user