Bug fixes: RELEASE MODE - asserts
This commit is contained in:
parent
021da26ac9
commit
362bc3ba48
@ -118,7 +118,8 @@ FILE(COPY ${include_dir}/utils/char_str.hpp DESTINATION ${build_include_dir}/uti
|
||||
FILE(COPY ${include_dir}/utils/void.hpp DESTINATION ${build_include_dir}/utils)
|
||||
FILE(COPY ${include_dir}/utils/array_store.hpp DESTINATION ${build_include_dir}/utils)
|
||||
FILE(COPY ${include_dir}/utils/bswap.hpp DESTINATION ${build_include_dir}/utils)
|
||||
FILE(COPY ${include_dir}/utils/stacktrace.hpp DESTINATION ${build_include_dir}/utils)
|
||||
FILE(COPY ${include_dir}/utils/stacktrace/stacktrace.hpp DESTINATION ${build_include_dir}/utils/stacktrace)
|
||||
FILE(COPY ${include_dir}/utils/stacktrace/log.hpp DESTINATION ${build_include_dir}/utils/stacktrace)
|
||||
FILE(COPY ${include_dir}/utils/auto_scope.hpp DESTINATION ${build_include_dir}/utils)
|
||||
FILE(COPY ${include_dir}/utils/assert.hpp DESTINATION ${build_include_dir}/utils)
|
||||
FILE(COPY ${include_dir}/utils/reference_wrapper.hpp DESTINATION ${build_include_dir}/utils)
|
||||
|
@ -25,9 +25,12 @@
|
||||
|
||||
// parmanant exception will always be executed
|
||||
#define permanent_assert(condition, message) \
|
||||
if (!(condition)) { \
|
||||
if (!(condition)) \
|
||||
{ \
|
||||
std::ostringstream s; \
|
||||
s << message; \
|
||||
std::cout << s.str() << std::endl; \
|
||||
std::exit(EXIT_FAILURE); \
|
||||
}
|
||||
// assert_error_handler_(__FILE__, __LINE__, s.str().c_str());
|
||||
|
||||
|
@ -4,39 +4,25 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#include "utils/auto_scope.hpp"
|
||||
#include "utils/stacktrace.hpp"
|
||||
#include "utils/stacktrace/stacktrace.hpp"
|
||||
|
||||
class BasicException : public std::exception {
|
||||
public:
|
||||
BasicException(const std::string &message, uint64_t stacktrace_size) noexcept
|
||||
: message_(message),
|
||||
stacktrace_size_(stacktrace_size) {
|
||||
generate_stacktrace();
|
||||
}
|
||||
BasicException(const std::string &message) noexcept : message_(message),
|
||||
stacktrace_size_(10) {
|
||||
generate_stacktrace();
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
BasicException(const std::string &format, Args &&... args) noexcept
|
||||
: BasicException(fmt::format(format, std::forward<Args>(args)...)) {}
|
||||
|
||||
const char *what() const noexcept override { return message_.c_str(); }
|
||||
|
||||
private:
|
||||
std::string message_;
|
||||
uint64_t stacktrace_size_;
|
||||
|
||||
void generate_stacktrace() {
|
||||
#ifndef NDEBUG
|
||||
Stacktrace stacktrace;
|
||||
|
||||
int size = std::min(stacktrace_size_, stacktrace.size());
|
||||
for (int i = 0; i < size; i++) {
|
||||
message_.append(fmt::format("\n at {} ({})", stacktrace[i].function,
|
||||
stacktrace[i].location));
|
||||
class BasicException : public std::exception
|
||||
{
|
||||
public:
|
||||
BasicException(const std::string &message) noexcept : message_(message)
|
||||
{
|
||||
Stacktrace stacktrace;
|
||||
message_.append(stacktrace.dump());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
BasicException(const std::string &format, Args &&... args) noexcept
|
||||
: BasicException(fmt::format(format, std::forward<Args>(args)...))
|
||||
{
|
||||
}
|
||||
|
||||
const char *what() const noexcept override { return message_.c_str(); }
|
||||
|
||||
private:
|
||||
std::string message_;
|
||||
};
|
||||
|
@ -8,34 +8,40 @@
|
||||
|
||||
using Function = std::function<void()>;
|
||||
|
||||
enum class Signal : int {
|
||||
Terminate = SIGTERM,
|
||||
SegmentationFault = SIGSEGV,
|
||||
Interupt = SIGINT,
|
||||
Quit = SIGQUIT,
|
||||
Abort = SIGABRT
|
||||
// TODO: align bits so signals can be combined
|
||||
// Signal::Terminate | Signal::Interupt
|
||||
enum class Signal : int
|
||||
{
|
||||
Terminate = SIGTERM,
|
||||
SegmentationFault = SIGSEGV,
|
||||
Interupt = SIGINT,
|
||||
Quit = SIGQUIT,
|
||||
Abort = SIGABRT,
|
||||
BusError = SIGBUS,
|
||||
};
|
||||
|
||||
class SignalHandler {
|
||||
private:
|
||||
static std::map<int, std::function<void()>> handlers_;
|
||||
class SignalHandler
|
||||
{
|
||||
private:
|
||||
static std::map<int, std::function<void()>> handlers_;
|
||||
|
||||
static void handle(int signal) { handlers_[signal](); }
|
||||
static void handle(int signal) { handlers_[signal](); }
|
||||
|
||||
public:
|
||||
static void register_handler(Signal signal, Function func) {
|
||||
int signal_number = static_cast<int>(signal);
|
||||
handlers_[signal_number] = func;
|
||||
std::signal(signal_number, SignalHandler::handle);
|
||||
}
|
||||
|
||||
// TODO possible changes if signelton needed later
|
||||
/*
|
||||
static SignalHandler& instance() {
|
||||
static SignalHandler instance;
|
||||
return instance;
|
||||
public:
|
||||
static void register_handler(Signal signal, Function func)
|
||||
{
|
||||
int signal_number = static_cast<int>(signal);
|
||||
handlers_[signal_number] = func;
|
||||
std::signal(signal_number, SignalHandler::handle);
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO possible changes if signelton needed later
|
||||
/*
|
||||
static SignalHandler& instance() {
|
||||
static SignalHandler instance;
|
||||
return instance;
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
std::map<int, std::function<void()>> SignalHandler::handlers_ = {};
|
||||
|
11
include/utils/stacktrace/log.hpp
Normal file
11
include/utils/stacktrace/log.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "logging/default.hpp"
|
||||
#include "utils/stacktrace/stacktrace.hpp"
|
||||
|
||||
void log_stacktrace(const std::string& title)
|
||||
{
|
||||
Stacktrace stacktrace;
|
||||
logging::info(title);
|
||||
logging::info(stacktrace.dump());
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <stdexcept>
|
||||
#include <execinfo.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "utils/auto_scope.hpp"
|
||||
|
||||
class Stacktrace
|
||||
@ -13,11 +13,13 @@ public:
|
||||
class Line
|
||||
{
|
||||
public:
|
||||
Line(const std::string& original) : original(original) {}
|
||||
Line(const std::string &original) : original(original) {}
|
||||
|
||||
Line(const std::string& original, const std::string& function,
|
||||
const std::string& location)
|
||||
: original(original), function(function), location(location) {}
|
||||
Line(const std::string &original, const std::string &function,
|
||||
const std::string &location)
|
||||
: original(original), function(function), location(location)
|
||||
{
|
||||
}
|
||||
|
||||
std::string original, function, location;
|
||||
};
|
||||
@ -26,17 +28,17 @@ public:
|
||||
|
||||
Stacktrace()
|
||||
{
|
||||
void* addresses[stacktrace_depth];
|
||||
void *addresses[stacktrace_depth];
|
||||
auto depth = backtrace(addresses, stacktrace_depth);
|
||||
|
||||
// will this leak if backtrace_symbols throws?
|
||||
char** symbols = nullptr;
|
||||
char **symbols = nullptr;
|
||||
Auto(free(symbols));
|
||||
|
||||
symbols = backtrace_symbols(addresses, depth);
|
||||
|
||||
// skip the first one since it will be Stacktrace::Stacktrace()
|
||||
for(int i = 1; i < depth; ++i)
|
||||
for (int i = 1; i < depth; ++i)
|
||||
lines.emplace_back(format(symbols[i]));
|
||||
}
|
||||
|
||||
@ -48,54 +50,53 @@ public:
|
||||
auto end() const { return lines.end(); }
|
||||
auto cend() const { return lines.cend(); }
|
||||
|
||||
const Line& operator[](size_t idx) const
|
||||
{
|
||||
return lines[idx];
|
||||
}
|
||||
const Line &operator[](size_t idx) const { return lines[idx]; }
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return lines.size();
|
||||
}
|
||||
size_t size() const { return lines.size(); }
|
||||
|
||||
template <class Stream>
|
||||
void dump(Stream& stream) {
|
||||
stream << dump();
|
||||
void dump(Stream &stream)
|
||||
{
|
||||
stream << dump();
|
||||
}
|
||||
|
||||
std::string dump() {
|
||||
std::string message;
|
||||
for (int i = 0; i < size(); i++) {
|
||||
message.append(fmt::format("at {} ({}) \n", lines[i].function,
|
||||
lines[i].location));
|
||||
}
|
||||
return message;
|
||||
|
||||
std::string dump()
|
||||
{
|
||||
std::string message;
|
||||
for (size_t i = 0; i < size(); i++)
|
||||
{
|
||||
message.append(fmt::format("at {} ({}) \n", lines[i].function,
|
||||
lines[i].location));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Line> lines;
|
||||
|
||||
Line format(const std::string& original)
|
||||
Line format(const std::string &original)
|
||||
{
|
||||
using namespace abi;
|
||||
auto line = original;
|
||||
|
||||
auto begin = line.find('(');
|
||||
auto end = line.find('+');
|
||||
auto end = line.find('+');
|
||||
|
||||
if(begin == std::string::npos || end == std::string::npos)
|
||||
if (begin == std::string::npos || end == std::string::npos)
|
||||
return {original};
|
||||
|
||||
line[end] = '\0';
|
||||
|
||||
int s;
|
||||
auto demangled = __cxa_demangle(line.data() + begin + 1, nullptr,
|
||||
nullptr, &s);
|
||||
auto demangled =
|
||||
__cxa_demangle(line.data() + begin + 1, nullptr, nullptr, &s);
|
||||
|
||||
auto location = line.substr(0, begin);
|
||||
|
||||
auto function = demangled ? std::string(demangled)
|
||||
: fmt::format("{}()", original.substr(begin + 1, end - begin - 1));
|
||||
auto function =
|
||||
demangled ? std::string(demangled)
|
||||
: fmt::format("{}()", original.substr(begin + 1,
|
||||
end - begin - 1));
|
||||
|
||||
return {original, function, location};
|
||||
}
|
@ -1,28 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/auto_scope.hpp"
|
||||
#include "utils/stacktrace.hpp"
|
||||
#include "utils/stacktrace/stacktrace.hpp"
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <iostream>
|
||||
|
||||
// TODO: log to local file or remote database
|
||||
void stacktrace(std::ostream& stream) noexcept {
|
||||
Stacktrace stacktrace;
|
||||
stacktrace.dump(stream);
|
||||
void stacktrace(std::ostream &stream) noexcept
|
||||
{
|
||||
Stacktrace stacktrace;
|
||||
stacktrace.dump(stream);
|
||||
}
|
||||
|
||||
// TODO: log to local file or remote database
|
||||
void terminate_handler(std::ostream& stream) noexcept {
|
||||
if (auto exc = std::current_exception()) {
|
||||
try {
|
||||
std::rethrow_exception(exc);
|
||||
} catch (std::exception& ex) {
|
||||
stream << ex.what() << std::endl << std::endl;
|
||||
stacktrace(stream);
|
||||
void terminate_handler(std::ostream &stream) noexcept
|
||||
{
|
||||
if (auto exc = std::current_exception())
|
||||
{
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(exc);
|
||||
}
|
||||
catch (std::exception &ex)
|
||||
{
|
||||
stream << ex.what() << std::endl << std::endl;
|
||||
stacktrace(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::abort();
|
||||
std::abort();
|
||||
}
|
||||
|
||||
void terminate_handler() noexcept { terminate_handler(std::cout); }
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <signal.h>
|
||||
#include <iostream>
|
||||
#include <signal.h>
|
||||
|
||||
#include "communication/bolt/v1/server/server.hpp"
|
||||
#include "communication/bolt/v1/server/worker.hpp"
|
||||
@ -10,78 +10,74 @@
|
||||
#include "logging/streams/stdout.hpp"
|
||||
|
||||
#include "utils/signals/handler.hpp"
|
||||
#include "utils/stacktrace.hpp"
|
||||
#include "utils/terminate_handler.hpp"
|
||||
#include "utils/stacktrace/log.hpp"
|
||||
|
||||
static bolt::Server<bolt::Worker>* serverptr;
|
||||
static bolt::Server<bolt::Worker> *serverptr;
|
||||
|
||||
Logger logger;
|
||||
|
||||
static constexpr const char* interface = "0.0.0.0";
|
||||
static constexpr const char* port = "7687";
|
||||
// TODO: load from configuration
|
||||
static constexpr const char *interface = "0.0.0.0";
|
||||
static constexpr const char *port = "7687";
|
||||
|
||||
void throw_and_stacktace(std::string message) {
|
||||
Stacktrace stacktrace;
|
||||
logger.info(stacktrace.dump());
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// TODO figure out what is the relationship between this and signals
|
||||
// that are configured below
|
||||
std::set_terminate(&terminate_handler);
|
||||
|
||||
// logger init
|
||||
int main(void)
|
||||
{
|
||||
// logging init
|
||||
#ifdef SYNC_LOGGER
|
||||
logging::init_sync();
|
||||
logging::init_sync();
|
||||
#else
|
||||
logging::init_async();
|
||||
logging::init_async();
|
||||
#endif
|
||||
logging::log->pipe(std::make_unique<Stdout>());
|
||||
logging::log->pipe(std::make_unique<Stdout>());
|
||||
|
||||
// get Main logger
|
||||
logger = logging::log->logger("Main");
|
||||
logger.info("{}", logging::log->type());
|
||||
// logger init
|
||||
logger = logging::log->logger("Main");
|
||||
logger.info("{}", logging::log->type());
|
||||
|
||||
SignalHandler::register_handler(Signal::SegmentationFault, []() {
|
||||
throw_and_stacktace("SegmentationFault signal raised");
|
||||
exit(1);
|
||||
});
|
||||
// unhandled exception handler
|
||||
std::set_terminate(&terminate_handler);
|
||||
|
||||
SignalHandler::register_handler(Signal::Terminate, []() {
|
||||
throw_and_stacktace("Terminate signal raised");
|
||||
exit(1);
|
||||
});
|
||||
// signal handling
|
||||
SignalHandler::register_handler(Signal::SegmentationFault, []() {
|
||||
log_stacktrace("SegmentationFault signal raised");
|
||||
std::exit(EXIT_FAILURE);
|
||||
});
|
||||
SignalHandler::register_handler(Signal::Terminate, []() {
|
||||
log_stacktrace("Terminate signal raised");
|
||||
std::exit(EXIT_FAILURE);
|
||||
});
|
||||
SignalHandler::register_handler(Signal::Abort, []() {
|
||||
log_stacktrace("Abort signal raised");
|
||||
std::exit(EXIT_FAILURE);
|
||||
});
|
||||
|
||||
SignalHandler::register_handler(Signal::Abort, []() {
|
||||
throw_and_stacktace("Abort signal raised");
|
||||
exit(1);
|
||||
});
|
||||
// initialize socket
|
||||
io::Socket socket;
|
||||
try
|
||||
{
|
||||
socket = io::Socket::bind(interface, port);
|
||||
}
|
||||
catch (io::NetworkError e)
|
||||
{
|
||||
logger.error("Cannot bind to socket on {} at {}", interface, port);
|
||||
logger.error("{}", e.what());
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
socket.set_non_blocking();
|
||||
socket.listen(1024);
|
||||
logger.info("Listening on {} at {}", interface, port);
|
||||
|
||||
io::Socket socket;
|
||||
// initialize server
|
||||
bolt::Server<bolt::Worker> server(std::move(socket));
|
||||
serverptr = &server;
|
||||
|
||||
try {
|
||||
socket = io::Socket::bind(interface, port);
|
||||
} catch (io::NetworkError e) {
|
||||
logger.error("Cannot bind to socket on {} at {}", interface, port);
|
||||
logger.error("{}", e.what());
|
||||
// server start with N threads
|
||||
// TODO: N should be configurable
|
||||
auto N = std::thread::hardware_concurrency();
|
||||
logger.info("Starting {} workers", N);
|
||||
server.start(N);
|
||||
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
socket.set_non_blocking();
|
||||
socket.listen(1024);
|
||||
|
||||
logger.info("Listening on {} at {}", interface, port);
|
||||
|
||||
bolt::Server<bolt::Worker> server(std::move(socket));
|
||||
serverptr = &server;
|
||||
|
||||
// TODO: N should be configurable
|
||||
auto N = std::thread::hardware_concurrency();
|
||||
logger.info("Starting {} workers", N);
|
||||
server.start(N);
|
||||
|
||||
logger.info("Shutting down...");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
logger.info("Shutting down...");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "utils/assert.hpp"
|
||||
#include "storage/vertex_record.hpp"
|
||||
#include "storage/edge_type/edge_type.hpp"
|
||||
|
||||
@ -10,10 +11,12 @@ void EdgeAccessor::remove() const
|
||||
RecordAccessor::remove();
|
||||
|
||||
auto from_va = from();
|
||||
assert(from_va.fill());
|
||||
auto from_va_is_full = from_va.fill();
|
||||
runtime_assert(from_va_is_full, "From Vertex Accessor is empty");
|
||||
|
||||
auto to_va = to();
|
||||
assert(to_va.fill());
|
||||
auto to_va_is_full = to_va.fill();
|
||||
permanent_assert(to_va_is_full, "To Vertex Accessor is empty");
|
||||
|
||||
from_va.update().record->data.out.remove(vlist);
|
||||
to_va.update().record->data.in.remove(vlist);
|
||||
|
@ -1,19 +1,24 @@
|
||||
#include "_hardcoded_query/basic.hpp"
|
||||
#include "logging/default.hpp"
|
||||
#include "logging/streams/stdout.hpp"
|
||||
#include "query/preprocesor.hpp"
|
||||
#include "query/strip/stripper.hpp"
|
||||
#include "utils/assert.hpp"
|
||||
#include "utils/sysinfo/memory.hpp"
|
||||
|
||||
template <class S, class Q>
|
||||
void run(size_t n, std::string &query, S &stripper, Q &qf)
|
||||
QueryPreprocessor preprocessor;
|
||||
|
||||
template <class Q>
|
||||
void run(size_t n, std::string &query, Q &qf)
|
||||
{
|
||||
auto stripped = stripper.strip(query);
|
||||
std::cout << "Running query [" << stripped.hash << "] for " << n << " time."
|
||||
<< std::endl;
|
||||
auto stripped = preprocessor.preprocess(query);
|
||||
|
||||
logging::info("Running query [{}] x {}.", stripped.hash, n);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
properties_t vec = stripped.arguments;
|
||||
assert(qf[stripped.hash](std::move(vec)));
|
||||
permanent_assert(qf[stripped.hash](std::move(vec)), "Query failed!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,13 +34,10 @@ int main(void)
|
||||
logging::init_async();
|
||||
logging::log->pipe(std::make_unique<Stdout>());
|
||||
|
||||
size_t entities_number = 1000;
|
||||
|
||||
Db db("cleaning");
|
||||
|
||||
auto query_functions = hardcode::load_basic_functions(db);
|
||||
|
||||
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
|
||||
size_t entities_number = 1000;
|
||||
auto query_functions = hardcode::load_basic_functions(db);
|
||||
|
||||
std::string create_vertex_label =
|
||||
"CREATE (n:LABEL {name: \"cleaner_test\"}) RETURN n";
|
||||
@ -49,17 +51,21 @@ int main(void)
|
||||
// clean vertices
|
||||
// delete vertices a
|
||||
// clean vertices
|
||||
run(entities_number, create_vertex_label, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == entities_number);
|
||||
run(entities_number, create_vertex_label, query_functions);
|
||||
permanent_assert(db.graph.vertices.access().size() == entities_number,
|
||||
"Entities number doesn't match");
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == entities_number);
|
||||
permanent_assert(db.graph.vertices.access().size() == entities_number,
|
||||
"Entities number doesn't match (after cleaning)");
|
||||
|
||||
run(1, delete_label_vertices, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == entities_number);
|
||||
run(1, delete_label_vertices, query_functions);
|
||||
permanent_assert(db.graph.vertices.access().size() == entities_number,
|
||||
"Entities number doesn't match (delete label vertices)");
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == 0);
|
||||
permanent_assert(db.graph.vertices.access().size() == 0,
|
||||
"Db should be empty");
|
||||
|
||||
// ******************************* TEST 2 ********************************//
|
||||
// add vertices a
|
||||
@ -68,26 +74,33 @@ int main(void)
|
||||
// delete vertices a
|
||||
// clean vertices
|
||||
// delete vertices all
|
||||
run(entities_number, create_vertex_label, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == entities_number);
|
||||
run(entities_number, create_vertex_label, query_functions);
|
||||
permanent_assert(db.graph.vertices.access().size() == entities_number,
|
||||
"Entities number doesn't match");
|
||||
|
||||
run(entities_number, create_vertex_other, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == entities_number * 2);
|
||||
run(entities_number, create_vertex_other, query_functions);
|
||||
permanent_assert(db.graph.vertices.access().size() == entities_number * 2,
|
||||
"Entities number doesn't match");
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == entities_number * 2);
|
||||
permanent_assert(db.graph.vertices.access().size() == entities_number * 2,
|
||||
"Entities number doesn't match");
|
||||
|
||||
run(1, delete_label_vertices, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == entities_number * 2);
|
||||
run(1, delete_label_vertices, query_functions);
|
||||
permanent_assert(db.graph.vertices.access().size() == entities_number * 2,
|
||||
"Entities number doesn't match");
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == entities_number);
|
||||
permanent_assert(db.graph.vertices.access().size() == entities_number,
|
||||
"Entities number doesn't match");
|
||||
|
||||
run(1, delete_all_vertices, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == entities_number);
|
||||
run(1, delete_all_vertices, query_functions);
|
||||
permanent_assert(db.graph.vertices.access().size() == entities_number,
|
||||
"Entities number doesn't match");
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == 0);
|
||||
permanent_assert(db.graph.vertices.access().size() == 0,
|
||||
"Db should be empty");
|
||||
|
||||
// TODO: more tests
|
||||
|
||||
|
@ -3,10 +3,16 @@
|
||||
#include "_hardcoded_query/basic.hpp"
|
||||
#include "logging/default.hpp"
|
||||
#include "logging/streams/stdout.hpp"
|
||||
#include "query/preprocesor.hpp"
|
||||
#include "query/strip/stripper.hpp"
|
||||
#include "storage/indexes/indexes.hpp"
|
||||
#include "utils/assert.hpp"
|
||||
#include "utils/signals/handler.hpp"
|
||||
#include "utils/stacktrace/log.hpp"
|
||||
#include "utils/sysinfo/memory.hpp"
|
||||
|
||||
QueryPreprocessor preprocessor;
|
||||
|
||||
// Returns uniform random size_t generator from range [0,n>
|
||||
auto rand_gen(size_t n)
|
||||
{
|
||||
@ -17,44 +23,43 @@ auto rand_gen(size_t n)
|
||||
|
||||
void run(size_t n, std::string &query, Db &db)
|
||||
{
|
||||
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
|
||||
auto qf = hardcode::load_basic_functions(db);
|
||||
auto stripped = preprocessor.preprocess(query);
|
||||
|
||||
auto qf = hardcode::load_basic_functions(db);
|
||||
logging::info("Running query [{}] x {}.", stripped.hash, n);
|
||||
|
||||
auto stripped = stripper.strip(query);
|
||||
std::cout << "Running query [" << stripped.hash << "] for " << n << " time."
|
||||
<< std::endl;
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
properties_t vec = stripped.arguments;
|
||||
assert(qf[stripped.hash](std::move(vec)));
|
||||
auto commited = qf[stripped.hash](std::move(vec));
|
||||
permanent_assert(commited, "Query execution failed");
|
||||
}
|
||||
}
|
||||
|
||||
void add_edge(size_t n, Db &db)
|
||||
{
|
||||
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
|
||||
|
||||
auto qf = hardcode::load_basic_functions(db);
|
||||
|
||||
std::string query = "MATCH (n1), (n2) WHERE ID(n1)=0 AND "
|
||||
"ID(n2)=1 CREATE (n1)<-[r:IS {age: "
|
||||
"25,weight: 70}]-(n2) RETURN r";
|
||||
auto stripped = preprocessor.preprocess(query);
|
||||
|
||||
auto stripped = stripper.strip(query);
|
||||
std::cout << "Running query [" << stripped.hash << "] for " << n
|
||||
<< " time to add edge." << std::endl;
|
||||
logging::info("Running query [{}] (add edge) x {}", stripped.hash, n);
|
||||
|
||||
std::vector<int64_t> vertices;
|
||||
for (auto &v : db.graph.vertices.access()) {
|
||||
for (auto &v : db.graph.vertices.access())
|
||||
{
|
||||
vertices.push_back(v.second.id);
|
||||
}
|
||||
permanent_assert(vertices.size() > 0, "Vertices size is zero");
|
||||
|
||||
auto rand = rand_gen(vertices.size());
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
properties_t vec = stripped.arguments;
|
||||
vec[0] = Property(Int64(vertices[rand()]), Flags::Int64);
|
||||
vec[1] = Property(Int64(vertices[rand()]), Flags::Int64);
|
||||
assert(qf[stripped.hash](std::move(vec)));
|
||||
vec[0] = Property(Int64(vertices[rand()]), Flags::Int64);
|
||||
vec[1] = Property(Int64(vertices[rand()]), Flags::Int64);
|
||||
permanent_assert(qf[stripped.hash](std::move(vec)), "Add edge failed");
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +69,7 @@ void add_property(Db &db, StoredProperty<TypeGroupVertex> &prop)
|
||||
|
||||
t.vertex_access().fill().update().for_all([&](auto va) { va.set(prop); });
|
||||
|
||||
assert(t.commit());
|
||||
permanent_assert(t.commit(), "Add property failed");
|
||||
}
|
||||
|
||||
void add_vertex_property_serial_int(Db &db, PropertyFamily<TypeGroupVertex> &f)
|
||||
@ -79,7 +84,7 @@ void add_vertex_property_serial_int(Db &db, PropertyFamily<TypeGroupVertex> &f)
|
||||
i++;
|
||||
});
|
||||
|
||||
assert(t.commit());
|
||||
permanent_assert(t.commit(), "Add vertex property serial int failed");
|
||||
}
|
||||
|
||||
void add_edge_property_serial_int(Db &db, PropertyFamily<TypeGroupEdge> &f)
|
||||
@ -94,7 +99,7 @@ void add_edge_property_serial_int(Db &db, PropertyFamily<TypeGroupEdge> &f)
|
||||
i++;
|
||||
});
|
||||
|
||||
assert(t.commit());
|
||||
permanent_assert(t.commit(), "Add Edge property serial int failed");
|
||||
}
|
||||
|
||||
template <class TG>
|
||||
@ -103,8 +108,9 @@ size_t size(Db &db, IndexHolder<TG, std::nullptr_t> &h)
|
||||
DbAccessor t(db);
|
||||
|
||||
size_t count = 0;
|
||||
auto oin = h.get_read();
|
||||
if (oin.is_present()) {
|
||||
auto oin = h.get_read();
|
||||
if (oin.is_present())
|
||||
{
|
||||
oin.get()->for_range(t).for_all([&](auto va) mutable { count++; });
|
||||
}
|
||||
|
||||
@ -115,8 +121,10 @@ size_t size(Db &db, IndexHolder<TG, std::nullptr_t> &h)
|
||||
|
||||
void assert_empty(Db &db)
|
||||
{
|
||||
assert(db.graph.vertices.access().size() == 0);
|
||||
assert(db.graph.edges.access().size() == 0);
|
||||
permanent_assert(db.graph.vertices.access().size() == 0,
|
||||
"DB isn't empty (vertices)");
|
||||
permanent_assert(db.graph.edges.access().size() == 0,
|
||||
"DB isn't empty (edges)");
|
||||
}
|
||||
|
||||
void clean_vertex(Db &db)
|
||||
@ -136,7 +144,7 @@ void clean_edge(Db &db)
|
||||
void clear_database(Db &db)
|
||||
{
|
||||
std::string delete_all_vertices = "MATCH (n) DELETE n";
|
||||
std::string delete_all_edges = "MATCH ()-[r]-() DELETE r";
|
||||
std::string delete_all_edges = "MATCH ()-[r]-() DELETE r";
|
||||
|
||||
run(1, delete_all_edges, db);
|
||||
run(1, delete_all_vertices, db);
|
||||
@ -151,14 +159,16 @@ bool equal(Db &a, Db &b)
|
||||
auto acc_a = a.graph.vertices.access();
|
||||
auto acc_b = b.graph.vertices.access();
|
||||
|
||||
if (acc_a.size() != acc_b.size()) {
|
||||
if (acc_a.size() != acc_b.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto it_a = acc_a.begin();
|
||||
auto it_b = acc_b.begin();
|
||||
|
||||
for (auto i = acc_a.size(); i > 0; i--) {
|
||||
for (auto i = acc_a.size(); i > 0; i--)
|
||||
{
|
||||
// TODO: compare
|
||||
}
|
||||
}
|
||||
@ -167,14 +177,16 @@ bool equal(Db &a, Db &b)
|
||||
auto acc_a = a.graph.edges.access();
|
||||
auto acc_b = b.graph.edges.access();
|
||||
|
||||
if (acc_a.size() != acc_b.size()) {
|
||||
if (acc_a.size() != acc_b.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto it_a = acc_a.begin();
|
||||
auto it_b = acc_b.begin();
|
||||
|
||||
for (auto i = acc_a.size(); i > 0; i--) {
|
||||
for (auto i = acc_a.size(); i > 0; i--)
|
||||
{
|
||||
// TODO: compare
|
||||
}
|
||||
}
|
||||
@ -187,6 +199,16 @@ int main(void)
|
||||
logging::init_async();
|
||||
logging::log->pipe(std::make_unique<Stdout>());
|
||||
|
||||
SignalHandler::register_handler(Signal::SegmentationFault, []() {
|
||||
log_stacktrace("SegmentationFault signal raised");
|
||||
std::exit(EXIT_FAILURE);
|
||||
});
|
||||
|
||||
SignalHandler::register_handler(Signal::BusError, []() {
|
||||
log_stacktrace("Bus error signal raised");
|
||||
std::exit(EXIT_FAILURE);
|
||||
});
|
||||
|
||||
size_t cvl_n = 1;
|
||||
|
||||
std::string create_vertex_label =
|
||||
@ -194,7 +216,7 @@ int main(void)
|
||||
std::string create_vertex_other =
|
||||
"CREATE (n:OTHER {name: \"cleaner_test\"}) RETURN n";
|
||||
std::string delete_label_vertices = "MATCH (n:LABEL) DELETE n";
|
||||
std::string delete_all_vertices = "MATCH (n) DELETE n";
|
||||
std::string delete_all_vertices = "MATCH (n) DELETE n";
|
||||
|
||||
IndexDefinition vertex_property_nonunique_unordered = {
|
||||
IndexLocation{VertexSide, Option<std::string>("prop"),
|
||||
@ -215,15 +237,19 @@ int main(void)
|
||||
|
||||
// ******************************* TEST 1 ********************************//
|
||||
{
|
||||
std::cout << "TEST1" << std::endl;
|
||||
logging::info("TEST 1");
|
||||
// add indexes
|
||||
// add vertices LABEL
|
||||
// add edges
|
||||
// add vertices property
|
||||
// assert index size.
|
||||
Db db("index", false);
|
||||
assert(db.indexes().add_index(vertex_property_nonunique_unordered));
|
||||
assert(db.indexes().add_index(edge_property_nonunique_unordered));
|
||||
permanent_assert(
|
||||
db.indexes().add_index(vertex_property_nonunique_unordered),
|
||||
"Add vertex index failed");
|
||||
permanent_assert(
|
||||
db.indexes().add_index(edge_property_nonunique_unordered),
|
||||
"Add edge index failed");
|
||||
|
||||
run(cvl_n, create_vertex_label, db);
|
||||
auto sp = StoredProperty<TypeGroupVertex>(
|
||||
@ -232,18 +258,21 @@ int main(void)
|
||||
.family_key());
|
||||
add_property(db, sp);
|
||||
|
||||
assert(cvl_n ==
|
||||
size(db, db.graph.vertices.property_family_find_or_create("prop")
|
||||
.index));
|
||||
permanent_assert(
|
||||
cvl_n == size(db, db.graph.vertices
|
||||
.property_family_find_or_create("prop")
|
||||
.index),
|
||||
"Create vertex property failed");
|
||||
|
||||
add_edge(cvl_n, db);
|
||||
add_edge_property_serial_int(
|
||||
db, db.graph.edges.property_family_find_or_create("prop"));
|
||||
|
||||
assert(
|
||||
permanent_assert(
|
||||
cvl_n ==
|
||||
size(db,
|
||||
db.graph.edges.property_family_find_or_create("prop").index));
|
||||
size(db, db.graph.edges.property_family_find_or_create("prop")
|
||||
.index),
|
||||
"Create edge property failed");
|
||||
}
|
||||
|
||||
// TODO: more tests
|
||||
|
@ -1,12 +1,18 @@
|
||||
#include <random>
|
||||
|
||||
#include "_hardcoded_query/basic.hpp"
|
||||
#include "logging/default.hpp"
|
||||
#include "logging/streams/stdout.hpp"
|
||||
#include "_hardcoded_query/basic.hpp"
|
||||
#include "query/preprocesor.hpp"
|
||||
#include "query/strip/stripper.hpp"
|
||||
#include "storage/indexes/indexes.hpp"
|
||||
#include "utils/assert.hpp"
|
||||
#include "utils/signals/handler.hpp"
|
||||
#include "utils/stacktrace/log.hpp"
|
||||
#include "utils/sysinfo/memory.hpp"
|
||||
|
||||
QueryPreprocessor preprocessor;
|
||||
|
||||
// Returns uniform random size_t generator from range [0,n>
|
||||
auto rand_gen(size_t n)
|
||||
{
|
||||
@ -17,32 +23,28 @@ auto rand_gen(size_t n)
|
||||
|
||||
void run(size_t n, std::string &query, Db &db)
|
||||
{
|
||||
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
|
||||
auto qf = hardcode::load_basic_functions(db);
|
||||
auto stripped = preprocessor.preprocess(query);
|
||||
|
||||
auto qf = hardcode::load_basic_functions(db);
|
||||
logging::info("Running query {} [{}] x {}.", query, stripped.hash, n);
|
||||
|
||||
auto stripped = stripper.strip(query);
|
||||
std::cout << "Running query [" << stripped.hash << "] for " << n << " time."
|
||||
<< std::endl;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
properties_t vec = stripped.arguments;
|
||||
assert(qf[stripped.hash](std::move(vec)));
|
||||
permanent_assert(qf[stripped.hash](std::move(vec)), "Query aborted");
|
||||
}
|
||||
}
|
||||
|
||||
void add_edge(size_t n, Db &db)
|
||||
{
|
||||
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
|
||||
auto qf = hardcode::load_basic_functions(db);
|
||||
auto qf = hardcode::load_basic_functions(db);
|
||||
|
||||
std::string query = "MATCH (n1), (n2) WHERE ID(n1)=0 AND "
|
||||
"ID(n2)=1 CREATE (n1)<-[r:IS {age: "
|
||||
"25,weight: 70}]-(n2) RETURN r";
|
||||
auto stripped = preprocessor.preprocess(query);
|
||||
|
||||
auto stripped = stripper.strip(query);
|
||||
std::cout << "Running query [" << stripped.hash << "] for " << n
|
||||
<< " time to add edge." << std::endl;
|
||||
logging::info("Running query {} [{}] x {}.", query, stripped.hash, n);
|
||||
|
||||
std::vector<int64_t> vertices;
|
||||
for (auto &v : db.graph.vertices.access())
|
||||
@ -56,7 +58,7 @@ void add_edge(size_t n, Db &db)
|
||||
properties_t vec = stripped.arguments;
|
||||
vec[0] = Property(Int64(vertices[rand()]), Flags::Int64);
|
||||
vec[1] = Property(Int64(vertices[rand()]), Flags::Int64);
|
||||
assert(qf[stripped.hash](std::move(vec)));
|
||||
permanent_assert(qf[stripped.hash](std::move(vec)), "Query aborted");
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +68,8 @@ void add_property(Db &db, StoredProperty<TypeGroupVertex> &prop)
|
||||
|
||||
t.vertex_access().fill().for_all([&](auto va) { va.set(prop); });
|
||||
|
||||
assert(t.commit());
|
||||
permanent_assert(t.commit(), "add property query aborted");
|
||||
;
|
||||
}
|
||||
|
||||
void add_property_different_int(Db &db, PropertyFamily<TypeGroupVertex> &f)
|
||||
@ -81,7 +84,7 @@ void add_property_different_int(Db &db, PropertyFamily<TypeGroupVertex> &f)
|
||||
i++;
|
||||
});
|
||||
|
||||
assert(t.commit());
|
||||
permanent_assert(t.commit(), "add property different int aborted");
|
||||
}
|
||||
|
||||
size_t size(Db &db, IndexHolder<TypeGroupVertex, std::nullptr_t> &h)
|
||||
@ -102,8 +105,8 @@ size_t size(Db &db, IndexHolder<TypeGroupVertex, std::nullptr_t> &h)
|
||||
|
||||
void assert_empty(Db &db)
|
||||
{
|
||||
assert(db.graph.vertices.access().size() == 0);
|
||||
assert(db.graph.edges.access().size() == 0);
|
||||
permanent_assert(db.graph.vertices.access().size() == 0, "Db isn't empty");
|
||||
permanent_assert(db.graph.edges.access().size() == 0, "Db isn't empty");
|
||||
}
|
||||
|
||||
void clean_vertex(Db &db)
|
||||
@ -178,6 +181,11 @@ int main(void)
|
||||
logging::init_async();
|
||||
logging::log->pipe(std::make_unique<Stdout>());
|
||||
|
||||
SignalHandler::register_handler(Signal::SegmentationFault, []() {
|
||||
log_stacktrace("SegmentationFault signal raised");
|
||||
std::exit(EXIT_FAILURE);
|
||||
});
|
||||
|
||||
size_t cvl_n = 1000;
|
||||
|
||||
std::string create_vertex_label =
|
||||
@ -187,9 +195,8 @@ int main(void)
|
||||
std::string delete_label_vertices = "MATCH (n:LABEL) DELETE n";
|
||||
std::string delete_all_vertices = "MATCH (n) DELETE n";
|
||||
|
||||
// ******************************* TEST 1 ********************************//
|
||||
{
|
||||
std::cout << "TEST1" << std::endl;
|
||||
logging::info("TEST 1");
|
||||
// make snapshot of empty db
|
||||
// add vertexs
|
||||
// add edges
|
||||
@ -203,11 +210,11 @@ int main(void)
|
||||
clear_database(db);
|
||||
db.snap_engine.import();
|
||||
assert_empty(db);
|
||||
logging::info("END of TEST 1");
|
||||
}
|
||||
|
||||
// ******************************* TEST 2 ********************************//
|
||||
{
|
||||
std::cout << "TEST2" << std::endl;
|
||||
logging::info("TEST 2");
|
||||
// add vertexs
|
||||
// add edges
|
||||
// make snapshot of db
|
||||
@ -223,13 +230,12 @@ int main(void)
|
||||
db.snap_engine.import();
|
||||
{
|
||||
Db db2("snapshot");
|
||||
assert(equal(db, db2));
|
||||
permanent_assert(equal(db, db2), "Dbs aren't equal");
|
||||
}
|
||||
}
|
||||
|
||||
// ******************************* TEST 3 ********************************//
|
||||
{
|
||||
std::cout << "TEST3" << std::endl;
|
||||
logging::info("TEST 3");
|
||||
// add vertexs
|
||||
// add edges
|
||||
// make snapshot of db
|
||||
@ -240,13 +246,12 @@ int main(void)
|
||||
db.snap_engine.make_snapshot();
|
||||
{
|
||||
Db db2("not_snapshot");
|
||||
assert(!equal(db, db2));
|
||||
permanent_assert(!equal(db, db2), "Dbs are equal");
|
||||
}
|
||||
}
|
||||
|
||||
// ******************************* TEST 4 ********************************//
|
||||
{
|
||||
std::cout << "TEST4" << std::endl;
|
||||
logging::info("TEST 4");
|
||||
// add vertices LABEL
|
||||
// add properties
|
||||
// add vertices LABEL
|
||||
@ -265,14 +270,17 @@ int main(void)
|
||||
IndexLocation{VertexSide, Option<std::string>("prop"),
|
||||
Option<std::string>(), Option<std::string>()},
|
||||
IndexType{false, None}};
|
||||
assert(db.indexes().add_index(idef));
|
||||
assert(cvl_n == size(db, family.index));
|
||||
permanent_assert(db.indexes().add_index(idef), "Index isn't added");
|
||||
permanent_assert(cvl_n == size(db, family.index),
|
||||
"Index size isn't valid");
|
||||
db.snap_engine.make_snapshot();
|
||||
{
|
||||
Db db2("snapshot");
|
||||
assert(cvl_n == size(db, db2.graph.vertices
|
||||
.property_family_find_or_create("prop")
|
||||
.index));
|
||||
permanent_assert(
|
||||
cvl_n == size(db, db2.graph.vertices
|
||||
.property_family_find_or_create("prop")
|
||||
.index),
|
||||
"Index size isn't valid");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,15 @@
|
||||
#include <utility>
|
||||
|
||||
#include "utils/signals/handler.hpp"
|
||||
#include "utils/stacktrace.hpp"
|
||||
#include "utils/stacktrace/stacktrace.hpp"
|
||||
|
||||
TEST_CASE("SignalHandler Segmentation Fault Test") {
|
||||
SignalHandler::register_handler(Signal::SegmentationFault, []() {
|
||||
std::cout << "Segmentation Fault" << std::endl;
|
||||
Stacktrace stacktrace;
|
||||
std::cout << stacktrace.dump() << std::endl;
|
||||
});
|
||||
TEST_CASE("SignalHandler Segmentation Fault Test")
|
||||
{
|
||||
SignalHandler::register_handler(Signal::SegmentationFault, []() {
|
||||
std::cout << "Segmentation Fault" << std::endl;
|
||||
Stacktrace stacktrace;
|
||||
std::cout << stacktrace.dump() << std::endl;
|
||||
});
|
||||
|
||||
std::raise(SIGSEGV);
|
||||
std::raise(SIGSEGV);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user