Rename VersionCountingBlockStore -> IntegrityBlockStore
This commit is contained in:
parent
00d098952b
commit
f6b6875bb2
@ -24,10 +24,10 @@ set(SOURCES
|
|||||||
implementations/caching/cache/QueueMap.cpp
|
implementations/caching/cache/QueueMap.cpp
|
||||||
implementations/low2highlevel/LowToHighLevelBlock.cpp
|
implementations/low2highlevel/LowToHighLevelBlock.cpp
|
||||||
implementations/low2highlevel/LowToHighLevelBlockStore.cpp
|
implementations/low2highlevel/LowToHighLevelBlockStore.cpp
|
||||||
implementations/versioncounting/VersionCountingBlockStore2.cpp
|
implementations/integrity/IntegrityBlockStore2.cpp
|
||||||
implementations/versioncounting/KnownBlockVersions.cpp
|
implementations/integrity/KnownBlockVersions.cpp
|
||||||
implementations/versioncounting/ClientIdAndBlockKey.cpp
|
implementations/integrity/ClientIdAndBlockKey.cpp
|
||||||
implementations/versioncounting/IntegrityViolationError.cpp
|
implementations/integrity/IntegrityViolationError.cpp
|
||||||
implementations/mock/MockBlockStore.cpp
|
implementations/mock/MockBlockStore.cpp
|
||||||
implementations/mock/MockBlock.cpp
|
implementations/mock/MockBlock.cpp
|
||||||
)
|
)
|
||||||
|
@ -142,7 +142,7 @@ inline boost::optional<cpputils::Data> EncryptedBlockStore2<Cipher>::_tryDecrypt
|
|||||||
}
|
}
|
||||||
*decrypted = _migrateBlock(*decrypted);
|
*decrypted = _migrateBlock(*decrypted);
|
||||||
// no need to write migrated back to block store because
|
// no need to write migrated back to block store because
|
||||||
// this migration happens in line with a migration in VersionCountingBlockStore2
|
// this migration happens in line with a migration in IntegrityBlockStore2
|
||||||
// which then writes it back
|
// which then writes it back
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_CLIENTIDANDBLOCKKEY_H_
|
||||||
|
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_CLIENTIDANDBLOCKKEY_H_
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include "../../utils/Key.h"
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
namespace integrity {
|
||||||
|
|
||||||
|
struct ClientIdAndBlockKey {
|
||||||
|
uint32_t clientId;
|
||||||
|
Key blockKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow using it in std::unordered_set / std::unordered_map
|
||||||
|
namespace std {
|
||||||
|
template<> struct hash<blockstore::integrity::ClientIdAndBlockKey> {
|
||||||
|
size_t operator()(const blockstore::integrity::ClientIdAndBlockKey &ref) const {
|
||||||
|
return std::hash<uint32_t>()(ref.clientId) ^ std::hash<blockstore::Key>()(ref.blockKey);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct equal_to<blockstore::integrity::ClientIdAndBlockKey> {
|
||||||
|
size_t operator()(const blockstore::integrity::ClientIdAndBlockKey &lhs, const blockstore::integrity::ClientIdAndBlockKey &rhs) const {
|
||||||
|
return lhs.clientId == rhs.clientId && lhs.blockKey == rhs.blockKey;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,5 @@
|
|||||||
#include <blockstore/interface/BlockStore2.h>
|
#include <blockstore/interface/BlockStore2.h>
|
||||||
#include "VersionCountingBlockStore2.h"
|
#include "IntegrityBlockStore2.h"
|
||||||
#include "KnownBlockVersions.h"
|
#include "KnownBlockVersions.h"
|
||||||
|
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
@ -10,19 +10,19 @@ using boost::none;
|
|||||||
using namespace cpputils::logging;
|
using namespace cpputils::logging;
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace versioncounting {
|
namespace integrity {
|
||||||
|
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
constexpr uint16_t VersionCountingBlockStore2::FORMAT_VERSION_HEADER_OLD;
|
constexpr uint16_t IntegrityBlockStore2::FORMAT_VERSION_HEADER_OLD;
|
||||||
#endif
|
#endif
|
||||||
constexpr uint16_t VersionCountingBlockStore2::FORMAT_VERSION_HEADER;
|
constexpr uint16_t IntegrityBlockStore2::FORMAT_VERSION_HEADER;
|
||||||
constexpr uint64_t VersionCountingBlockStore2::VERSION_ZERO;
|
constexpr uint64_t IntegrityBlockStore2::VERSION_ZERO;
|
||||||
constexpr unsigned int VersionCountingBlockStore2::ID_HEADER_OFFSET;
|
constexpr unsigned int IntegrityBlockStore2::ID_HEADER_OFFSET;
|
||||||
constexpr unsigned int VersionCountingBlockStore2::CLIENTID_HEADER_OFFSET;
|
constexpr unsigned int IntegrityBlockStore2::CLIENTID_HEADER_OFFSET;
|
||||||
constexpr unsigned int VersionCountingBlockStore2::VERSION_HEADER_OFFSET;
|
constexpr unsigned int IntegrityBlockStore2::VERSION_HEADER_OFFSET;
|
||||||
constexpr unsigned int VersionCountingBlockStore2::HEADER_LENGTH;
|
constexpr unsigned int IntegrityBlockStore2::HEADER_LENGTH;
|
||||||
|
|
||||||
Data VersionCountingBlockStore2::_prependHeaderToData(const Key& key, uint32_t myClientId, uint64_t version, const Data &data) {
|
Data IntegrityBlockStore2::_prependHeaderToData(const Key& key, uint32_t myClientId, uint64_t version, const Data &data) {
|
||||||
static_assert(HEADER_LENGTH == sizeof(FORMAT_VERSION_HEADER) + Key::BINARY_LENGTH + sizeof(myClientId) + sizeof(version), "Wrong header length");
|
static_assert(HEADER_LENGTH == sizeof(FORMAT_VERSION_HEADER) + Key::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));
|
std::memcpy(result.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER));
|
||||||
@ -33,19 +33,19 @@ Data VersionCountingBlockStore2::_prependHeaderToData(const Key& key, uint32_t m
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionCountingBlockStore2::_checkHeader(const Key &key, const Data &data) const {
|
void IntegrityBlockStore2::_checkHeader(const Key &key, const Data &data) const {
|
||||||
_checkFormatHeader(data);
|
_checkFormatHeader(data);
|
||||||
_checkIdHeader(key, data);
|
_checkIdHeader(key, data);
|
||||||
_checkVersionHeader(key, data);
|
_checkVersionHeader(key, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionCountingBlockStore2::_checkFormatHeader(const Data &data) const {
|
void IntegrityBlockStore2::_checkFormatHeader(const Data &data) const {
|
||||||
if (FORMAT_VERSION_HEADER != _readFormatHeader(data)) {
|
if (FORMAT_VERSION_HEADER != _readFormatHeader(data)) {
|
||||||
throw std::runtime_error("The versioned block has the wrong format. Was it created with a newer version of CryFS?");
|
throw std::runtime_error("The versioned block has the wrong format. Was it created with a newer version of CryFS?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionCountingBlockStore2::_checkVersionHeader(const Key &key, const Data &data) const {
|
void IntegrityBlockStore2::_checkVersionHeader(const Key &key, const Data &data) const {
|
||||||
uint32_t clientId = _readClientId(data);
|
uint32_t clientId = _readClientId(data);
|
||||||
uint64_t version = _readVersion(data);
|
uint64_t version = _readVersion(data);
|
||||||
|
|
||||||
@ -54,38 +54,38 @@ void VersionCountingBlockStore2::_checkVersionHeader(const Key &key, const Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionCountingBlockStore2::_checkIdHeader(const Key &expectedKey, const Data &data) const {
|
void IntegrityBlockStore2::_checkIdHeader(const Key &expectedKey, const Data &data) const {
|
||||||
Key actualKey = _readBlockId(data);
|
Key actualKey = _readBlockId(data);
|
||||||
if (expectedKey != actualKey) {
|
if (expectedKey != actualKey) {
|
||||||
integrityViolationDetected("The block key is wrong. Did an attacker try to rename some blocks?");
|
integrityViolationDetected("The block key is wrong. Did an attacker try to rename some blocks?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t VersionCountingBlockStore2::_readFormatHeader(const Data &data) {
|
uint16_t IntegrityBlockStore2::_readFormatHeader(const Data &data) {
|
||||||
return *reinterpret_cast<decltype(FORMAT_VERSION_HEADER)*>(data.data());
|
return *reinterpret_cast<decltype(FORMAT_VERSION_HEADER)*>(data.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t VersionCountingBlockStore2::_readClientId(const Data &data) {
|
uint32_t IntegrityBlockStore2::_readClientId(const Data &data) {
|
||||||
uint32_t clientId;
|
uint32_t clientId;
|
||||||
std::memcpy(&clientId, data.dataOffset(CLIENTID_HEADER_OFFSET), sizeof(clientId));
|
std::memcpy(&clientId, data.dataOffset(CLIENTID_HEADER_OFFSET), sizeof(clientId));
|
||||||
return clientId;
|
return clientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
Key VersionCountingBlockStore2::_readBlockId(const Data &data) {
|
Key IntegrityBlockStore2::_readBlockId(const Data &data) {
|
||||||
return Key::FromBinary(data.dataOffset(ID_HEADER_OFFSET));
|
return Key::FromBinary(data.dataOffset(ID_HEADER_OFFSET));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t VersionCountingBlockStore2::_readVersion(const Data &data) {
|
uint64_t IntegrityBlockStore2::_readVersion(const Data &data) {
|
||||||
uint64_t version;
|
uint64_t version;
|
||||||
std::memcpy(&version, data.dataOffset(VERSION_HEADER_OFFSET), sizeof(version));
|
std::memcpy(&version, data.dataOffset(VERSION_HEADER_OFFSET), sizeof(version));
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
Data VersionCountingBlockStore2::_removeHeader(const Data &data) {
|
Data IntegrityBlockStore2::_removeHeader(const Data &data) {
|
||||||
return data.copyAndRemovePrefix(HEADER_LENGTH);
|
return data.copyAndRemovePrefix(HEADER_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionCountingBlockStore2::_checkNoPastIntegrityViolations() const {
|
void IntegrityBlockStore2::_checkNoPastIntegrityViolations() const {
|
||||||
if (_integrityViolationDetected) {
|
if (_integrityViolationDetected) {
|
||||||
throw std::runtime_error(string() +
|
throw std::runtime_error(string() +
|
||||||
"There was an integrity violation detected. Preventing any further access to the file system. " +
|
"There was an integrity violation detected. Preventing any further access to the file system. " +
|
||||||
@ -95,29 +95,29 @@ void VersionCountingBlockStore2::_checkNoPastIntegrityViolations() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionCountingBlockStore2::integrityViolationDetected(const string &reason) const {
|
void IntegrityBlockStore2::integrityViolationDetected(const string &reason) const {
|
||||||
_integrityViolationDetected = true;
|
_integrityViolationDetected = true;
|
||||||
throw IntegrityViolationError(reason);
|
throw IntegrityViolationError(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionCountingBlockStore2::VersionCountingBlockStore2(unique_ref<BlockStore2> baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool missingBlockIsIntegrityViolation)
|
IntegrityBlockStore2::IntegrityBlockStore2(unique_ref<BlockStore2> baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool missingBlockIsIntegrityViolation)
|
||||||
: _baseBlockStore(std::move(baseBlockStore)), _knownBlockVersions(integrityFilePath, myClientId), _missingBlockIsIntegrityViolation(missingBlockIsIntegrityViolation), _integrityViolationDetected(false) {
|
: _baseBlockStore(std::move(baseBlockStore)), _knownBlockVersions(integrityFilePath, myClientId), _missingBlockIsIntegrityViolation(missingBlockIsIntegrityViolation), _integrityViolationDetected(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VersionCountingBlockStore2::tryCreate(const Key &key, const Data &data) {
|
bool IntegrityBlockStore2::tryCreate(const Key &key, const Data &data) {
|
||||||
_checkNoPastIntegrityViolations();
|
_checkNoPastIntegrityViolations();
|
||||||
uint64_t version = _knownBlockVersions.incrementVersion(key);
|
uint64_t version = _knownBlockVersions.incrementVersion(key);
|
||||||
Data dataWithHeader = _prependHeaderToData(key, _knownBlockVersions.myClientId(), version, data);
|
Data dataWithHeader = _prependHeaderToData(key, _knownBlockVersions.myClientId(), version, data);
|
||||||
return _baseBlockStore->tryCreate(key, dataWithHeader);
|
return _baseBlockStore->tryCreate(key, dataWithHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VersionCountingBlockStore2::remove(const Key &key) {
|
bool IntegrityBlockStore2::remove(const Key &key) {
|
||||||
_checkNoPastIntegrityViolations();
|
_checkNoPastIntegrityViolations();
|
||||||
_knownBlockVersions.markBlockAsDeleted(key);
|
_knownBlockVersions.markBlockAsDeleted(key);
|
||||||
return _baseBlockStore->remove(key);
|
return _baseBlockStore->remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<Data> VersionCountingBlockStore2::load(const Key &key) const {
|
optional<Data> IntegrityBlockStore2::load(const Key &key) const {
|
||||||
_checkNoPastIntegrityViolations();
|
_checkNoPastIntegrityViolations();
|
||||||
auto loaded = _baseBlockStore->load(key);
|
auto loaded = _baseBlockStore->load(key);
|
||||||
if (none == loaded) {
|
if (none == loaded) {
|
||||||
@ -131,7 +131,7 @@ optional<Data> VersionCountingBlockStore2::load(const Key &key) const {
|
|||||||
Data migrated = _migrateBlock(key, *loaded);
|
Data migrated = _migrateBlock(key, *loaded);
|
||||||
_checkHeader(key, migrated);
|
_checkHeader(key, migrated);
|
||||||
Data content = _removeHeader(migrated);
|
Data content = _removeHeader(migrated);
|
||||||
const_cast<VersionCountingBlockStore2*>(this)->store(key, content);
|
const_cast<IntegrityBlockStore2*>(this)->store(key, content);
|
||||||
return optional<Data>(_removeHeader(migrated));
|
return optional<Data>(_removeHeader(migrated));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -140,7 +140,7 @@ optional<Data> VersionCountingBlockStore2::load(const Key &key) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
Data VersionCountingBlockStore2::_migrateBlock(const Key &key, const Data &data) {
|
Data IntegrityBlockStore2::_migrateBlock(const Key &key, const Data &data) {
|
||||||
Data migrated(data.size() + Key::BINARY_LENGTH);
|
Data migrated(data.size() + Key::BINARY_LENGTH);
|
||||||
std::memcpy(migrated.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER));
|
std::memcpy(migrated.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER));
|
||||||
std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET), key.data(), Key::BINARY_LENGTH);
|
std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET), key.data(), Key::BINARY_LENGTH);
|
||||||
@ -150,22 +150,22 @@ Data VersionCountingBlockStore2::_migrateBlock(const Key &key, const Data &data)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void VersionCountingBlockStore2::store(const Key &key, const Data &data) {
|
void IntegrityBlockStore2::store(const Key &key, const Data &data) {
|
||||||
_checkNoPastIntegrityViolations();
|
_checkNoPastIntegrityViolations();
|
||||||
uint64_t version = _knownBlockVersions.incrementVersion(key);
|
uint64_t version = _knownBlockVersions.incrementVersion(key);
|
||||||
Data dataWithHeader = _prependHeaderToData(key, _knownBlockVersions.myClientId(), version, data);
|
Data dataWithHeader = _prependHeaderToData(key, _knownBlockVersions.myClientId(), version, data);
|
||||||
return _baseBlockStore->store(key, dataWithHeader);
|
return _baseBlockStore->store(key, dataWithHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t VersionCountingBlockStore2::numBlocks() const {
|
uint64_t IntegrityBlockStore2::numBlocks() const {
|
||||||
return _baseBlockStore->numBlocks();
|
return _baseBlockStore->numBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t VersionCountingBlockStore2::estimateNumFreeBytes() const {
|
uint64_t IntegrityBlockStore2::estimateNumFreeBytes() const {
|
||||||
return _baseBlockStore->estimateNumFreeBytes();
|
return _baseBlockStore->estimateNumFreeBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t VersionCountingBlockStore2::blockSizeFromPhysicalBlockSize(uint64_t blockSize) const {
|
uint64_t IntegrityBlockStore2::blockSizeFromPhysicalBlockSize(uint64_t blockSize) const {
|
||||||
uint64_t baseBlockSize = _baseBlockStore->blockSizeFromPhysicalBlockSize(blockSize);
|
uint64_t baseBlockSize = _baseBlockStore->blockSizeFromPhysicalBlockSize(blockSize);
|
||||||
if (baseBlockSize <= HEADER_LENGTH) {
|
if (baseBlockSize <= HEADER_LENGTH) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -173,7 +173,7 @@ uint64_t VersionCountingBlockStore2::blockSizeFromPhysicalBlockSize(uint64_t blo
|
|||||||
return baseBlockSize - HEADER_LENGTH;
|
return baseBlockSize - HEADER_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionCountingBlockStore2::forEachBlock(std::function<void (const Key &)> callback) const {
|
void IntegrityBlockStore2::forEachBlock(std::function<void (const Key &)> callback) const {
|
||||||
if (!_missingBlockIsIntegrityViolation) {
|
if (!_missingBlockIsIntegrityViolation) {
|
||||||
return _baseBlockStore->forEachBlock(std::move(callback));
|
return _baseBlockStore->forEachBlock(std::move(callback));
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ void VersionCountingBlockStore2::forEachBlock(std::function<void (const Key &)>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
void VersionCountingBlockStore2::migrateFromBlockstoreWithoutVersionNumbers(BlockStore2 *baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId) {
|
void IntegrityBlockStore2::migrateFromBlockstoreWithoutVersionNumbers(BlockStore2 *baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId) {
|
||||||
std::cout << "Migrating file system for integrity features. Please don't interrupt this process. This can take a while..." << std::flush;
|
std::cout << "Migrating file system for integrity features. Please don't interrupt this process. This can take a while..." << std::flush;
|
||||||
KnownBlockVersions knownBlockVersions(integrityFilePath, myClientId);
|
KnownBlockVersions knownBlockVersions(integrityFilePath, myClientId);
|
||||||
baseBlockStore->forEachBlock([&baseBlockStore, &knownBlockVersions] (const Key &key) {
|
baseBlockStore->forEachBlock([&baseBlockStore, &knownBlockVersions] (const Key &key) {
|
||||||
@ -202,7 +202,7 @@ void VersionCountingBlockStore2::migrateFromBlockstoreWithoutVersionNumbers(Bloc
|
|||||||
std::cout << "done" << std::endl;
|
std::cout << "done" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionCountingBlockStore2::migrateBlockFromBlockstoreWithoutVersionNumbers(blockstore::BlockStore2* baseBlockStore, const blockstore::Key& key, KnownBlockVersions *knownBlockVersions) {
|
void IntegrityBlockStore2::migrateBlockFromBlockstoreWithoutVersionNumbers(blockstore::BlockStore2* baseBlockStore, const blockstore::Key& key, KnownBlockVersions *knownBlockVersions) {
|
||||||
uint64_t version = knownBlockVersions->incrementVersion(key);
|
uint64_t version = knownBlockVersions->incrementVersion(key);
|
||||||
|
|
||||||
auto data_ = baseBlockStore->load(key);
|
auto data_ = baseBlockStore->load(key);
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_VERSIONCOUNTING_VERSIONCOUNTINGBLOCKSTORE2_H_
|
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_INTEGRITYBLOCKSTORE2_H_
|
||||||
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_VERSIONCOUNTING_VERSIONCOUNTINGBLOCKSTORE2_H_
|
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_INTEGRITYBLOCKSTORE2_H_
|
||||||
|
|
||||||
#include "../../interface/BlockStore2.h"
|
#include "../../interface/BlockStore2.h"
|
||||||
#include <cpp-utils/macros.h>
|
#include <cpp-utils/macros.h>
|
||||||
@ -8,13 +8,15 @@
|
|||||||
#include "IntegrityViolationError.h"
|
#include "IntegrityViolationError.h"
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace versioncounting {
|
namespace integrity {
|
||||||
|
|
||||||
//TODO Format version headers
|
//TODO Format version headers
|
||||||
|
|
||||||
class VersionCountingBlockStore2 final: public BlockStore2 {
|
// This blockstore implements integrity measures.
|
||||||
|
// It depends on being used on top of an encrypted block store that protects integrity of the block contents (i.e. uses an authenticated cipher).
|
||||||
|
class IntegrityBlockStore2 final: public BlockStore2 {
|
||||||
public:
|
public:
|
||||||
VersionCountingBlockStore2(cpputils::unique_ref<BlockStore2> baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool missingBlockIsIntegrityViolation);
|
IntegrityBlockStore2(cpputils::unique_ref<BlockStore2> baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool missingBlockIsIntegrityViolation);
|
||||||
|
|
||||||
bool tryCreate(const Key &key, const cpputils::Data &data) override;
|
bool tryCreate(const Key &key, const cpputils::Data &data) override;
|
||||||
bool remove(const Key &key) override;
|
bool remove(const Key &key) override;
|
||||||
@ -67,7 +69,7 @@ private:
|
|||||||
const bool _missingBlockIsIntegrityViolation;
|
const bool _missingBlockIsIntegrityViolation;
|
||||||
mutable bool _integrityViolationDetected;
|
mutable bool _integrityViolationDetected;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(VersionCountingBlockStore2);
|
DISALLOW_COPY_AND_ASSIGN(IntegrityBlockStore2);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_VERSIONCOUNTING_INTEGRITYVIOLATIONERROR_H_
|
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_INTEGRITYVIOLATIONERROR_H_
|
||||||
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_VERSIONCOUNTING_INTEGRITYVIOLATIONERROR_H_
|
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_INTEGRITYVIOLATIONERROR_H_
|
||||||
|
|
||||||
#include <cpp-utils/macros.h>
|
#include <cpp-utils/macros.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace versioncounting {
|
namespace integrity {
|
||||||
|
|
||||||
class IntegrityViolationError final : public std::exception {
|
class IntegrityViolationError final : public std::exception {
|
||||||
public:
|
public:
|
||||||
@ -16,14 +16,13 @@ namespace blockstore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constructor is private to make sure that only VersionCountingBlockStore can throw this exception.
|
// Constructor is private to make sure that only IntegrityBlockStore can throw this exception.
|
||||||
// This is because VersionCountingBlockStore wants to know about integrity violations and
|
// This is because IntegrityBlockStore wants to know about integrity violations and
|
||||||
// block all further file system access if it happens.
|
// block all further file system access if it happens.
|
||||||
IntegrityViolationError(const std::string &reason)
|
IntegrityViolationError(const std::string &reason)
|
||||||
: _reason("Integrity violation: " + reason) {
|
: _reason("Integrity violation: " + reason) {
|
||||||
}
|
}
|
||||||
friend class VersionCountingBlockStore;
|
friend class IntegrityBlockStore2;
|
||||||
friend class VersionCountingBlockStore2;
|
|
||||||
|
|
||||||
std::string _reason;
|
std::string _reason;
|
||||||
};
|
};
|
@ -17,7 +17,7 @@ using cpputils::Serializer;
|
|||||||
using cpputils::Deserializer;
|
using cpputils::Deserializer;
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace versioncounting {
|
namespace integrity {
|
||||||
|
|
||||||
const string KnownBlockVersions::HEADER = "cryfs.integritydata.knownblockversions;0";
|
const string KnownBlockVersions::HEADER = "cryfs.integritydata.knownblockversions;0";
|
||||||
constexpr uint32_t KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK;
|
constexpr uint32_t KnownBlockVersions::CLIENT_ID_FOR_DELETED_BLOCK;
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_VERSIONCOUNTING_KNOWNBLOCKVERSIONS_H_
|
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_KNOWNBLOCKVERSIONS_H_
|
||||||
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_VERSIONCOUNTING_KNOWNBLOCKVERSIONS_H_
|
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_KNOWNBLOCKVERSIONS_H_
|
||||||
|
|
||||||
#include <cpp-utils/macros.h>
|
#include <cpp-utils/macros.h>
|
||||||
#include <blockstore/utils/Key.h>
|
#include <blockstore/utils/Key.h>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace versioncounting {
|
namespace integrity {
|
||||||
|
|
||||||
class KnownBlockVersions final {
|
class KnownBlockVersions final {
|
||||||
public:
|
public:
|
@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_VERSIONCOUNTING_CLIENTIDANDBLOCKKEY_H_
|
|
||||||
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_VERSIONCOUNTING_CLIENTIDANDBLOCKKEY_H_
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include "../../utils/Key.h"
|
|
||||||
|
|
||||||
namespace blockstore {
|
|
||||||
namespace versioncounting {
|
|
||||||
|
|
||||||
struct ClientIdAndBlockKey {
|
|
||||||
uint32_t clientId;
|
|
||||||
Key blockKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow using it in std::unordered_set / std::unordered_map
|
|
||||||
namespace std {
|
|
||||||
template<> struct hash<blockstore::versioncounting::ClientIdAndBlockKey> {
|
|
||||||
size_t operator()(const blockstore::versioncounting::ClientIdAndBlockKey &ref) const {
|
|
||||||
return std::hash<uint32_t>()(ref.clientId) ^ std::hash<blockstore::Key>()(ref.blockKey);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> struct equal_to<blockstore::versioncounting::ClientIdAndBlockKey> {
|
|
||||||
size_t operator()(const blockstore::versioncounting::ClientIdAndBlockKey &lhs, const blockstore::versioncounting::ClientIdAndBlockKey &rhs) const {
|
|
||||||
return lhs.clientId == rhs.clientId && lhs.blockKey == rhs.blockKey;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -12,7 +12,7 @@
|
|||||||
#include <blobstore/implementations/onblocks/BlobOnBlocks.h>
|
#include <blobstore/implementations/onblocks/BlobOnBlocks.h>
|
||||||
#include <blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h>
|
#include <blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h>
|
||||||
#include <blockstore/implementations/encrypted/EncryptedBlockStore2.h>
|
#include <blockstore/implementations/encrypted/EncryptedBlockStore2.h>
|
||||||
#include <blockstore/implementations/versioncounting/VersionCountingBlockStore2.h>
|
#include <blockstore/implementations/integrity/IntegrityBlockStore2.h>
|
||||||
#include "parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
|
#include "parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
|
||||||
#include "cachingfsblobstore/CachingFsBlobStore.h"
|
#include "cachingfsblobstore/CachingFsBlobStore.h"
|
||||||
#include "../config/CryCipher.h"
|
#include "../config/CryCipher.h"
|
||||||
@ -37,7 +37,7 @@ using blockstore::lowtohighlevel::LowToHighLevelBlockStore;
|
|||||||
using blobstore::onblocks::BlobStoreOnBlocks;
|
using blobstore::onblocks::BlobStoreOnBlocks;
|
||||||
using blobstore::onblocks::BlobOnBlocks;
|
using blobstore::onblocks::BlobOnBlocks;
|
||||||
using blockstore::caching::CachingBlockStore2;
|
using blockstore::caching::CachingBlockStore2;
|
||||||
using blockstore::versioncounting::VersionCountingBlockStore2;
|
using blockstore::integrity::IntegrityBlockStore2;
|
||||||
using gitversion::VersionCompare;
|
using gitversion::VersionCompare;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
@ -90,33 +90,33 @@ unique_ref<fsblobstore::FsBlobStore> CryDevice::MigrateOrCreateFsBlobStore(uniqu
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
unique_ref<blobstore::BlobStore> CryDevice::CreateBlobStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId) {
|
unique_ref<blobstore::BlobStore> CryDevice::CreateBlobStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId) {
|
||||||
auto versionCountingEncryptedBlockStore = CreateVersionCountingEncryptedBlockStore(std::move(blockStore), configFile, myClientId);
|
auto integrityEncryptedBlockStore = CreateIntegrityEncryptedBlockStore(std::move(blockStore), configFile, myClientId);
|
||||||
// Create versionCountingEncryptedBlockStore not in the same line as BlobStoreOnBlocks, because it can modify BlocksizeBytes
|
// Create integrityEncryptedBlockStore not in the same line as BlobStoreOnBlocks, because it can modify BlocksizeBytes
|
||||||
// in the configFile and therefore has to be run before the second parameter to the BlobStoreOnBlocks parameter is evaluated.
|
// in the configFile and therefore has to be run before the second parameter to the BlobStoreOnBlocks parameter is evaluated.
|
||||||
return make_unique_ref<BlobStoreOnBlocks>(
|
return make_unique_ref<BlobStoreOnBlocks>(
|
||||||
make_unique_ref<LowToHighLevelBlockStore>(
|
make_unique_ref<LowToHighLevelBlockStore>(
|
||||||
make_unique_ref<CachingBlockStore2>(
|
make_unique_ref<CachingBlockStore2>(
|
||||||
std::move(versionCountingEncryptedBlockStore)
|
std::move(integrityEncryptedBlockStore)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
configFile->config()->BlocksizeBytes());
|
configFile->config()->BlocksizeBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<BlockStore2> CryDevice::CreateVersionCountingEncryptedBlockStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId) {
|
unique_ref<BlockStore2> CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref<BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId) {
|
||||||
auto encryptedBlockStore = CreateEncryptedBlockStore(*configFile->config(), std::move(blockStore));
|
auto encryptedBlockStore = CreateEncryptedBlockStore(*configFile->config(), std::move(blockStore));
|
||||||
auto statePath = LocalStateDir::forFilesystemId(configFile->config()->FilesystemId());
|
auto statePath = LocalStateDir::forFilesystemId(configFile->config()->FilesystemId());
|
||||||
auto integrityFilePath = statePath / "integritydata";
|
auto integrityFilePath = statePath / "integritydata";
|
||||||
|
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
if (!configFile->config()->HasVersionNumbers()) {
|
if (!configFile->config()->HasVersionNumbers()) {
|
||||||
VersionCountingBlockStore2::migrateFromBlockstoreWithoutVersionNumbers(encryptedBlockStore.get(), integrityFilePath, myClientId);
|
IntegrityBlockStore2::migrateFromBlockstoreWithoutVersionNumbers(encryptedBlockStore.get(), integrityFilePath, myClientId);
|
||||||
configFile->config()->SetBlocksizeBytes(configFile->config()->BlocksizeBytes() + VersionCountingBlockStore2::HEADER_LENGTH);
|
configFile->config()->SetBlocksizeBytes(configFile->config()->BlocksizeBytes() + IntegrityBlockStore2::HEADER_LENGTH);
|
||||||
configFile->config()->SetHasVersionNumbers(true);
|
configFile->config()->SetHasVersionNumbers(true);
|
||||||
configFile->save();
|
configFile->save();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return make_unique_ref<VersionCountingBlockStore2>(std::move(encryptedBlockStore), integrityFilePath, myClientId, false);
|
return make_unique_ref<IntegrityBlockStore2>(std::move(encryptedBlockStore), integrityFilePath, myClientId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Key CryDevice::CreateRootBlobAndReturnKey() {
|
Key CryDevice::CreateRootBlobAndReturnKey() {
|
||||||
|
@ -58,7 +58,7 @@ private:
|
|||||||
static cpputils::unique_ref<fsblobstore::FsBlobStore> MigrateOrCreateFsBlobStore(cpputils::unique_ref<blobstore::BlobStore> blobStore, CryConfigFile *configFile);
|
static cpputils::unique_ref<fsblobstore::FsBlobStore> MigrateOrCreateFsBlobStore(cpputils::unique_ref<blobstore::BlobStore> blobStore, CryConfigFile *configFile);
|
||||||
#endif
|
#endif
|
||||||
static cpputils::unique_ref<blobstore::BlobStore> CreateBlobStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId);
|
static cpputils::unique_ref<blobstore::BlobStore> CreateBlobStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId);
|
||||||
static cpputils::unique_ref<blockstore::BlockStore2> CreateVersionCountingEncryptedBlockStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId);
|
static cpputils::unique_ref<blockstore::BlockStore2> CreateIntegrityEncryptedBlockStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId);
|
||||||
static cpputils::unique_ref<blockstore::BlockStore2> CreateEncryptedBlockStore(const CryConfig &config, cpputils::unique_ref<blockstore::BlockStore2> baseBlockStore);
|
static cpputils::unique_ref<blockstore::BlockStore2> CreateEncryptedBlockStore(const CryConfig &config, cpputils::unique_ref<blockstore::BlockStore2> baseBlockStore);
|
||||||
|
|
||||||
struct BlobWithParent {
|
struct BlobWithParent {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#include "MyClientId.h"
|
#include "MyClientId.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cpp-utils/random/Random.h>
|
#include <cpp-utils/random/Random.h>
|
||||||
#include <blockstore/implementations/versioncounting/KnownBlockVersions.h>
|
#include <blockstore/implementations/integrity/KnownBlockVersions.h>
|
||||||
|
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
using std::ifstream;
|
using std::ifstream;
|
||||||
using std::ofstream;
|
using std::ofstream;
|
||||||
using cpputils::Random;
|
using cpputils::Random;
|
||||||
using blockstore::versioncounting::KnownBlockVersions;
|
using blockstore::integrity::KnownBlockVersions;
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
@ -35,9 +35,9 @@ set(SOURCES
|
|||||||
implementations/caching/cache/CacheTest_RaceCondition.cpp
|
implementations/caching/cache/CacheTest_RaceCondition.cpp
|
||||||
implementations/caching/cache/PeriodicTaskTest.cpp
|
implementations/caching/cache/PeriodicTaskTest.cpp
|
||||||
implementations/caching/cache/QueueMapTest_Peek.cpp
|
implementations/caching/cache/QueueMapTest_Peek.cpp
|
||||||
implementations/versioncounting/KnownBlockVersionsTest.cpp
|
implementations/integrity/KnownBlockVersionsTest.cpp
|
||||||
implementations/versioncounting/VersionCountingBlockStoreTest_Generic.cpp
|
implementations/integrity/IntegrityBlockStoreTest_Generic.cpp
|
||||||
implementations/versioncounting/VersionCountingBlockStoreTest_Specific.cpp
|
implementations/integrity/IntegrityBlockStoreTest_Specific.cpp
|
||||||
implementations/low2highlevel/LowToHighLevelBlockStoreTest.cpp
|
implementations/low2highlevel/LowToHighLevelBlockStoreTest.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
#include "blockstore/implementations/integrity/IntegrityBlockStore2.h"
|
||||||
|
#include "blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h"
|
||||||
|
#include "blockstore/implementations/inmemory/InMemoryBlockStore2.h"
|
||||||
|
#include "../../testutils/BlockStoreTest.h"
|
||||||
|
#include "../../testutils/BlockStore2Test.h"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <cpp-utils/tempfile/TempFile.h>
|
||||||
|
|
||||||
|
using ::testing::Test;
|
||||||
|
|
||||||
|
using blockstore::BlockStore;
|
||||||
|
using blockstore::BlockStore2;
|
||||||
|
using blockstore::integrity::IntegrityBlockStore2;
|
||||||
|
using blockstore::integrity::KnownBlockVersions;
|
||||||
|
using blockstore::lowtohighlevel::LowToHighLevelBlockStore;
|
||||||
|
using blockstore::inmemory::InMemoryBlockStore2;
|
||||||
|
|
||||||
|
using cpputils::Data;
|
||||||
|
using cpputils::DataFixture;
|
||||||
|
using cpputils::make_unique_ref;
|
||||||
|
using cpputils::unique_ref;
|
||||||
|
using cpputils::TempFile;
|
||||||
|
|
||||||
|
template<bool MissingBlockIsIntegrityViolation>
|
||||||
|
class IntegrityBlockStoreTestFixture: public BlockStoreTestFixture {
|
||||||
|
public:
|
||||||
|
IntegrityBlockStoreTestFixture() :stateFile(false) {}
|
||||||
|
|
||||||
|
TempFile stateFile;
|
||||||
|
unique_ref<BlockStore> createBlockStore() override {
|
||||||
|
return make_unique_ref<LowToHighLevelBlockStore>(
|
||||||
|
make_unique_ref<IntegrityBlockStore2>(make_unique_ref<InMemoryBlockStore2>(), stateFile.path(), 0x12345678, MissingBlockIsIntegrityViolation)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO Why is here no IntegrityBlockStoreWithRandomKeysTest?
|
||||||
|
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient, BlockStoreTest, IntegrityBlockStoreTestFixture<false>);
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient, BlockStoreTest, IntegrityBlockStoreTestFixture<true>);
|
||||||
|
|
||||||
|
template<bool MissingBlockIsIntegrityViolation>
|
||||||
|
class IntegrityBlockStore2TestFixture: public BlockStore2TestFixture {
|
||||||
|
public:
|
||||||
|
IntegrityBlockStore2TestFixture() :stateFile(false) {}
|
||||||
|
|
||||||
|
TempFile stateFile;
|
||||||
|
unique_ref<BlockStore2> createBlockStore() override {
|
||||||
|
return make_unique_ref<IntegrityBlockStore2>(make_unique_ref<InMemoryBlockStore2>(), stateFile.path(), 0x12345678, MissingBlockIsIntegrityViolation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_multiclient, BlockStore2Test, IntegrityBlockStore2TestFixture<false>);
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(Integrity_singleclient, BlockStore2Test, IntegrityBlockStore2TestFixture<true>);
|
@ -1,5 +1,5 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include "blockstore/implementations/versioncounting/VersionCountingBlockStore2.h"
|
#include "blockstore/implementations/integrity/IntegrityBlockStore2.h"
|
||||||
#include "blockstore/implementations/inmemory/InMemoryBlockStore2.h"
|
#include "blockstore/implementations/inmemory/InMemoryBlockStore2.h"
|
||||||
#include "blockstore/utils/BlockStoreUtils.h"
|
#include "blockstore/utils/BlockStoreUtils.h"
|
||||||
#include <cpp-utils/data/DataFixture.h>
|
#include <cpp-utils/data/DataFixture.h>
|
||||||
@ -19,32 +19,32 @@ using std::unique_ptr;
|
|||||||
|
|
||||||
using blockstore::inmemory::InMemoryBlockStore2;
|
using blockstore::inmemory::InMemoryBlockStore2;
|
||||||
|
|
||||||
using namespace blockstore::versioncounting;
|
using namespace blockstore::integrity;
|
||||||
|
|
||||||
class VersionCountingBlockStoreTest: public Test {
|
class IntegrityBlockStoreTest: public Test {
|
||||||
public:
|
public:
|
||||||
static constexpr unsigned int BLOCKSIZE = 1024;
|
static constexpr unsigned int BLOCKSIZE = 1024;
|
||||||
VersionCountingBlockStoreTest():
|
IntegrityBlockStoreTest():
|
||||||
stateFile(false),
|
stateFile(false),
|
||||||
baseBlockStore(new InMemoryBlockStore2),
|
baseBlockStore(new InMemoryBlockStore2),
|
||||||
blockStore(make_unique_ref<VersionCountingBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, false)),
|
blockStore(make_unique_ref<IntegrityBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, false)),
|
||||||
data(DataFixture::generate(BLOCKSIZE)) {
|
data(DataFixture::generate(BLOCKSIZE)) {
|
||||||
}
|
}
|
||||||
static constexpr uint32_t myClientId = 0x12345678;
|
static constexpr uint32_t myClientId = 0x12345678;
|
||||||
TempFile stateFile;
|
TempFile stateFile;
|
||||||
InMemoryBlockStore2 *baseBlockStore;
|
InMemoryBlockStore2 *baseBlockStore;
|
||||||
unique_ref<VersionCountingBlockStore2> blockStore;
|
unique_ref<IntegrityBlockStore2> blockStore;
|
||||||
Data data;
|
Data data;
|
||||||
|
|
||||||
std::pair<InMemoryBlockStore2 *, unique_ptr<VersionCountingBlockStore2>> makeBlockStoreWithDeletionPrevention() {
|
std::pair<InMemoryBlockStore2 *, unique_ptr<IntegrityBlockStore2>> makeBlockStoreWithDeletionPrevention() {
|
||||||
InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2;
|
InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2;
|
||||||
auto blockStore = make_unique<VersionCountingBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, true);
|
auto blockStore = make_unique<IntegrityBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, true);
|
||||||
return std::make_pair(baseBlockStore, std::move(blockStore));
|
return std::make_pair(baseBlockStore, std::move(blockStore));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<InMemoryBlockStore2 *, unique_ptr<VersionCountingBlockStore2>> makeBlockStoreWithoutDeletionPrevention() {
|
std::pair<InMemoryBlockStore2 *, unique_ptr<IntegrityBlockStore2>> makeBlockStoreWithoutDeletionPrevention() {
|
||||||
InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2;
|
InMemoryBlockStore2 *baseBlockStore = new InMemoryBlockStore2;
|
||||||
auto blockStore = make_unique<VersionCountingBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, false);
|
auto blockStore = make_unique<IntegrityBlockStore2>(std::move(cpputils::nullcheck(std::unique_ptr<InMemoryBlockStore2>(baseBlockStore)).value()), stateFile.path(), myClientId, false);
|
||||||
return std::make_pair(baseBlockStore, std::move(blockStore));
|
return std::make_pair(baseBlockStore, std::move(blockStore));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ public:
|
|||||||
|
|
||||||
void decreaseVersionNumber(const blockstore::Key &key) {
|
void decreaseVersionNumber(const blockstore::Key &key) {
|
||||||
auto baseBlock = baseBlockStore->load(key).value();
|
auto baseBlock = baseBlockStore->load(key).value();
|
||||||
uint64_t* version = (uint64_t*)((uint8_t*)baseBlock.data()+VersionCountingBlockStore2::VERSION_HEADER_OFFSET);
|
uint64_t* version = (uint64_t*)((uint8_t*)baseBlock.data()+IntegrityBlockStore2::VERSION_HEADER_OFFSET);
|
||||||
ASSERT(*version > 1, "Can't decrease the lowest allowed version number");
|
ASSERT(*version > 1, "Can't decrease the lowest allowed version number");
|
||||||
*version -= 1;
|
*version -= 1;
|
||||||
baseBlockStore->store(key, baseBlock);
|
baseBlockStore->store(key, baseBlock);
|
||||||
@ -85,14 +85,14 @@ public:
|
|||||||
|
|
||||||
void increaseVersionNumber(const blockstore::Key &key) {
|
void increaseVersionNumber(const blockstore::Key &key) {
|
||||||
auto baseBlock = baseBlockStore->load(key).value();
|
auto baseBlock = baseBlockStore->load(key).value();
|
||||||
uint64_t* version = (uint64_t*)((uint8_t*)baseBlock.data()+VersionCountingBlockStore2::VERSION_HEADER_OFFSET);
|
uint64_t* version = (uint64_t*)((uint8_t*)baseBlock.data()+IntegrityBlockStore2::VERSION_HEADER_OFFSET);
|
||||||
*version += 1;
|
*version += 1;
|
||||||
baseBlockStore->store(key, baseBlock);
|
baseBlockStore->store(key, baseBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeClientId(const blockstore::Key &key) {
|
void changeClientId(const blockstore::Key &key) {
|
||||||
auto baseBlock = baseBlockStore->load(key).value();
|
auto baseBlock = baseBlockStore->load(key).value();
|
||||||
uint32_t* clientId = (uint32_t*)((uint8_t*)baseBlock.data()+VersionCountingBlockStore2::CLIENTID_HEADER_OFFSET);
|
uint32_t* clientId = (uint32_t*)((uint8_t*)baseBlock.data()+IntegrityBlockStore2::CLIENTID_HEADER_OFFSET);
|
||||||
*clientId += 1;
|
*clientId += 1;
|
||||||
baseBlockStore->store(key, baseBlock);
|
baseBlockStore->store(key, baseBlock);
|
||||||
}
|
}
|
||||||
@ -106,13 +106,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(VersionCountingBlockStoreTest);
|
DISALLOW_COPY_AND_ASSIGN(IntegrityBlockStoreTest);
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr uint32_t VersionCountingBlockStoreTest::myClientId;
|
constexpr uint32_t IntegrityBlockStoreTest::myClientId;
|
||||||
|
|
||||||
// Test that a decreasing version number is not allowed
|
// Test that a decreasing version number is not allowed
|
||||||
TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesntAllowDecreasingVersionNumberForSameClient_1) {
|
TEST_F(IntegrityBlockStoreTest, RollbackPrevention_DoesntAllowDecreasingVersionNumberForSameClient_1) {
|
||||||
auto key = CreateBlockReturnKey();
|
auto key = CreateBlockReturnKey();
|
||||||
Data oldBaseBlock = loadBaseBlock(key);
|
Data oldBaseBlock = loadBaseBlock(key);
|
||||||
modifyBlock(key);
|
modifyBlock(key);
|
||||||
@ -123,7 +123,7 @@ TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesntAllowDecreasingVe
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesntAllowDecreasingVersionNumberForSameClient_2) {
|
TEST_F(IntegrityBlockStoreTest, RollbackPrevention_DoesntAllowDecreasingVersionNumberForSameClient_2) {
|
||||||
auto key = CreateBlockReturnKey();
|
auto key = CreateBlockReturnKey();
|
||||||
// Increase the version number
|
// Increase the version number
|
||||||
modifyBlock(key);
|
modifyBlock(key);
|
||||||
@ -136,7 +136,7 @@ TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesntAllowDecreasingVe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test that a different client doesn't need to have a higher version number (i.e. version numbers are per client).
|
// Test that a different client doesn't need to have a higher version number (i.e. version numbers are per client).
|
||||||
TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesAllowDecreasingVersionNumberForDifferentClient) {
|
TEST_F(IntegrityBlockStoreTest, RollbackPrevention_DoesAllowDecreasingVersionNumberForDifferentClient) {
|
||||||
auto key = CreateBlockReturnKey();
|
auto key = CreateBlockReturnKey();
|
||||||
// Increase the version number
|
// Increase the version number
|
||||||
modifyBlock(key);
|
modifyBlock(key);
|
||||||
@ -147,7 +147,7 @@ TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesAllowDecreasingVers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test that it doesn't allow a rollback to the "newest" block of a client, when this block was superseded by a version of a different client
|
// Test that it doesn't allow a rollback to the "newest" block of a client, when this block was superseded by a version of a different client
|
||||||
TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesntAllowSameVersionNumberForOldClient) {
|
TEST_F(IntegrityBlockStoreTest, RollbackPrevention_DoesntAllowSameVersionNumberForOldClient) {
|
||||||
auto key = CreateBlockReturnKey();
|
auto key = CreateBlockReturnKey();
|
||||||
// Increase the version number
|
// Increase the version number
|
||||||
modifyBlock(key);
|
modifyBlock(key);
|
||||||
@ -164,7 +164,7 @@ TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesntAllowSameVersionN
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test that deleted blocks cannot be re-introduced
|
// Test that deleted blocks cannot be re-introduced
|
||||||
TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesntAllowReintroducingDeletedBlocks) {
|
TEST_F(IntegrityBlockStoreTest, RollbackPrevention_DoesntAllowReintroducingDeletedBlocks) {
|
||||||
auto key = CreateBlockReturnKey();
|
auto key = CreateBlockReturnKey();
|
||||||
Data oldBaseBlock = loadBaseBlock(key);
|
Data oldBaseBlock = loadBaseBlock(key);
|
||||||
deleteBlock(key);
|
deleteBlock(key);
|
||||||
@ -176,7 +176,7 @@ TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_DoesntAllowReintroducin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This can happen if a client synchronization is delayed. Another client might have won the conflict and pushed a new version for the deleted block.
|
// This can happen if a client synchronization is delayed. Another client might have won the conflict and pushed a new version for the deleted block.
|
||||||
TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_AllowsReintroducingDeletedBlocksWithNewVersionNumber) {
|
TEST_F(IntegrityBlockStoreTest, RollbackPrevention_AllowsReintroducingDeletedBlocksWithNewVersionNumber) {
|
||||||
auto key = CreateBlockReturnKey();
|
auto key = CreateBlockReturnKey();
|
||||||
Data oldBaseBlock = loadBaseBlock(key);
|
Data oldBaseBlock = loadBaseBlock(key);
|
||||||
deleteBlock(key);
|
deleteBlock(key);
|
||||||
@ -186,9 +186,9 @@ TEST_F(VersionCountingBlockStoreTest, RollbackPrevention_AllowsReintroducingDele
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that in a multi-client scenario, missing blocks are not integrity errors, because another client might have deleted them.
|
// Check that in a multi-client scenario, missing blocks are not integrity errors, because another client might have deleted them.
|
||||||
TEST_F(VersionCountingBlockStoreTest, DeletionPrevention_AllowsDeletingBlocksWhenDeactivated) {
|
TEST_F(IntegrityBlockStoreTest, DeletionPrevention_AllowsDeletingBlocksWhenDeactivated) {
|
||||||
InMemoryBlockStore2 *baseBlockStore;
|
InMemoryBlockStore2 *baseBlockStore;
|
||||||
unique_ptr<VersionCountingBlockStore2> blockStore;
|
unique_ptr<IntegrityBlockStore2> blockStore;
|
||||||
std::tie(baseBlockStore, blockStore) = makeBlockStoreWithoutDeletionPrevention();
|
std::tie(baseBlockStore, blockStore) = makeBlockStoreWithoutDeletionPrevention();
|
||||||
auto key = blockStore->create(Data(0));
|
auto key = blockStore->create(Data(0));
|
||||||
baseBlockStore->remove(key);
|
baseBlockStore->remove(key);
|
||||||
@ -196,9 +196,9 @@ TEST_F(VersionCountingBlockStoreTest, DeletionPrevention_AllowsDeletingBlocksWhe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that in a single-client scenario, missing blocks are integrity errors.
|
// Check that in a single-client scenario, missing blocks are integrity errors.
|
||||||
TEST_F(VersionCountingBlockStoreTest, DeletionPrevention_DoesntAllowDeletingBlocksWhenActivated) {
|
TEST_F(IntegrityBlockStoreTest, DeletionPrevention_DoesntAllowDeletingBlocksWhenActivated) {
|
||||||
InMemoryBlockStore2 *baseBlockStore;
|
InMemoryBlockStore2 *baseBlockStore;
|
||||||
unique_ptr<VersionCountingBlockStore2> blockStore;
|
unique_ptr<IntegrityBlockStore2> blockStore;
|
||||||
std::tie(baseBlockStore, blockStore) = makeBlockStoreWithDeletionPrevention();
|
std::tie(baseBlockStore, blockStore) = makeBlockStoreWithDeletionPrevention();
|
||||||
auto key = blockStore->create(Data(0));
|
auto key = blockStore->create(Data(0));
|
||||||
baseBlockStore->remove(key);
|
baseBlockStore->remove(key);
|
||||||
@ -209,9 +209,9 @@ TEST_F(VersionCountingBlockStoreTest, DeletionPrevention_DoesntAllowDeletingBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that in a multi-client scenario, missing blocks are not integrity errors, because another client might have deleted them.
|
// Check that in a multi-client scenario, missing blocks are not integrity errors, because another client might have deleted them.
|
||||||
TEST_F(VersionCountingBlockStoreTest, DeletionPrevention_InForEachBlock_AllowsDeletingBlocksWhenDeactivated) {
|
TEST_F(IntegrityBlockStoreTest, DeletionPrevention_InForEachBlock_AllowsDeletingBlocksWhenDeactivated) {
|
||||||
InMemoryBlockStore2 *baseBlockStore;
|
InMemoryBlockStore2 *baseBlockStore;
|
||||||
unique_ptr<VersionCountingBlockStore2> blockStore;
|
unique_ptr<IntegrityBlockStore2> blockStore;
|
||||||
std::tie(baseBlockStore, blockStore) = makeBlockStoreWithoutDeletionPrevention();
|
std::tie(baseBlockStore, blockStore) = makeBlockStoreWithoutDeletionPrevention();
|
||||||
auto key = blockStore->create(Data(0));
|
auto key = blockStore->create(Data(0));
|
||||||
baseBlockStore->remove(key);
|
baseBlockStore->remove(key);
|
||||||
@ -223,9 +223,9 @@ TEST_F(VersionCountingBlockStoreTest, DeletionPrevention_InForEachBlock_AllowsDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that in a single-client scenario, missing blocks are integrity errors.
|
// Check that in a single-client scenario, missing blocks are integrity errors.
|
||||||
TEST_F(VersionCountingBlockStoreTest, DeletionPrevention_InForEachBlock_DoesntAllowDeletingBlocksWhenActivated) {
|
TEST_F(IntegrityBlockStoreTest, DeletionPrevention_InForEachBlock_DoesntAllowDeletingBlocksWhenActivated) {
|
||||||
InMemoryBlockStore2 *baseBlockStore;
|
InMemoryBlockStore2 *baseBlockStore;
|
||||||
unique_ptr<VersionCountingBlockStore2> blockStore;
|
unique_ptr<IntegrityBlockStore2> blockStore;
|
||||||
std::tie(baseBlockStore, blockStore) = makeBlockStoreWithDeletionPrevention();
|
std::tie(baseBlockStore, blockStore) = makeBlockStoreWithDeletionPrevention();
|
||||||
auto key = blockStore->create(Data(0));
|
auto key = blockStore->create(Data(0));
|
||||||
baseBlockStore->remove(key);
|
baseBlockStore->remove(key);
|
||||||
@ -235,7 +235,7 @@ TEST_F(VersionCountingBlockStoreTest, DeletionPrevention_InForEachBlock_DoesntAl
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VersionCountingBlockStoreTest, LoadingWithDifferentBlockIdFails) {
|
TEST_F(IntegrityBlockStoreTest, LoadingWithDifferentBlockIdFails) {
|
||||||
auto key = CreateBlockReturnKey();
|
auto key = CreateBlockReturnKey();
|
||||||
blockstore::Key key2 = blockstore::Key::FromString("1491BB4932A389EE14BC7090AC772972");
|
blockstore::Key key2 = blockstore::Key::FromString("1491BB4932A389EE14BC7090AC772972");
|
||||||
baseBlockStore->store(key2, baseBlockStore->load(key).value());
|
baseBlockStore->store(key2, baseBlockStore->load(key).value());
|
||||||
@ -250,17 +250,17 @@ TEST_F(VersionCountingBlockStoreTest, LoadingWithDifferentBlockIdFails) {
|
|||||||
// - RollbackPrevention_AllowsReintroducingDeletedBlocksWithNewVersionNumber with different client id
|
// - RollbackPrevention_AllowsReintroducingDeletedBlocksWithNewVersionNumber with different client id
|
||||||
// - Think about more...
|
// - Think about more...
|
||||||
|
|
||||||
TEST_F(VersionCountingBlockStoreTest, PhysicalBlockSize_zerophysical) {
|
TEST_F(IntegrityBlockStoreTest, PhysicalBlockSize_zerophysical) {
|
||||||
EXPECT_EQ(0u, blockStore->blockSizeFromPhysicalBlockSize(0));
|
EXPECT_EQ(0u, blockStore->blockSizeFromPhysicalBlockSize(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VersionCountingBlockStoreTest, PhysicalBlockSize_zerovirtual) {
|
TEST_F(IntegrityBlockStoreTest, PhysicalBlockSize_zerovirtual) {
|
||||||
auto key = CreateBlockReturnKey(Data(0));
|
auto key = CreateBlockReturnKey(Data(0));
|
||||||
auto base = baseBlockStore->load(key).value();
|
auto base = baseBlockStore->load(key).value();
|
||||||
EXPECT_EQ(0u, blockStore->blockSizeFromPhysicalBlockSize(base.size()));
|
EXPECT_EQ(0u, blockStore->blockSizeFromPhysicalBlockSize(base.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VersionCountingBlockStoreTest, PhysicalBlockSize_negativeboundaries) {
|
TEST_F(IntegrityBlockStoreTest, PhysicalBlockSize_negativeboundaries) {
|
||||||
// This tests that a potential if/else in blockSizeFromPhysicalBlockSize that catches negative values has the
|
// This tests that a potential if/else in blockSizeFromPhysicalBlockSize that catches negative values has the
|
||||||
// correct boundary set. We test the highest value that is negative and the smallest value that is positive.
|
// correct boundary set. We test the highest value that is negative and the smallest value that is positive.
|
||||||
auto physicalSizeForVirtualSizeZero = baseBlockStore->load(CreateBlockReturnKey(Data(0))).value().size();
|
auto physicalSizeForVirtualSizeZero = baseBlockStore->load(CreateBlockReturnKey(Data(0))).value().size();
|
||||||
@ -271,7 +271,7 @@ TEST_F(VersionCountingBlockStoreTest, PhysicalBlockSize_negativeboundaries) {
|
|||||||
EXPECT_EQ(1u, blockStore->blockSizeFromPhysicalBlockSize(physicalSizeForVirtualSizeZero + 1));
|
EXPECT_EQ(1u, blockStore->blockSizeFromPhysicalBlockSize(physicalSizeForVirtualSizeZero + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VersionCountingBlockStoreTest, PhysicalBlockSize_positive) {
|
TEST_F(IntegrityBlockStoreTest, PhysicalBlockSize_positive) {
|
||||||
auto key = CreateBlockReturnKey(Data(10*1024));
|
auto key = CreateBlockReturnKey(Data(10*1024));
|
||||||
auto base = baseBlockStore->load(key).value();
|
auto base = baseBlockStore->load(key).value();
|
||||||
EXPECT_EQ(10*1024u, blockStore->blockSizeFromPhysicalBlockSize(base.size()));
|
EXPECT_EQ(10*1024u, blockStore->blockSizeFromPhysicalBlockSize(base.size()));
|
@ -1,8 +1,8 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <blockstore/implementations/versioncounting/KnownBlockVersions.h>
|
#include <blockstore/implementations/integrity/KnownBlockVersions.h>
|
||||||
#include <cpp-utils/tempfile/TempFile.h>
|
#include <cpp-utils/tempfile/TempFile.h>
|
||||||
|
|
||||||
using blockstore::versioncounting::KnownBlockVersions;
|
using blockstore::integrity::KnownBlockVersions;
|
||||||
using blockstore::Key;
|
using blockstore::Key;
|
||||||
using cpputils::TempFile;
|
using cpputils::TempFile;
|
||||||
using std::unordered_set;
|
using std::unordered_set;
|
@ -1,54 +0,0 @@
|
|||||||
#include "blockstore/implementations/versioncounting/VersionCountingBlockStore2.h"
|
|
||||||
#include "blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h"
|
|
||||||
#include "blockstore/implementations/inmemory/InMemoryBlockStore2.h"
|
|
||||||
#include "../../testutils/BlockStoreTest.h"
|
|
||||||
#include "../../testutils/BlockStore2Test.h"
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <cpp-utils/tempfile/TempFile.h>
|
|
||||||
|
|
||||||
using ::testing::Test;
|
|
||||||
|
|
||||||
using blockstore::BlockStore;
|
|
||||||
using blockstore::BlockStore2;
|
|
||||||
using blockstore::versioncounting::VersionCountingBlockStore2;
|
|
||||||
using blockstore::versioncounting::KnownBlockVersions;
|
|
||||||
using blockstore::lowtohighlevel::LowToHighLevelBlockStore;
|
|
||||||
using blockstore::inmemory::InMemoryBlockStore2;
|
|
||||||
|
|
||||||
using cpputils::Data;
|
|
||||||
using cpputils::DataFixture;
|
|
||||||
using cpputils::make_unique_ref;
|
|
||||||
using cpputils::unique_ref;
|
|
||||||
using cpputils::TempFile;
|
|
||||||
|
|
||||||
template<bool MissingBlockIsIntegrityViolation>
|
|
||||||
class VersionCountingBlockStoreTestFixture: public BlockStoreTestFixture {
|
|
||||||
public:
|
|
||||||
VersionCountingBlockStoreTestFixture() :stateFile(false) {}
|
|
||||||
|
|
||||||
TempFile stateFile;
|
|
||||||
unique_ref<BlockStore> createBlockStore() override {
|
|
||||||
return make_unique_ref<LowToHighLevelBlockStore>(
|
|
||||||
make_unique_ref<VersionCountingBlockStore2>(make_unique_ref<InMemoryBlockStore2>(), stateFile.path(), 0x12345678, MissingBlockIsIntegrityViolation)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO Why is here no VersionCountingBlockStoreWithRandomKeysTest?
|
|
||||||
|
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(VersionCounting_multiclient, BlockStoreTest, VersionCountingBlockStoreTestFixture<false>);
|
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(VersionCounting_singleclient, BlockStoreTest, VersionCountingBlockStoreTestFixture<true>);
|
|
||||||
|
|
||||||
template<bool MissingBlockIsIntegrityViolation>
|
|
||||||
class VersionCountingBlockStore2TestFixture: public BlockStore2TestFixture {
|
|
||||||
public:
|
|
||||||
VersionCountingBlockStore2TestFixture() :stateFile(false) {}
|
|
||||||
|
|
||||||
TempFile stateFile;
|
|
||||||
unique_ref<BlockStore2> createBlockStore() override {
|
|
||||||
return make_unique_ref<VersionCountingBlockStore2>(make_unique_ref<InMemoryBlockStore2>(), stateFile.path(), 0x12345678, MissingBlockIsIntegrityViolation);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(VersionCounting_multiclient, BlockStore2Test, VersionCountingBlockStore2TestFixture<false>);
|
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(VersionCounting_singleclient, BlockStore2Test, VersionCountingBlockStore2TestFixture<true>);
|
|
Loading…
Reference in New Issue
Block a user