diff --git a/cmake/copy_includes.cmake b/cmake/copy_includes.cmake index 4b0ad5a4b..5508be6cd 100644 --- a/cmake/copy_includes.cmake +++ b/cmake/copy_includes.cmake @@ -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) diff --git a/include/utils/assert.hpp b/include/utils/assert.hpp index 52c4ee49c..b5fec6070 100644 --- a/include/utils/assert.hpp +++ b/include/utils/assert.hpp @@ -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()); diff --git a/include/utils/exceptions/basic_exception.hpp b/include/utils/exceptions/basic_exception.hpp index 32459dcbf..9a30e854b 100644 --- a/include/utils/exceptions/basic_exception.hpp +++ b/include/utils/exceptions/basic_exception.hpp @@ -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_; }; diff --git a/include/utils/signals/handler.hpp b/include/utils/signals/handler.hpp index 18d833870..c9328b28d 100644 --- a/include/utils/signals/handler.hpp +++ b/include/utils/signals/handler.hpp @@ -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_ = {}; diff --git a/include/utils/stacktrace/log.hpp b/include/utils/stacktrace/log.hpp new file mode 100644 index 000000000..31f273f4f --- /dev/null +++ b/include/utils/stacktrace/log.hpp @@ -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()); +} diff --git a/include/utils/stacktrace.hpp b/include/utils/stacktrace/stacktrace.hpp similarity index 52% rename from include/utils/stacktrace.hpp rename to include/utils/stacktrace/stacktrace.hpp index ce063438a..e33050def 100644 --- a/include/utils/stacktrace.hpp +++ b/include/utils/stacktrace/stacktrace.hpp @@ -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}; } diff --git a/include/utils/terminate_handler.hpp b/include/utils/terminate_handler.hpp index 467522e44..c24e1a27f 100644 --- a/include/utils/terminate_handler.hpp +++ b/include/utils/terminate_handler.hpp @@ -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); } diff --git a/src/memgraph_bolt.cpp b/src/memgraph_bolt.cpp index 1c0585068..7f6498794 100644 --- a/src/memgraph_bolt.cpp +++ b/src/memgraph_bolt.cpp @@ -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; } diff --git a/src/storage/edge_accessor.cpp b/src/storage/edge_accessor.cpp index c8267e91b..3dbded0f7 100644 --- a/src/storage/edge_accessor.cpp +++ b/src/storage/edge_accessor.cpp @@ -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); diff --git a/tests/integration/cleaning.cpp b/tests/integration/cleaning.cpp index 7bdbb3bf8..1cbfeb45b 100644 --- a/tests/integration/cleaning.cpp +++ b/tests/integration/cleaning.cpp @@ -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 diff --git a/tests/integration/index.cpp b/tests/integration/index.cpp index 6afc345b6..762134d58 100644 --- a/tests/integration/index.cpp +++ b/tests/integration/index.cpp @@ -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 diff --git a/tests/integration/snapshot.cpp b/tests/integration/snapshot.cpp index 6c8309e44..2c2157c87 100644 --- a/tests/integration/snapshot.cpp +++ b/tests/integration/snapshot.cpp @@ -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"); } } diff --git a/tests/unit/signal_handler.cpp b/tests/unit/signal_handler.cpp index 12ee95e5a..d61e50e09 100644 --- a/tests/unit/signal_handler.cpp +++ b/tests/unit/signal_handler.cpp @@ -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); }