From 6be2399ad1a54724286c6f3c86515d7116b52109 Mon Sep 17 00:00:00 2001 From: Dominik Gleich <dominik.gleich@memgraph.io> Date: Tue, 21 Mar 2017 13:48:35 +0100 Subject: [PATCH] Fix warnings all over the codebase. Reviewers: florijan, buda Reviewed By: buda Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D146 --- src/communication/server.hpp | 4 +- .../concurrent/concurrent_list.hpp | 2 +- src/data_structures/concurrent/skiplist.hpp | 2 +- src/data_structures/map/rh_common.hpp | 2 +- src/data_structures/map/rh_hashmap.hpp | 20 +- src/data_structures/map/rh_hashmultimap.hpp | 64 ++-- .../concurrent/skiplist_reverse_iteration.cpp | 1 - tests/benchmark/query/strip/stripper.cpp | 7 +- tests/concurrent/common.h | 343 ++++++++---------- tests/concurrent/network_common.hpp | 13 +- tests/concurrent/sl_insert_competetive.cpp | 6 +- tests/unit/rh_hashmap.cpp | 76 ++-- tests/unit/rh_hashmultimap.cpp | 114 +++--- tests/unit/traversal.cpp | 315 ++++++++-------- 14 files changed, 506 insertions(+), 463 deletions(-) diff --git a/src/communication/server.hpp b/src/communication/server.hpp index 9c3ec09a9..72d8a92a8 100644 --- a/src/communication/server.hpp +++ b/src/communication/server.hpp @@ -37,9 +37,9 @@ class Server public: Server(Socket &&socket, Dbms &dbms, QueryEngine<OutputStream> &query_engine) - : socket_(std::forward<Socket>(socket)), - dbms_(dbms), + : dbms_(dbms), query_engine_(query_engine), + socket_(std::forward<Socket>(socket)), logger_(logging::log->logger("communication::Server")) { event_.data.fd = socket_; diff --git a/src/data_structures/concurrent/concurrent_list.hpp b/src/data_structures/concurrent/concurrent_list.hpp index b28e88fb7..ff8670532 100644 --- a/src/data_structures/concurrent/concurrent_list.hpp +++ b/src/data_structures/concurrent/concurrent_list.hpp @@ -74,7 +74,7 @@ class ConcurrentList { IteratorBase(const IteratorBase &) = delete; IteratorBase(IteratorBase &&other) - : list(other.list), curr(other.curr), prev(other.prev) { + : list(other.list), prev(other.prev), curr(other.curr) { other.list = nullptr; other.curr = nullptr; other.prev = nullptr; diff --git a/src/data_structures/concurrent/skiplist.hpp b/src/data_structures/concurrent/skiplist.hpp index 426d92ce1..8a526abfb 100644 --- a/src/data_structures/concurrent/skiplist.hpp +++ b/src/data_structures/concurrent/skiplist.hpp @@ -771,7 +771,7 @@ class SkipList : private Lockable<lock_t> { } Node *preds[H]; - auto level = find_path(this, H - 1, item, preds); + find_path(this, H - 1, item, preds); return std::make_pair(ReverseIterator(this, preds[0], preds), true); } diff --git a/src/data_structures/map/rh_common.hpp b/src/data_structures/map/rh_common.hpp index 252e28f49..67b7ea924 100644 --- a/src/data_structures/map/rh_common.hpp +++ b/src/data_structures/map/rh_common.hpp @@ -78,7 +78,7 @@ class RhBase { } } IteratorBase(const RhBase *map, size_t start) - : map(map), index(start), advanced(0) {} + : map(map), advanced(0), index(start) {} const RhBase *map; diff --git a/src/data_structures/map/rh_hashmap.hpp b/src/data_structures/map/rh_hashmap.hpp index ff73a2355..1948e9931 100644 --- a/src/data_structures/map/rh_hashmap.hpp +++ b/src/data_structures/map/rh_hashmap.hpp @@ -1,16 +1,20 @@ #include <functional> #include "data_structures/map/rh_common.hpp" +#include "utils/assert.hpp" #include "utils/crtp.hpp" #include "utils/option_ptr.hpp" -// HashMap with RobinHood collision resolution policy. -// Single threaded. -// Entrys are saved as pointers alligned to 8B. -// Entrys must know thers key. -// D must have method const K & get_key() -// K must be comparable with ==. -// HashMap behaves as if it isn't owner of entrys. +/** + * HashMap with RobinHood collision resolution policy. + * Single threaded. + * Entries are saved as pointers alligned to 8B. + * Entries must know thers key. + * D must have method const K & get_key() + * K must be comparable with ==. + * HashMap behaves as if it isn't owner of entries. + * BE CAREFUL - this structure assumes that the pointer to Data is 8-alligned! +*/ template <class K, class D, size_t init_size_pow2 = 2> class RhHashMap : public RhBase<K, D, init_size_pow2> { typedef RhBase<K, D, init_size_pow2> base; @@ -69,6 +73,8 @@ class RhHashMap : public RhBase<K, D, init_size_pow2> { // Inserts element. Returns true if element wasn't in the map. bool insert(D *data) { + permanent_assert(!(((uint64_t) static_cast<void *>(data) & 7)), + "Data is not 8-alligned."); if (count < capacity) { size_t mask = this->mask(); auto key = std::ref(data->get_key()); diff --git a/src/data_structures/map/rh_hashmultimap.hpp b/src/data_structures/map/rh_hashmultimap.hpp index 60781e883..85c332e6c 100644 --- a/src/data_structures/map/rh_hashmultimap.hpp +++ b/src/data_structures/map/rh_hashmultimap.hpp @@ -4,39 +4,45 @@ #include <functional> #include "data_structures/map/rh_common.hpp" #include "utils/assert.hpp" +#include "utils/assert.hpp" #include "utils/crtp.hpp" #include "utils/likely.hpp" #include "utils/option.hpp" #include "utils/option_ptr.hpp" -// HashMultiMap with RobinHood collision resolution policy. -// Single threaded. -// Entrys are POINTERS alligned to 8B. -// Entrys must know thers key. -// D must have method K& get_key() -// K must be comparable with ==. -// HashMap behaves as if it isn't owner of entrys. -// -// Main idea of this MultiMap is a tweak of logic in RobinHood. -// RobinHood offset from prefered slot is equal to the number of slots between -// [current slot and prefered slot>. -// While in this flavour of "multi RobinHood" offset from prefered slot is equal -// to the number of different keyed elements between his current slot and -// prefered slot. -// In the following examples slots will have keys as caracters. So something -// like this: |a| will mean that in this slot there is data with key 'a'. -// like this: | | will mean empty slot. -// like this: |...| will mean arbitary number of slots. -// like this: |b:a| will mean that a want's to be in slot but b is in't. -// -// Examples: -// |...|a:a|...| => off(a) = 0 -// |...|a:a|a|...|a|...| => off(a) = 0 -// |...|b:a|a|...| => off(a) = 1 -// |...|b:a|b|...|b|a|...| => off(a) = 1 -// |...|c:a|b|a|...| => off(a) = 2 -// |...|c:a|c|...|c|b|...|b||a|...|a|...| => off(a) = 2 -// ... +/** + * HashMultiMap with RobinHood collision resolution policy. + * Single threaded. + * Entries are POINTERS alligned to 8B. + * Entries must know thers key. + * D must have method K& get_key() + * K must be comparable with ==. + * HashMap behaves as if it isn't owner of entries. + * BE CAREFUL - this structure assumes that the pointer to Data is + * 8-alligned! + * + * Main idea of this MultiMap is a tweak of logic in RobinHood. + * RobinHood offset from prefered slot is equal to the number of slots between + * [current slot and prefered slot>. + * While in this flavour of "multi RobinHood" offset from prefered slot is + * equal + * to the number of different keyed elements between his current slot and + * prefered slot. + * In the following examples slots will have keys as caracters. So something + * like this: |a| will mean that in this slot there is data with key 'a'. + * like this: | | will mean empty slot. + * like this: |...| will mean arbitary number of slots. + * like this: |b:a| will mean that a want's to be in slot but b is in't. + * + * Examples: + * |...|a:a|...| => off(a) = 0 + * |...|a:a|a|...|a|...| => off(a) = 0 + * |...|b:a|a|...| => off(a) = 1 + * |...|b:a|b|...|b|a|...| => off(a) = 1 + * |...|c:a|b|a|...| => off(a) = 2 + * |...|c:a|c|...|c|b|...|b||a|...|a|...| => off(a) = 2 + * ... +*/ template <class K, class D, size_t init_size_pow2 = 2> class RhHashMultiMap : public RhBase<K, D, init_size_pow2> { typedef RhBase<K, D, init_size_pow2> base; @@ -124,6 +130,8 @@ class RhHashMultiMap : public RhBase<K, D, init_size_pow2> { // Inserts element with the given key. void add(const K &key_in, D *data) { debug_assert(key_in == data->get_key(), "Key doesn't match data key."); + permanent_assert(!((uint64_t)(static_cast<void *>(data)) & 7), + "Data is not 8-alligned."); if (count < capacity) { auto key = std::ref(key_in); diff --git a/tests/benchmark/data_structures/concurrent/skiplist_reverse_iteration.cpp b/tests/benchmark/data_structures/concurrent/skiplist_reverse_iteration.cpp index 96b705072..ee9a9b868 100644 --- a/tests/benchmark/data_structures/concurrent/skiplist_reverse_iteration.cpp +++ b/tests/benchmark/data_structures/concurrent/skiplist_reverse_iteration.cpp @@ -75,7 +75,6 @@ static void FindFromRBegin(benchmark::State &state) { auto accessor = skiplist.access(); auto rbegin = accessor.rbegin(); - auto rend = accessor.rend(); state.ResumeTiming(); diff --git a/tests/benchmark/query/strip/stripper.cpp b/tests/benchmark/query/strip/stripper.cpp index bd0e077e3..dc3639c8a 100644 --- a/tests/benchmark/query/strip/stripper.cpp +++ b/tests/benchmark/query/strip/stripper.cpp @@ -29,10 +29,9 @@ int main(int argc, char **argv) { auto tests = dataset["benchmark_queries"].as<std::vector<std::string>>(); for (auto &test : tests) { - auto *benchmark = - benchmark::RegisterBenchmark(test.c_str(), BM_Strip, preprocess, test) - ->Range(1, 1) - ->Complexity(benchmark::oN); + benchmark::RegisterBenchmark(test.c_str(), BM_Strip, preprocess, test) + ->Range(1, 1) + ->Complexity(benchmark::oN); } benchmark::Initialize(&argc, argv); diff --git a/tests/concurrent/common.h b/tests/concurrent/common.h index 4bfbf0f6a..4173eb0ce 100644 --- a/tests/concurrent/common.h +++ b/tests/concurrent/common.h @@ -25,188 +25,158 @@ constexpr int max_no_threads = 8; using std::cout; using std::endl; -using map_t = ConcurrentMap<int, int>; -using set_t = ConcurrentSet<int>; +using map_t = ConcurrentMap<int, int>; +using set_t = ConcurrentSet<int>; using multiset_t = ConcurrentMultiSet<int>; using multimap_t = ConcurrentMultiMap<int, int>; using namespace std::chrono_literals; // Returns uniform random size_t generator from range [0,n> -auto rand_gen(size_t n) -{ - std::default_random_engine generator; - std::uniform_int_distribution<size_t> distribution(0, n - 1); - return std::bind(distribution, generator); +auto rand_gen(size_t n) { + std::default_random_engine generator; + std::uniform_int_distribution<size_t> distribution(0, n - 1); + return std::bind(distribution, generator); } // Returns random bool generator with distribution of 1 true for n false. -auto rand_gen_bool(size_t n = 1) -{ - auto gen = rand_gen(n + 1); - return [=]() mutable { return gen() == 0; }; +auto rand_gen_bool(size_t n = 1) { + auto gen = rand_gen(n + 1); + return [=]() mutable { return gen() == 0; }; } // Checks for all owned keys if there data is data. template <typename S> void check_present_same(typename S::Accessor &acc, size_t data, - std::vector<size_t> &owned) -{ - for (auto num : owned) - { - permanent_assert(acc.find(num)->second == data, - "My data is present and my"); - } + std::vector<size_t> &owned) { + for (auto num : owned) { + permanent_assert(acc.find(num)->second == data, + "My data is present and my"); + } } // Checks for all owned.second keys if there data is owned.first. template <typename S> void check_present_same(typename S::Accessor &acc, - std::pair<size_t, std::vector<size_t>> &owned) -{ - check_present_same<S>(acc, owned.first, owned.second); + std::pair<size_t, std::vector<size_t>> &owned) { + check_present_same<S>(acc, owned.first, owned.second); } // Checks if reported size and traversed size are equal to given size. template <typename S> -void check_size_list(S &acc, long long size) -{ - // check size +void check_size_list(S &acc, long long size) { + // check size - permanent_assert(acc.size() == size, "Size should be " << size - << ", but size is " - << acc.size()); + permanent_assert(acc.size() == size, + "Size should be " << size << ", but size is " << acc.size()); - // check count + // check count - size_t iterator_counter = 0; + size_t iterator_counter = 0; - for (auto elem : acc) - { - ++iterator_counter; - } - permanent_assert(iterator_counter == size, "Iterator count should be " - << size << ", but size is " - << iterator_counter); + for ([[gnu::unused]] auto elem : acc) { + ++iterator_counter; + } + permanent_assert(iterator_counter == size, "Iterator count should be " + << size << ", but size is " + << iterator_counter); } template <typename S> -void check_size(typename S::Accessor &acc, long long size) -{ - // check size +void check_size(typename S::Accessor &acc, long long size) { + // check size - permanent_assert(acc.size() == size, "Size should be " << size - << ", but size is " - << acc.size()); + permanent_assert(acc.size() == size, + "Size should be " << size << ", but size is " << acc.size()); - // check count + // check count - size_t iterator_counter = 0; + size_t iterator_counter = 0; - for (auto elem : acc) - { - ++iterator_counter; - } - permanent_assert(iterator_counter == size, "Iterator count should be " - << size << ", but size is " - << iterator_counter); + for ([[gnu::unused]] auto elem : acc) { + ++iterator_counter; + } + permanent_assert(iterator_counter == size, "Iterator count should be " + << size << ", but size is " + << iterator_counter); } // Checks if order in list is maintened. It expects map template <typename S> -void check_order(typename S::Accessor &acc) -{ - if (acc.begin() != acc.end()) - { - auto last = acc.begin()->first; - for (auto elem : acc) - { - if (!(last <= elem)) - std::cout << "Order isn't maintained. Before was: " << last - << " next is " << elem.first << "\n"; - last = elem.first; - } +void check_order(typename S::Accessor &acc) { + if (acc.begin() != acc.end()) { + auto last = acc.begin()->first; + for (auto elem : acc) { + if (!(last <= elem)) + std::cout << "Order isn't maintained. Before was: " << last + << " next is " << elem.first << "\n"; + last = elem.first; } + } } -void check_zero(size_t key_range, long array[], const char *str) -{ - for (int i = 0; i < key_range; i++) - { - permanent_assert(array[i] == 0, - str << " doesn't hold it's guarantees. It has " - << array[i] << " extra elements."); - } +void check_zero(size_t key_range, long array[], const char *str) { + for (int i = 0; i < key_range; i++) { + permanent_assert(array[i] == 0, + str << " doesn't hold it's guarantees. It has " << array[i] + << " extra elements."); + } } -void check_set(DynamicBitset<> &db, std::vector<bool> &set) -{ - for (int i = 0; i < set.size(); i++) - { - permanent_assert(!(set[i] ^ db.at(i)), - "Set constraints aren't fullfilled."); - } +void check_set(DynamicBitset<> &db, std::vector<bool> &set) { + for (int i = 0; i < set.size(); i++) { + permanent_assert(!(set[i] ^ db.at(i)), + "Set constraints aren't fullfilled."); + } } // Checks multiIterator and iterator guarantees void check_multi_iterator(multimap_t::Accessor &accessor, size_t key_range, - long set[]) -{ - for (int i = 0; i < key_range; i++) - { - auto it = accessor.find(i); - auto it_m = accessor.find_multi(i); - permanent_assert( - !(it_m != accessor.end(i) && it == accessor.end()), - "MultiIterator ended before Iterator. Set: " << set[i]); - permanent_assert( - !(it_m == accessor.end(i) && it != accessor.end()), - "Iterator ended before MultiIterator. Set: " << set[i]); - permanent_assert((it_m == accessor.end(i) && it == accessor.end()) || - it->second == it_m->second, - "MultiIterator didn't found the same " - "first element. Set: " - << set[i]); - if (set[i] > 0) - { - for (int j = 0; j < set[i]; j++) - { - permanent_assert( - it->second == it_m->second, - "MultiIterator and iterator aren't on the same " - "element."); - permanent_assert(it_m->first == i, - "MultiIterator is showing illegal data") it++; - it_m++; - } - } - permanent_assert( - it_m == accessor.end(i), - "There is more data than it should be in MultiIterator. " - << it_m->first << "\n"); + long set[]) { + for (int i = 0; i < key_range; i++) { + auto it = accessor.find(i); + auto it_m = accessor.find_multi(i); + permanent_assert(!(it_m != accessor.end(i) && it == accessor.end()), + "MultiIterator ended before Iterator. Set: " << set[i]); + permanent_assert(!(it_m == accessor.end(i) && it != accessor.end()), + "Iterator ended before MultiIterator. Set: " << set[i]); + permanent_assert((it_m == accessor.end(i) && it == accessor.end()) || + it->second == it_m->second, + "MultiIterator didn't found the same " + "first element. Set: " + << set[i]); + if (set[i] > 0) { + for (int j = 0; j < set[i]; j++) { + permanent_assert(it->second == it_m->second, + "MultiIterator and iterator aren't on the same " + "element."); + permanent_assert(it_m->first == i, + "MultiIterator is showing illegal data") it++; + it_m++; + } } + permanent_assert(it_m == accessor.end(i), + "There is more data than it should be in MultiIterator. " + << it_m->first << "\n"); + } } // Runs given function in threads_no threads and returns vector of futures for // there // results. template <class R, typename S> -std::vector<std::future<std::pair<size_t, R>>> -run(size_t threads_no, S &skiplist, - std::function<R(typename S::Accessor, size_t)> f) -{ - std::vector<std::future<std::pair<size_t, R>>> futures; +std::vector<std::future<std::pair<size_t, R>>> run( + size_t threads_no, S &skiplist, + std::function<R(typename S::Accessor, size_t)> f) { + std::vector<std::future<std::pair<size_t, R>>> futures; - for (size_t thread_i = 0; thread_i < threads_no; ++thread_i) - { - std::packaged_task<std::pair<size_t, R>()> task( - [&skiplist, f, thread_i]() { - return std::pair<size_t, R>(thread_i, - f(skiplist.access(), thread_i)); - }); // wrap the function - futures.push_back(task.get_future()); // get a future - std::thread(std::move(task)).detach(); - } - return futures; + for (size_t thread_i = 0; thread_i < threads_no; ++thread_i) { + std::packaged_task<std::pair<size_t, R>()> task([&skiplist, f, thread_i]() { + return std::pair<size_t, R>(thread_i, f(skiplist.access(), thread_i)); + }); // wrap the function + futures.push_back(task.get_future()); // get a future + std::thread(std::move(task)).detach(); + } + return futures; } // Runs given function in threads_no threads and returns vector of futures for @@ -214,98 +184,87 @@ run(size_t threads_no, S &skiplist, // results. template <class R> std::vector<std::future<std::pair<size_t, R>>> run(size_t threads_no, - std::function<R(size_t)> f) -{ - std::vector<std::future<std::pair<size_t, R>>> futures; + std::function<R(size_t)> f) { + std::vector<std::future<std::pair<size_t, R>>> futures; - for (size_t thread_i = 0; thread_i < threads_no; ++thread_i) - { - std::packaged_task<std::pair<size_t, R>()> task([f, thread_i]() { - return std::pair<size_t, R>(thread_i, f(thread_i)); - }); // wrap the function - futures.push_back(task.get_future()); // get a future - std::thread(std::move(task)).detach(); - } - return futures; + for (size_t thread_i = 0; thread_i < threads_no; ++thread_i) { + std::packaged_task<std::pair<size_t, R>()> task([f, thread_i]() { + return std::pair<size_t, R>(thread_i, f(thread_i)); + }); // wrap the function + futures.push_back(task.get_future()); // get a future + std::thread(std::move(task)).detach(); + } + return futures; } // Collects all data from futures. template <class R> -auto collect(std::vector<std::future<R>> &collect) -{ - std::vector<R> collection; - for (auto &fut : collect) - { - collection.push_back(fut.get()); - } - return collection; +auto collect(std::vector<std::future<R>> &collect) { + std::vector<R> collection; + for (auto &fut : collect) { + collection.push_back(fut.get()); + } + return collection; } std::vector<bool> collect_set( - std::vector<std::future<std::pair<size_t, std::vector<bool>>>> &&futures) -{ - std::vector<bool> set; - for (auto &data : collect(futures)) - { - set.resize(data.second.size()); - for (int i = 0; i < data.second.size(); i++) - { - set[i] = set[i] | data.second[i]; - } + std::vector<std::future<std::pair<size_t, std::vector<bool>>>> &&futures) { + std::vector<bool> set; + for (auto &data : collect(futures)) { + set.resize(data.second.size()); + for (int i = 0; i < data.second.size(); i++) { + set[i] = set[i] | data.second[i]; } - return set; + } + return set; } // Returns object which tracs in owned which (key,data) where added and // downcounts. template <class K, class D, class S> auto insert_try(typename S::Accessor &acc, long long &downcount, - std::vector<K> &owned) -{ - return [&](K key, D data) mutable { - if (acc.insert(key, data).second) - { - downcount--; - owned.push_back(key); - } - }; + std::vector<K> &owned) { + return [&](K key, D data) mutable { + if (acc.insert(key, data).second) { + downcount--; + owned.push_back(key); + } + }; } // Performs memory check to determine if memory usage before calling given // function // is aproximately equal to memory usage after function. Memory usage is thread // senstive so no_threads spawned in function is necessary. -void memory_check(size_t no_threads, std::function<void()> f) -{ - logging::info("Number of threads: {}", no_threads); +void memory_check(size_t no_threads, std::function<void()> f) { + logging::info("Number of threads: {}", no_threads); - // TODO: replace vm_size with something more appropriate - // the past implementation was teribble wrong - // to that ASAP - // OR - // use custom allocation wrapper - // OR - // user Boost.Test - auto start = vm_size(); - logging::info("Memory check (used memory at the beginning): {}", start); + // TODO: replace vm_size with something more appropriate + // the past implementation was teribble wrong + // to that ASAP + // OR + // use custom allocation wrapper + // OR + // user Boost.Test + auto start = vm_size(); + logging::info("Memory check (used memory at the beginning): {}", start); - f(); + f(); - auto end = vm_size(); - logging::info("Memory check (used memory at the end): {}", end); + auto end = vm_size(); + logging::info("Memory check (used memory at the end): {}", end); - long long delta = end - start; - logging::info("Delta: {}", delta); + long long delta = end - start; + logging::info("Delta: {}", delta); - // TODO: do memory check somehow - // the past implementation was wrong - permanent_assert(true, "Memory leak"); + // TODO: do memory check somehow + // the past implementation was wrong + permanent_assert(true, "Memory leak"); } // TODO: move this inside logging/default // Initializes loging faccilityes -void init_log() -{ - logging::init_async(); - logging::log->pipe(std::make_unique<Stdout>()); +void init_log() { + logging::init_async(); + logging::log->pipe(std::make_unique<Stdout>()); } diff --git a/tests/concurrent/network_common.hpp b/tests/concurrent/network_common.hpp index 1fa294be4..d4d7bcfc1 100644 --- a/tests/concurrent/network_common.hpp +++ b/tests/concurrent/network_common.hpp @@ -17,7 +17,6 @@ #include "io/network/socket.hpp" #include "query/engine.hpp" - static constexpr const int SIZE = 60000; static constexpr const int REPLY = 10; @@ -28,9 +27,10 @@ class TestOutputStream {}; class TestSession { public: - TestSession(socket_t &&socket, Dbms &dbms, - QueryEngine<TestOutputStream> &query_engine) - : socket(std::move(socket)), logger_(logging::log->logger("TestSession")) { + TestSession(socket_t&& socket, Dbms& dbms, + QueryEngine<TestOutputStream>& query_engine) + : logger_(logging::log->logger("TestSession")), + socket(std::move(socket)) { event.data.ptr = this; } @@ -38,7 +38,7 @@ class TestSession { int id() const { return socket.id(); } - void execute(const byte *data, size_t len) { + void execute(const byte* data, size_t len) { if (size_ == 0) { size_ = data[0]; size_ <<= 8; @@ -77,7 +77,8 @@ void server_start(void* serverptr, int num) { ((test_server_t*)serverptr)->Start(num); } -void client_run(int num, const char* interface, const char* port, const unsigned char* data, int lo, int hi) { +void client_run(int num, const char* interface, const char* port, + const unsigned char* data, int lo, int hi) { std::stringstream name; name << "Client " << num; Logger logger = logging::log->logger(name.str()); diff --git a/tests/concurrent/sl_insert_competetive.cpp b/tests/concurrent/sl_insert_competetive.cpp index a06d933ba..d3aa3d0bf 100644 --- a/tests/concurrent/sl_insert_competetive.cpp +++ b/tests/concurrent/sl_insert_competetive.cpp @@ -2,7 +2,6 @@ constexpr size_t THREADS_NO = std::min(max_no_threads, 8); constexpr size_t elems_per_thread = 100000; -constexpr size_t key_range = elems_per_thread * THREADS_NO * 2; // TODO: document the test @@ -18,16 +17,17 @@ int main() { auto futures = run<std::vector<size_t>>( THREADS_NO, skiplist, [](auto acc, auto index) { - auto rand = rand_gen(key_range); long long downcount = elems_per_thread; std::vector<size_t> owned; auto inserter = insert_try<size_t, size_t, map_t>(acc, downcount, owned); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfor-loop-analysis" for (int i = 0; downcount > 0; i++) { inserter(i, index); } - +#pragma GCC diagnostic pop check_present_same<map_t>(acc, index, owned); return owned; }); diff --git a/tests/unit/rh_hashmap.cpp b/tests/unit/rh_hashmap.cpp index dcb07d76d..0ea1b3042 100644 --- a/tests/unit/rh_hashmap.cpp +++ b/tests/unit/rh_hashmap.cpp @@ -1,10 +1,10 @@ #include "gtest/gtest.h" +#include <memory> #include "data_structures/map/rh_hashmap.hpp" class Data { private: - size_t data = 0; int key; public: @@ -19,14 +19,16 @@ TEST(RobinHoodHashmap, BasicFunctionality) { RhHashMap<int, Data> map; ASSERT_EQ(map.size(), 0); - ASSERT_EQ(map.insert(new Data(0)), true); + Data d0(0); + ASSERT_EQ(map.insert(&d0), true); ASSERT_EQ(map.size(), 1); } TEST(RobinHoodHashmap, RemoveFunctionality) { RhHashMap<int, Data> map; - ASSERT_EQ(map.insert(new Data(0)), true); + Data d0(0); + ASSERT_EQ(map.insert(&d0), true); ASSERT_EQ(map.remove(0).is_present(), true); ASSERT_EQ(map.size(), 0); ASSERT_EQ(!map.find(0).is_present(), true); @@ -36,25 +38,29 @@ TEST(RobinHoodHashmap, InsertGetCheck) { RhHashMap<int, Data> map; ASSERT_EQ(!map.find(0).is_present(), true); - auto ptr0 = new Data(0); - ASSERT_EQ(map.insert(ptr0), true); + Data d0(0); + ASSERT_EQ(map.insert(&d0), true); ASSERT_EQ(map.find(0).is_present(), true); - ASSERT_EQ(map.find(0).get(), ptr0); + ASSERT_EQ(map.find(0).get(), &d0); } TEST(RobinHoodHashmap, DoubleInsert) { RhHashMap<int, Data> map; - ASSERT_EQ(map.insert(new Data(0)), true); - ASSERT_EQ(!map.insert(new Data(0)), true); + Data d0(0); + ASSERT_EQ(map.insert(&d0), true); + ASSERT_EQ(!map.insert(&d0), true); } TEST(RobinHoodHashmap, FindInsertFind) { RhHashMap<int, Data> map; + std::vector<std::unique_ptr<Data>> di; + di.reserve(128); + for (int i = 0; i < 128; ++i) di.emplace_back(std::make_unique<Data>(i)); for (int i = 0; i < 128; i++) { ASSERT_EQ(!map.find(i).is_present(), true); - ASSERT_EQ(map.insert(new Data(i)), true); + ASSERT_EQ(map.insert(di[i].get()), true); ASSERT_EQ(map.find(i).is_present(), true); } @@ -67,9 +73,12 @@ TEST(RobinHoodHashmap, FindInsertFind) { TEST(RobinHoodHashmap, Iterate) { RhHashMap<int, Data> map; + std::vector<std::unique_ptr<Data>> di; + di.reserve(128); + for (int i = 0; i < 128; ++i) di.emplace_back(std::make_unique<Data>(i)); for (int i = 0; i < 128; i++) { ASSERT_EQ(!map.find(i).is_present(), true); - ASSERT_EQ(map.insert(new Data(i)), true); + ASSERT_EQ(map.insert(di[i].get()), true); ASSERT_EQ(map.find(i).is_present(), true); } @@ -88,14 +97,21 @@ TEST(RobinHoodHashmap, Checked) { RhHashMap<int, Data> map; std::map<int, Data *> s_map; + std::vector<std::unique_ptr<Data>> di; + std::vector<int> key; + di.reserve(128); + key.reserve(128); + for (int i = 0; i < 128; ++i) { + const int curr_key = std::rand(); + key.emplace_back(curr_key); + di.emplace_back(std::make_unique<Data>(curr_key)); + } for (int i = 0; i < 128; i++) { - int key = std::rand(); - auto data = new Data(key); - if (map.insert(data)) { - ASSERT_EQ(s_map.find(key), s_map.end()); - s_map[key] = data; + if (map.insert(di[i].get())) { + ASSERT_EQ(s_map.find(key[i]), s_map.end()); + s_map[key[i]] = di[i].get(); } else { - ASSERT_NE(s_map.find(key), s_map.end()); + ASSERT_NE(s_map.find(key[i]), s_map.end()); } } @@ -105,17 +121,24 @@ TEST(RobinHoodHashmap, Checked) { TEST(RobinHoodHashMap, CheckWithRemove) { RhHashMap<int, Data> map; std::map<int, Data *> s_map; + std::vector<std::unique_ptr<Data>> di; + std::vector<int> key; + di.reserve(1280); + key.reserve(1280); + for (int i = 0; i < 1280; ++i) { + const int curr_key = std::rand() % 100; + key.emplace_back(curr_key); + di.emplace_back(std::make_unique<Data>(curr_key)); + } for (int i = 0; i < 1280; i++) { - int key = std::rand() % 100; - auto data = new Data(key); - if (map.insert(data)) { - ASSERT_EQ(s_map.find(key), s_map.end()); - s_map[key] = data; + if (map.insert(di[i].get())) { + ASSERT_EQ(s_map.find(key[i]), s_map.end()); + s_map[key[i]] = di[i].get(); cross_validate(map, s_map); } else { - ASSERT_EQ(map.remove(key).is_present(), true); - ASSERT_EQ(s_map.erase(key), 1); + ASSERT_EQ(map.remove(key[i]).is_present(), true); + ASSERT_EQ(s_map.erase(key[i]), 1); cross_validate(map, s_map); } } @@ -123,6 +146,13 @@ TEST(RobinHoodHashMap, CheckWithRemove) { cross_validate(map, s_map); } +TEST(RobinhoodHashmmap, AlignmentCheck) { + RhHashMap<int, Data> map; + char *block = static_cast<char *>(std::malloc(20)); + ++block; // not alligned - offset 1 + EXPECT_DEATH(map.insert((Data *)(block)), "not 8-alligned"); +} + void cross_validate(RhHashMap<int, Data> &map, std::map<int, Data *> &s_map) { for (auto e : map) { ASSERT_NE(s_map.find(e->get_key()), s_map.end()); diff --git a/tests/unit/rh_hashmultimap.cpp b/tests/unit/rh_hashmultimap.cpp index 9033294e7..f324a07bf 100644 --- a/tests/unit/rh_hashmultimap.cpp +++ b/tests/unit/rh_hashmultimap.cpp @@ -4,7 +4,6 @@ class Data { private: - size_t data = 0; int key; public: @@ -23,7 +22,8 @@ TEST(RobinHoodHashmultimap, BasicFunctionality) { RhHashMultiMap<int, Data> map; ASSERT_EQ(map.size(), 0); - map.add(new Data(0)); + Data d0(0); + map.add(&d0); ASSERT_EQ(map.size(), 1); } @@ -31,67 +31,72 @@ TEST(RobinHoodHashmultimap, InsertGetCheck) { RhHashMultiMap<int, Data> map; ASSERT_EQ(map.find(0), map.end()); - auto ptr0 = new Data(0); - map.add(ptr0); + Data d0(0); + map.add(&d0); ASSERT_NE(map.find(0), map.end()); - ASSERT_EQ(*map.find(0), ptr0); + ASSERT_EQ(*map.find(0), &d0); } TEST(RobinHoodHashmultimap, ExtremeSameKeyValusFull) { RhHashMultiMap<int, Data> map; + std::vector<std::unique_ptr<Data>> di; + di.reserve(128); for (int i = 0; i < 128; i++) { - map.add(new Data(7)); + di.emplace_back(std::make_unique<Data>(7)); + map.add(di[i].get()); } ASSERT_EQ(map.size(), 128); ASSERT_NE(map.find(7), map.end()); ASSERT_EQ(map.find(0), map.end()); - auto ptr0 = new Data(0); - map.add(ptr0); + Data d0(0); + map.add(&d0); ASSERT_NE(map.find(0), map.end()); - ASSERT_EQ(*map.find(0), ptr0); + ASSERT_EQ(*map.find(0), &d0); } TEST(RobinHoodHashmultimap, ExtremeSameKeyValusFullWithRemove) { RhHashMultiMap<int, Data> map; + std::vector<std::unique_ptr<Data>> di; + di.reserve(128); for (int i = 0; i < 127; i++) { - map.add(new Data(7)); + di.emplace_back(std::make_unique<Data>(7)); + map.add(di[i].get()); } - auto ptr = new Data(7); - map.add(ptr); + Data d7(7); + map.add(&d7); ASSERT_EQ(map.size(), 128); - ASSERT_EQ(!map.remove(new Data(0)), true); - ASSERT_EQ(map.remove(ptr), true); + Data d0(0); + ASSERT_EQ(!map.remove(&d0), true); + ASSERT_EQ(map.remove(&d7), true); } TEST(RobinHoodHasmultihmap, RemoveFunctionality) { RhHashMultiMap<int, Data> map; ASSERT_EQ(map.find(0), map.end()); - auto ptr0 = new Data(0); - map.add(ptr0); + Data d0(0); + map.add(&d0); ASSERT_NE(map.find(0), map.end()); - ASSERT_EQ(*map.find(0), ptr0); - ASSERT_EQ(map.remove(ptr0), true); + ASSERT_EQ(*map.find(0), &d0); + ASSERT_EQ(map.remove(&d0), true); ASSERT_EQ(map.find(0), map.end()); } TEST(RobinHoodHashmultimap, DoubleInsert) { RhHashMultiMap<int, Data> map; - auto ptr0 = new Data(0); - auto ptr1 = new Data(0); - map.add(ptr0); - map.add(ptr1); + Data d0(0); + Data d01(0); + map.add(&d0); + map.add(&d01); for (auto e : map) { - if (ptr0 == e) { - ptr0 = nullptr; + if (&d0 == e) { continue; } - if (ptr1 == e) { - ptr1 = nullptr; + if (&d01 == e) { continue; } ASSERT_EQ(true, false); @@ -101,9 +106,12 @@ TEST(RobinHoodHashmultimap, DoubleInsert) { TEST(RobinHoodHashmultimap, FindAddFind) { RhHashMultiMap<int, Data> map; + std::vector<std::unique_ptr<Data>> di; + di.reserve(128); for (int i = 0; i < 128; i++) { ASSERT_EQ(map.find(i), map.end()); - map.add(new Data(i)); + di.emplace_back(std::make_unique<Data>(i)); + map.add(di[i].get()); ASSERT_NE(map.find(i), map.end()); } @@ -116,9 +124,12 @@ TEST(RobinHoodHashmultimap, FindAddFind) { TEST(RobinHoodHashmultimap, Iterate) { RhHashMultiMap<int, Data> map; + std::vector<std::unique_ptr<Data>> di; + di.reserve(128); for (int i = 0; i < 128; i++) { ASSERT_EQ(map.find(i), map.end()); - map.add(new Data(i)); + di.emplace_back(std::make_unique<Data>(i)); + map.add(di[i].get()); ASSERT_NE(map.find(i), map.end()); } @@ -137,12 +148,18 @@ TEST(RobinHoodHashmultimap, Checked) { RhHashMultiMap<int, Data> map; std::multimap<int, Data *> s_map; - for (int i = 0; i < 1638; i++) { - int key = (std::rand() % 100) << 3; + std::vector<std::unique_ptr<Data>> di; + std::vector<int> keys; + di.reserve(1638); + for (int i = 0; i < 1638; ++i) { + const int key = (std::rand() % 100) << 3; + keys.push_back(key); + di.emplace_back(std::make_unique<Data>(key)); + } - auto data = new Data(key); - map.add(data); - s_map.insert(std::pair<int, Data *>(key, data)); + for (int i = 0; i < 1638; i++) { + map.add(di[i].get()); + s_map.insert(std::pair<int, Data *>(keys[i], di[i].get())); } cross_validate(map, s_map); } @@ -151,12 +168,19 @@ TEST(RobinHoodHashmultimap, CheckedRand) { RhHashMultiMap<int, Data> map; std::multimap<int, Data *> s_map; std::srand(std::time(0)); - for (int i = 0; i < 164308; i++) { - int key = (std::rand() % 10000) << 3; - auto data = new Data(key); - map.add(data); - s_map.insert(std::pair<int, Data *>(key, data)); + std::vector<std::unique_ptr<Data>> di; + std::vector<int> keys; + di.reserve(164308); + for (int i = 0; i < 164308; ++i) { + const int key = (std::rand() % 10000) << 3; + keys.push_back(key); + di.emplace_back(std::make_unique<Data>(key)); + } + + for (int i = 0; i < 164308; i++) { + map.add(di[i].get()); + s_map.insert(std::pair<int, Data *>(keys[i], di[i].get())); } cross_validate(map, s_map); } @@ -166,6 +190,7 @@ TEST(RobinHoodHashmultimap, WithRemoveDataChecked) { std::multimap<int, Data *> s_map; std::srand(std::time(0)); + std::vector<std::unique_ptr<Data>> di; for (int i = 0; i < 162638; i++) { int key = (std::rand() % 10000) << 3; if ((std::rand() % 2) == 0) { @@ -177,15 +202,22 @@ TEST(RobinHoodHashmultimap, WithRemoveDataChecked) { ASSERT_EQ(map.remove(it->second), true); } } else { - auto data = new Data(key); - map.add(data); - s_map.insert(std::pair<int, Data *>(key, data)); + di.emplace_back(std::make_unique<Data>(key)); + map.add(di.back().get()); + s_map.insert(std::pair<int, Data *>(key, di.back().get())); } } cross_validate(map, s_map); } +TEST(RobinhoodHashmultimap, AlignmentCheck) { + RhHashMultiMap<int, Data> map; + char *block = static_cast<char *>(std::malloc(20)); + ++block; // not alligned - offset 1 + EXPECT_DEATH(map.add((Data *)(block)), "not 8-alligned"); +} + void cross_validate(RhHashMultiMap<int, Data> &map, std::multimap<int, Data *> &s_map) { for (auto e : map) { diff --git a/tests/unit/traversal.cpp b/tests/unit/traversal.cpp index fb68b5c59..b7d32ccb3 100644 --- a/tests/unit/traversal.cpp +++ b/tests/unit/traversal.cpp @@ -3,12 +3,12 @@ // Created by Florijan Stamenkovic on 24.01.17.. // -#include <vector> -#include <list> -#include <unordered_set> #include <iostream> #include <list> +#include <list> #include <memory> +#include <unordered_set> +#include <vector> #include "gtest/gtest.h" @@ -38,14 +38,14 @@ class Edge; class Vertex { friend class Edge; -public: + public: // unique identifier (uniqueness guaranteed by this class) const int id_; // vertex set by the user, for testing purposes const int label_; - Vertex(int label=0) : id_(counter_++), label_(label) {} + Vertex(int label = 0) : id_(counter_++), label_(label) {} const auto &in() const { return *in_; } const auto &out() const { return *out_; } @@ -57,15 +57,16 @@ public: bool operator==(const Vertex &v) const { return this->id_ == v.id_; } bool operator!=(const Vertex &v) const { return !(*this == v); } -private: + private: // shared pointers to outgoing and incoming edges are used so that when // a Vertex is copied it still points to the same connectivity storage - std::shared_ptr<std::vector<Edge>> in_ = std::make_shared<std::vector<Edge>>(); - std::shared_ptr<std::vector<Edge>> out_ = std::make_shared<std::vector<Edge>>(); + std::shared_ptr<std::vector<Edge>> in_ = + std::make_shared<std::vector<Edge>>(); + std::shared_ptr<std::vector<Edge>> out_ = + std::make_shared<std::vector<Edge>>(); // Vertex counter, used for generating IDs static int counter_; - }; int Vertex::counter_ = 0; @@ -75,15 +76,15 @@ int Vertex::counter_ = 0; * and an exposed id_ member. */ class Edge { -public: + public: // unique identifier (uniqueness guaranteed by this class) const int id_; // vertex set by the user, for testing purposes const int type_; - Edge(const Vertex &from, const Vertex &to, int type=0) : - id_(counter_++), from_(from), to_(to), type_(type) { + Edge(const Vertex &from, const Vertex &to, int type = 0) + : id_(counter_++), type_(type), from_(from), to_(to) { from.out_->emplace_back(*this); to.in_->emplace_back(*this); } @@ -98,7 +99,7 @@ public: return stream << "[" << e.id_ << "]"; } -private: + private: const Vertex &from_; const Vertex &to_; @@ -115,34 +116,34 @@ using Paths = traversal_template::Paths<Vertex, Edge>; /** * Specialization of the traversal_template::Begin function. */ -template<typename TCollection> -auto Begin(const TCollection &vertices, std::function<bool(const Vertex &)> vertex_filter = {}) { - return traversal_template::Begin<TCollection, Vertex, Edge>(vertices, vertex_filter); +template <typename TCollection> +auto Begin(const TCollection &vertices, + std::function<bool(const Vertex &)> vertex_filter = {}) { + return traversal_template::Begin<TCollection, Vertex, Edge>(vertices, + vertex_filter); } /** * Specialization of the traversal_template::Cartesian function that accepts * a single argument. */ -template<typename TVisitable> +template <typename TVisitable> auto Cartesian(TVisitable &&visitable) { return traversal_template::Cartesian<TVisitable, Vertex, Edge>( std::forward<TVisitable>(visitable)); } - /** * Specialization of the traversal_template::Cartesian function that accepts * multiple arguments. */ -template<typename TVisitableFirst, typename... TVisitableOthers> +template <typename TVisitableFirst, typename... TVisitableOthers> auto Cartesian(TVisitableFirst &&first, TVisitableOthers &&... others) { - return traversal_template::CartesianBinaryType<TVisitableFirst, decltype(Cartesian( - std::forward<TVisitableOthers>(others)...)), - Vertex, Edge>( - std::forward<TVisitableFirst>(first), - Cartesian(std::forward<TVisitableOthers>(others)...) - ); + return traversal_template::CartesianBinaryType< + TVisitableFirst, + decltype(Cartesian(std::forward<TVisitableOthers>(others)...)), Vertex, + Edge>(std::forward<TVisitableFirst>(first), + Cartesian(std::forward<TVisitableOthers>(others)...)); } } @@ -150,27 +151,27 @@ auto Cartesian(TVisitableFirst &&first, TVisitableOthers &&... others) { * Hash calculations for text vertex, edge, Path and Paths. * Only for testing purposes. */ -namespace std{ +namespace std { template <> -class hash<traversal_test::Vertex> { -public: +struct hash<traversal_test::Vertex> { + public: size_t operator()(const traversal_test::Vertex &vertex) const { - return (size_t) vertex.id_; + return (size_t)vertex.id_; } }; template <> -class hash<traversal_test::Edge> { -public: +struct hash<traversal_test::Edge> { + public: size_t operator()(const traversal_test::Edge &edge) const { - return (size_t) edge.id_; + return (size_t)edge.id_; } }; template <> -class hash<traversal_test::Path> { -public: +struct hash<traversal_test::Path> { + public: std::size_t operator()(const traversal_test::Path &path) const { std::size_t r_val = 0; @@ -182,8 +183,8 @@ public: }; template <> -class hash<traversal_test::Paths> { -public: +struct hash<traversal_test::Paths> { + public: std::size_t operator()(const traversal_test::Paths &paths) const { std::size_t r_val = 0; @@ -195,14 +196,13 @@ public: }; } - /** * Hash for a list of edges, used in tests. */ -namespace std{ +namespace std { template <> -class hash<std::list<traversal_test::Edge>> { -public: +struct hash<std::list<traversal_test::Edge>> { + public: std::size_t operator()(const std::list<traversal_test::Edge> &edges) const { std::size_t r_val = 0; @@ -221,7 +221,8 @@ std::unordered_set<TElement> accumulate_visited(const TVisitable &visitable) { // we accept const here so we can receive r-values // we cast the const-ness away because the Visit function is not const std::unordered_set<TElement> results; - const_cast<TVisitable&>(visitable).Visit([&results](auto e) { results.insert(e); }); + const_cast<TVisitable &>(visitable).Visit( + [&results](auto e) { results.insert(e); }); return results; }; @@ -276,8 +277,7 @@ TEST(Traversal, Begin) { std::vector<Vertex> vertices(3); std::unordered_set<Path> expected; - for (const auto &vertex : vertices) - expected.insert(Path().Start(vertex)); + for (const auto &vertex : vertices) expected.insert(Path().Start(vertex)); EXPECT_EQ(expected.size(), 3); auto result = accumulate_visited<Path>(Begin(vertices)); @@ -291,13 +291,10 @@ TEST(Traversal, BeginExpand) { Edge e2(v2, v3); // test traversal from (v0) - auto expected = std::unordered_set<Path>{ - Path().Start(v0).Append(e0, v1), - Path().Start(v0).Append(e1, v2) - }; - auto result= accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - Expand(Expansion::Back, Direction::Out)); + auto expected = std::unordered_set<Path>{Path().Start(v0).Append(e0, v1), + Path().Start(v0).Append(e1, v2)}; + auto result = accumulate_visited<Path>( + Begin(std::vector<Vertex>{v0}).Expand(Expansion::Back, Direction::Out)); EXPECT_EQ(expected, result); } @@ -312,29 +309,23 @@ TEST(Traversal, BeginExpandVariable) { // test traversal from (v0) auto expected = std::unordered_set<Path>{ - Path().Start(v0).Append(e0, v1), - Path().Start(v0).Append(e1, v2), - Path().Start(v0).Append(e1, v2).Append(e2, v3) - }; - auto result= accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - ExpandVariable(Expansion::Back, Direction::Out)); + Path().Start(v0).Append(e0, v1), Path().Start(v0).Append(e1, v2), + Path().Start(v0).Append(e1, v2).Append(e2, v3)}; + auto result = accumulate_visited<Path>( + Begin(std::vector<Vertex>{v0}) + .ExpandVariable(Expansion::Back, Direction::Out)); EXPECT_EQ(expected, result); - } TEST(Traversal, BeginFilter) { Vertex v0(1), v1(1), v2(2); - std::unordered_set<Path> expected{ - Path().Start(v0), - Path().Start(v1) - }; + std::unordered_set<Path> expected{Path().Start(v0), Path().Start(v1)}; - auto result = accumulate_visited<Path>(Begin(std::vector<Vertex>{v0, v1, v2}, - [](const Vertex &v) { return v.label_ == 1; })); + auto result = accumulate_visited<Path>( + Begin(std::vector<Vertex>{v0, v1, v2}, + [](const Vertex &v) { return v.label_ == 1; })); EXPECT_EQ(expected, result); - } TEST(Traversal, BeginCurrent) { @@ -344,7 +335,7 @@ TEST(Traversal, BeginCurrent) { std::vector<Vertex> begin_input{v0, v1, v2}; auto b = Begin(begin_input); - b.Visit([&b, &expected](Path &path){ + b.Visit([&b, &expected](Path &path) { EXPECT_EQ(1, expected.erase(b.CurrentVertex())); }); @@ -365,32 +356,36 @@ TEST(Traversal, ExpandExpand) { Edge e6(v7, v1); // test traversal from (v0) - auto expected = std::unordered_set<Path>{ - Path().Start(v0).Append(e0, v1).Append(e2, v3), - Path().Start(v0).Append(e1, v2).Append(e3, v4), - Path().Start(v0).Append(e1, v2).Append(e4, v5) - }; - auto result= accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - Expand(Expansion::Back, Direction::Out). - Expand(Expansion::Back, Direction::Out)); + auto expected = + std::unordered_set<Path>{Path().Start(v0).Append(e0, v1).Append(e2, v3), + Path().Start(v0).Append(e1, v2).Append(e3, v4), + Path().Start(v0).Append(e1, v2).Append(e4, v5)}; + auto result = + accumulate_visited<Path>(Begin(std::vector<Vertex>{v0}) + .Expand(Expansion::Back, Direction::Out) + .Expand(Expansion::Back, Direction::Out)); EXPECT_EQ(expected, result); } TEST(Traversal, ExpandFilter) { - // make a one-level deep tree and 4 children that have {1,2} vertex labels and {3,4} edge types + // make a one-level deep tree and 4 children that have {1,2} vertex labels and + // {3,4} edge types Vertex root; - Vertex v1(1); Edge e1(root, v1, 3); - Vertex v2(1); Edge e2(root, v2, 4); - Vertex v3(2); Edge e3(root, v3, 3); - Vertex v4(2); Edge e4(root, v4, 4); + Vertex v1(1); + Edge e1(root, v1, 3); + Vertex v2(1); + Edge e2(root, v2, 4); + Vertex v3(2); + Edge e3(root, v3, 3); + Vertex v4(2); + Edge e4(root, v4, 4); // filter to accept only label 1 and edge type 3, expect exactly one path auto result = accumulate_visited<Path>( - Begin(std::vector<Vertex>{root}). - Expand(Expansion::Back, Direction::Out, - [](const Vertex &v) { return v.label_ == 1; }, - [](const Edge &e) { return e.type_ == 3; })); + Begin(std::vector<Vertex>{root}) + .Expand(Expansion::Back, Direction::Out, + [](const Vertex &v) { return v.label_ == 1; }, + [](const Edge &e) { return e.type_ == 3; })); auto expected = std::unordered_set<Path>{Path().Start(root).Append(e1, v1)}; EXPECT_EQ(expected, result); @@ -416,7 +411,7 @@ TEST(Traversal, ExpandCurrent) { std::unordered_set<Vertex> expected_expand1_vertices{v3, v4, v5, v6}; std::unordered_set<Edge> expected_expand1_edges{e3, e4, e5, e6}; - expand1.Visit([&](Path &path){ + expand1.Visit([&](Path &path) { // we can't check that erasure on the first level because it only gets // erased the first time a path containing first level stuff gets visited expected_expand0_vertices.erase(expand0.CurrentVertex()); @@ -434,10 +429,14 @@ TEST(Traversal, ExpandCurrent) { TEST(Traversal, ExpandVariableLimits) { // make a chain Vertex v0; - Vertex v1; Edge e1(v0, v1); - Vertex v2; Edge e2(v1, v2); - Vertex v3; Edge e3(v2, v3); - Vertex v4; Edge e4(v3, v4); + Vertex v1; + Edge e1(v0, v1); + Vertex v2; + Edge e2(v1, v2); + Vertex v3; + Edge e3(v2, v3); + Vertex v4; + Edge e4(v3, v4); // all possible results std::vector<Path> all_possible{Path().Start(v0)}; @@ -448,29 +447,36 @@ TEST(Traversal, ExpandVariableLimits) { // default is one or more traversals auto result0 = accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}).ExpandVariable(Expansion::Back, Direction::Out)); - EXPECT_EQ(result0, std::unordered_set<Path>(all_possible.begin() + 1, all_possible.end())); + Begin(std::vector<Vertex>{v0}) + .ExpandVariable(Expansion::Back, Direction::Out)); + EXPECT_EQ(result0, std::unordered_set<Path>(all_possible.begin() + 1, + all_possible.end())); // zero or more traversals auto result1 = accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - ExpandVariable(Expansion::Back, Direction::Out, {}, {}, 0)); - EXPECT_EQ(result1, std::unordered_set<Path>(all_possible.begin(), all_possible.end())); + Begin(std::vector<Vertex>{v0}) + .ExpandVariable(Expansion::Back, Direction::Out, {}, {}, 0)); + EXPECT_EQ(result1, + std::unordered_set<Path>(all_possible.begin(), all_possible.end())); // an exact number of traversals [2, 4) auto result2 = accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - ExpandVariable(Expansion::Back, Direction::Out, {}, {}, 2, 4)); - EXPECT_EQ(result2, std::unordered_set<Path>(all_possible.begin() + 2, all_possible.begin() + 4)); + Begin(std::vector<Vertex>{v0}) + .ExpandVariable(Expansion::Back, Direction::Out, {}, {}, 2, 4)); + EXPECT_EQ(result2, std::unordered_set<Path>(all_possible.begin() + 2, + all_possible.begin() + 4)); } TEST(Traversal, ExpandVariableFilter) { // make a chain with vertex labels and edge types with these values // (0)-[1]->(1)-[2]->(2)-[3]->(3) Vertex v0(0); - Vertex v1(1); Edge e1(v0, v1, 1); - Vertex v2(2); Edge e2(v1, v2, 2); - Vertex v3(3); Edge e3(v2, v3, 3); + Vertex v1(1); + Edge e1(v0, v1, 1); + Vertex v2(2); + Edge e2(v1, v2, 2); + Vertex v3(3); + Edge e3(v2, v3, 3); // all possible paths std::vector<Path> all_possible{Path().Start(v0)}; @@ -480,46 +486,49 @@ TEST(Traversal, ExpandVariableFilter) { // filter on edge type < 3 auto result0 = accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - ExpandVariable(Expansion::Back, Direction::Out, {}, - [](const Edge &e) { return e.type_ < 3; })); - EXPECT_EQ(result0, std::unordered_set<Path>(all_possible.begin() + 1, all_possible.begin() + 3)); + Begin(std::vector<Vertex>{v0}) + .ExpandVariable(Expansion::Back, Direction::Out, {}, + [](const Edge &e) { return e.type_ < 3; })); + EXPECT_EQ(result0, std::unordered_set<Path>(all_possible.begin() + 1, + all_possible.begin() + 3)); // filter on edge type > 1, expect nothing because the first edge is 1 auto result1 = accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - ExpandVariable(Expansion::Back, Direction::Out, {}, - [](const Edge &e) { return e.type_ > 1; })); + Begin(std::vector<Vertex>{v0}) + .ExpandVariable(Expansion::Back, Direction::Out, {}, + [](const Edge &e) { return e.type_ > 1; })); EXPECT_EQ(result1.size(), 0); // filter on vertex label > 1, expect last 2 results auto result2 = accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - ExpandVariable(Expansion::Back, Direction::Out, - [](const Vertex &v) { return v.label_ > 1; }, {})); - EXPECT_EQ(result2, std::unordered_set<Path>(all_possible.end() - 2, all_possible.end())); + Begin(std::vector<Vertex>{v0}) + .ExpandVariable(Expansion::Back, Direction::Out, + [](const Vertex &v) { return v.label_ > 1; }, {})); + EXPECT_EQ(result2, std::unordered_set<Path>(all_possible.end() - 2, + all_possible.end())); } TEST(Traversal, ExpandVariableCurrent) { // a chain Vertex v0; - Vertex v1; Edge e1(v0, v1); - Vertex v2; Edge e2(v1, v2); - Vertex v3; Edge e3(v2, v3); + Vertex v1; + Edge e1(v0, v1); + Vertex v2; + Edge e2(v1, v2); + Vertex v3; + Edge e3(v2, v3); // ensure that expanded vertices and all edge sets get visited as current std::unordered_set<Vertex> expected_vertices{v1, v2, v3}; std::unordered_set<std::list<Edge>> expected_edge_lists{ - std::list<Edge>{e1}, - std::list<Edge>{e1, e2}, - std::list<Edge>{e1, e2, e3} - }; + std::list<Edge>{e1}, std::list<Edge>{e1, e2}, + std::list<Edge>{e1, e2, e3}}; std::vector<Vertex> begin_input{v0}; auto begin = Begin(begin_input); auto expand = begin.ExpandVariable(Expansion::Back, Direction::Out); - expand.Visit([&](Path &path){ + expand.Visit([&](Path &path) { EXPECT_EQ(1, expected_vertices.erase(expand.CurrentVertex())); EXPECT_EQ(1, expected_edge_lists.erase(expand.CurrentEdges())); }); @@ -531,13 +540,13 @@ TEST(Traversal, EnumExpansion) { Edge e0(v0, v1); // Expansion::Back - auto result0= accumulate_visited<Path>( + auto result0 = accumulate_visited<Path>( Begin(std::vector<Vertex>{v0}).Expand(Expansion::Back, Direction::Out)); auto expected0 = std::unordered_set<Path>{Path().Start(v0).Append(e0, v1)}; EXPECT_EQ(result0, expected0); // Expansion::Front - auto result1= accumulate_visited<Path>( + auto result1 = accumulate_visited<Path>( Begin(std::vector<Vertex>{v0}).Expand(Expansion::Front, Direction::Out)); auto expected1 = std::unordered_set<Path>{Path().Start(v0).Prepend(e0, v1)}; EXPECT_EQ(result1, expected1); @@ -549,24 +558,22 @@ TEST(Traversal, EnumDirection) { Edge e0(v0, v1), e1(v1, v2); // Direction::Out - auto result0= accumulate_visited<Path>( + auto result0 = accumulate_visited<Path>( Begin(std::vector<Vertex>{v1}).Expand(Expansion::Back, Direction::Out)); auto expected0 = std::unordered_set<Path>{Path().Start(v1).Append(e1, v2)}; EXPECT_EQ(result0, expected0); // Direction::In - auto result1= accumulate_visited<Path>( + auto result1 = accumulate_visited<Path>( Begin(std::vector<Vertex>{v1}).Expand(Expansion::Back, Direction::In)); auto expected1 = std::unordered_set<Path>{Path().Start(v1).Append(e0, v0)}; EXPECT_EQ(result1, expected1); // Direction::Both - auto result2= accumulate_visited<Path>( + auto result2 = accumulate_visited<Path>( Begin(std::vector<Vertex>{v1}).Expand(Expansion::Back, Direction::Both)); - auto expected2 = std::unordered_set<Path>{ - Path().Start(v1).Append(e0, v0), - Path().Start(v1).Append(e1, v2) - }; + auto expected2 = std::unordered_set<Path>{Path().Start(v1).Append(e0, v0), + Path().Start(v1).Append(e1, v2)}; EXPECT_EQ(result2, expected2); } @@ -577,30 +584,28 @@ TEST(Traversal, EnumUniqueness) { // Uniqueness::Edge auto result0 = accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Edge). - Expand(Expansion::Back, Direction::Out)); - auto expected0 = std::unordered_set<Path>{ - Path().Start(v0).Append(e0, v0).Append(e1, v1) - }; + Begin(std::vector<Vertex>{v0}) + .Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Edge) + .Expand(Expansion::Back, Direction::Out)); + auto expected0 = + std::unordered_set<Path>{Path().Start(v0).Append(e0, v0).Append(e1, v1)}; EXPECT_EQ(result0, expected0); // Uniqueness::Vertex auto result1 = accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Vertex). - Expand(Expansion::Back, Direction::Out)); + Begin(std::vector<Vertex>{v0}) + .Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Vertex) + .Expand(Expansion::Back, Direction::Out)); EXPECT_EQ(result1.size(), 0); // Uniqueness::None auto result2 = accumulate_visited<Path>( - Begin(std::vector<Vertex>{v0}). - Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::None). - Expand(Expansion::Back, Direction::Out)); - auto expected2 = std::unordered_set<Path>{ - Path().Start(v0).Append(e0, v0).Append(e1, v1), - Path().Start(v0).Append(e0, v0).Append(e0, v0) - }; + Begin(std::vector<Vertex>{v0}) + .Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::None) + .Expand(Expansion::Back, Direction::Out)); + auto expected2 = + std::unordered_set<Path>{Path().Start(v0).Append(e0, v0).Append(e1, v1), + Path().Start(v0).Append(e0, v0).Append(e0, v0)}; EXPECT_EQ(result2, expected2); } @@ -624,11 +629,11 @@ TEST(Traversal, Cartesian) { std::unordered_set<Paths> expected; for (auto &path1 : paths0_set) for (auto &path2 : paths1_set) - for (auto &path3: paths0_set) { + for (auto &path3 : paths0_set) { Paths paths; - paths.emplace_back(std::ref(const_cast<Path&>(path1))); - paths.emplace_back(std::ref(const_cast<Path&>(path2))); - paths.emplace_back(std::ref(const_cast<Path&>(path3))); + paths.emplace_back(std::ref(const_cast<Path &>(path1))); + paths.emplace_back(std::ref(const_cast<Path &>(path2))); + paths.emplace_back(std::ref(const_cast<Path &>(path3))); expected.insert(paths); } EXPECT_EQ(8, expected.size()); @@ -651,7 +656,7 @@ TEST(Traversal, UniquenessSubgroups) { // counts the number of visits to the visitable auto visit_counter = [](const auto &visitable) { auto r_val = 0; - visitable.Visit([&r_val](const auto &x) {r_val++;}); + visitable.Visit([&r_val](const auto &x) { r_val++; }); return r_val; }; @@ -666,16 +671,20 @@ TEST(Traversal, UniquenessSubgroups) { // edge uniqueness sharing { - auto paths0 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Edge); - auto paths1 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Edge); + auto paths0 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {}, + Uniqueness::Edge); + auto paths1 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {}, + Uniqueness::Edge); paths1.UniquenessGroup().Add(paths0.UniquenessGroup()); EXPECT_EQ(2, visit_counter(Cartesian(paths0, paths1))); } // vertex uniqueness sharing { - auto paths0 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Vertex); - auto paths1 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {}, Uniqueness::Vertex); + auto paths0 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {}, + Uniqueness::Vertex); + auto paths1 = Begin(begin_v).Expand(Expansion::Back, Direction::Out, {}, {}, + Uniqueness::Vertex); paths1.UniquenessGroup().Add(paths0.UniquenessGroup()); EXPECT_EQ(0, visit_counter(Cartesian(paths0, paths1))); }