Add DB performance analysis tests and performance improvements. 65/28865/1
authorMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Tue, 7 Oct 2014 11:02:28 +0000 (13:02 +0200)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Thu, 16 Oct 2014 13:44:31 +0000 (15:44 +0200)
Change-Id: I5e3bd05e6390392dde2d9837d067de36da82d978

src/manager/service/db-crypto.cpp
tests/CMakeLists.txt
tests/DBFixture.cpp [new file with mode: 0644]
tests/DBFixture.h [new file with mode: 0644]
tests/test_common.h
tests/test_db_crypto.cpp

index fa33752..7155846 100644 (file)
@@ -49,8 +49,7 @@ namespace {
             "   data BLOB NOT NULL,"
             "   tag BLOB NOT NULL,"
             "   PRIMARY KEY(alias)"
-            ");";
-
+            "); CREATE INDEX alias_idx ON CKM_TABLE(alias);";
 
     const char *insert_main_cmd =
             "INSERT INTO CKM_TABLE("
@@ -114,7 +113,7 @@ namespace {
             "   accessFlags TEXT NOT NULL,"
             "   FOREIGN KEY(alias) REFERENCES CKM_TABLE(alias) ON DELETE CASCADE,"
             "   PRIMARY KEY(alias, label)"
-            ");";
+            "); CREATE INDEX alias_label_idx ON PERMISSION_TABLE(alias, label);";
 
     const char *set_permission_alias_cmd =
             "REPLACE INTO PERMISSION_TABLE(alias, label, accessFlags) VALUES (?, ?, ?);";
@@ -131,17 +130,12 @@ namespace {
 // CKM_TABLE x PERMISSION_TABLE
 
     const char *select_type_cross_cmd =
-            //                                                1              2                                                                     3
-            "SELECT c.alias FROM CKM_TABLE c WHERE c.dataType=? AND (c.label=? OR c.alias IN (SELECT p.alias FROM PERMISSION_TABLE p WHERE p.label=?));";
+            //                                                                                                        1              2             3
+            "SELECT C.alias FROM CKM_TABLE AS C LEFT JOIN PERMISSION_TABLE AS P ON C.alias = P.alias WHERE C.dataType=? AND (C.label=? OR (P.label=? AND P.accessFlags IS NOT NULL)) GROUP BY C.alias;";
 
     const char *select_key_type_cross_cmd =
-            "SELECT c.alias FROM CKM_TABLE c WHERE "
-            //                  1
-                " c.dataType >= ? AND "
-            //                  2
-                " c.dataType <= ? AND "
-            //             3                                                                     4
-                " (c.label=? OR c.alias IN (SELECT p.alias FROM PERMISSION_TABLE p WHERE p.label=?));";
+            //                                                                                                       1                 2              3             4
+            "SELECT C.alias FROM CKM_TABLE AS C LEFT JOIN PERMISSION_TABLE AS P ON C.alias=P.alias WHERE C.dataType>=? AND C.dataType<=? AND (C.label=? OR (P.label=? AND P.accessFlags IS NOT NULL)) GROUP BY C.alias;";
 }
 
 namespace CKM {
index f7b6eeb..21478fa 100644 (file)
@@ -27,6 +27,7 @@ INCLUDE_DIRECTORIES(
 
 SET(TEST_MERGED_SOURCES
     ${KEY_MANAGER_TEST_MERGED_SRC}/test_common.cpp
+    ${KEY_MANAGER_TEST_MERGED_SRC}/DBFixture.cpp
     ${KEY_MANAGER_TEST_MERGED_SRC}/colour_log_formatter.cpp
     ${KEY_MANAGER_TEST_MERGED_SRC}/test_db_crypto.cpp
     ${KEY_MANAGER_TEST_MERGED_SRC}/test_sql.cpp
diff --git a/tests/DBFixture.cpp b/tests/DBFixture.cpp
new file mode 100644 (file)
index 0000000..f463613
--- /dev/null
@@ -0,0 +1,208 @@
+#include <boost/test/unit_test.hpp>
+#include <db-crypto.h>
+#include <ckm/ckm-error.h>
+#include <DBFixture.h>
+
+using namespace CKM;
+using namespace std::chrono;
+
+
+DBFixture::DBFixture()
+{
+    high_resolution_clock::time_point srand_feed = high_resolution_clock::now();
+    srand(srand_feed.time_since_epoch().count());
+
+    BOOST_CHECK(unlink(m_crypto_db_fname) == 0 || errno == ENOENT);
+    BOOST_REQUIRE_NO_THROW(m_db = DBCrypto(m_crypto_db_fname, defaultPass));
+}
+
+double DBFixture::performance_get_time_elapsed_ms()
+{
+    return duration_cast<milliseconds>(m_end_time - m_start_time).count();
+}
+
+void DBFixture::performance_start(const char *operation_name)
+{
+    m_operation = std::string(operation_name?operation_name:"unknown");
+    BOOST_TEST_MESSAGE("\t<performance> running " << m_operation << " performance test...");
+    m_start_time = high_resolution_clock::now();
+}
+
+void DBFixture::performance_stop(long num_operations_performed)
+{
+    m_end_time = high_resolution_clock::now();
+    double time_elapsed_ms = performance_get_time_elapsed_ms();
+    BOOST_TEST_MESSAGE("\t<performance> time elapsed: " << time_elapsed_ms << "[ms], number of " << m_operation << ": " << num_operations_performed);
+    if(num_operations_performed>0)
+        BOOST_TEST_MESSAGE("\t<performance> average time per " << m_operation << ": " << time_elapsed_ms/num_operations_performed << "[ms]");
+}
+
+void DBFixture::generate_alias(unsigned int id, std::string & output)
+{
+    std::stringstream ss;
+    ss << "alias_no_" << id;
+    output = ss.str();
+}
+
+void DBFixture::generate_label(unsigned int id, std::string & output)
+{
+    std::stringstream ss;
+    ss << "label_no_" << id;
+    output = ss.str();
+}
+
+void DBFixture::generate_perf_DB(unsigned int num_alias, unsigned int num_label)
+{
+    // to speed up data creation - cache the row
+    DBRow rowPattern = create_default_row(DBDataType::BINARY_DATA);
+    rowPattern.data = RawBuffer(100, 20);
+    rowPattern.dataSize = rowPattern.data.size();
+    rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
+
+    for(unsigned int i=0; i<num_alias; i++)
+    {
+        generate_alias(i, rowPattern.alias);
+        generate_label(i/num_label, rowPattern.smackLabel);
+
+        BOOST_REQUIRE_NO_THROW(m_db.saveDBRow(rowPattern));
+    }
+}
+
+long DBFixture::add_full_access_rights(unsigned int num_alias, unsigned int num_alias_per_label)
+{
+    long iterations = 0;
+    unsigned int num_labels = num_alias / num_alias_per_label;
+    std::string alias, owner_label, accessor_label;
+    for(unsigned int a=0; a<num_alias; a++)
+    {
+        generate_alias(a, alias);
+        generate_label(a/num_alias_per_label, owner_label);
+        for(unsigned int l=0; l<num_labels; l++)
+        {
+            // bypass the owner label
+            if(l == (a/num_alias_per_label))
+                continue;
+
+            // add permission
+            generate_label(l, accessor_label);
+            add_permission(alias, owner_label, accessor_label);
+            iterations ++;
+        }
+    }
+
+    return iterations;
+}
+
+DBRow DBFixture::create_default_row(DBDataType type)
+{
+    return create_default_row(m_default_alias, m_default_label, type);
+}
+
+DBRow DBFixture::create_default_row(const std::string &alias,
+                                    const std::string &label,
+                                    DBDataType type)
+{
+    DBRow row;
+    row.alias = alias;
+    row.smackLabel = label;
+    row.exportable = 1;
+    row.algorithmType = DBCMAlgType::AES_GCM_256;
+    row.dataType = type;
+    row.iv = createDefaultPass();
+    row.encryptionScheme = 0;
+    row.dataSize = 0;
+
+    return row;
+}
+
+void DBFixture::compare_row(const DBRow &lhs, const DBRow &rhs)
+{
+    BOOST_CHECK_MESSAGE(lhs.alias == rhs.alias,
+            "Aliases didn't match! Got: " << rhs.alias
+                << " , expected : " << lhs.alias);
+
+    BOOST_CHECK_MESSAGE(lhs.smackLabel == rhs.smackLabel,
+            "smackLabel didn't match! Got: " << rhs.smackLabel
+                << " , expected : " << lhs.smackLabel);
+
+    BOOST_CHECK_MESSAGE(lhs.exportable == rhs.exportable,
+            "exportable didn't match! Got: " << rhs.exportable
+                << " , expected : " << lhs.exportable);
+
+    BOOST_CHECK_MESSAGE(lhs.iv == rhs.iv,
+            "iv didn't match! Got: " << rhs.iv.size()
+                << " , expected : " << lhs.iv.size());
+
+    BOOST_CHECK_MESSAGE(lhs.data == rhs.data,
+            "data didn't match! Got: " << rhs.data.size()
+                << " , expected : " << lhs.data.size());
+}
+
+void DBFixture::check_DB_integrity(const DBRow &rowPattern)
+{
+    BOOST_REQUIRE_NO_THROW(m_db.saveDBRow(rowPattern));
+    DBRow selectRow = rowPattern;
+
+    DBCrypto::DBRowOptional optional_row;
+    BOOST_REQUIRE_NO_THROW(optional_row = m_db.getDBRow("alias", "label", DBDataType::BINARY_DATA));
+    BOOST_REQUIRE_MESSAGE(optional_row, "Select didn't return any row");
+
+    compare_row(selectRow, rowPattern);
+    DBRow alias_duplicate = rowPattern;
+    alias_duplicate.data = createDefaultPass();
+    alias_duplicate.dataSize = alias_duplicate.data.size();
+
+    BOOST_REQUIRE_THROW(m_db.saveDBRow(alias_duplicate), DBCrypto::Exception::AliasExists);
+    unsigned int erased;
+    BOOST_REQUIRE_NO_THROW(erased = m_db.deleteDBRow("alias", "label"));
+    BOOST_REQUIRE_MESSAGE(erased > 0, "Inserted row didn't exist in db");
+
+    DBCrypto::DBRowOptional row_optional;
+    BOOST_REQUIRE_NO_THROW(row_optional = m_db.getDBRow("alias", "label", DBDataType::BINARY_DATA));
+    BOOST_REQUIRE_MESSAGE(!row_optional, "Select should not return row after deletion");
+}
+
+void DBFixture::insert_row()
+{
+    insert_row(m_default_alias, m_default_label);
+}
+
+void DBFixture::insert_row(const std::string &alias, const std::string &accessor_label)
+{
+    DBRow rowPattern = create_default_row(alias, accessor_label, DBDataType::BINARY_DATA);
+    rowPattern.data = RawBuffer(100, 20);
+    rowPattern.dataSize = rowPattern.data.size();
+    rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
+    BOOST_REQUIRE_NO_THROW(m_db.saveDBRow(rowPattern));
+}
+
+void DBFixture::delete_row(const std::string &alias, const std::string &accessor_label)
+{
+    bool exit_flag;
+    BOOST_REQUIRE_NO_THROW(exit_flag = m_db.deleteDBRow(alias, accessor_label));
+    BOOST_REQUIRE_MESSAGE(true == exit_flag, "remove alias failed: no rows removed");
+}
+
+void DBFixture::add_permission(const std::string &alias, const std::string &owner_label, const std::string &accessor_label)
+{
+    int ec;
+    BOOST_REQUIRE_NO_THROW(ec = m_db.setAccessRights(owner_label,
+                                                   alias,
+                                                   accessor_label,
+                                                   CKM::AccessRight::AR_READ_REMOVE));
+    BOOST_REQUIRE_MESSAGE(CKM_API_SUCCESS == ec, "add permission failed: " << ec);
+}
+
+void DBFixture::read_row_expect_fail(const std::string &alias, const std::string &accessor_label)
+{
+    DBCrypto::DBRowOptional row;
+    BOOST_REQUIRE_THROW(row = m_db.getDBRow(alias, accessor_label, DBDataType::BINARY_DATA), DBCrypto::Exception::PermissionDenied);
+}
+
+void DBFixture::read_row_expect_success(const std::string &alias, const std::string &accessor_label)
+{
+    DBCrypto::DBRowOptional row;
+    BOOST_REQUIRE_NO_THROW(row = m_db.getDBRow(alias, accessor_label, DBDataType::BINARY_DATA));
+    BOOST_REQUIRE_MESSAGE(row, "row is empty");
+    BOOST_REQUIRE_MESSAGE(row->alias == alias, "alias is not valid");
+}
diff --git a/tests/DBFixture.h b/tests/DBFixture.h
new file mode 100644 (file)
index 0000000..883e963
--- /dev/null
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <test_common.h>
+#include <ckm/ckm-type.h>
+#include <chrono>
+
+class DBFixture
+{
+    public:
+        DBFixture();
+
+        constexpr static const char* m_default_alias = "alias";
+        constexpr static const char* m_default_label = "label";
+
+        // ::::::::::::::::::::::::: helper methods :::::::::::::::::::::::::
+        static void generate_alias(unsigned int id, std::string & output);
+        static void generate_label(unsigned int id, std::string & output);
+        static CKM::DBRow create_default_row(CKM::DBDataType type = CKM::DBDataType::BINARY_DATA);
+        static CKM::DBRow create_default_row(const std::string &alias,
+                                             const std::string &label,
+                                             CKM::DBDataType type = CKM::DBDataType::BINARY_DATA);
+        static void compare_row(const CKM::DBRow &lhs, const CKM::DBRow &rhs);
+
+        // ::::::::::::::::::::::::: time measurement :::::::::::::::::::::::::
+        void performance_start(const char *operation_name);
+        void performance_stop(long num_operations_performed);
+
+        // ::::::::::::::::::::::::: DB :::::::::::::::::::::::::
+        void generate_perf_DB(unsigned int num_alias, unsigned int num_label);
+        long add_full_access_rights(unsigned int num_alias, unsigned int num_alias_per_label);
+        void check_DB_integrity(const CKM::DBRow &rowPattern);
+        void insert_row();
+        void insert_row(const std::string &alias, const std::string &accessor_label);
+        void delete_row(const std::string &alias, const std::string &accessor_label);
+        void add_permission(const std::string &alias, const std::string &owner_label, const std::string &accessor_label);
+        void read_row_expect_fail(const std::string &alias, const std::string &accessor_label);
+        void read_row_expect_success(const std::string &alias, const std::string &accessor_label);
+
+        CKM::DBCrypto    m_db;
+    private:
+        double  performance_get_time_elapsed_ms();
+
+        constexpr static const char* m_crypto_db_fname = "/tmp/testme.db";
+        std::string m_operation;
+        std::chrono::high_resolution_clock::time_point m_start_time, m_end_time;
+};
index 681bd4d..83234f1 100644 (file)
@@ -16,6 +16,9 @@ struct TestConfig {
 private:
 };
 
+// mirrors the API-defined value
+#define AES_GCM_TAG_SIZE 16
+
 CKM::RawBuffer createDefaultPass();
 CKM::RawBuffer createBigBlob(std::size_t size);
 
index e15fa44..4344541 100644 (file)
@@ -6,8 +6,8 @@
 #include <ckm/ckm-type.h>
 #include <ckm/ckm-error.h>
 #include <errno.h>
-
 #include <test_common.h>
+#include <DBFixture.h>
 
 BOOST_GLOBAL_FIXTURE(TestConfig)
 
@@ -15,191 +15,59 @@ using namespace CKM;
 
 namespace
 {
-
-const char* default_alias = "alias";
-const char* default_label = "label";
-
-const char* crypto_db = "/tmp/testme.db";
-
 const int restricted_local = 1;
 const int restricted_global = 0;
 
-// mirrors the API-defined value
-#define AES_GCM_TAG_SIZE 16
-
-const char *row_A_alias = "row_A_alias";
-const char *row_A_label = "app_A";
-
-const char *row_B_alias = "row_B_alias";
-const char *row_B_label = "app_B";
-
-const char *row_C_alias = "row_C_alias";
-const char *row_C_label = "app_C";
-
-void initDB(DBCrypto & db)
-{
-    BOOST_CHECK(unlink(crypto_db) == 0 || errno == ENOENT);
-    BOOST_REQUIRE_NO_THROW(db = DBCrypto(crypto_db, defaultPass));
-}
-
-DBRow createDefaultRow( DBDataType type = DBDataType::BINARY_DATA,
-                        const char *optional_alias = NULL,
-                        const char *optional_label = NULL)
-{
-    DBRow row;
-    row.alias = optional_alias?optional_alias:default_alias;
-    row.smackLabel = optional_label?optional_label:default_label;
-    row.exportable = 1;
-    row.algorithmType = DBCMAlgType::AES_GCM_256;
-    row.dataType = type;
-    row.iv = createDefaultPass();
-    row.encryptionScheme = 0;
-    row.dataSize = 0;
-
-    return row;
-}
-
-void compareDBRow(const DBRow &lhs, const DBRow &rhs) {
-    BOOST_CHECK_MESSAGE(lhs.alias == rhs.alias,
-            "Aliases didn't match! Got: " << rhs.alias
-                << " , expected : " << lhs.alias);
-
-    BOOST_CHECK_MESSAGE(lhs.smackLabel == rhs.smackLabel,
-            "smackLabel didn't match! Got: " << rhs.smackLabel
-                << " , expected : " << lhs.smackLabel);
-
-    BOOST_CHECK_MESSAGE(lhs.exportable == rhs.exportable,
-            "exportable didn't match! Got: " << rhs.exportable
-                << " , expected : " << lhs.exportable);
-
-    BOOST_CHECK_MESSAGE(lhs.iv == rhs.iv,
-            "iv didn't match! Got: " << rhs.iv.size()
-                << " , expected : " << lhs.iv.size());
-
-    BOOST_CHECK_MESSAGE(lhs.data == rhs.data,
-            "data didn't match! Got: " << rhs.data.size()
-                << " , expected : " << lhs.data.size());
+const unsigned int c_test_retries = 1000;
+const unsigned int c_num_aliases = 500;
+const unsigned int c_num_aliases_add_test = 5000;
+const unsigned int c_alias_per_label = 15;
 }
 
-void checkDBIntegrity(const DBRow &rowPattern, DBCrypto &db) {
-
-    BOOST_REQUIRE_NO_THROW(db.saveDBRow(rowPattern));
-    DBRow selectRow = rowPattern;
-
-    DBCrypto::DBRowOptional optional_row;
-    BOOST_REQUIRE_NO_THROW(optional_row = db.getDBRow("alias", "label", DBDataType::BINARY_DATA));
-    BOOST_REQUIRE_MESSAGE(optional_row, "Select didn't return any row");
 
-    compareDBRow(selectRow, rowPattern);
-    DBRow alias_duplicate = rowPattern;
-    alias_duplicate.data = createDefaultPass();
-    alias_duplicate.dataSize = alias_duplicate.data.size();
-
-    BOOST_REQUIRE_THROW(db.saveDBRow(alias_duplicate), DBCrypto::Exception::AliasExists);
-    unsigned int erased;
-    BOOST_REQUIRE_NO_THROW(erased = db.deleteDBRow("alias", "label"));
-    BOOST_REQUIRE_MESSAGE(erased > 0, "Inserted row didn't exist in db");
-
-    DBCrypto::DBRowOptional row_optional;
-    BOOST_REQUIRE_NO_THROW(row_optional = db.getDBRow("alias", "label", DBDataType::BINARY_DATA));
-    BOOST_REQUIRE_MESSAGE(!row_optional, "Select should not return row after deletion");
-}
-
-void insertRow(DBCrypto & db, const char *alias, const char *label)
-{
-    DBRow rowPattern = createDefaultRow(DBDataType::BINARY_DATA, alias, label);
-    rowPattern.data = RawBuffer(100, 20);
-    rowPattern.dataSize = rowPattern.data.size();
-    rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
-    BOOST_REQUIRE_NO_THROW(db.saveDBRow(rowPattern));
-}
-
-void deleteRow(DBCrypto & db, const char *alias, const char *label)
-{
-    bool exit_flag;
-    BOOST_REQUIRE_NO_THROW(exit_flag = db.deleteDBRow(alias, label));
-    BOOST_REQUIRE_MESSAGE(true == exit_flag, "remove alias failed: no rows removed");
-}
-
-void addPermission(DBCrypto & db, const char *alias, const char *owner_label, const char *accessor_label)
-{
-    int ec;
-    BOOST_REQUIRE_NO_THROW(ec = db.setAccessRights(std::string(owner_label),
-                                                   std::string(alias),
-                                                   std::string(accessor_label),
-                                                   CKM::AccessRight::AR_READ_REMOVE));
-    BOOST_REQUIRE_MESSAGE(CKM_API_SUCCESS == ec, "add permission failed: " << ec);
-}
-
-void readRowExpectFail(DBCrypto & db, const char *alias, const char *accessor_label)
-{
-    DBCrypto::DBRowOptional row;
-    BOOST_REQUIRE_THROW(row = db.getDBRow(alias, accessor_label, DBDataType::BINARY_DATA), DBCrypto::Exception::PermissionDenied);
-}
-
-void readRowExpectSuccess(DBCrypto & db, const char *alias, const char *accessor_label)
-{
-    DBCrypto::DBRowOptional row;
-    BOOST_REQUIRE_NO_THROW(row = db.getDBRow(alias, accessor_label, DBDataType::BINARY_DATA));
-    BOOST_REQUIRE_MESSAGE(row, "row is empty");
-}
-}
-
-BOOST_AUTO_TEST_SUITE(DBCRYPTO_TEST)
+BOOST_FIXTURE_TEST_SUITE(DBCRYPTO_TEST, DBFixture)
 BOOST_AUTO_TEST_CASE(DBtestSimple) {
-    DBCrypto db;
-    initDB(db);
-
-    DBRow rowPattern = createDefaultRow();
+    DBRow rowPattern = create_default_row();
     rowPattern.data = RawBuffer(32, 1);
     rowPattern.dataSize = rowPattern.data.size();
     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
 
-    checkDBIntegrity(rowPattern, db);
+    check_DB_integrity(rowPattern);
 }
 BOOST_AUTO_TEST_CASE(DBtestBIG) {
-    DBCrypto db;
-    initDB(db);
-
-    DBRow rowPattern = createDefaultRow();
+    DBRow rowPattern = create_default_row();
     rowPattern.data = createBigBlob(4096);
     rowPattern.dataSize = rowPattern.data.size();
     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
 
-    checkDBIntegrity(rowPattern, db);
+    check_DB_integrity(rowPattern);
 }
 BOOST_AUTO_TEST_CASE(DBtestGlobal) {
-    DBCrypto db;
-    initDB(db);
-
-    DBRow rowPattern = createDefaultRow();
+    DBRow rowPattern = create_default_row();
     rowPattern.data = RawBuffer(1024, 2);
     rowPattern.dataSize = rowPattern.data.size();
     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
 
-    BOOST_REQUIRE_NO_THROW(db.saveDBRow(rowPattern));
+    BOOST_REQUIRE_NO_THROW(m_db.saveDBRow(rowPattern));
 
     DBRow alias_duplicate = rowPattern;
     rowPattern.smackLabel = rowPattern.smackLabel + "1";
 
-    BOOST_REQUIRE_THROW(db.saveDBRow(alias_duplicate),
+    BOOST_REQUIRE_THROW(m_db.saveDBRow(alias_duplicate),
             DBCrypto::Exception::AliasExists);
 }
 BOOST_AUTO_TEST_CASE(DBtestTransaction) {
-    DBCrypto db;
-    initDB(db);
-
-    DBRow rowPattern = createDefaultRow();
+    DBRow rowPattern = create_default_row();
     rowPattern.data = RawBuffer(100, 20);
     rowPattern.dataSize = rowPattern.data.size();
     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
-    DBCrypto::Transaction transaction(&db);
+    DBCrypto::Transaction transaction(&m_db);
 
-    BOOST_REQUIRE_NO_THROW(db.saveDBRow(rowPattern));
+    BOOST_REQUIRE_NO_THROW(m_db.saveDBRow(rowPattern));
     BOOST_REQUIRE_NO_THROW(transaction.rollback());
 
     DBCrypto::DBRowOptional row_optional;
-    BOOST_REQUIRE_NO_THROW(row_optional = db.getDBRow(default_alias, default_label,
+    BOOST_REQUIRE_NO_THROW(row_optional = m_db.getDBRow(m_default_alias, m_default_label,
             DBDataType::BINARY_DATA));
     BOOST_CHECK_MESSAGE(!row_optional, "Row still present after rollback");
 
@@ -207,84 +75,256 @@ BOOST_AUTO_TEST_CASE(DBtestTransaction) {
 
 BOOST_AUTO_TEST_CASE(DBaddDataCheckIfPermissionIsAdded)
 {
-    DBCrypto db;
-    initDB(db);
+    std::string row_A_alias, row_B_alias;
+    std::string row_A_label, row_B_label;
+    generate_alias(0, row_A_alias); generate_label(0, row_A_label);
+    generate_alias(1, row_B_alias); generate_label(1, row_B_label);
 
     // insert initial data set
-    insertRow(db, row_A_alias, row_A_label);
-    insertRow(db, row_B_alias, row_B_label);
-    readRowExpectSuccess(db, row_A_alias, row_A_label);
-    readRowExpectSuccess(db, row_B_alias, row_B_label);
+    insert_row(row_A_alias, row_A_label);
+    insert_row(row_B_alias, row_B_label);
+    read_row_expect_success(row_A_alias, row_A_label);
+    read_row_expect_success(row_B_alias, row_B_label);
 
     // verify that no entries present in the permission table
     // read row A from label B and vice versa
-    readRowExpectFail(db, row_A_alias, row_B_label);
-    readRowExpectFail(db, row_B_alias, row_A_label);
+    read_row_expect_fail(row_A_alias, row_B_label);
+    read_row_expect_fail(row_B_alias, row_A_label);
 
     // add appropriate permissions for label B
-    addPermission(db, row_A_alias, row_A_label, row_B_label);
+    add_permission(row_A_alias, row_A_label, row_B_label);
 
     // B should have access to A, while A should not to B
     // read row A from label B and vice versa
-    readRowExpectSuccess(db, row_A_alias, row_B_label);
-    readRowExpectFail(db, row_B_alias, row_A_label);
+    read_row_expect_success(row_A_alias, row_B_label);
+    read_row_expect_fail(row_B_alias, row_A_label);
 
     // add appropriate permissions for label A
-    addPermission(db, row_B_alias, row_B_label, row_A_label);
+    add_permission(row_B_alias, row_B_label, row_A_label);
 
     // B should have access to A, same as A have access to B
     // read row A from label B and vice versa
-    readRowExpectSuccess(db, row_A_alias, row_B_label);
-    readRowExpectSuccess(db, row_B_alias, row_A_label);
+    read_row_expect_success(row_A_alias, row_B_label);
+    read_row_expect_success(row_B_alias, row_A_label);
 }
 
 
 BOOST_AUTO_TEST_CASE(DBremoveDataCheckIfPermissionIsRemoved)
 {
-    DBCrypto db;
-    initDB(db);
+    std::string row_A_alias, row_B_alias, row_C_alias;
+    std::string row_A_label, row_B_label, row_C_label;
+    generate_alias(0, row_A_alias); generate_label(0, row_A_label);
+    generate_alias(1, row_B_alias); generate_label(1, row_B_label);
+    generate_alias(2, row_C_alias); generate_label(2, row_C_label);
 
     // insert initial data set
-    insertRow(db, row_A_alias, row_A_label);
-    insertRow(db, row_B_alias, row_B_label);
-    insertRow(db, row_C_alias, row_C_label);
-    addPermission(db, row_A_alias, row_A_label, row_B_label);
-    addPermission(db, row_B_alias, row_B_label, row_A_label);
+    insert_row(row_A_alias, row_A_label);
+    insert_row(row_B_alias, row_B_label);
+    insert_row(row_C_alias, row_C_label);
+    add_permission(row_A_alias, row_A_label, row_B_label);
+    add_permission(row_B_alias, row_B_label, row_A_label);
     // to test multiple permissions removal
     // put intentionally after row_B_alias permission entry
-    addPermission(db, row_A_alias, row_A_label, row_C_label);
+    add_permission(row_A_alias, row_A_label, row_C_label);
 
     // B should have access to A, same as A have access to B
     // read row A from label B and vice versa
-    readRowExpectSuccess(db, row_A_alias, row_B_label);
-    readRowExpectSuccess(db, row_A_alias, row_C_label);
-    readRowExpectSuccess(db, row_B_alias, row_A_label);
-    readRowExpectFail(db, row_B_alias, row_C_label);
+    read_row_expect_success(row_A_alias, row_B_label);
+    read_row_expect_success(row_A_alias, row_C_label);
+    read_row_expect_success(row_B_alias, row_A_label);
+    read_row_expect_fail(row_B_alias, row_C_label);
 
     // remove data A - expect permissions for B and C to be removed as well
-    deleteRow(db, row_A_alias, row_A_label);
+    delete_row(row_A_alias, row_A_label);
     // insert it again - expect permissions for label B and C not to be there anymore
-    insertRow(db, row_A_alias, row_A_label);
+    insert_row(row_A_alias, row_A_label);
 
     // read row A from label B and vice versa
-    readRowExpectFail(db, row_A_alias, row_B_label);
-    readRowExpectFail(db, row_A_alias, row_C_label);
-    readRowExpectSuccess(db, row_B_alias, row_A_label);
+    read_row_expect_fail(row_A_alias, row_B_label);
+    read_row_expect_fail(row_A_alias, row_C_label);
+    read_row_expect_success(row_B_alias, row_A_label);
 
     // remove data B - expect permission to be removed as well
-    deleteRow(db, row_B_alias, row_B_label);
+    delete_row(row_B_alias, row_B_label);
     // insert it again - expect permissions for label A not to be there anymore
-    insertRow(db, row_B_alias, row_B_label);
+    insert_row(row_B_alias, row_B_label);
 
     // read row A from label B and vice versa
-    readRowExpectFail(db, row_A_alias, row_B_label);
-    readRowExpectFail(db, row_A_alias, row_C_label);
-    readRowExpectFail(db, row_B_alias, row_A_label);
+    read_row_expect_fail(row_A_alias, row_B_label);
+    read_row_expect_fail(row_A_alias, row_C_label);
+    read_row_expect_fail(row_B_alias, row_A_label);
 
     // sanity check: data exists
-    readRowExpectSuccess(db, row_A_alias, row_A_label);
-    readRowExpectSuccess(db, row_B_alias, row_B_label);
+    read_row_expect_success(row_A_alias, row_A_label);
+    read_row_expect_success(row_B_alias, row_B_label);
+}
+BOOST_AUTO_TEST_SUITE_END()
+
+
+
+BOOST_FIXTURE_TEST_SUITE(DBCRYPTO_PERF_TEST, DBFixture)
+
+BOOST_AUTO_TEST_CASE(DBperfAddAliases)
+{
+    // actual test
+    performance_start("saveDBRow");
+    {
+        generate_perf_DB(c_num_aliases_add_test, c_alias_per_label);
+    }
+    performance_stop(c_num_aliases_add_test);
+}
+
+BOOST_AUTO_TEST_CASE(DBperfLookupAliasByOwner)
+{
+    // prepare data
+    generate_perf_DB(c_num_aliases, c_alias_per_label);
+
+    unsigned int num_labels = c_num_aliases/c_alias_per_label;
+    std::string alias, label;
+
+    // actual test - successful lookup
+    performance_start("getDBRow");
+    for(unsigned int t=0; t<c_test_retries; t++)
+    {
+        int label_num = rand() % num_labels;
+        generate_label(label_num, label);
+
+        unsigned int start_alias = label_num*c_alias_per_label;
+        for(unsigned int alias_num=start_alias; alias_num<(start_alias+c_alias_per_label); alias_num++)
+        {
+            generate_alias(alias_num, alias);
+            read_row_expect_success(alias, label);
+        }
+    }
+    performance_stop(c_test_retries * c_num_aliases);
+}
+
+BOOST_AUTO_TEST_CASE(DBperfLookupAliasByNotAllowed)
+{
+    // prepare data
+    generate_perf_DB(c_num_aliases, c_alias_per_label);
+
+    std::string alias, label;
+    const unsigned int unavailable_label_idx = (c_num_aliases/c_alias_per_label) + 1;
+    generate_label(unavailable_label_idx, label);
+
+    // actual test - failure lookup
+    performance_start("getDBRow");
+    for(unsigned int t=0; t<c_test_retries; t++)
+    {
+        generate_alias(rand()%c_num_aliases, alias);
+
+        read_row_expect_fail(alias, label);
+    }
+    performance_stop(c_test_retries * c_num_aliases);
+}
+
+BOOST_AUTO_TEST_CASE(DBperfLookupAliasRandomOwnershipNoPermissions)
+{
+    // prepare data
+    generate_perf_DB(c_num_aliases, c_alias_per_label);
+
+    std::string alias, label;
+    unsigned int num_labels = c_num_aliases / c_alias_per_label;
+
+    // actual test - random lookup
+    performance_start("getDBRow");
+    for(unsigned int t=0; t<c_test_retries; t++)
+    {
+        generate_alias(rand()%c_num_aliases, alias);
+        generate_label(rand()%num_labels, label);
+
+        try
+        {
+            m_db.getDBRow(alias, label, DBDataType::BINARY_DATA);
+        }
+        catch (const DBCrypto::Exception::PermissionDenied &e) {}
+    }
+    performance_stop(c_test_retries * c_num_aliases);
 }
 
+BOOST_AUTO_TEST_CASE(DBperfAddPermissions)
+{
+    // prepare data
+    generate_perf_DB(c_num_aliases, c_alias_per_label);
+
+    // actual test - add access rights
+    performance_start("setAccessRights");
+    long iterations = add_full_access_rights(c_num_aliases, c_alias_per_label);
+    performance_stop(iterations);
+}
+
+BOOST_AUTO_TEST_CASE(DBperfLookupAliasRandomOwnershipWithPermissions)
+{
+    // prepare data
+    generate_perf_DB(c_num_aliases, c_alias_per_label);
+    add_full_access_rights(c_num_aliases, c_alias_per_label);
+
+    std::string alias, label;
+    unsigned int num_labels = c_num_aliases / c_alias_per_label;
+
+    // actual test - random lookup
+    performance_start("getDBRow/perm");
+    for(unsigned int t=0; t<c_test_retries; t++)
+    {
+        generate_alias(rand()%c_num_aliases, alias);
+        generate_label(rand()%num_labels, label);
+
+        read_row_expect_success(alias, label);
+    }
+    performance_stop(c_test_retries * c_num_aliases);
+}
+
+BOOST_AUTO_TEST_CASE(DBperfAliasRemoval)
+{
+    // prepare data
+    generate_perf_DB(c_num_aliases, c_alias_per_label);
+    add_full_access_rights(c_num_aliases, c_alias_per_label);
+
+    // actual test - random lookup
+    performance_start("deleteDBRow");
+    std::string alias, label;
+    for(unsigned int t=0; t<c_num_aliases; t++)
+    {
+        generate_alias(t, alias);
+        generate_label(t/c_alias_per_label, label);
+
+        BOOST_REQUIRE_NO_THROW(m_db.deleteDBRow(alias, label));
+    }
+    performance_stop(c_num_aliases);
+
+    // verify everything has been removed
+    unsigned int num_labels = c_num_aliases / c_alias_per_label;
+    for(unsigned int l=0; l<num_labels; l++)
+    {
+        generate_label(l, label);
+        AliasVector expect_no_data;
+        BOOST_REQUIRE_NO_THROW(m_db.getAliases(label, DBDataType::BINARY_DATA, expect_no_data));
+        BOOST_REQUIRE(0 == expect_no_data.size());
+    }
+}
+
+BOOST_AUTO_TEST_CASE(DBperfGetAliasList)
+{
+    // prepare data
+    generate_perf_DB(c_num_aliases, c_alias_per_label);
+    add_full_access_rights(c_num_aliases, c_alias_per_label);
+
+    unsigned int num_labels = c_num_aliases / c_alias_per_label;
+    std::string label;
+
+    // actual test - random lookup
+    performance_start("getAliases");
+    for(unsigned int t=0; t<(c_test_retries/num_labels); t++)
+    {
+        AliasVector ret_list;
+        generate_label(rand()%num_labels, label);
+
+        BOOST_REQUIRE_NO_THROW(m_db.getAliases(label, DBDataType::BINARY_DATA, ret_list));
+        BOOST_REQUIRE(c_num_aliases == ret_list.size());
+        ret_list.clear();
+    }
+    performance_stop(c_test_retries/num_labels);
+}
 
 BOOST_AUTO_TEST_SUITE_END()