add db module 41/66341/1
authorDongsun Lee <ds73.lee@samsung.com>
Fri, 25 Mar 2016 11:04:15 +0000 (20:04 +0900)
committerKyungwook Tak <k.tak@samsung.com>
Mon, 18 Apr 2016 11:11:59 +0000 (20:11 +0900)
Change-Id: I55fc9a7a405d61d24c66368fdec4dc1c8b418c4d
Signed-off-by: Dongsun Lee <ds73.lee@samsung.com>
15 files changed:
CMakeLists.txt
data/scripts/create_schema.sql [new file with mode: 0644]
data/scripts/drop_all.sql [new file with mode: 0644]
packaging/csr-framework.spec
src/CMakeLists.txt
src/framework/database/column.cpp [new file with mode: 0644]
src/framework/database/column.h [new file with mode: 0644]
src/framework/database/connection.cpp [new file with mode: 0644]
src/framework/database/connection.h [new file with mode: 0644]
src/framework/database/csr_db.cpp [new file with mode: 0644]
src/framework/database/csr_db.h [new file with mode: 0644]
src/framework/database/statement.cpp [new file with mode: 0644]
src/framework/database/statement.h [new file with mode: 0644]
test/CMakeLists.txt
test/test-internal-database.cpp [new file with mode: 0644]

index c4fffd6..73f44d0 100644 (file)
@@ -39,6 +39,8 @@ STRING(REGEX MATCH "([^.]*)" API_VERSION "${VERSION}")
 ADD_DEFINITIONS("-DSERVICE_NAME=\"${SERVICE_NAME}\"")
 ADD_DEFINITIONS("-DINCLUDE_INSTALL_DIR=\"${INCLUDE_INSTALL_DIR}\"")
 ADD_DEFINITIONS("-DBIN_DIR=\"${BIN_DIR}\"")
+ADD_DEFINITIONS("-DRO_DBSPACE=\"${RO_DBSPACE}\"")
+ADD_DEFINITIONS("-DRW_DBSPACE=\"${RW_DBSPACE}\"")
 ADD_DEFINITIONS("-DSAMPLE_ENGINE_WORKING_DIR=\"${SAMPLE_ENGINE_WORKING_DIR}\"")
 ADD_DEFINITIONS("-DTEST_DIR=\"${TEST_DIR}\"")
 
diff --git a/data/scripts/create_schema.sql b/data/scripts/create_schema.sql
new file mode 100644 (file)
index 0000000..9edf76d
--- /dev/null
@@ -0,0 +1,17 @@
+CREATE TABLE IF NOT EXISTS SCHEMA_INFO(name TEXT PRIMARY KEY NOT NULL,
+                                       value TEXT);
+
+CREATE TABLE IF NOT EXISTS SCAN_REQUEST(dir TEXT PRIMARY KEY,
+                                        last_scan INTEGER NOT NULL,
+                                        data_version TEXT NOT NULL);
+
+CREATE TABLE IF NOT EXISTS DETECTED_MALWARE_FILE(path TEXT PRIMARY KEY NOT NULL,
+                                                 data_version TEXT NOT NULL,
+                                                 severity_level INTEGER NOT NULL,
+                                                 threat_type INTEGER NOT NULL,
+                                                 malware_name TEXT NOT NULL,
+                                                 detailed_url TEXT,
+                                                 detected_time INTEGER NOT NULL,
+                                                 modified_time INTEGER NOT NULL,
+                                                 ignored INTEGER NOT NULL);
+
diff --git a/data/scripts/drop_all.sql b/data/scripts/drop_all.sql
new file mode 100644 (file)
index 0000000..9af2f06
--- /dev/null
@@ -0,0 +1,5 @@
+DROP TABLE IF EXISTS DETECTED_MALWARE_FILE;
+
+DROP TABLE IF EXISTS SCAN_REQUEST;
+
+DROP TABLE IF EXISTS SCHEMA_INFO;
index 92e38dc..06a19bf 100644 (file)
@@ -11,6 +11,7 @@ BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(libsystemd-daemon)
 BuildRequires: pkgconfig(vconf)
 BuildRequires: pkgconfig(elementary)
+BuildRequires: pkgconfig(sqlite3)
 Requires:      lib%{name}-common = %{version}-%{release}
 %{?systemd_requires}
 
@@ -22,6 +23,8 @@ file contents and checking url to prevent malicious items.
 %global bin_dir                   %{_bindir}
 %global sbin_dir                  /sbin
 %global ro_data_dir               %{_datadir}
+%global ro_db_dir                 %{_datadir}/%{service_name}/dbspace
+%global rw_db_dir                 /opt/share//%{service_name}/dbspace
 %global sample_engine_working_dir /opt/share/%{service_name}/engine
 %global sample_engine_dir         %{_libdir}
 %global test_dir                  /opt/share/%{service_name}-test
@@ -82,6 +85,8 @@ test program of csr-framework
     -DBIN_DIR:PATH=%{bin_dir} \
     -DSYSTEMD_UNIT_DIR=%{_unitdir} \
     -DSYSTEMD_UNIT_USER_DIR=%{_unitdir_user} \
+    -DRO_DBSPACE:PATH=%{ro_db_dir} \
+    -DRW_DBSPACE:PATH=%{rw_db_dir} \
     -DSAMPLE_ENGINE_WORKING_DIR:PATH=%{sample_engine_working_dir} \
     -DSAMPLE_ENGINE_DIR:PATH=%{sample_engine_dir} \
     -DTEST_DIR:PATH=%{test_dir}
@@ -108,6 +113,10 @@ cp LICENSE %{buildroot}%{ro_data_dir}/license/lib%{name}-common
 cp LICENSE %{buildroot}%{ro_data_dir}/license/%{name}-test
 cp LICENSE.BSL-1.0 %{buildroot}%{ro_data_dir}/license/%{name}-test.BSL-1.0
 
+mkdir -p %{buildroot}%{ro_db_dir}
+mkdir -p %{buildroot}%{rw_db_dir}
+cp data/scripts/*.sql %{buildroot}%{ro_db_dir}
+
 %post
 systemctl daemon-reload
 if [ $1 = 1 ]; then
@@ -155,6 +164,8 @@ fi
 %{_unitdir}/sockets.target.wants/%{service_name}-popup.socket
 %{_unitdir}/%{service_name}-popup.socket
 
+%attr(444, system, system) %{ro_db_dir}/*.sql
+
 # sample engine related files
 %{sample_engine_dir}/lib%{service_name}-cs-engine.so
 %{sample_engine_dir}/lib%{service_name}-wp-engine.so
index 4cce495..95d1e95 100644 (file)
@@ -21,6 +21,7 @@
 PKG_CHECK_MODULES(${TARGET_CSR_SERVER}_DEP
        REQUIRED
        libsystemd-daemon
+       sqlite3
 )
 
 SET(${TARGET_CSR_SERVER}_SRCS
@@ -32,6 +33,10 @@ SET(${TARGET_CSR_SERVER}_SRCS
        # question and response codes needed on both of
        # csr-server and popup-backend service
        framework/ui/common.cpp
+       framework/database/column.cpp
+       framework/database/connection.cpp
+       framework/database/statement.cpp
+       framework/database/csr_db.cpp
 )
 
 INCLUDE_DIRECTORIES(
diff --git a/src/framework/database/column.cpp b/src/framework/database/column.cpp
new file mode 100644 (file)
index 0000000..58e0d89
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include <string>
+
+#include "database/column.h"
+
+namespace Csr {
+
+namespace Database {
+
+Column::Column(const Statement &stmt, int idx)
+       : statement(stmt.get()),
+         index(idx)
+{
+}
+
+Column::~Column() noexcept {
+}
+
+std::string Column::getName() const
+{
+       return sqlite3_column_name(statement, index);
+}
+
+int Column::getInt() const
+{
+       return sqlite3_column_int(statement, index);
+}
+
+sqlite3_int64 Column::getInt64() const
+{
+       return sqlite3_column_int64(statement, index);
+}
+
+double Column::getDouble() const
+{
+       return sqlite3_column_double(statement, index);
+}
+
+const char *Column::getText() const
+{
+       return reinterpret_cast<const char *>(sqlite3_column_text(statement, index));
+}
+
+const void *Column::getBlob() const
+{
+       return sqlite3_column_blob(statement, index);
+}
+
+int Column::getType() const
+{
+       return sqlite3_column_type(statement, index);
+}
+
+int Column::getBytes() const
+{
+       return sqlite3_column_bytes(statement, index);
+}
+
+} // namespace Database
+
+} // namespace Csr
diff --git a/src/framework/database/column.h b/src/framework/database/column.h
new file mode 100644 (file)
index 0000000..be93ed5
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#ifndef __COLUMN__
+#define __COLUMN__
+
+#include <string>
+
+#include <sqlite3.h>
+
+#include "database/statement.h"
+
+namespace Csr {
+
+namespace Database {
+
+class Column {
+public:
+       Column(const Statement &stmt, int idx);
+       virtual ~Column() noexcept;
+
+       std::string getName() const;
+       sqlite3_int64 getInt64() const;
+       const char *getText() const;
+       double getDouble() const;
+       const void *getBlob() const;
+       int getInt() const;
+       int getType() const;
+       int getBytes() const;
+
+       inline int size() const {
+               return getBytes();
+       }
+
+       inline operator int() const {
+               return getInt();
+       }
+
+       inline operator sqlite3_int64() const {
+               return getInt64();
+       }
+
+       inline operator double() const {
+               return getDouble();
+       }
+
+       inline operator const char *() const {
+               return getText();
+       }
+
+       inline operator const void *() const {
+               return getBlob();
+       }
+
+private:
+       sqlite3_stmt *statement;
+       int index;
+};
+
+} // namespace Database
+
+} // namespace Csr
+#endif //__COLUMN__
diff --git a/src/framework/database/connection.cpp b/src/framework/database/connection.cpp
new file mode 100644 (file)
index 0000000..ad45944
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include <iostream>
+#include <stdexcept>
+
+
+#include "database/connection.h"
+
+namespace Csr {
+
+namespace Database {
+
+Connection::Connection(const std::string &name, const int flags)
+       : handle(nullptr),
+         filename(name)
+{
+       if (::sqlite3_open_v2(filename.c_str(), &handle, flags, NULL)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+Connection::~Connection()
+{
+       sqlite3_close(handle);
+}
+
+int Connection::exec(const std::string &query)
+{
+       if (::sqlite3_exec(handle, query.c_str(), NULL, NULL, NULL) != SQLITE_OK) {
+               throw std::runtime_error(getErrorMessage());
+       }
+
+       return sqlite3_changes(handle);
+}
+
+} // namespace Database
+
+} // namespace Csr
diff --git a/src/framework/database/connection.h b/src/framework/database/connection.h
new file mode 100644 (file)
index 0000000..45e6d8c
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#ifndef __DB_CONNECTION__
+#define __DB_CONNECTION__
+
+#include <string>
+
+#include <sqlite3.h>
+
+namespace Csr {
+
+namespace Database {
+
+class Connection {
+public:
+       enum Mode {
+               Create = SQLITE_OPEN_CREATE,
+               ReadWrite = SQLITE_OPEN_READWRITE
+       };
+
+       Connection(const std::string &name, const int flags);
+       virtual ~Connection();
+
+       int exec(const std::string &query);
+
+       inline long long getLastInsertRowId() const noexcept {
+               return sqlite3_last_insert_rowid(handle);
+       }
+
+       inline const std::string &getName() const noexcept {
+               return filename;
+       }
+
+       inline int getErrorCode() const {
+               return sqlite3_errcode(handle);
+       }
+
+       inline int getExtendedErrorCode() const {
+               return sqlite3_extended_errcode(handle);
+       }
+
+       inline std::string getErrorMessage() const {
+               return sqlite3_errmsg(handle);
+       }
+
+       inline sqlite3 *get() const noexcept {
+               return handle;
+       }
+
+private:
+       sqlite3 *handle;
+       std::string filename;
+};
+
+} // namespace Database
+
+} // namespace Csr
+#endif //__DB_CONNECTION__
diff --git a/src/framework/database/csr_db.cpp b/src/framework/database/csr_db.cpp
new file mode 100644 (file)
index 0000000..0a742f2
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include <fstream>
+#include <iostream>
+#include <stdexcept>
+
+#include "database/csr_db.h"
+#include "database/connection.h"
+#include "database/statement.h"
+#include "database/column.h"
+
+namespace Csr {
+
+namespace Database {
+
+enum DBVersion : int {
+       DB_VERSION_1                   = 1,
+       DB_VERSION_CURRENT             = 1
+};
+
+const char *SCRIPT_CREATE_SCHEMA                = "create_schema";
+const char *SCRIPT_DROP_ALL_ITEMS               = "drop_all";
+const char *SCRIPT_MIGRATE                      = "migrate_";
+
+const std::string DB_VERSION_STR = "DB_VERSION";
+
+//===========================================================================
+// Queries
+//===========================================================================
+
+const std::string QUERY_SEL_SCHEMA_INFO =
+       "select value from SCHEMA_INFO where name = ?";
+
+const std::string QUERY_INS_SCHEMA_INFO =
+       "insert or replace into SCHEMA_INFO (name, value) values (?, ?)";
+
+
+const std::string QUERY_SEL_SCAN_REQUEST =
+       "select dir, last_scan from SCAN_REQUEST where dir = ? and data_version = ?";
+
+const std::string QUERY_INS_SCAN_REQUEST =
+       "insert or replace into SCAN_REQUEST (dir, last_scan, data_version) "
+       "values (?, ?, ?)";
+
+const std::string QUERY_DEL_SCAN_REQUEST_BY_DIR =
+       "delete from SCAN_REQUEST where dir = ?";
+
+const std::string QUERY_DEL_SCAN_REQUEST =
+       "delete from SCAN_REQUEST ";
+
+
+const std::string QUERY_SEL_DETECTED_BY_DIR =
+       "SELECT path, data_version, "
+       " severity_level, threat_type, malware_name, "
+       " detailed_url, detected_time, modified_time, ignored "
+       " FROM detected_malware_file where path like ? || '%' ";
+
+const std::string QUERY_SEL_DETECTED_BY_PATH =
+       "SELECT path, data_version, "
+       " severity_level, threat_type, malware_name, "
+       " detailed_url, detected_time, modified_time, ignored "
+       " FROM detected_malware_file where path = ? ";
+
+const std::string QUERY_INS_DETECTED =
+       "insert or replace into DETECTED_MALWARE_FILE "
+       " (path, data_version, severity_level, threat_type, malware_name, "
+       " detailed_url, detected_time, modified_time, ignored) "
+       " values (?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+const std::string QUERY_UPD_DETECTED_INGNORED =
+       "update DETECTED_MALWARE_FILE set ignored = ? where path = ?";
+
+const std::string QUERY_DEL_DETECTED_BY_PATH =
+       "delete from DETECTED_MALWARE_FILE where path = ?";
+
+const std::string QUERY_DEL_DETECTED_DEPRECATED =
+       "delete from DETECTED_MALWARE_FILE where path like ? || '%' "
+       " and data_version != ?";
+
+
+//===========================================================================
+// Constructor
+//===========================================================================
+
+CsrDB::CsrDB(const std::string &dbfile, const std::string &scriptsDirectory)
+       : conn(dbfile, Connection::Create | Connection::ReadWrite), scriptsDir(scriptsDirectory)
+{
+       initDatabase();
+       conn.exec("VACUUM;");
+}
+
+CsrDB::~CsrDB()
+{
+}
+
+//===========================================================================
+// SCHEMA_INFO table
+//===========================================================================
+
+
+bool CsrDB::initDatabase() noexcept {
+       // run migration if old database is present
+       int schemaVersion;
+       if ((schemaVersion = getDbVersion()) <= 0  || schemaVersion > DB_VERSION_CURRENT) {
+               // DB empty or corrupted or too new scheme
+               // LogDebug("no database or database corrupted, initializing the DB");
+               resetDatabase();
+       } else if (schemaVersion < DB_VERSION_CURRENT) {
+               // migration needed
+               //LogDebug("DB migration from version " << schemaVersion << " to version " << DB_VERSION_CURRENT << " started.");
+               for (int vi = schemaVersion; vi < DB_VERSION_CURRENT; vi++) {
+                       std::string script = getMigrationScript(vi);
+                       if (script.size() <= 0) {
+                               //LogWarn("script to migrate database from version: " << vi <<
+                               //              " to version: " << vi+1 << " not available, resetting the DB");
+                               resetDatabase();
+                               break;
+                       }
+
+                       //LogInfo("migrating from version " << vi << " to version " << vi+1);
+                       if (!conn.exec(script.c_str())) {
+                               //LogWarn("Error, migration database from version: " << vi <<
+                               //              " to version: " << vi+1 << " failed, resetting the DB");
+                               resetDatabase();
+                               break;
+                       }
+               }
+               // update DB version info
+               if (!setDbVersion(DB_VERSION_CURRENT)) {
+                       //LogWarn("setting db version failed. version=: " << DB_VERSION_CURRENT <<", resetting the DB");
+                       resetDatabase();
+               }
+       }
+
+       return true;
+}
+
+bool CsrDB::createSchema() noexcept {
+       try {
+               std::string script = getScript(SCRIPT_CREATE_SCHEMA);
+               if (script.size() <= 0) {
+                       std::string errmsg = "Can not create the database schema: no initialization script";
+                       throw std::runtime_error(errmsg);
+               }
+               return conn.exec(script.c_str());
+       } catch (std::exception &e) {
+               //LogWarn("createSchema failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+bool CsrDB::resetDatabase() noexcept {
+       try {
+               std::string script = getScript(SCRIPT_DROP_ALL_ITEMS);
+               if (script.size() <= 0) {
+                       std::string errmsg = "Can not clear the database: no clearing script";
+                       throw std::runtime_error(errmsg);
+               }
+               conn.exec(script.c_str());
+               return createSchema();
+       } catch (std::exception &e) {
+               //LogWarn("resetDatabase failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+std::string CsrDB::getMigrationScript(int dbVersion)
+{
+       std::string scriptPath = std::string(SCRIPT_MIGRATE) + std::to_string(dbVersion);
+       return getScript(scriptPath);
+}
+
+std::string CsrDB::getScript(std::string scriptName)
+{
+       std::string scriptPath = scriptsDir + std::string("/") + scriptName + std::string(".sql");
+       std::ifstream is(scriptPath);
+       if (is.fail()) {
+               return std::string();
+       }
+       std::istreambuf_iterator<char> begin(is), end;
+       return std::string(begin, end);
+}
+
+int CsrDB::getDbVersion() noexcept {
+       try{
+               Statement stmt(conn, QUERY_SEL_SCHEMA_INFO);
+
+               int idx = 0;
+               stmt.bind(++idx, DB_VERSION_STR);
+
+               if (!stmt.step())
+                       return -1;
+
+               return stmt.getColumn(0).getInt();
+       } catch (std::exception &e) {
+               //LogWarn("getDbVersion failed.error_msg=" << e.what());
+               return -1;
+       }
+}
+
+bool CsrDB::setDbVersion(int version) noexcept {
+       try {
+               Statement stmt(conn, QUERY_INS_SCHEMA_INFO);
+
+               int idx = 0;
+               stmt.bind(++idx, DB_VERSION_STR);
+               stmt.bind(++idx, version);
+               return stmt.exec();
+       } catch (std::exception &e) {
+               //LogWarn("setDbVersion failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+//===========================================================================
+// SCAN_REQUEST table
+//===========================================================================
+
+long CsrDB::getLastScanTime(const std::string &dir, const std::string &dataVersion) noexcept {
+       try{
+               Statement stmt(conn, QUERY_SEL_SCAN_REQUEST);
+
+               int idx = 0;
+               stmt.bind(++idx, dir);
+               stmt.bind(++idx, dataVersion);
+
+               if (!stmt.step())
+                       return -1;
+
+               return static_cast<long>(stmt.getColumn(1).getInt64());
+       } catch (std::exception &e) {
+               //LogWarn("getLastScanTime failed.error_msg=" << e.what());
+               return -1;
+       }
+}
+
+bool CsrDB::insertLastScanTime(const std::string &dir, long scanTime, const std::string &dataVersion) noexcept {
+       try {
+               Statement stmt(conn, QUERY_INS_SCAN_REQUEST);
+
+               int idx = 0;
+               stmt.bind(++idx, dir);
+               stmt.bind(++idx, static_cast<sqlite3_int64>(scanTime));
+               stmt.bind(++idx, dataVersion);
+               return stmt.exec();
+       } catch (std::exception &e) {
+               //LogWarn("insertLastScanTime failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+bool CsrDB::deleteLastScanTime(const std::string &dir) noexcept {
+       try {
+               Statement stmt(conn, QUERY_DEL_SCAN_REQUEST_BY_DIR);
+
+               int idx = 0;
+               stmt.bind(++idx, dir);
+               stmt.exec();
+               return true; // even if no rows are deleted
+       } catch (std::exception &e) {
+               //LogWarn("deleteLastScanTime failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+bool CsrDB::cleanLastScanTime() noexcept {
+       try {
+               Statement stmt(conn, QUERY_DEL_SCAN_REQUEST);
+               stmt.exec();
+               return true; // even if no rows are deleted
+       } catch (std::exception &e) {
+               //LogWarn("cleanLastScanTime failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+//===========================================================================
+// DETECTED_MALWARE_FILE table
+//===========================================================================
+DetectedListShrPtr CsrDB::getDetectedMalwares(const std::string &dir) noexcept {
+       DetectedListShrPtr detectedList = std::make_shared<std::vector<DetectedShrPtr>>();
+
+       try {
+               Statement stmt(conn, QUERY_SEL_DETECTED_BY_DIR);
+
+               int idx = 0;
+               stmt.bind(++idx, dir);
+
+               while (stmt.step()) {
+                       DetectedShrPtr detected = std::make_shared<RowDetected>();
+                       idx = -1;
+                       detected->path = std::string(stmt.getColumn(++idx).getText());
+                       detected->dataVersion = std::string(stmt.getColumn(++idx).getText());
+                       detected->severityLevel = stmt.getColumn(++idx).getInt();
+                       detected->threatType = stmt.getColumn(++idx).getInt();
+                       detected->name = std::string(stmt.getColumn(++idx).getText());
+                       detected->detailedUrl = std::string(stmt.getColumn(++idx).getText());
+                       detected->detected_time = static_cast<long>(stmt.getColumn(++idx).getInt64());
+                       detected->modified_time = static_cast<long>(stmt.getColumn(++idx).getInt64());
+                       detected->ignored = stmt.getColumn(++idx).getInt();
+
+                       detectedList->push_back(detected);
+               }
+       } catch (std::exception &e) {
+               //LogWarn("getDetectedMalwares failed.error_msg=" << e.what());
+       }
+       return detectedList;
+}
+
+DetectedShrPtr CsrDB::getDetectedMalware(const std::string &path) noexcept {
+       DetectedShrPtr detected = std::make_shared<RowDetected>();
+
+       try {
+               Statement stmt(conn, QUERY_SEL_DETECTED_BY_PATH);
+
+               int idx = 0;
+               stmt.bind(++idx, path);
+
+               if (!stmt.step())
+                       return nullptr;
+
+               idx = -1;
+               detected->path = std::string(stmt.getColumn(++idx).getText());
+               detected->dataVersion = std::string(stmt.getColumn(++idx).getText());
+               detected->severityLevel = stmt.getColumn(++idx).getInt();
+               detected->threatType = stmt.getColumn(++idx).getInt();
+               detected->name = std::string(stmt.getColumn(++idx).getText());
+               detected->detailedUrl = std::string(stmt.getColumn(++idx).getText());
+               detected->detected_time = static_cast<long>(stmt.getColumn(++idx).getInt64());
+               detected->modified_time = static_cast<long>(stmt.getColumn(++idx).getInt64());
+               detected->ignored = stmt.getColumn(++idx).getInt();
+
+       } catch (std::exception &e) {
+               //LogWarn("getDetectedMalware failed.error_msg=" << e.what());
+               return nullptr;
+       }
+       return detected;
+}
+
+bool CsrDB::insertDetectedMalware(const RowDetected &malware) noexcept {
+       try {
+               Statement stmt(conn, QUERY_INS_DETECTED);
+
+               int idx = 0;
+               stmt.bind(++idx, malware.path);
+               stmt.bind(++idx, malware.dataVersion);
+               stmt.bind(++idx, malware.severityLevel);
+               stmt.bind(++idx, malware.threatType);
+               stmt.bind(++idx, malware.name);
+               stmt.bind(++idx, malware.detailedUrl);
+               stmt.bind(++idx, static_cast<sqlite3_int64>(malware.detected_time));
+               stmt.bind(++idx, static_cast<sqlite3_int64>(malware.modified_time));
+               stmt.bind(++idx, malware.ignored);
+
+               return stmt.exec();
+       } catch (std::exception &e) {
+               //LogWarn("insertDetectedMalware failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+bool CsrDB::setDetectedMalwareIgnored(const std::string &path, int ignored) noexcept {
+       try {
+               Statement stmt(conn, QUERY_UPD_DETECTED_INGNORED);
+
+               int idx = 0;
+               stmt.bind(++idx, ignored);
+               stmt.bind(++idx, path);
+
+               return stmt.exec();
+       } catch (std::exception &e) {
+               //LogWarn("setDetectedMalwareIgnored failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+bool CsrDB::deleteDetecedMalware(const std::string &path) noexcept {
+       try {
+               Statement stmt(conn, QUERY_DEL_DETECTED_BY_PATH);
+
+               int idx = 0;
+               stmt.bind(++idx, path);
+               stmt.exec();
+               return true; // even if no rows are deleted
+       } catch (std::exception &e) {
+               //LogWarn("deleteDetecedMalware failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+bool CsrDB::deleteDeprecatedDetecedMalwares(const std::string &dir, const std::string &dataVersion) noexcept {
+       try {
+               Statement stmt(conn, QUERY_DEL_DETECTED_DEPRECATED);
+
+               int idx = 0;
+               stmt.bind(++idx, dir);
+               stmt.bind(++idx, dataVersion);
+               stmt.exec();
+               return true; // even if no rows are deleted
+       } catch (std::exception &e) {
+               //LogWarn("deleteDeprecatedDetecedMalwares failed.error_msg=" << e.what());
+               return false;
+       }
+}
+
+
+}// namespace Database
+
+}// namespace Csr
diff --git a/src/framework/database/csr_db.h b/src/framework/database/csr_db.h
new file mode 100644 (file)
index 0000000..7a3a412
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#ifndef CONTENT_SCANNING_DB_HXX_
+#define CONTENT_SCANNING_DB_HXX_
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include "database/connection.h"
+
+namespace Csr {
+
+namespace Database {
+
+struct RowDetected {
+       std::string path;
+       std::string dataVersion; // engine's data version
+       int severityLevel;
+       int threatType;
+       std::string name;
+       std::string detailedUrl;
+       long detected_time;
+       long modified_time;
+       int ignored;
+
+       RowDetected() : path(""), dataVersion(""),
+               severityLevel(-1), threatType(-1),
+               name(""), detailedUrl(""), detected_time(-1),
+               modified_time(-1), ignored(-1) {};
+       ~RowDetected() {};
+};
+
+typedef std::shared_ptr<RowDetected> DetectedShrPtr;
+typedef std::shared_ptr<std::vector<DetectedShrPtr>> DetectedListShrPtr;
+
+class CsrDB {
+public:
+       CsrDB(const std::string &dbfile, const std::string &scriptsDir);
+       virtual ~CsrDB();
+
+       // SCHEMA_INFO
+       bool initDatabase()  noexcept;
+       bool createSchema()  noexcept;
+       bool resetDatabase() noexcept;
+       std::string getMigrationScript(int dbVersion);
+       std::string getScript(std::string scriptName);
+       int getDbVersion() noexcept;
+       bool setDbVersion(int version) noexcept;
+
+       // SCAN_REQUEST
+       long getLastScanTime(const std::string &dir, const std::string &dataVersion)  noexcept;
+       bool insertLastScanTime(const std::string &dir, long scanTime, const std::string &dataVersion)  noexcept;
+       bool deleteLastScanTime(const std::string &dir)  noexcept;
+       bool cleanLastScanTime()  noexcept;
+
+       // DETECTED_MALWARE_FILE & USER_RESPONSE
+       DetectedListShrPtr getDetectedMalwares(const std::string &dir)  noexcept;
+       DetectedShrPtr getDetectedMalware(const std::string &path)  noexcept;
+       bool insertDetectedMalware(const RowDetected &malware)  noexcept;
+       bool setDetectedMalwareIgnored(const std::string &path, int userResponse)  noexcept;
+       bool deleteDetecedMalware(const std::string &path) noexcept;
+       bool deleteDeprecatedDetecedMalwares(const std::string &dir, const std::string &dataVersion)  noexcept;
+
+private:
+       Connection conn;
+       std::string scriptsDir;
+};
+
+}// namespace Database
+
+
+}// namespace Csr
+#endif /* CONTENT_SCANNING_DB_HXX_ */
diff --git a/src/framework/database/statement.cpp b/src/framework/database/statement.cpp
new file mode 100644 (file)
index 0000000..68c49eb
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#include <string>
+#include <stdexcept>
+
+#include "database/connection.h"
+#include "database/statement.h"
+#include "database/column.h"
+
+
+namespace Csr {
+
+namespace Database {
+
+Statement::Statement(const Connection &db, const std::string &query)
+       : statement(nullptr),
+         columnCount(0),
+         validRow(false)
+{
+       if (SQLITE_OK != ::sqlite3_prepare_v2(db.get(),
+                                                                                 query.c_str(),
+                                                                                 query.size(),
+                                                                                 &statement,
+                                                                                 NULL)) {
+               throw std::runtime_error(db.getErrorMessage());
+       }
+
+       columnCount = sqlite3_column_count(statement);
+}
+
+Statement::~Statement()
+{
+       if (::sqlite3_finalize(statement) != SQLITE_OK) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::reset()
+{
+       if (::sqlite3_clear_bindings(statement) != SQLITE_OK) {
+               throw std::runtime_error(getErrorMessage());
+       }
+
+       if (::sqlite3_reset(statement) != SQLITE_OK) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::clearBindings()
+{
+       if (::sqlite3_clear_bindings(statement) != SQLITE_OK) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+std::string Statement::getErrorMessage() const
+{
+       return ::sqlite3_errmsg(::sqlite3_db_handle(statement));
+}
+
+std::string Statement::getErrorMessage(int errorCode) const
+{
+       return ::sqlite3_errstr(errorCode);
+}
+
+bool Statement::step()
+{
+       if (SQLITE_ROW == ::sqlite3_step(statement)) {
+               return (validRow = true);
+       }
+
+       return (validRow = false);
+}
+
+int Statement::exec()
+{
+       if (SQLITE_DONE == ::sqlite3_step(statement)) {
+               validRow = false;
+       }
+
+       return sqlite3_changes(sqlite3_db_handle(statement));
+}
+
+Column Statement::getColumn(const int index)
+{
+       if (!validRow || (index >= columnCount)) {
+               throw std::runtime_error(getErrorMessage(SQLITE_RANGE));
+       }
+
+       return Column(*this, index);
+}
+
+bool Statement::isNullColumn(const int index) const
+{
+       if (!validRow || (index >= columnCount)) {
+               throw std::runtime_error(getErrorMessage(SQLITE_RANGE));
+       }
+
+       return (SQLITE_NULL == sqlite3_column_type(statement, index));
+}
+
+std::string Statement::getColumnName(const int index) const
+{
+       if (index >= columnCount) {
+               throw std::runtime_error(getErrorMessage(SQLITE_RANGE));
+       }
+
+       return sqlite3_column_name(statement, index);
+}
+
+
+void Statement::bind(const int index, const int &value)
+{
+       if (SQLITE_OK != ::sqlite3_bind_int(statement, index, value)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const int index, const sqlite3_int64 &value)
+{
+       if (SQLITE_OK != ::sqlite3_bind_int64(statement, index, value)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const int index, const double &value)
+{
+       if (SQLITE_OK != ::sqlite3_bind_double(statement, index, value)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+
+}
+
+void Statement::bind(const int index, const char *value)
+{
+       if (SQLITE_OK != ::sqlite3_bind_text(statement, index, value, -1, SQLITE_TRANSIENT)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const int index, const std::string &value)
+{
+       if (SQLITE_OK != ::sqlite3_bind_text(statement, index, value.c_str(),
+                                                                                static_cast<int>(value.size()), SQLITE_TRANSIENT)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const int index, const void *value, const int size)
+{
+       if (SQLITE_OK != ::sqlite3_bind_blob(statement, index, value, size, SQLITE_TRANSIENT)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const int index)
+{
+       if (SQLITE_OK != ::sqlite3_bind_null(statement, index)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const std::string &name, const int &value)
+{
+       int index = sqlite3_bind_parameter_index(statement, name.c_str());
+       if (SQLITE_OK != sqlite3_bind_int(statement, index, value)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const std::string &name, const sqlite3_int64 &value)
+{
+       int index = sqlite3_bind_parameter_index(statement, name.c_str());
+       if (SQLITE_OK != ::sqlite3_bind_int64(statement, index, value)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const std::string &name, const double &value)
+{
+       int index = sqlite3_bind_parameter_index(statement, name.c_str());
+       if (SQLITE_OK != ::sqlite3_bind_double(statement, index, value)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const std::string &name, const std::string &value)
+{
+       int index = sqlite3_bind_parameter_index(statement, name.c_str());
+       if (SQLITE_OK != ::sqlite3_bind_text(statement, index, value.c_str(),
+                                                                                static_cast<int>(value.size()), SQLITE_TRANSIENT)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const std::string &name, const char *value)
+{
+       int index = sqlite3_bind_parameter_index(statement, name.c_str());
+       if (SQLITE_OK != ::sqlite3_bind_text(statement, index, value, -1, SQLITE_TRANSIENT)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const std::string &name, const void *value, const int size)
+{
+       int index = sqlite3_bind_parameter_index(statement, name.c_str());
+       if (SQLITE_OK != ::sqlite3_bind_blob(statement, index, value, size, SQLITE_TRANSIENT)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+void Statement::bind(const std::string &name)
+{
+       int index = sqlite3_bind_parameter_index(statement, name.c_str());
+       if (SQLITE_OK != ::sqlite3_bind_null(statement, index)) {
+               throw std::runtime_error(getErrorMessage());
+       }
+}
+
+} // namespace Database
+
+} // namespace Csr
diff --git a/src/framework/database/statement.h b/src/framework/database/statement.h
new file mode 100644 (file)
index 0000000..c49c537
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+
+#ifndef __STATEMENT__
+#define __STATEMENT__
+
+#include <string>
+#include <map>
+
+#include <sqlite3.h>
+
+namespace Csr {
+
+namespace Database {
+
+class Column;
+class Connection;
+
+class Statement {
+public:
+       Statement(const Connection &db, const std::string &query);
+       virtual ~Statement();
+
+       int exec();
+       bool step();
+
+       void reset();
+       void clearBindings();
+       std::string getErrorMessage() const;
+       std::string getErrorMessage(int errorCode) const;
+
+       Column getColumn(const int index);
+       std::string getColumnName(const int index) const;
+       bool isNullColumn(const int index) const;
+
+       void bind(const int index, const int &value);
+       void bind(const int index, const sqlite3_int64 &value);
+       void bind(const int index, const double &value);
+       void bind(const int index, const std::string &value);
+       void bind(const int index, const char *value);
+       void bind(const int index, const void *value, const int size);
+       void bind(const int index);
+
+       void bind(const std::string &name, const int &value);
+       void bind(const std::string &name, const sqlite3_int64 &value);
+       void bind(const std::string &name, const double &value);
+       void bind(const std::string &name, const std::string &value);
+       void bind(const std::string &name, const char *value);
+       void bind(const std::string &name, const void *value, const int size);
+       void bind(const std::string &name);
+
+       inline int getColumnCount() const {
+               return columnCount;
+       }
+
+       inline sqlite3_stmt *get() const noexcept {
+               return statement;
+       }
+
+private:
+       typedef std::map<std::string, int> ColumnMap;
+
+       sqlite3_stmt *statement;
+       int columnCount;
+       int validRow;
+       ColumnMap columnNames;
+};
+
+} // namespace Database
+
+} // namespace Csr
+#endif //__STATEMENT__
index bea5d44..aa1f420 100644 (file)
 FIND_PACKAGE(Threads REQUIRED)
 ADD_DEFINITIONS("-DBOOST_TEST_DYN_LINK")
 
+SET(CSR_FW_SRC_PATH ${PROJECT_SOURCE_DIR}/src/framework)
+SET(CSR_FW_DB_SRC_PATH ${CSR_FW_SRC_PATH}/database)
+
 PKG_CHECK_MODULES(${TARGET_CSR_TEST}_DEP
        REQUIRED
+       sqlite3
 )
 
 SET(${TARGET_CSR_TEST}_SRCS
+       ${CSR_FW_DB_SRC_PATH}/column.cpp
+       ${CSR_FW_DB_SRC_PATH}/connection.cpp
+       ${CSR_FW_DB_SRC_PATH}/statement.cpp
+       ${CSR_FW_DB_SRC_PATH}/csr_db.cpp
        colour_log_formatter.cpp
        test-api-content-screening.cpp
        test-api-engine-manager.cpp
        test-api-web-protection.cpp
        test-api-engine-content-screening.cpp
        test-api-engine-web-protection.cpp
+       test-internal-database.cpp
        test-main.cpp
 )
 
 INCLUDE_DIRECTORIES(
        ${PROJECT_SOURCE_DIR}/src/include
+        ${CSR_FW_SRC_PATH}
        ./
        ${${TARGET_CSR_TEST}_DEP_INCLUDE_DIRS}
 )
diff --git a/test/test-internal-database.cpp b/test/test-internal-database.cpp
new file mode 100644 (file)
index 0000000..6e7f8ef
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file        test-internal-database.cpp
+ * @author      Dongsun Lee(ds73.lee@samsung.com)
+ * @version     1.0
+ * @brief       CSR Content screening DB internal test
+ */
+
+#include "database/csr_db.h"
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+#define TEST_DB_FILE     TEST_DIR "/test.db"
+#define TEST_DB_SCRIPTS  RO_DBSPACE
+
+namespace {
+
+inline void checkSameMalware(Csr::Database::RowDetected &malware1, Csr::Database::RowDetected &malware2)
+{
+       BOOST_REQUIRE_MESSAGE(malware1.path.compare(malware2.path) == 0,
+                                                 "Failed. checkSameMalware. path1=" << malware1.path << ", path2=" << malware2.path);
+
+       BOOST_REQUIRE_MESSAGE(malware1.dataVersion.compare(malware2.dataVersion) == 0,
+                                                 "Failed. checkSameMalware. dataVersion1=" << malware1.dataVersion
+                                                 << ", dataVersion2=" << malware2.dataVersion);
+
+       BOOST_REQUIRE_MESSAGE(malware1.severityLevel == malware2.severityLevel,
+                                                 "Failed. checkSameMalware. severityLevel1=" << malware1.severityLevel
+                                                 << ", severityLevel2=" << malware2.severityLevel);
+
+       BOOST_REQUIRE_MESSAGE(malware1.threatType == malware2.threatType,
+                                                 "Failed. checkSameMalware. threatType1=" << malware1.threatType
+                                                 << ", threatType2=" << malware2.threatType);
+
+       BOOST_REQUIRE_MESSAGE(malware1.name.compare(malware2.name) == 0,
+                                                 "Failed. checkSameMalware. name1=" << malware1.name
+                                                 << ", name2=" << malware2.name);
+
+       BOOST_REQUIRE_MESSAGE(malware1.detailedUrl.compare(malware2.detailedUrl) == 0,
+                                                 "Failed. checkSameMalware. detailedUrl1=" << malware1.detailedUrl
+                                                 << ", detailedUrl2=" << malware2.detailedUrl);
+
+       BOOST_REQUIRE_MESSAGE(malware1.detected_time == malware2.detected_time,
+                                                 "Failed. checkSameMalware. detected_time1=" << malware1.detected_time
+                                                 << ", detected_time2=" << malware2.detected_time);
+
+       BOOST_REQUIRE_MESSAGE(malware1.modified_time == malware2.modified_time,
+                                                 "Failed. checkSameMalware. modified_time1=" << malware1.modified_time
+                                                 << ", modified_time2=" << malware2.modified_time);
+
+       BOOST_REQUIRE_MESSAGE(malware1.ignored == malware2.ignored,
+                                                 "Failed. checkSameMalware. ignored1=" << malware1.ignored
+                                                 << ", ignored2=" << malware2.ignored);
+}
+
+} // end of namespace
+
+
+BOOST_AUTO_TEST_SUITE(INTERNAL_DATABASE)
+
+BOOST_AUTO_TEST_CASE(schema_info)
+{
+       bool result;
+       Csr::Database::CsrDB db(TEST_DB_FILE, TEST_DB_SCRIPTS);
+
+       int version = 1;
+       result = db.setDbVersion(version);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. setDbVersion");
+
+       version = db.getDbVersion();
+       BOOST_REQUIRE_MESSAGE(version == 1, "Failed. getDbVersion. expected=1, actual=" << version);
+}
+
+BOOST_AUTO_TEST_CASE(scan_time)
+{
+       bool result;
+       Csr::Database::CsrDB db(TEST_DB_FILE, TEST_DB_SCRIPTS);
+
+       std::string dir = "/opt";
+       long scantime = 100;
+       long retrievedTime;
+       std::string dataVersion = "1.0.0";
+
+       result = db.cleanLastScanTime();
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. cleanLastScanTime");
+
+       retrievedTime = db.getLastScanTime(dir, dataVersion);
+       BOOST_REQUIRE_MESSAGE(retrievedTime == -1, "Failed. getLastScanTime."
+                                                 "expected=-1, actual=" << retrievedTime);
+
+       result = db.insertLastScanTime(dir, scantime, dataVersion);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. insertLastScanTime");
+
+       result = db.insertLastScanTime(std::string("/opt/data"), scantime + 100, dataVersion);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. insertLastScanTime");
+
+       result = db.insertLastScanTime(std::string("/opt/data/etc"), scantime + 200, dataVersion);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. insertLastScanTime");
+
+       retrievedTime = db.getLastScanTime(dir, dataVersion);
+       BOOST_REQUIRE_MESSAGE(retrievedTime == scantime, "Failed. getLastScanTime."
+                                                 "expected=" << scantime << ", actual=" << retrievedTime);
+
+       result = db.cleanLastScanTime();
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. cleanLastScanTime");
+}
+
+BOOST_AUTO_TEST_CASE(detected_malware_file)
+{
+       bool result;
+       Csr::Database::CsrDB db(TEST_DB_FILE, TEST_DB_SCRIPTS);
+
+       std::string initDataVersion = "1.0.0";
+       std::string changedDataVersion = "2.0.0";
+
+       // insert
+       Csr::Database::RowDetected malware1;
+       malware1.path = "/opt/testmalware1";
+       malware1.dataVersion = initDataVersion;
+       malware1.severityLevel = 1;
+       malware1.threatType = 1;
+       malware1.name = "testmalware1";
+       malware1.detailedUrl = "http://detailed.malware.com";
+       malware1.detected_time = 100;
+       malware1.modified_time = 100;
+       malware1.ignored = 1;
+
+       Csr::Database::RowDetected malware2;
+       malware2.path = "/opt/testmalware2";
+       malware2.dataVersion = initDataVersion;
+       malware2.severityLevel = 2;
+       malware2.threatType = 2;
+       malware2.name = "testmalware2";
+       malware2.detailedUrl = "http://detailed2.malware.com";
+       malware2.detected_time = 210;
+       malware2.modified_time = 210;
+       malware2.ignored = 2;
+
+       Csr::Database::RowDetected malware3;
+       malware3.path = "/opt/testmalware3";
+       malware3.dataVersion = changedDataVersion;
+       malware3.severityLevel = 3;
+       malware3.threatType = 3;
+       malware3.name = "testmalware2";
+       malware3.detailedUrl = "http://detailed2.malware.com";
+       malware3.detected_time = 310;
+       malware3.modified_time = 310;
+       malware3.ignored = 3;
+
+       // select test with vacant data
+       Csr::Database::DetectedShrPtr detected = db.getDetectedMalware(malware1.path);
+       BOOST_REQUIRE_MESSAGE(detected == nullptr, "Failed. getDetectedMalware for no data");
+
+       Csr::Database::DetectedListShrPtr detectedList = db.getDetectedMalwares(std::string("/opt"));
+       BOOST_REQUIRE_MESSAGE(detectedList->size() == 0, "Failed. getDetectedMalwares for no data. size="
+                                                 <<  detectedList->size());
+
+       // insertDetectedMalware test
+       result = db.insertDetectedMalware(malware1);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. insertDetectedMalware");
+
+       result = db.insertDetectedMalware(malware2);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. insertDetectedMalware");
+
+       // getDetectedMalware test
+       detected = db.getDetectedMalware(malware1.path);
+       checkSameMalware(malware1, *detected.get());
+
+       detected = db.getDetectedMalware(malware2.path);
+       checkSameMalware(malware2, *detected.get());
+
+       // getDetectedMalwares test
+       detectedList = db.getDetectedMalwares(std::string("/opt"));
+       BOOST_REQUIRE_MESSAGE(detectedList->size() == 2, "Failed. getDetectedMalwares. Size="
+                                                 << detectedList->size());
+       std::vector<Csr::Database::DetectedShrPtr>::iterator iter;
+       for (iter = detectedList->begin(); iter != detectedList->end(); iter++) {
+               if (malware1.path.compare((*iter)->path) == 0) {
+                       checkSameMalware(malware1, **iter);
+               } else if (malware2.path.compare((*iter)->path) == 0) {
+                       checkSameMalware(malware2, **iter);
+               } else {
+                       BOOST_REQUIRE_MESSAGE(false, "Failed. getDetectedMalwares");
+               }
+       }
+
+       // setDetectedMalwareIgnored test
+       result = db.setDetectedMalwareIgnored(malware1.path, 1);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. setDetectedMalwareIgnored");
+
+       malware1.ignored = 1;
+       detected = db.getDetectedMalware(malware1.path);
+       checkSameMalware(malware1, *detected.get());
+
+       // deleteDeprecatedDetecedMalwares test
+       result = db.insertDetectedMalware(malware3);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. insertDetectedMalware");
+
+       result = db.deleteDeprecatedDetecedMalwares(std::string("/opt"), changedDataVersion);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. deleteDeprecatedDetecedMalwares");
+
+       detected = db.getDetectedMalware(malware3.path);
+       checkSameMalware(malware3, *detected.get());
+
+       detected = db.getDetectedMalware(malware1.path);
+       BOOST_REQUIRE_MESSAGE(detected.get() == nullptr,
+                                                 "Failed. deleteDeprecatedDetecedMalwares:getDetectedMalware");
+       detected = db.getDetectedMalware(malware2.path);
+       BOOST_REQUIRE_MESSAGE(detected.get() == nullptr,
+                                                 "Failed. deleteDeprecatedDetecedMalwares:getDetectedMalware");
+
+       // deleteDetecedMalware test
+       result = db.deleteDetecedMalware(malware3.path);
+       BOOST_REQUIRE_MESSAGE(result == true, "Failed. deleteDetecedMalware");
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()