From 81abee0d3358571c6927f073543e9f9833a96939 Mon Sep 17 00:00:00 2001
From: Kruno Tomola Fabro <krunotf@memgraph.io>
Date: Tue, 13 Sep 2016 10:59:40 +0100
Subject: [PATCH 1/5] Tmp commit

---
 tests/poc/profile.cpp | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 tests/poc/profile.cpp

diff --git a/tests/poc/profile.cpp b/tests/poc/profile.cpp
new file mode 100644
index 000000000..e69de29bb

From e22074ad9f898af77af63db3a51a8170e5211ee8 Mon Sep 17 00:00:00 2001
From: Kruno Tomola Fabro <krunotf@memgraph.io>
Date: Tue, 13 Sep 2016 17:02:04 +0100
Subject: [PATCH 2/5] Added test for snapshot with stored index.

---
 include/snapshot/snapshot_engine.hpp |  10 +-
 src/snapshot/snapshot_engine.cpp     |  50 ++++---
 src/storage/indexes/indexes.cpp      |   2 +-
 tests/integration/snapshot.cpp       | 187 +++++++++++++++++++--------
 4 files changed, 171 insertions(+), 78 deletions(-)

diff --git a/include/snapshot/snapshot_engine.hpp b/include/snapshot/snapshot_engine.hpp
index 96069bdf2..20d25e475 100644
--- a/include/snapshot/snapshot_engine.hpp
+++ b/include/snapshot/snapshot_engine.hpp
@@ -4,6 +4,7 @@
 #include <unordered_map>
 
 #include "logging/default.hpp"
+#include "storage/indexes/index_definition.hpp"
 #include "transactions/transaction.hpp"
 
 class SnapshotEncoder;
@@ -42,9 +43,14 @@ private:
     void snapshot(DbTransaction const &dt, SnapshotEncoder &snap,
                   tx::TransactionRead const &old_trans);
 
-    // Loads snapshot. True if success
-    bool snapshot_load(DbAccessor &t, SnapshotDecoder &snap);
+    // Loads snapshot. True if success. Returns indexes which were in snapshot.
+    std::vector<IndexDefinition> snapshot_load(DbAccessor &t,
+                                               SnapshotDecoder &snap);
 
+    // Adds indexes. Should be called outside transactions.
+    void add_indexes(std::vector<IndexDefinition> &v);
+
+    // Will return different name on every call.
     std::string snapshot_file(std::time_t const &now, const char *type);
 
     std::string snapshot_commit_file();
diff --git a/src/snapshot/snapshot_engine.cpp b/src/snapshot/snapshot_engine.cpp
index 397144aaf..8f5fe0449 100644
--- a/src/snapshot/snapshot_engine.cpp
+++ b/src/snapshot/snapshot_engine.cpp
@@ -156,22 +156,18 @@ bool SnapshotEngine::import()
                                             std::fstream::binary);
                 SnapshotDecoder decoder(snapshot_file);
 
-                if (snapshot_load(t, decoder)) {
-                    if (t.commit()) {
-                        logger.info("Succesfully imported snapshot \"{}\"",
-                                    snapshots.back());
-                        success = true;
-                        break;
+                auto indexes = snapshot_load(t, decoder);
+                if (t.commit()) {
+                    logger.info("Succesfully imported snapshot \"{}\"",
+                                snapshots.back());
+                    add_indexes(indexes);
+                    success = true;
+                    break;
 
-                    } else {
-                        logger.info("Unuccesfully tryed to import snapshot "
-                                    "\"{}\" because indexes where unuccesfully "
-                                    "with updating",
-                                    snapshots.back());
-                    }
                 } else {
-                    t.abort();
-                    logger.info("Unuccesfully tryed to import snapshot \"{}\"",
+                    logger.info("Unuccesfully tryed to import snapshot "
+                                "\"{}\" because indexes where unuccesfully "
+                                "with updating",
                                 snapshots.back());
                 }
 
@@ -241,7 +237,8 @@ void SnapshotEngine::snapshot(DbTransaction const &dt, SnapshotEncoder &snap,
     snap.end();
 }
 
-bool SnapshotEngine::snapshot_load(DbAccessor &t, SnapshotDecoder &snap)
+std::vector<IndexDefinition>
+SnapshotEngine::snapshot_load(DbAccessor &t, SnapshotDecoder &snap)
 {
     std::unordered_map<uint64_t, VertexAccessor> vertices;
 
@@ -268,23 +265,36 @@ bool SnapshotEngine::snapshot_load(DbAccessor &t, SnapshotDecoder &snap)
 
     // Load indexes
     snap.start_indexes();
+    std::vector<IndexDefinition> indexes;
     while (!snap.end()) {
-        // This will add index.
+        indexes.push_back(snap.load_index());
+    }
+
+    return indexes;
+}
+
+void SnapshotEngine::add_indexes(std::vector<IndexDefinition> &v)
+{
+    logger.info("Adding: {} indexes", v.size());
+    for (auto id : v) {
         // TODO: It is alright for now to ignore if add_index return false. I am
         // not even sure if false should stop snapshot loading.
-        if (!db.indexes().add_index(snap.load_index())) {
+        if (!db.indexes().add_index(id)) {
             logger.warn("Failed to add index, but still continuing with "
                         "loading snapshot");
         }
     }
-
-    return true;
 }
 
 std::string SnapshotEngine::snapshot_file(std::time_t const &now,
                                           const char *type)
 {
-    return snapshot_db_dir() + "/" + std::to_string(now) + "_" + type;
+    auto now_nano = std::chrono::time_point_cast<std::chrono::nanoseconds>(
+                        std::chrono::high_resolution_clock::now())
+                        .time_since_epoch()
+                        .count();
+    return snapshot_db_dir() + "/" + std::to_string(now) + "_" +
+           std::to_string(now_nano) + "_" + type;
 }
 
 std::string SnapshotEngine::snapshot_commit_file()
diff --git a/src/storage/indexes/indexes.cpp b/src/storage/indexes/indexes.cpp
index bdad611d8..72d17abd0 100644
--- a/src/storage/indexes/indexes.cpp
+++ b/src/storage/indexes/indexes.cpp
@@ -13,7 +13,7 @@ bool Indexes::add_index(IndexDefinition id)
     // Creates transaction and during it's creation adds index into it's
     // place. Also created finish closure which will add necessary elements
     // into index.
-    DbTransaction t(db, db.tx_engine.begin([&, id](auto &t) mutable {
+    DbTransaction t(db, db.tx_engine.begin([&](auto &t) mutable {
         size_t code = id.loc.location_code();
 
         switch (code) {
diff --git a/tests/integration/snapshot.cpp b/tests/integration/snapshot.cpp
index 614068585..c68c1a5bd 100644
--- a/tests/integration/snapshot.cpp
+++ b/tests/integration/snapshot.cpp
@@ -7,6 +7,7 @@
 #include "logging/default.hpp"
 #include "logging/streams/stdout.hpp"
 #include "query_engine/query_stripper.hpp"
+#include "storage/indexes/indexes.hpp"
 #include "utils/sysinfo/memory.hpp"
 
 // Returns uniform random size_t generator from range [0,n>
@@ -17,9 +18,10 @@ auto rand_gen(size_t n)
     return std::bind(distribution, generator);
 }
 
-template <class S, class Q>
-void run(size_t n, std::string &query, S &stripper, Q &qf)
+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 = load_queries(barrier::trans(db));
     auto stripped = stripper.strip(query);
     std::cout << "Running query [" << stripped.hash << "] for " << n << " time."
               << std::endl;
@@ -29,10 +31,10 @@ void run(size_t n, std::string &query, S &stripper, Q &qf)
     }
 }
 
-template <class S, class Q>
-void add_edge(size_t n, Db &db, S &stripper, Q &qf)
+void add_edge(size_t n, Db &db)
 {
-
+    auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
+    auto qf = load_queries(barrier::trans(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";
@@ -55,6 +57,45 @@ void add_edge(size_t n, Db &db, S &stripper, Q &qf)
     }
 }
 
+void add_property(Db &db, StoredProperty<TypeGroupVertex> &prop)
+{
+    DbAccessor t(db);
+
+    t.vertex_access().fill().for_all([&](auto va) { va.set(prop); });
+
+    assert(t.commit());
+}
+
+void add_property_different_int(Db &db, PropertyFamily<TypeGroupVertex> &f)
+{
+    DbAccessor t(db);
+
+    auto key = f.get(Int64::type).family_key();
+
+    size_t i = 0;
+    t.vertex_access().fill().for_all([&](auto va) mutable {
+        va.set(StoredProperty<TypeGroupVertex>(Int64(i), key));
+        i++;
+    });
+
+    assert(t.commit());
+}
+
+size_t size(Db &db, IndexHolder<TypeGroupVertex, std::nullptr_t> &h)
+{
+    DbAccessor t(db);
+
+    size_t count = 0;
+    auto oin = h.get_read();
+    if (oin.is_present()) {
+        oin.get()->for_range(t).for_all([&](auto va) mutable { count++; });
+    }
+
+    t.commit();
+
+    return count;
+}
+
 void assert_empty(Db &db)
 {
     assert(db.graph.vertices.access().size() == 0);
@@ -75,14 +116,13 @@ void clean_edge(Db &db)
     t.trans.commit();
 }
 
-template <class S, class Q>
-void clear_database(Db &db, S &stripper, Q &qf)
+void clear_database(Db &db)
 {
     std::string delete_all_vertices = "MATCH (n) DELETE n";
     std::string delete_all_edges = "MATCH ()-[r]-() DELETE r";
 
-    run(1, delete_all_edges, stripper, qf);
-    run(1, delete_all_vertices, stripper, qf);
+    run(1, delete_all_edges, db);
+    run(1, delete_all_vertices, db);
     clean_vertex(db);
     clean_edge(db);
     assert_empty(db);
@@ -132,12 +172,6 @@ int main(void)
 
     size_t cvl_n = 1000;
 
-    Db db("snapshot");
-
-    auto query_functions = load_queries(barrier::trans(db));
-
-    auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
-
     std::string create_vertex_label =
         "CREATE (n:LABEL {name: \"cleaner_test\"}) RETURN n";
     std::string create_vertex_other =
@@ -145,51 +179,94 @@ int main(void)
     std::string delete_label_vertices = "MATCH (n:LABEL) DELETE n";
     std::string delete_all_vertices = "MATCH (n) DELETE n";
 
-    // ********************* MAKE SURE THAT DB IS EMPTY **********************//
-    clear_database(db, stripper, query_functions);
-
-    std::cout << "TEST1" << std::endl;
     // ******************************* TEST 1 ********************************//
-    // make snapshot of empty db
-    // add vertexs
-    // add edges
-    // empty database
-    // import snapshot
-    // assert database empty
-
-    db.snap_engine.make_snapshot();
-    run(cvl_n, create_vertex_label, stripper, query_functions);
-    add_edge(cvl_n, db, stripper, query_functions);
-    clear_database(db, stripper, query_functions);
-    db.snap_engine.import();
-    assert_empty(db);
-
-    std::cout << "TEST2" << std::endl;
-    // ******************************* TEST 2 ********************************//
-    // add vertexs
-    // add edges
-    // make snapshot of db
-    // empty database
-    // import snapshot
-    // create new db
-    // compare database with new db
-
-    run(cvl_n, create_vertex_label, stripper, query_functions);
-    add_edge(cvl_n, db, stripper, query_functions);
-    db.snap_engine.make_snapshot();
-    clear_database(db, stripper, query_functions);
-    db.snap_engine.import();
     {
-        Db db2("snapshot");
-        assert(equal(db, db2));
+        std::cout << "TEST1" << std::endl;
+        // make snapshot of empty db
+        // add vertexs
+        // add edges
+        // empty database
+        // import snapshot
+        // assert database empty
+
+        Db db("snapshot", false);
+        db.snap_engine.make_snapshot();
+        run(cvl_n, create_vertex_label, db);
+        add_edge(cvl_n, db);
+        clear_database(db);
+        db.snap_engine.import();
+        assert_empty(db);
     }
 
-    std::cout << "TEST3" << std::endl;
-    // ******************************* TEST 3 ********************************//
-    // compare database with different named database
+    // ******************************* TEST 2 ********************************//
     {
-        Db db2("not_snapshot");
-        assert(!equal(db, db2));
+        std::cout << "TEST2" << std::endl;
+        // add vertexs
+        // add edges
+        // make snapshot of db
+        // empty database
+        // import snapshot
+        // create new db
+        // compare database with new db
+        Db db("snapshot", false);
+        run(cvl_n, create_vertex_label, db);
+        add_edge(cvl_n, db);
+        db.snap_engine.make_snapshot();
+        clear_database(db);
+        db.snap_engine.import();
+        {
+            Db db2("snapshot");
+            assert(equal(db, db2));
+        }
+    }
+
+    // ******************************* TEST 3 ********************************//
+    {
+        std::cout << "TEST3" << std::endl;
+        // add vertexs
+        // add edges
+        // make snapshot of db
+        // compare database with different named database
+        Db db("snapshot", false);
+        run(cvl_n, create_vertex_label, db);
+        add_edge(cvl_n, db);
+        db.snap_engine.make_snapshot();
+        {
+            Db db2("not_snapshot");
+            assert(!equal(db, db2));
+        }
+    }
+
+    // ******************************* TEST 4 ********************************//
+    {
+        std::cout << "TEST4" << std::endl;
+        // add vertices LABEL
+        // add properties
+        // add vertices LABEL
+        // add index on proprety
+        // assert index containts vertices
+        // make snapshot
+        // create new db
+        // assert index on LABEL in new db exists
+        // assert index in new db containts vertice
+        Db db("snapshot", false);
+        run(cvl_n, create_vertex_label, db);
+        auto &family = db.graph.vertices.property_family_find_or_create("prop");
+        add_property_different_int(db, family);
+        run(cvl_n, create_vertex_other, db);
+        IndexDefinition idef = {
+            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));
+        db.snap_engine.make_snapshot();
+        {
+            Db db2("snapshot");
+            assert(cvl_n == size(db, db2.graph.vertices
+                                         .property_family_find_or_create("prop")
+                                         .index));
+        }
     }
 
     // TODO: more tests

From a6f72dc3fd533f5c594376db4c65d40dee4a2ec0 Mon Sep 17 00:00:00 2001
From: Kruno Tomola Fabro <krunotf@memgraph.io>
Date: Tue, 13 Sep 2016 17:53:40 +0100
Subject: [PATCH 3/5] Added stress test for ConncurentList.

---
 poc/add_double.cpp                   |  5 ++
 src/snapshot/snapshot_engine.cpp     |  3 +-
 tests/concurrent/common.h            | 22 ++++++++
 tests/concurrent/conncurent_list.cpp | 77 ++++++++++++++++++++++++++++
 4 files changed, 106 insertions(+), 1 deletion(-)
 create mode 100644 tests/concurrent/conncurent_list.cpp

diff --git a/poc/add_double.cpp b/poc/add_double.cpp
index 4c003ede1..5c0dd003b 100644
--- a/poc/add_double.cpp
+++ b/poc/add_double.cpp
@@ -27,6 +27,11 @@ void add_scores(Db &db, double max_value, std::string const &property_name)
     t.commit();
 }
 
+// Tool to add double propertys to all vertices.
+// // Accepts flags for csv import.
+// -db name , will create database with that name.
+// -pn name , will name property with that name,default: name=score.
+// -max number , will set range of property [0,max], default: max=1
 int main(int argc, char **argv)
 {
     logging::init_async();
diff --git a/src/snapshot/snapshot_engine.cpp b/src/snapshot/snapshot_engine.cpp
index 8f5fe0449..70d2fcd8e 100644
--- a/src/snapshot/snapshot_engine.cpp
+++ b/src/snapshot/snapshot_engine.cpp
@@ -292,7 +292,8 @@ std::string SnapshotEngine::snapshot_file(std::time_t const &now,
     auto now_nano = std::chrono::time_point_cast<std::chrono::nanoseconds>(
                         std::chrono::high_resolution_clock::now())
                         .time_since_epoch()
-                        .count();
+                        .count() %
+                    (1000 * 1000 * 1000);
     return snapshot_db_dir() + "/" + std::to_string(now) + "_" +
            std::to_string(now_nano) + "_" + type;
 }
diff --git a/tests/concurrent/common.h b/tests/concurrent/common.h
index 82910cdd4..e32926251 100644
--- a/tests/concurrent/common.h
+++ b/tests/concurrent/common.h
@@ -13,6 +13,7 @@
 #include "data_structures/concurrent/concurrent_multiset.hpp"
 #include "data_structures/concurrent/concurrent_set.hpp"
 #include "data_structures/concurrent/skiplist.hpp"
+#include "data_structures/concurrent/concurrent_list.hpp"
 #include "data_structures/static_array.hpp"
 #include "utils/assert.hpp"
 #include "logging/default.hpp"
@@ -64,6 +65,26 @@ void check_present_same(typename S::Accessor &acc,
 
 // 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
+
+    permanent_assert(acc.size() == size, "Size should be " << size
+                                                           << ", but size is "
+                                                           << acc.size());
+
+    // check count
+
+    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);
+}
+template <typename S>
 void check_size(typename S::Accessor &acc, long long size)
 {
     // check size
@@ -83,6 +104,7 @@ void check_size(typename S::Accessor &acc, long long size)
                                                    << 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)
diff --git a/tests/concurrent/conncurent_list.cpp b/tests/concurrent/conncurent_list.cpp
new file mode 100644
index 000000000..ab6bff71e
--- /dev/null
+++ b/tests/concurrent/conncurent_list.cpp
@@ -0,0 +1,77 @@
+#include "common.h"
+
+#define THREADS_NO 8
+constexpr size_t key_range = 1e2;
+constexpr size_t op_per_thread = 1e5;
+// Depending on value there is a possiblity of numerical overflow
+constexpr size_t max_number = 10;
+constexpr size_t no_find_per_change = 2;
+constexpr size_t no_insert_for_one_delete = 1;
+
+// This test simulates behavior of transactions.
+// Each thread makes a series of finds interleaved with method which change.
+// Exact ratio of finds per change and insert per delete can be regulated with
+// no_find_per_change and no_insert_for_one_delete.
+int main()
+{
+    init_log();
+    memory_check(THREADS_NO, [] {
+        ConcurrentList<std::pair<int, int>> list;
+
+        auto futures = run<std::pair<long long, long long>>(
+            THREADS_NO, [&](auto index) mutable {
+                auto rand = rand_gen(key_range);
+                auto rand_change = rand_gen_bool(no_find_per_change);
+                auto rand_delete = rand_gen_bool(no_insert_for_one_delete);
+                long long sum = 0;
+                long long count = 0;
+
+                for (int i = 0; i < op_per_thread; i++) {
+                    auto num = rand();
+                    auto data = num % max_number;
+                    if (rand_change()) {
+                        if (rand_delete()) {
+                            for (auto it = list.begin(); it != list.end();
+                                 it++) {
+                                if (it->first == num) {
+                                    if (it.remove()) {
+                                        sum -= data;
+                                        count--;
+                                    }
+                                    break;
+                                }
+                            }
+                        } else {
+                            list.begin().push(std::make_pair(num, data));
+                            sum += data;
+                            count++;
+                        }
+                    } else {
+                        for (auto &v : list) {
+                            if (v.first == num) {
+                                permanent_assert(v.second == data,
+                                                 "Data is invalid");
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                return std::pair<long long, long long>(sum, count);
+            });
+
+        auto it = list.begin();
+        long long sums = 0;
+        long long counters = 0;
+        for (auto &data : collect(futures)) {
+            sums += data.second.first;
+            counters += data.second.second;
+        }
+
+        for (auto &e : list) {
+            sums -= e.second;
+        }
+        permanent_assert(sums == 0, "Same values aren't present");
+        check_size_list<ConcurrentList<std::pair<int, int>>>(list, counters);
+    });
+}

From 9bd845a62e08adc2db13c264c02f62fca87732ab Mon Sep 17 00:00:00 2001
From: Kruno Tomola Fabro <krunotf@memgraph.io>
Date: Tue, 13 Sep 2016 18:08:34 +0100
Subject: [PATCH 4/5] Added max_no_threads. It is meant for easily change no
 threads in concurrent tests.

---
 tests/concurrent/common.h                               | 3 +++
 tests/concurrent/conncurent_list.cpp                    | 2 +-
 tests/concurrent/dynamic_bitset.cpp                     | 2 +-
 tests/concurrent/dynamic_bitset_clear_n.cpp             | 2 +-
 tests/concurrent/dynamic_bitset_set.cpp                 | 2 +-
 tests/concurrent/dynamic_bitset_set_n.cpp               | 2 +-
 tests/concurrent/sl_insert.cpp                          | 2 +-
 tests/concurrent/sl_insert_competetive.cpp              | 2 +-
 tests/concurrent/sl_map.cpp                             | 2 +-
 tests/concurrent/sl_memory.cpp                          | 2 +-
 tests/concurrent/sl_memory_leak.cpp                     | 2 +-
 tests/concurrent/sl_multiiterator.cpp                   | 2 +-
 tests/concurrent/sl_multiiterator_remove.cpp            | 2 +-
 tests/concurrent/sl_multiiterator_remove_duplicates.cpp | 2 +-
 tests/concurrent/sl_multimap.cpp                        | 2 +-
 tests/concurrent/sl_multiset.cpp                        | 2 +-
 tests/concurrent/sl_remove_competetive.cpp              | 2 +-
 tests/concurrent/sl_remove_disjoint.cpp                 | 2 +-
 tests/concurrent/sl_remove_joint.cpp                    | 2 +-
 tests/concurrent/sl_set.cpp                             | 2 +-
 tests/concurrent/sl_simulation.cpp                      | 2 +-
 tests/integration/snapshot.cpp                          | 1 -
 tests/poc/profile.cpp                                   | 0
 23 files changed, 23 insertions(+), 21 deletions(-)
 delete mode 100644 tests/poc/profile.cpp

diff --git a/tests/concurrent/common.h b/tests/concurrent/common.h
index e32926251..d43f7976b 100644
--- a/tests/concurrent/common.h
+++ b/tests/concurrent/common.h
@@ -20,6 +20,9 @@
 #include "logging/streams/stdout.hpp"
 #include "utils/sysinfo/memory.hpp"
 
+// Sets max number of threads that will be used in concurrent tests.
+constexpr int max_no_threads=8;
+
 using std::cout;
 using std::endl;
 using map_t = ConcurrentMap<int, int>;
diff --git a/tests/concurrent/conncurent_list.cpp b/tests/concurrent/conncurent_list.cpp
index ab6bff71e..aeea7bfda 100644
--- a/tests/concurrent/conncurent_list.cpp
+++ b/tests/concurrent/conncurent_list.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t key_range = 1e2;
 constexpr size_t op_per_thread = 1e5;
 // Depending on value there is a possiblity of numerical overflow
diff --git a/tests/concurrent/dynamic_bitset.cpp b/tests/concurrent/dynamic_bitset.cpp
index 252874650..ac24109ea 100644
--- a/tests/concurrent/dynamic_bitset.cpp
+++ b/tests/concurrent/dynamic_bitset.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t op_per_thread = 1e5;
 constexpr size_t bit_part_len = 2;
 constexpr size_t no_slots = 1e4;
diff --git a/tests/concurrent/dynamic_bitset_clear_n.cpp b/tests/concurrent/dynamic_bitset_clear_n.cpp
index 61b5384aa..6f38bbf64 100644
--- a/tests/concurrent/dynamic_bitset_clear_n.cpp
+++ b/tests/concurrent/dynamic_bitset_clear_n.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 4
+constexpr size_t THREADS_NO = std::min(max_no_threads, 4);
 constexpr size_t op_per_thread = 1e5;
 constexpr size_t up_border_bit_set_pow2 = 3;
 constexpr size_t key_range =
diff --git a/tests/concurrent/dynamic_bitset_set.cpp b/tests/concurrent/dynamic_bitset_set.cpp
index f219a6a97..b1ec1eae8 100644
--- a/tests/concurrent/dynamic_bitset_set.cpp
+++ b/tests/concurrent/dynamic_bitset_set.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t op_per_thread = 1e5;
 constexpr size_t key_range = op_per_thread * THREADS_NO * 3;
 
diff --git a/tests/concurrent/dynamic_bitset_set_n.cpp b/tests/concurrent/dynamic_bitset_set_n.cpp
index c05118feb..b31bcda2a 100644
--- a/tests/concurrent/dynamic_bitset_set_n.cpp
+++ b/tests/concurrent/dynamic_bitset_set_n.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 4
+constexpr size_t THREADS_NO = std::min(max_no_threads, 4);
 constexpr size_t op_per_thread = 1e5;
 constexpr size_t up_border_bit_set_pow2 = 3;
 constexpr size_t key_range =
diff --git a/tests/concurrent/sl_insert.cpp b/tests/concurrent/sl_insert.cpp
index a0b83e18f..7948c2291 100644
--- a/tests/concurrent/sl_insert.cpp
+++ b/tests/concurrent/sl_insert.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+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;
diff --git a/tests/concurrent/sl_insert_competetive.cpp b/tests/concurrent/sl_insert_competetive.cpp
index 8050a377c..636ca9264 100644
--- a/tests/concurrent/sl_insert_competetive.cpp
+++ b/tests/concurrent/sl_insert_competetive.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+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;
 
diff --git a/tests/concurrent/sl_map.cpp b/tests/concurrent/sl_map.cpp
index 8b7684073..c56a1aa2f 100644
--- a/tests/concurrent/sl_map.cpp
+++ b/tests/concurrent/sl_map.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t elems_per_thread = 1e5;
 
 int main()
diff --git a/tests/concurrent/sl_memory.cpp b/tests/concurrent/sl_memory.cpp
index cc7522a3b..f69bd66a5 100644
--- a/tests/concurrent/sl_memory.cpp
+++ b/tests/concurrent/sl_memory.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 
 constexpr size_t elements = 2e6;
 
diff --git a/tests/concurrent/sl_memory_leak.cpp b/tests/concurrent/sl_memory_leak.cpp
index c5e384ee5..6c7bf64da 100644
--- a/tests/concurrent/sl_memory_leak.cpp
+++ b/tests/concurrent/sl_memory_leak.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 1
+constexpr size_t THREADS_NO = std::min(max_no_threads, 1);
 constexpr size_t elems_per_thread = 16e5;
 
 // Known memory leak at 1,600,000 elements.
diff --git a/tests/concurrent/sl_multiiterator.cpp b/tests/concurrent/sl_multiiterator.cpp
index ebff8c0ca..68bde7fbc 100644
--- a/tests/concurrent/sl_multiiterator.cpp
+++ b/tests/concurrent/sl_multiiterator.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t key_range = 1e4;
 constexpr size_t op_per_thread = 1e5;
 // Depending on value there is a possiblity of numerical overflow
diff --git a/tests/concurrent/sl_multiiterator_remove.cpp b/tests/concurrent/sl_multiiterator_remove.cpp
index e8b8e3d07..228788e7f 100644
--- a/tests/concurrent/sl_multiiterator_remove.cpp
+++ b/tests/concurrent/sl_multiiterator_remove.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t key_range = 1e4;
 constexpr size_t op_per_thread = 1e5;
 // Depending on value there is a possiblity of numerical overflow
diff --git a/tests/concurrent/sl_multiiterator_remove_duplicates.cpp b/tests/concurrent/sl_multiiterator_remove_duplicates.cpp
index da2215ec0..01712d199 100644
--- a/tests/concurrent/sl_multiiterator_remove_duplicates.cpp
+++ b/tests/concurrent/sl_multiiterator_remove_duplicates.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 4
+constexpr size_t THREADS_NO = std::min(max_no_threads, 4);
 constexpr size_t key_range = 1e4;
 constexpr size_t op_per_thread = 1e5;
 // Depending on value there is a possiblity of numerical overflow
diff --git a/tests/concurrent/sl_multimap.cpp b/tests/concurrent/sl_multimap.cpp
index 5953a4ca5..9c1fa97ba 100644
--- a/tests/concurrent/sl_multimap.cpp
+++ b/tests/concurrent/sl_multimap.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t key_range = 1e4;
 constexpr size_t op_per_thread = 1e5;
 // Depending on value there is a possiblity of numerical overflow
diff --git a/tests/concurrent/sl_multiset.cpp b/tests/concurrent/sl_multiset.cpp
index eaca13ca0..9a5bdd006 100644
--- a/tests/concurrent/sl_multiset.cpp
+++ b/tests/concurrent/sl_multiset.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t key_range = 1e4;
 constexpr size_t op_per_thread = 1e5;
 constexpr size_t no_insert_for_one_delete = 1;
diff --git a/tests/concurrent/sl_remove_competetive.cpp b/tests/concurrent/sl_remove_competetive.cpp
index 614d00d46..13a7967da 100644
--- a/tests/concurrent/sl_remove_competetive.cpp
+++ b/tests/concurrent/sl_remove_competetive.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t op_per_thread = 1e5;
 // Depending on value there is a possiblity of numerical overflow
 constexpr size_t max_number = 10;
diff --git a/tests/concurrent/sl_remove_disjoint.cpp b/tests/concurrent/sl_remove_disjoint.cpp
index 031d5106e..99b9465ca 100644
--- a/tests/concurrent/sl_remove_disjoint.cpp
+++ b/tests/concurrent/sl_remove_disjoint.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t key_range = 1e5;
 constexpr size_t op_per_thread = 1e6;
 constexpr size_t no_insert_for_one_delete = 1;
diff --git a/tests/concurrent/sl_remove_joint.cpp b/tests/concurrent/sl_remove_joint.cpp
index b32bae485..495433966 100644
--- a/tests/concurrent/sl_remove_joint.cpp
+++ b/tests/concurrent/sl_remove_joint.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t key_range = 1e4;
 constexpr size_t op_per_thread = 1e5;
 // Depending on value there is a possiblity of numerical overflow
diff --git a/tests/concurrent/sl_set.cpp b/tests/concurrent/sl_set.cpp
index e86d0a6ae..84c6c582c 100644
--- a/tests/concurrent/sl_set.cpp
+++ b/tests/concurrent/sl_set.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t key_range = 1e4;
 constexpr size_t op_per_thread = 1e5;
 constexpr size_t no_insert_for_one_delete = 2;
diff --git a/tests/concurrent/sl_simulation.cpp b/tests/concurrent/sl_simulation.cpp
index 564d3d1eb..ffeb11f2c 100644
--- a/tests/concurrent/sl_simulation.cpp
+++ b/tests/concurrent/sl_simulation.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 
-#define THREADS_NO 8
+constexpr size_t THREADS_NO = std::min(max_no_threads, 8);
 constexpr size_t key_range = 1e5;
 constexpr size_t op_per_thread = 1e6;
 // Depending on value there is a possiblity of numerical overflow
diff --git a/tests/integration/snapshot.cpp b/tests/integration/snapshot.cpp
index c68c1a5bd..50975722d 100644
--- a/tests/integration/snapshot.cpp
+++ b/tests/integration/snapshot.cpp
@@ -188,7 +188,6 @@ int main(void)
         // empty database
         // import snapshot
         // assert database empty
-
         Db db("snapshot", false);
         db.snap_engine.make_snapshot();
         run(cvl_n, create_vertex_label, db);
diff --git a/tests/poc/profile.cpp b/tests/poc/profile.cpp
deleted file mode 100644
index e69de29bb..000000000

From c75382cb02dc2c7b83f9264fd720d430388fc4ef Mon Sep 17 00:00:00 2001
From: Kruno Tomola Fabro <krunotf@memgraph.io>
Date: Wed, 14 Sep 2016 12:19:56 +0100
Subject: [PATCH 5/5] Tmp commit.

---
 include/storage/indexes/indexes.hpp |  57 ++++++-
 tests/CMakeLists.txt                |   9 ++
 tests/integration/index.cpp         | 240 ++++++++++++++++++++++++++++
 3 files changed, 305 insertions(+), 1 deletion(-)
 create mode 100644 tests/integration/index.cpp

diff --git a/include/storage/indexes/indexes.hpp b/include/storage/indexes/indexes.hpp
index a385223fb..153d306b0 100644
--- a/include/storage/indexes/indexes.hpp
+++ b/include/storage/indexes/indexes.hpp
@@ -20,6 +20,61 @@ public:
 
     // Adds index defined in given definition. Returns true if successfull.
     bool add_index(IndexDefinition id);
+    //
+    // // Returns index from location.
+    // template <class TG, class K>
+    // Option<IndexHolder<TG, K>> get_index(IndexLocation loc)
+    // {
+    //     size_t code = loc.location_code();
+    //
+    //     switch (code) {
+    //     case 0: // Illegal location
+    //         return Option<IndexHolder<TG, K>>();
+    //
+    //     case 1:
+    //         switch (loc.side) {
+    //         case EdgeSide: {
+    //             return make_option(
+    //                 db.graph.edges
+    //                     .property_family_find_or_create(loc.property_name.get())
+    //                     .index);
+    //         }
+    //         case VertexSide: {
+    //             return make_option(
+    //                 db.graph.vertices
+    //                     .property_family_find_or_create(loc.property_name.get())
+    //                     .index);
+    //         }
+    //         default:
+    //             throw new NonExhaustiveSwitch("Unkown side: " +
+    //                                           std::to_string(loc.side));
+    //         };
+    //
+    //     case 2: // Can't be removed
+    //         return Option<IndexHolder<TG, K>>();
+    //
+    //     case 3: // Not yet implemented
+    //         throw new NotYetImplemented("Getting index over label and "
+    //                                     "property isn't yet implemented");
+    //     case 4: // Can't be removed
+    //         return Option<IndexHolder<TG, K>>();
+    //
+    //     case 5: // Not yet implemented
+    //         throw new NotYetImplemented("Getting index over edge_type and "
+    //                                     "property isn't yet implemented");
+    //     case 6: // Not yet implemented
+    //         throw new NotYetImplemented("Getting index over edge_type and "
+    //                                     "label isn't yet implemented");
+    //     case 7: // Not yet implemented
+    //         throw new NotYetImplemented("Getting index over label, edge_type
+    //         "
+    //                                     "and property isn't yet
+    //                                     implemented");
+    //     default:
+    //         throw new NonExhaustiveSwitch("Unkown index location code: " +
+    //                                       std::to_string(code));
+    //     }
+    // }
 
     // Removes index from given location. Returns true if successfull or if no
     // index was present. False if index location is illegal.
@@ -98,7 +153,7 @@ public:
                                       f);
     }
 
-    // Updates property indexes for given TypeGroup TG and IU index update
+    // Updates property indexes for given TypeGroup TG and IU index_update
     template <class TG, class IU>
     bool update_property_indexes(IU &iu, const tx::Transaction &t)
     {
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 16d377a87..5e8a88c40 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -89,6 +89,15 @@ target_link_libraries(snapshot ${yaml_static_lib})
 add_test(NAME snapshot COMMAND snapshot)
 set_property(TARGET snapshot PROPERTY CXX_STANDARD 14)
 
+# test index validity
+add_executable(index integration/index.cpp)
+target_link_libraries(index memgraph)
+target_link_libraries(index Threads::Threads)
+target_link_libraries(index ${fmt_static_lib})
+target_link_libraries(index ${yaml_static_lib})
+add_test(NAME index COMMAND index)
+set_property(TARGET index PROPERTY CXX_STANDARD 14)
+
 # test query engine
 add_executable(integration_query_engine integration/query_engine.cpp)
 target_link_libraries(integration_query_engine Threads::Threads)
diff --git a/tests/integration/index.cpp b/tests/integration/index.cpp
new file mode 100644
index 000000000..1f9790f02
--- /dev/null
+++ b/tests/integration/index.cpp
@@ -0,0 +1,240 @@
+#include "query_engine/hardcode/queries.hpp"
+
+#include <random>
+
+#include "barrier/barrier.cpp"
+
+#include "logging/default.hpp"
+#include "logging/streams/stdout.hpp"
+#include "query_engine/query_stripper.hpp"
+#include "storage/indexes/indexes.hpp"
+#include "utils/sysinfo/memory.hpp"
+
+// 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);
+}
+
+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 = load_queries(barrier::trans(db));
+    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)));
+    }
+}
+
+void add_edge(size_t n, Db &db)
+{
+    auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
+    auto qf = load_queries(barrier::trans(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 = stripper.strip(query);
+    std::cout << "Running query [" << stripped.hash << "] for " << n
+              << " time to add edge." << std::endl;
+
+    std::vector<int64_t> vertices;
+    for (auto &v : db.graph.vertices.access()) {
+        vertices.push_back(v.second.id);
+    }
+
+    auto rand = rand_gen(vertices.size());
+    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)));
+    }
+}
+
+void add_property(Db &db, StoredProperty<TypeGroupVertex> &prop)
+{
+    DbAccessor t(db);
+
+    t.vertex_access().fill().for_all([&](auto va) { va.set(prop); });
+
+    assert(t.commit());
+}
+
+void add_vertex_property_serial_int(Db &db, PropertyFamily<TypeGroupVertex> &f)
+{
+    DbAccessor t(db);
+
+    auto key = f.get(Int64::type).family_key();
+
+    size_t i = 0;
+    t.vertex_access().fill().for_all([&](auto va) mutable {
+        va.set(StoredProperty<TypeGroupVertex>(Int64(i), key));
+        i++;
+    });
+
+    assert(t.commit());
+}
+
+void add_edge_property_serial_int(Db &db, PropertyFamily<TypeGroupEdge> &f)
+{
+    DbAccessor t(db);
+
+    auto key = f.get(Int64::type).family_key();
+
+    size_t i = 0;
+    t.edge_access().fill().for_all([&](auto va) mutable {
+        va.set(StoredProperty<TypeGroupEdge>(Int64(i), key));
+        i++;
+    });
+
+    assert(t.commit());
+}
+
+template <class TG>
+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()) {
+        oin.get()->for_range(t).for_all([&](auto va) mutable { count++; });
+    }
+
+    t.commit();
+
+    return count;
+}
+
+void assert_empty(Db &db)
+{
+    assert(db.graph.vertices.access().size() == 0);
+    assert(db.graph.edges.access().size() == 0);
+}
+
+void clean_vertex(Db &db)
+{
+    DbTransaction t(db);
+    t.clean_vertex_section();
+    t.trans.commit();
+}
+
+void clean_edge(Db &db)
+{
+    DbTransaction t(db);
+    t.clean_edge_section();
+    t.trans.commit();
+}
+
+void clear_database(Db &db)
+{
+    std::string delete_all_vertices = "MATCH (n) DELETE n";
+    std::string delete_all_edges = "MATCH ()-[r]-() DELETE r";
+
+    run(1, delete_all_edges, db);
+    run(1, delete_all_vertices, db);
+    clean_vertex(db);
+    clean_edge(db);
+    assert_empty(db);
+}
+
+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()) {
+            return false;
+        }
+
+        auto it_a = acc_a.begin();
+        auto it_b = acc_b.begin();
+
+        for (auto i = acc_a.size(); i > 0; i--) {
+            // TODO: compare
+        }
+    }
+
+    {
+        auto acc_a = a.graph.edges.access();
+        auto acc_b = b.graph.edges.access();
+
+        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--) {
+            // TODO: compare
+        }
+    }
+
+    return true;
+}
+
+int main(void)
+{
+    logging::init_async();
+    logging::log->pipe(std::make_unique<Stdout>());
+
+    size_t cvl_n = 1000;
+
+    std::string create_vertex_label =
+        "CREATE (n:LABEL {name: \"cleaner_test\"}) RETURN n";
+    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";
+
+    IndexDefinition vertex_property_nonunique_unordered = {
+        IndexLocation{VertexSide, Option<std::string>("prop"),
+                      Option<std::string>(), Option<std::string>()},
+        IndexType{false, None}};
+    IndexDefinition edge_property_nonunique_unordered = {
+        IndexLocation{EdgeSide, Option<std::string>("prop"),
+                      Option<std::string>(), Option<std::string>()},
+        IndexType{false, None}};
+    IndexDefinition edge_property_unique_ordered = {
+        IndexLocation{EdgeSide, Option<std::string>("prop"),
+                      Option<std::string>(), Option<std::string>()},
+        IndexType{true, Ascending}};
+    IndexDefinition vertex_property_unique_ordered = {
+        IndexLocation{VertexSide, Option<std::string>("prop"),
+                      Option<std::string>(), Option<std::string>()},
+        IndexType{true, Ascending}};
+
+    // ******************************* TEST 1 ********************************//
+    {
+        std::cout << "TEST1" << std::endl;
+        // 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));
+        run(cvl_n, create_vertex_label, db);
+        add_edge(cvl_n, db);
+        assert(cvl_n ==
+               size(db, db.graph.vertices.property_family_find_or_create("prop")
+                            .index));
+        assert(
+            cvl_n ==
+            size(db,
+                 db.graph.edges.property_family_find_or_create("prop").index));
+    }
+
+    // TODO: more tests
+
+    return 0;
+}