2015-02-17 00:23:33 +01:00
|
|
|
#include <messmer/blockstore/test/testutils/DataBlockFixture.h>
|
|
|
|
#include <messmer/blockstore/utils/Data.h>
|
|
|
|
#include <messmer/blockstore/utils/FileDoesntExistException.h>
|
|
|
|
#include "google/gtest/gtest.h"
|
2014-12-09 17:19:59 +01:00
|
|
|
|
2015-02-17 00:23:33 +01:00
|
|
|
#include "messmer/tempfile/src/TempFile.h"
|
2014-12-09 17:19:59 +01:00
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
using ::testing::Test;
|
|
|
|
using ::testing::WithParamInterface;
|
|
|
|
using ::testing::Values;
|
|
|
|
|
2015-02-17 00:23:33 +01:00
|
|
|
using tempfile::TempFile;
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
using std::ifstream;
|
|
|
|
using std::ofstream;
|
|
|
|
|
2015-02-17 00:23:33 +01:00
|
|
|
namespace bf = boost::filesystem;
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
using namespace blockstore;
|
|
|
|
|
|
|
|
class DataTest: public Test {
|
|
|
|
public:
|
|
|
|
bool DataIsZeroes(const Data &data) {
|
|
|
|
for (size_t i = 0; i != data.size(); ++ i) {
|
|
|
|
if (((char*)data.data())[i] != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FillData(const DataBlockFixture &fillData, Data *data) {
|
|
|
|
ASSERT_EQ(fillData.size(), data->size());
|
|
|
|
std::memcpy(data->data(), fillData.data(), fillData.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
void EXPECT_DATA_CORRECT(const DataBlockFixture &expectedData, const Data &data) {
|
|
|
|
ASSERT_EQ(expectedData.size(), data.size());
|
|
|
|
EXPECT_EQ(0, std::memcmp(expectedData.data(), data.data(), expectedData.size()));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DataTestWithSizeParam: public DataTest, public WithParamInterface<size_t> {
|
|
|
|
public:
|
|
|
|
DataBlockFixture randomData;
|
|
|
|
|
|
|
|
DataTestWithSizeParam(): randomData(GetParam()) {}
|
|
|
|
|
|
|
|
void FillData(Data *data) {
|
|
|
|
DataTest::FillData(randomData, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreData(const bf::path &filepath) {
|
|
|
|
ofstream file(filepath.c_str(), std::ios::binary | std::ios::trunc);
|
|
|
|
file.write(randomData.data(), randomData.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
void EXPECT_STORED_FILE_DATA_CORRECT(const bf::path &filepath) {
|
|
|
|
EXPECT_EQ(randomData.size(), bf::file_size(filepath));
|
|
|
|
|
|
|
|
ifstream file(filepath.c_str(), std::ios::binary);
|
|
|
|
char *read_data = new char[randomData.size()];
|
|
|
|
file.read(read_data, randomData.size());
|
|
|
|
|
|
|
|
EXPECT_EQ(0, std::memcmp(randomData.data(), read_data, randomData.size()));
|
|
|
|
delete[] read_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EXPECT_DATA_CORRECT(const Data &data) {
|
|
|
|
DataTest::EXPECT_DATA_CORRECT(randomData, data);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
INSTANTIATE_TEST_CASE_P(DataTestWithSizeParam, DataTestWithSizeParam, Values(0, 1, 2, 1024, 4096, 10*1024*1024));
|
|
|
|
|
|
|
|
// Working on a large data area without a crash is a good indicator that we
|
|
|
|
// are actually working on memory that was validly allocated for us.
|
|
|
|
TEST_P(DataTestWithSizeParam, WriteAndCheck) {
|
|
|
|
Data data(GetParam());
|
|
|
|
|
|
|
|
FillData(&data);
|
|
|
|
EXPECT_DATA_CORRECT(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_P(DataTestWithSizeParam, Size) {
|
|
|
|
Data data(GetParam());
|
|
|
|
EXPECT_EQ(GetParam(), data.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_P(DataTestWithSizeParam, CheckStoredFile) {
|
|
|
|
Data data(GetParam());
|
|
|
|
FillData(&data);
|
|
|
|
|
|
|
|
TempFile file;
|
|
|
|
data.StoreToFile(file.path());
|
|
|
|
|
|
|
|
EXPECT_STORED_FILE_DATA_CORRECT(file.path());
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_P(DataTestWithSizeParam, CheckLoadedData) {
|
|
|
|
TempFile file;
|
|
|
|
StoreData(file.path());
|
|
|
|
|
|
|
|
Data data = Data::LoadFromFile(file.path());
|
|
|
|
|
|
|
|
EXPECT_DATA_CORRECT(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_P(DataTestWithSizeParam, StoreDoesntChangeData) {
|
|
|
|
Data data(GetParam());
|
|
|
|
FillData(&data);
|
|
|
|
|
|
|
|
TempFile file;
|
|
|
|
data.StoreToFile(file.path());
|
|
|
|
|
|
|
|
EXPECT_DATA_CORRECT(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_P(DataTestWithSizeParam, StoreAndLoad) {
|
|
|
|
Data data(GetParam());
|
|
|
|
FillData(&data);
|
|
|
|
|
|
|
|
TempFile file;
|
|
|
|
data.StoreToFile(file.path());
|
|
|
|
Data loaded_data = Data::LoadFromFile(file.path());
|
|
|
|
|
|
|
|
EXPECT_DATA_CORRECT(loaded_data);
|
|
|
|
}
|
|
|
|
|
2014-12-11 01:41:08 +01:00
|
|
|
TEST_P(DataTestWithSizeParam, Copy) {
|
|
|
|
Data data(GetParam());
|
|
|
|
FillData(&data);
|
|
|
|
|
|
|
|
Data copy = data.copy();
|
|
|
|
|
|
|
|
EXPECT_DATA_CORRECT(copy);
|
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
TEST_F(DataTest, InitializeWithZeroes) {
|
|
|
|
Data data(10*1024);
|
|
|
|
data.FillWithZeroes();
|
|
|
|
EXPECT_TRUE(DataIsZeroes(data));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DataTest, FillModifiedDataWithZeroes) {
|
|
|
|
Data data(10*1024);
|
|
|
|
DataBlockFixture randomData(10*1024);
|
|
|
|
FillData(randomData, &data);
|
|
|
|
EXPECT_FALSE(DataIsZeroes(data));
|
|
|
|
|
|
|
|
data.FillWithZeroes();
|
|
|
|
EXPECT_TRUE(DataIsZeroes(data));
|
|
|
|
}
|
|
|
|
|
|
|
|
//Needs 64bit for representation. This value isn't in the size param list, because the list is also used for read/write checks.
|
|
|
|
TEST_F(DataTest, LargesizeSize) {
|
|
|
|
size_t size = 10L*1024*1024*1024;
|
|
|
|
Data data(size);
|
|
|
|
EXPECT_EQ(size, data.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
// This test doesn't ensure that the Data class gives the memory region free,
|
|
|
|
// but it is a good indicator.
|
|
|
|
TEST_F(DataTest, InaccessibleAfterDeletion) {
|
|
|
|
Data *data = new Data(1);
|
|
|
|
((char*)data->data())[0] = 0x3E; // Access data byte 0
|
|
|
|
|
|
|
|
delete data;
|
|
|
|
|
|
|
|
EXPECT_DEATH(
|
|
|
|
((char*)data->data())[0] = 0x3E,
|
|
|
|
""
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DataTest, LoadingNonexistingFile) {
|
|
|
|
TempFile file(false); // Pass false to constructor, so the tempfile is not created
|
|
|
|
EXPECT_THROW(
|
|
|
|
Data::LoadFromFile(file.path()),
|
|
|
|
FileDoesntExistException
|
|
|
|
);
|
|
|
|
}
|