Add internal tests for sql and db
authorZofia Abramowska <z.abramowska@samsung.com>
Tue, 10 Jun 2014 08:46:42 +0000 (10:46 +0200)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Fri, 12 Sep 2014 12:58:48 +0000 (14:58 +0200)
Add internal tests for SqlConnection class and DBCrypto
(with Transaction) class.

Change-Id: I5950aa4ed6f9da9effe1aec0bfacaf1957a752f3

CMakeLists.txt
packaging/key-manager.spec
src/CMakeLists.txt
tests/CMakeLists.txt
tests/test-key-provider.cpp
tests/test_common.cpp [new file with mode: 0644]
tests/test_common.h [new file with mode: 0644]
tests/test_db_crypto.cpp [new file with mode: 0644]
tests/test_sql.cpp [new file with mode: 0644]

index 4f7e570..56f727c 100644 (file)
@@ -61,9 +61,9 @@ ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
 SET(TARGET_KEY_MANAGER "key-manager")
 SET(TARGET_KEY_MANAGER_CLIENT "key-manager-client")
 SET(TARGET_KEY_MANAGER_COMMON "key-manager-commons")
-
 SET(TARGET_KEY_MANAGER_KEY_PROVIDER "key-manager-key-provider")
 
+SET(TARGET_TEST_MERGED "ckm-tests-internal")
 
 INSTALL(FILES
     ${CMAKE_SOURCE_DIR}/packaging/libkey-manager-client.manifest
index 6a88e20..3e492a7 100644 (file)
@@ -151,6 +151,7 @@ fi
 %{_libdir}/libkey-manager-client.so.*
 %{_datadir}/license/libkey-manager-client
 
+
 %files -n libkey-manager-client-devel
 %defattr(-,root,root,-)
 %{_libdir}/libkey-manager-client.so
@@ -162,4 +163,4 @@ fi
 
 %files -n key-manager-tests
 %defattr(-,root,root,-)
-%{_bindir}/ckm-tests-internal-provider
+%{_bindir}/ckm-tests-internal
index 6a624ad..cf9ba24 100644 (file)
@@ -101,6 +101,7 @@ INSTALL(TARGETS ${TARGET_KEY_MANAGER_CLIENT} DESTINATION ${LIB_INSTALL_DIR})
 
 INSTALL(TARGETS ${TARGET_KEY_MANAGER} DESTINATION bin)
 
+
 INSTALL(FILES
     ${KEY_MANAGER_SRC_PATH}/include/ckm/key-manager.h
     ${KEY_MANAGER_SRC_PATH}/include/ckm/ckm-error.h
index 4e8d20b..bd78cab 100644 (file)
@@ -4,36 +4,46 @@ PKG_CHECK_MODULES(KEY_MANAGER_TEST_DEP
     REQUIRED
     )
 
-SET(TARGET_KEY_MANAGER_TEST_PROVIDER "ckm-tests-internal-provider")
+ADD_DEFINITIONS( "-DBOOST_TEST_DYN_LINK" )
 
 SET(KEY_MANAGER_SRC_PATH ${PROJECT_SOURCE_DIR}/src)
 SET(KEY_MANAGER_PATH ${PROJECT_SOURCE_DIR}/src/manager)
 
-SET(KEY_MANAGER_TEST_PROVIDER_SOURCES
-    ${KEY_MANAGER_PATH}/service/key-provider.cpp
-    ${PROJECT_SOURCE_DIR}/tests/test-key-provider.cpp
-    )
+################################################################################
+
 
-SET_SOURCE_FILES_PROPERTIES(
-    ${KEY_MANAGER_TEST_SOURCES}
-    PROPERTIES
-        COMPILE_FLAGS "-D_GNU_SOURCE -fvisibility=hidden")
+SET(KEY_MANAGER_TEST_MERGED_SRC ${PROJECT_SOURCE_DIR}/tests)
 
-INCLUDE_DIRECTORIES(SYSTEM ${KEY_MANAGER_TEST_DEP_INCLUDE_DIRS})
 INCLUDE_DIRECTORIES(
-    ${KEY_MANAGER_SRC_PATH}/include
-    ${KEY_MANAGER_PATH}/service
+    ${KEY_MANAGER_PATH}/dpl/db/include
     ${KEY_MANAGER_PATH}/dpl/core/include
     ${KEY_MANAGER_PATH}/dpl/log/include
+    ${KEY_MANAGER_PATH}/sqlcipher
+    ${KEY_MANAGER_PATH}/service
+    ${KEY_MANAGER_PATH}/common/
+    ${KEY_MANAGER_SRC_PATH}/include
+    ${KEY_MANAGER_TEST_MERGED_SRC}/
+    )
+
+SET(TEST_MERGED_SOURCES
+    ${KEY_MANAGER_TEST_MERGED_SRC}/test_common.cpp
+    ${KEY_MANAGER_TEST_MERGED_SRC}/test_db_crypto.cpp
+    ${KEY_MANAGER_TEST_MERGED_SRC}/test_sql.cpp
+    ${KEY_MANAGER_TEST_MERGED_SRC}/test-key-provider.cpp
+    ${KEY_MANAGER_PATH}/service/db-crypto.cpp
+    ${KEY_MANAGER_PATH}/service/key-provider.cpp
+
     )
 
-ADD_EXECUTABLE(${TARGET_KEY_MANAGER_TEST_PROVIDER}
-            ${KEY_MANAGER_TEST_PROVIDER_SOURCES})
+ADD_EXECUTABLE(${TARGET_TEST_MERGED} ${TEST_MERGED_SOURCES})
 
-TARGET_LINK_LIBRARIES(${TARGET_KEY_MANAGER_TEST_PROVIDER}
-    ${KEY_MANAGER_TEST_DEP_LIBRARIES}
+TARGET_LINK_LIBRARIES(${TARGET_TEST_MERGED}
+    ${KEY_MANAGER_CLIENT_DEP_LIBRARIES}
+    ${KEY_MANAGER_DEP_LIBRARIES}
+    ${TARGET_KEY_MANAGER_CLIENT}
     ${TARGET_KEY_MANAGER_COMMON}
     ${TARGET_KEY_MANAGER_KEY_PROVIDER}
+    boost_unit_test_framework
     )
 
-INSTALL(TARGETS ${TARGET_KEY_MANAGER_TEST_PROVIDER} DESTINATION bin)
+INSTALL(TARGETS ${TARGET_TEST_MERGED} DESTINATION bin)
index 7d99be5..3765f10 100644 (file)
@@ -1,6 +1,7 @@
 #define BOOST_TEST_MODULE KEY_MANAGER_TEST
-#include <boost/test/included/unit_test.hpp>
+#include <boost/test/unit_test.hpp>
 #include <key-provider.h>
+#include <test_common.h>
 
 #define PASSWORD "12345TIZEN12345AAAAAAAAA"
 #define INCORRECT_PASSWORD "AAAAAAAAAAAAAAAAAAAAA"
@@ -16,11 +17,13 @@ CKM::RawBuffer rb_test;
 CKM::RawBuffer rb_DEK1;
 CKM::RawBuffer rb_pureDEK1;
 
+BOOST_GLOBAL_FIXTURE(TestConfig)
+
 // Test suite for key-provider module.
 BOOST_AUTO_TEST_SUITE(S1_KEY_PROVIDER)
 
 BOOST_AUTO_TEST_CASE(T00100_initialize){
-    boost::unit_test::unit_test_log.set_threshold_level( boost::unit_test::log_test_units);
+    boost::unit_test::results_reporter::set_level(boost::unit_test::SHORT_REPORT);
     BOOST_CHECK_NO_THROW(CKM::KeyProvider::initializeLibrary());
 }
 
diff --git a/tests/test_common.cpp b/tests/test_common.cpp
new file mode 100644 (file)
index 0000000..55feab3
--- /dev/null
@@ -0,0 +1,29 @@
+#include <test_common.h>
+#include <iostream>
+
+using namespace CKM;
+
+RawBuffer createDefaultPass() {
+    RawBuffer raw;
+    for(unsigned char i =0; i < RAW_PASS_SIZE; i++)
+        raw.push_back(i);
+    return raw;
+}
+
+RawBuffer createBigBlob(std::size_t size) {
+    RawBuffer raw;
+    for(std::size_t i = 0; i < size; i++) {
+        raw.push_back(static_cast<unsigned char>(i));
+    }
+    return raw;
+}
+
+//raw to hex string conversion from SqlConnection
+std::string rawToHexString(const std::vector<unsigned char> &raw) {
+    std::string dump(raw.size()*2, '0');
+    for(std::size_t i = 0; i < raw.size(); i++){
+        sprintf(&dump[2*i], "%02x", raw[i]);
+    }
+    return dump;
+}
+
diff --git a/tests/test_common.h b/tests/test_common.h
new file mode 100644 (file)
index 0000000..16fe2e4
--- /dev/null
@@ -0,0 +1,26 @@
+#pragma once
+#include <string>
+#include <ckm/ckm-type.h>
+#include <boost/test/unit_test_log.hpp>
+#include <boost/test/results_reporter.hpp>
+
+struct TestConfig {
+    TestConfig() {
+        boost::unit_test::unit_test_log.set_threshold_level( boost::unit_test::log_test_units);
+        boost::unit_test::results_reporter::set_level(boost::unit_test::SHORT_REPORT);
+    }
+    ~TestConfig(){}
+};
+
+CKM::RawBuffer createDefaultPass();
+CKM::RawBuffer createBigBlob(std::size_t size);
+
+const CKM::RawBuffer defaultPass = createDefaultPass();
+const std::string pattern =
+    "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
+
+const std::size_t RAW_PASS_SIZE = 32;
+const std::size_t HEX_PASS_SIZE = RAW_PASS_SIZE * 2;
+
+
+std::string rawToHexString(const std::vector<unsigned char> &raw);
diff --git a/tests/test_db_crypto.cpp b/tests/test_db_crypto.cpp
new file mode 100644 (file)
index 0000000..4933e6a
--- /dev/null
@@ -0,0 +1,145 @@
+#include <boost/test/unit_test.hpp>
+#include <boost/test/results_reporter.hpp>
+#include <unistd.h>
+#include <db-crypto.h>
+#include <iostream>
+#include <ckm/ckm-error.h>
+#include <errno.h>
+
+#include <test_common.h>
+
+BOOST_GLOBAL_FIXTURE(TestConfig)
+
+using namespace CKM;
+
+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;
+
+DBRow createDefaultRow(int restricted = restricted_local,
+        DBDataType type = DBDataType::BINARY_DATA) {
+    DBRow row;
+    row.alias = default_alias;
+    row.smackLabel = default_label;
+    row.exportable = 1;
+    row.restricted = restricted;
+    row.algorithmType = DBCMAlgType::AES_CBC_256;
+    row.dataType = type;
+    row.iv = createDefaultPass();
+
+    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.restricted == rhs.restricted,
+            "restricted didn't match! Got: " << rhs.restricted
+                << " , expected : " << lhs.restricted);
+
+    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 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);
+    BOOST_REQUIRE_NO_THROW(db.deleteDBRow("alias", "label"));
+
+    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");
+}
+
+BOOST_AUTO_TEST_SUITE(DBCRYPTO_TEST)
+BOOST_AUTO_TEST_CASE(DBtestSimple) {
+
+    BOOST_CHECK(unlink(crypto_db) == 0 || errno == ENOENT);
+    DBCrypto db;
+    BOOST_REQUIRE_NO_THROW(db = DBCrypto(crypto_db, defaultPass));
+
+    DBRow rowPattern = createDefaultRow();
+    rowPattern.data = RawBuffer(32, 1);
+    rowPattern.dataSize = rowPattern.data.size();
+
+    checkDBIntegrity(rowPattern, db);
+}
+BOOST_AUTO_TEST_CASE(DBtestBIG) {
+    BOOST_CHECK(unlink(crypto_db) == 0 || errno == ENOENT);
+    DBCrypto db;
+    BOOST_REQUIRE_NO_THROW(db = DBCrypto(crypto_db, defaultPass));
+
+    DBRow rowPattern = createDefaultRow();
+    rowPattern.data = createBigBlob(4096);
+    rowPattern.dataSize = rowPattern.data.size();
+
+    checkDBIntegrity(rowPattern, db);
+}
+BOOST_AUTO_TEST_CASE(DBtestGlobal) {
+    BOOST_CHECK(unlink(crypto_db) == 0 || errno == ENOENT);
+    DBCrypto db;
+    BOOST_REQUIRE_NO_THROW(db = DBCrypto(crypto_db, defaultPass));
+
+    DBRow rowPattern = createDefaultRow(restricted_global);
+    rowPattern.data = RawBuffer(1024, 2);
+    rowPattern.dataSize = rowPattern.data.size();
+
+    BOOST_REQUIRE_NO_THROW(db.saveDBRow(rowPattern));
+
+    DBRow alias_duplicate = rowPattern;
+    rowPattern.smackLabel = rowPattern.smackLabel + "1";
+
+    BOOST_REQUIRE_THROW(db.saveDBRow(alias_duplicate),
+            DBCrypto::Exception::AliasExists);
+}
+BOOST_AUTO_TEST_CASE(DBtestTransaction) {
+    BOOST_CHECK(unlink(crypto_db) == 0 || errno == ENOENT);
+    DBCrypto db;
+    BOOST_REQUIRE_NO_THROW(db = DBCrypto(crypto_db, defaultPass));
+
+    DBRow rowPattern = createDefaultRow(0);
+    rowPattern.data = RawBuffer(100, 20);
+    rowPattern.dataSize = rowPattern.data.size();
+    DBCrypto::Transaction transaction(&db);
+
+    BOOST_REQUIRE_NO_THROW(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,
+            DBDataType::BINARY_DATA));
+    BOOST_CHECK_MESSAGE(!row_optional, "Row still present after rollback");
+
+}
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/test_sql.cpp b/tests/test_sql.cpp
new file mode 100644 (file)
index 0000000..984504c
--- /dev/null
@@ -0,0 +1,133 @@
+#include <dpl/db/sql_connection.h>
+#include <boost/test/unit_test.hpp>
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <assert.h>
+#include <sqlcipher.h>
+#include <ckm/ckm-type.h>
+#include <errno.h>
+
+#include <test_common.h>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wdeprecated-declarations"
+
+
+const char *encrypt_me = "/tmp/encryptme.db";
+const char *encrypt_me_not = "/tmp/encryptmenot.db";
+
+const char *create_table = "CREATE TABLE t1(a,b);";
+const char *insert_table = "INSERT INTO t1(a,b) VALUES ("
+                                       " 'one for the money',"
+                                       " 'two for the show');";
+const char *select_table = "SELECT * FROM t1";
+
+CKM::RawBuffer raw_password = createDefaultPass();
+
+BOOST_AUTO_TEST_SUITE(SQL_TEST)
+BOOST_AUTO_TEST_CASE(sqlTestConversion){
+
+    BOOST_REQUIRE_MESSAGE(raw_password.size() == RAW_PASS_SIZE,
+            "Password should have 32 characters, got: " << raw_password.size());
+    std::string pass_check = rawToHexString(raw_password);
+    BOOST_REQUIRE_MESSAGE(pass_check.length() == HEX_PASS_SIZE,
+            "Hex string should have 64 characters, got: " << pass_check.length());
+    BOOST_CHECK(pass_check == pattern);
+}
+
+BOOST_AUTO_TEST_CASE(sqlTestSetKeyTooShort) {
+    using namespace CKM::DB;
+    BOOST_CHECK(unlink(encrypt_me_not) == 0 || errno == ENOENT);
+    SqlConnection connection(encrypt_me_not,
+                               SqlConnection::Flag::CRW);
+    CKM::RawBuffer wrong_key(RAW_PASS_SIZE - 1, 1);
+    BOOST_REQUIRE_THROW(connection.SetKey(wrong_key),
+            SqlConnection::Exception::InvalidArguments);
+}
+
+BOOST_AUTO_TEST_CASE(sqlTestSetKeyTooLong) {
+    using namespace CKM::DB;
+    BOOST_CHECK(unlink(encrypt_me_not) == 0 || errno == ENOENT);
+    SqlConnection connection(encrypt_me_not,
+                               SqlConnection::Flag::CRW);
+    CKM::RawBuffer wrong_key(RAW_PASS_SIZE + 1, 1);
+    BOOST_REQUIRE_THROW(connection.SetKey(wrong_key),
+            SqlConnection::Exception::InvalidArguments);
+}
+
+BOOST_AUTO_TEST_CASE(sqlTestConnectionUnencrypted) {
+    using namespace CKM::DB;
+    BOOST_CHECK(unlink(encrypt_me_not) == 0 || errno == ENOENT);
+    {
+        SqlConnection encrypting_you_not(encrypt_me_not,
+                                     SqlConnection::Flag::CRW);
+        BOOST_REQUIRE_NO_THROW(encrypting_you_not.ExecCommand(create_table));
+        BOOST_REQUIRE_NO_THROW(encrypting_you_not.ExecCommand(insert_table));
+    }
+    {
+        SqlConnection encrypting_you_not(encrypt_me_not,
+                                     SqlConnection::Flag::RW);
+        SqlConnection::DataCommandUniquePtr selectCommand;
+        BOOST_REQUIRE_NO_THROW(selectCommand = encrypting_you_not.
+            PrepareDataCommand(select_table));
+        BOOST_REQUIRE_NO_THROW(selectCommand->Step());
+        std::string value;
+        BOOST_REQUIRE_NO_THROW(value = selectCommand->GetColumnString(0));
+        BOOST_REQUIRE(value == "one for the money");
+    }
+}
+
+BOOST_AUTO_TEST_CASE(sqlTestConnectionEncrypted) {
+    using namespace CKM::DB;
+    BOOST_CHECK(unlink(encrypt_me) == 0 || errno == ENOENT);
+    {
+        SqlConnection encrypting_you(encrypt_me,
+                                     SqlConnection::Flag::CRW);
+        BOOST_REQUIRE_NO_THROW(encrypting_you.SetKey(raw_password));
+        BOOST_REQUIRE_NO_THROW(encrypting_you.ExecCommand(create_table));
+        BOOST_REQUIRE_NO_THROW(encrypting_you.ExecCommand(insert_table));
+    }
+    {
+        SqlConnection encrypting_you(encrypt_me,
+                                     SqlConnection::Flag::RW);
+        encrypting_you.SetKey(raw_password);
+        SqlConnection::DataCommandUniquePtr selectCommand;
+        BOOST_REQUIRE_NO_THROW(selectCommand = encrypting_you.
+            PrepareDataCommand(select_table));
+        BOOST_REQUIRE_NO_THROW(selectCommand->Step());
+        std::string value;
+        BOOST_REQUIRE_NO_THROW(value = selectCommand->GetColumnString(0));
+        BOOST_REQUIRE(value == "one for the money");
+    }
+}
+
+BOOST_AUTO_TEST_CASE(sqlTestConnectionEncryptedNegative) {
+
+    using namespace CKM::DB;
+    BOOST_CHECK(unlink(encrypt_me) == 0 || errno == ENOENT);
+    {
+        SqlConnection encrypting_you(encrypt_me,
+                                     SqlConnection::Flag::CRW);
+        BOOST_REQUIRE_NO_THROW(encrypting_you.SetKey(raw_password));
+        BOOST_REQUIRE_NO_THROW(encrypting_you.ExecCommand(create_table));
+        BOOST_REQUIRE_NO_THROW(encrypting_you.ExecCommand(insert_table));
+    }
+    {
+        SqlConnection encrypting_you(encrypt_me,
+                                     SqlConnection::Flag::RW);
+        CKM::RawBuffer wrong_password;
+        for(std::size_t i = 0; i < RAW_PASS_SIZE; i++) {
+            wrong_password.push_back(raw_password[i] + 1);
+        }
+        BOOST_REQUIRE_NO_THROW(encrypting_you.SetKey(wrong_password));
+
+        SqlConnection::DataCommandUniquePtr selectCommand;
+        BOOST_REQUIRE_THROW(selectCommand = encrypting_you.PrepareDataCommand(select_table),
+                SqlConnection::Exception::SyntaxError)
+    }
+}
+BOOST_AUTO_TEST_SUITE_END()
+#pragma GCC diagnostic pop