Commit f47e1110 authored by Giorgio Azzinnaro's avatar Giorgio Azzinnaro

started random generator

parent 685a131d
......@@ -3,6 +3,8 @@ add_subdirectory(protobuf) # Generated Protobuf (& gRPC if neeeded) code
add_subdirectory(format)
add_subdirectory(vault)
add_subdirectory(util)
add_library(profanedb)
target_link_libraries(profanedb profanedb_format profanedb_vault profanedb_protobuf)
......
find_package(Boost REQUIRED COMPONENTS random)
include_directories (${Boost_INCLUDE_DIRS})
add_library(profanedb_util randomgenerator.cpp)
target_link_libraries(profanedb_util ${Boost_LIBRARIES})
/*
* ProfaneDB - A Protocol Buffers database.
* Copyright (C) 2017 "Giorgio Azzinnaro" <giorgio.azzinnaro@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "randomgenerator.h"
using boost::random::random_device;
using boost::random::uniform_int_distribution;
using boost::random::uniform_real_distribution;
using google::protobuf::Message;
using google::protobuf::Descriptor;
using google::protobuf::FieldDescriptor;
using google::protobuf::Reflection;
using std::numeric_limits;
namespace profanedb {
namespace util {
RandomGenerator::RandomGenerator(const random_device & rng)
: rng(rng)
{
}
#define RANDOM_VALUE(TYPE, BODY) template<> TYPE RandomGenerator::RandomValue< TYPE >() { BODY }
#define INT_RANDOM_VALUE(TYPE) RANDOM_VALUE(TYPE, \
boost::random::mt19937 gen; \
uniform_int_distribution< TYPE > range( \
numeric_limits< TYPE >::min(), \
numeric_limits< TYPE >::min()); \
return range(gen); )
INT_RANDOM_VALUE(google::protobuf::int32);
INT_RANDOM_VALUE(google::protobuf::int64);
INT_RANDOM_VALUE(google::protobuf::uint32);
INT_RANDOM_VALUE(google::protobuf::uint64);
#undef INT_RANDOM_VALUE
RANDOM_VALUE(google::protobuf::string,
// TODO
return "string";
)
#define REAL_RANDOM_VALUE(TYPE) RANDOM_VALUE(TYPE, \
boost::random::mt19937 gen; \
uniform_real_distribution<> range( \
numeric_limits< TYPE >::min(), \
numeric_limits< TYPE >::max()); \
return range(gen); )
REAL_RANDOM_VALUE(double);
REAL_RANDOM_VALUE(float);
#undef REAL_RANDOM_VALUE
RANDOM_VALUE(bool,
// TODO
return true;
)
#undef RANDOM_VALUE
void RandomGenerator::FillRandomly(Message * message)
{
// Descriptor is used to iterate through the existing fields
const Descriptor * descriptor = message->GetDescriptor();
// Reflection is used to set the values without knowing the types at compile time
const Reflection * reflection = message->GetReflection();
for(int i = 0; i < descriptor->field_count(); i++) {
const FieldDescriptor * fd = descriptor->field(i);
// Fill field randomly
this->GenerateField(message, reflection, fd);
}
}
void RandomGenerator::GenerateField(
Message * message,
const Reflection * reflection,
const FieldDescriptor * fd)
{
if (fd->is_repeated()) {
// TODO If is repeated, generate a random number of random fields
for (uint k = 0; k < this->RandomValue<google::protobuf::uint32>(); k++) {
switch (fd->cpp_type()) {
#define HANDLE_TYPE(CPPTYPE, METHOD, TYPE) \
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
reflection->Add##METHOD(message, fd, this->RandomValue<TYPE>()); \
break;
HANDLE_TYPE(INT32 , Int32 , google::protobuf::int32 );
HANDLE_TYPE(INT64 , Int64 , google::protobuf::int64 );
HANDLE_TYPE(UINT32, UInt32, google::protobuf::uint32);
HANDLE_TYPE(UINT64, UInt64, google::protobuf::uint64);
HANDLE_TYPE(STRING, String, google::protobuf::string);
HANDLE_TYPE(DOUBLE, Double, double );
HANDLE_TYPE(FLOAT , Float , float );
HANDLE_TYPE(BOOL , Bool , bool );
#undef HANDLE_TYPE
}
}
}
else {
switch (fd->cpp_type()) {
#define HANDLE_TYPE(CPPTYPE, METHOD, TYPE) \
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
reflection->Set##METHOD(message, fd, this->RandomValue<TYPE>()); \
break;
HANDLE_TYPE(INT32 , Int32 , google::protobuf::int32 );
HANDLE_TYPE(INT64 , Int64 , google::protobuf::int64 );
HANDLE_TYPE(UINT32, UInt32, google::protobuf::uint32);
HANDLE_TYPE(UINT64, UInt64, google::protobuf::uint64);
HANDLE_TYPE(STRING, String, google::protobuf::string);
HANDLE_TYPE(DOUBLE, Double, double );
HANDLE_TYPE(FLOAT , Float , float );
HANDLE_TYPE(BOOL , Bool , bool );
#undef HANDLE_TYPE
}
}
// TODO Message
}
}
}
/*
* ProfaneDB - A Protocol Buffers database.
* Copyright (C) 2017 "Giorgio Azzinnaro" <giorgio.azzinnaro@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef PROFANEDB_UTIL_RANDOMGENERATOR_H
#define PROFANEDB_UTIL_RANDOMGENERATOR_H
#include <limits>
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <google/protobuf/message.h>
namespace profanedb {
namespace util {
class RandomGenerator
{
public:
RandomGenerator(const boost::random::random_device & rng);
// Iterate through all fields and fill with random data
void FillRandomly(google::protobuf::Message * message);
// Template function to generate random values for fields
template<typename T>
T RandomValue();
private:
const boost::random::random_device & rng;
void GenerateField(
google::protobuf::Message * message,
const google::protobuf::Reflection * reflection,
const google::protobuf::FieldDescriptor * fd
);
};
}
}
#endif // PROFANEDB_UTIL_RANDOMGENERATOR_H
......@@ -14,7 +14,7 @@ foreach(Test ${Tests})
get_filename_component(Name ${Test} NAME_WE)
add_executable(${Name} ${Test})
target_link_libraries(${Name} ${Boost_LIBRARIES} profanedb profanedb_test_protobuf_schema)
target_link_libraries(${Name} ${Boost_LIBRARIES} profanedb profanedb_test_protobuf_schema profanedb_util)
add_test(NAME ${Name} COMMAND ${Name})
endforeach()
......@@ -7,6 +7,8 @@
#include <profanedb/format/protobuf/marshaller.h>
#include <profanedb/vault/rocksdb/storage.h>
#include <profanedb/util/randomgenerator.h>
using profanedb::format::protobuf::Loader;
using profanedb::format::Marshaller;
using ProtobufMarshaller = profanedb::format::protobuf::Marshaller;
......@@ -15,6 +17,8 @@ using profanedb::protobuf::MessageTreeNode;
using RocksStorage = profanedb::vault::rocksdb::Storage;
using profanedb::util::RandomGenerator;
using google::protobuf::Message;
struct Format
......@@ -23,7 +27,10 @@ struct Format
std::shared_ptr<ProtobufMarshaller> marshaller;
std::shared_ptr<RocksStorage> storage;
RandomGenerator randomGen;
Format()
: randomGen(rng)
{
rocksdb::Options rocksOptions;
rocksOptions.create_if_missing = true;
......@@ -45,6 +52,9 @@ struct Format
this->marshaller = std::make_shared<ProtobufMarshaller>(storage, loader);
}
private:
boost::random::random_device rng;
};
......@@ -57,7 +67,8 @@ BOOST_FIXTURE_TEST_SUITE(marshal, Format)
BOOST_AUTO_TEST_CASE(int_key)
{
schema::KeyInt message;
message.set_int_key(17526); // TODO Should be random
randomGen.FillRandomly(&message);
DEBUG_MESSAGE
......@@ -67,7 +78,8 @@ BOOST_AUTO_TEST_CASE(int_key)
BOOST_AUTO_TEST_CASE(string_key)
{
schema::KeyStr message;
message.set_string_key("hp9gh3bv3wgqq"); // TODO Should be random
randomGen.FillRandomly(&message);
DEBUG_MESSAGE
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment