Improve unit tests coverage
[platform/core/appfw/shortcut.git] / lib / src / shortcut_db.c
old mode 100755 (executable)
new mode 100644 (file)
index 4385cc4..ea1cc3c
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2011 - 2017 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 <unistd.h>
 #include <dlog.h>
 #include <glib.h>
 #include <db-util.h>
 #include <shortcut_db.h>
 #include <vconf.h>
 #include <vconf-keys.h>
+#include <tzplatform_config.h>
+
+#include "shortcut_error.h"
+
+#define QUERY_CREATE_SHORTCUT_TABLE \
+       "PRAGMA journal_mode = PERSIST;" \
+       "CREATE TABLE IF NOT EXISTS shortcut_service (\n" \
+       "  id INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
+       "  pkgid TEXT,\n" \
+       "  appid TEXT,\n" \
+       "  icon TEXT,\n" \
+       "  name TEXT,\n" \
+       "  extra_key TEXT,\n" \
+       "  extra_data TEXT);\n" \
+       "CREATE TABLE IF NOT EXISTS shortcut_name (\n" \
+       "  id INTEGER,\n" \
+       "  pkgid TEXT,\n" \
+       "  lang TEXT,\n" \
+       "  name TEXT,\n" \
+       "  icon TEXT);\n" \
+       "CREATE TABLE IF NOT EXISTS version (\n" \
+       "  version INTEGER);"
+
+static bool is_db_corrupted = false;
+
+static const char* _db_path = DB_PATH;
+
+int shortcut_set_db_path(const char *db_path)
+{
+       _db_path = db_path;
+       return 0;
+}
+
+/* LCOV_EXCL_START */
+static int __check_integrity_cb(void *pid, int argc, char **argv, char **notUsed)
+{
+       if (strcmp(argv[0], "ok") != 0) {
+               SHORTCUT_ERR("db integrity result : %s", argv[0]);
+               is_db_corrupted = true;
+               return -1;
+       }
+
+       SHORTCUT_INFO("db integrity result : %s", argv[0]);
+       return 0;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+static int __recover_corrupted_db(sqlite3 *db)
+{
+       int ret = SHORTCUT_ERROR_NONE;
+       int sql_ret;
+       char *errmsg = NULL;
+
+       SHORTCUT_INFO("DB is corrupted, start to recover corrupted db");
+       if (db)
+               sqlite3_close(db);
+       unlink(_db_path);
+
+       sql_ret = sqlite3_open_v2(_db_path, &db,
+                               SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE,
+                               NULL);
+       if (sql_ret != SQLITE_OK) {
+               SHORTCUT_ERR("Failed to open db[%d]", sql_ret);
+               unlink(_db_path);
+               ret = SHORTCUT_ERROR_IO_ERROR;
+               goto out;
+       }
+
+       sql_ret = sqlite3_exec(db, QUERY_CREATE_SHORTCUT_TABLE, NULL, NULL, &errmsg);
+       if (sql_ret != SQLITE_OK) {
+               SHORTCUT_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
+               ret = SHORTCUT_ERROR_IO_ERROR;
+       }
+
+out:
+       if (errmsg)
+               sqlite3_free(errmsg);
+
+       return ret;
+}
+/* LCOV_EXCL_STOP */
+
+/* LCOV_EXCL_START */
+EAPI int shortcut_db_init(void)
+{
+       int ret = SHORTCUT_ERROR_NONE;
+       int sql_ret;
+       sqlite3 *db = NULL;
+       char *errmsg = NULL;
+
+       sql_ret = sqlite3_open_v2(_db_path, &db,
+                       SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
+       if (sql_ret != SQLITE_OK) {
+               SHORTCUT_ERR("Failed to open db[%d]", sql_ret);
+               ret = SHORTCUT_ERROR_IO_ERROR;
+               goto out;
+       }
 
+       sql_ret = sqlite3_exec(db, QUERY_CREATE_SHORTCUT_TABLE,
+                               NULL, NULL, &errmsg);
+       if (sql_ret != SQLITE_OK) {
+               SHORTCUT_ERR("Failed to exec query [%d][%s]", sql_ret, errmsg);
+               ret = SHORTCUT_ERROR_IO_ERROR;
+               goto out;
+       }
 
+       sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
+                              __check_integrity_cb, NULL, &errmsg);
+       if (sql_ret != SQLITE_OK || is_db_corrupted) {
+               SHORTCUT_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
+               ret = SHORTCUT_ERROR_IO_ERROR;
+       }
 
-static sqlite3 * _open_db(void)
+out:
+       if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
+               ret = __recover_corrupted_db(db);
+       if (errmsg)
+               sqlite3_free(errmsg);
+       if (db)
+               sqlite3_close(db);
+
+       return ret;
+}
+/* LCOV_EXCL_STOP */
+
+static sqlite3 *_open_db(void)
 {
        int ret;
-       const char *dbfile = DB_PATH;
+       const char *dbfile = _db_path;
        sqlite3 *db = NULL;
 
        ret = db_util_open(dbfile, &db, 0);
        if (ret != SQLITE_OK) {
-               DbgPrint("Failed to open a %s\n", dbfile);
+               /* LCOV_EXCL_START */
+               SHORTCUT_DBG("Failed to open a %s\n", dbfile);
                return NULL;
+               /* LCOV_EXCL_STOP */
        }
 
        return db;
 }
 
-static int _close_db(sqlite3 ** db)
+static int _close_db(sqlite3 **db)
 {
        int ret = 0;
 
@@ -32,8 +175,10 @@ static int _close_db(sqlite3 ** db)
 
        ret = db_util_close(*db);
        if (ret != SQLITE_OK) {
-               DbgPrint("DB close error(%d)", ret);
+               /* LCOV_EXCL_START */
+               SHORTCUT_DBG("DB close error(%d)", ret);
                return SHORTCUT_ERROR_IO_ERROR;
+               /* LCOV_EXCL_STOP */
        }
 
        *db = NULL;
@@ -41,7 +186,7 @@ static int _close_db(sqlite3 ** db)
        return SHORTCUT_ERROR_NONE;
 }
 
-
+/* LCOV_EXCL_START */
 /*!
  * \note this function will returns allocated(heap) string
  */
@@ -56,27 +201,27 @@ static inline int _get_i18n_name(sqlite3 *handle, const char *lang, int id, char
 
        status = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
        if (status != SQLITE_OK) {
-               ErrPrint("Failed to prepare stmt: %s\n", sqlite3_errmsg(handle));
+               SHORTCUT_ERR("Failed to prepare stmt: %s\n", sqlite3_errmsg(handle));
                return -EFAULT;
        }
 
        status = sqlite3_bind_int(stmt, 1, id);
        if (status != SQLITE_OK) {
-               ErrPrint("Failed to bind id: %s\n", sqlite3_errmsg(handle));
+               SHORTCUT_ERR("Failed to bind id: %s\n", sqlite3_errmsg(handle));
                ret = -EFAULT;
                goto out;
        }
 
        status = sqlite3_bind_text(stmt, 2, lang, -1, SQLITE_TRANSIENT);
        if (status != SQLITE_OK) {
-               ErrPrint("Failed to bind lang: %s\n", sqlite3_errmsg(handle));
+               SHORTCUT_ERR("Failed to bind lang: %s\n", sqlite3_errmsg(handle));
                ret = -EFAULT;
                goto out;
        }
 
-       DbgPrint("id: %d, lang: %s\n", id, lang);
+       SHORTCUT_DBG("id: %d, lang: %s\n", id, lang);
        if (SQLITE_ROW != sqlite3_step(stmt)) {
-               ErrPrint("Failed to do step: %s\n", sqlite3_errmsg(handle));
+               SHORTCUT_ERR("Failed to do step: %s\n", sqlite3_errmsg(handle));
                ret = -ENOENT;
                goto out;
        }
@@ -86,7 +231,7 @@ static inline int _get_i18n_name(sqlite3 *handle, const char *lang, int id, char
                if (_name && strlen((const char *)_name)) {
                        *name = strdup((const char *)_name);
                        if (!*name) {
-                               ErrPrint("strdup: %d\n", errno);
+                               SHORTCUT_ERR("strdup: %d\n", errno);
                                ret = -ENOMEM;
                                goto out;
                        }
@@ -100,10 +245,12 @@ static inline int _get_i18n_name(sqlite3 *handle, const char *lang, int id, char
                if (_icon && strlen((const char *)_icon)) {
                        *icon = strdup((const char *)_icon);
                        if (!*icon) {
-                               ErrPrint("strdup: %d\n", errno);
+                               SHORTCUT_ERR("strdup: %d\n", errno);
                                ret = -ENOMEM;
-                               if (name && *name)
+                               if (name && *name) {
                                        free(*name);
+                                       *name = NULL;
+                               }
 
                                goto out;
                        }
@@ -118,6 +265,7 @@ out:
        sqlite3_finalize(stmt);
        return ret;
 }
+/* LCOV_EXCL_STOP */
 
 static inline char *_cur_locale(void)
 {
@@ -141,7 +289,7 @@ static inline char *_cur_locale(void)
        } else {
                language = strdup("en-us");
                if (!language)
-                       ErrPrint("Heap: %d\n", errno);
+                       SHORTCUT_ERR("Heap: %d\n", errno);
        }
 
        return language;
@@ -166,49 +314,60 @@ EAPI int shortcut_db_get_list(const char *package_name, GList **shortcut_list)
 
        handle = _open_db();
        if (!handle) {
-               ErrPrint("Failed to open a DB\n");
+               /* LCOV_EXCL_START */
+               SHORTCUT_ERR("Failed to open a DB\n");
                return SHORTCUT_ERROR_IO_ERROR;
+               /* LCOV_EXCL_STOP */
        }
 
        language = _cur_locale();
        if (!language) {
-               ErrPrint("Locale is not valid\n");
+               /* LCOV_EXCL_START */
+               SHORTCUT_ERR("Locale is not valid\n");
                _close_db(&handle);
                return SHORTCUT_ERROR_FAULT;
+               /* LCOV_EXCL_STOP */
        }
 
        if (package_name) {
                query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service WHERE appid = ?";
                ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
                if (ret != SQLITE_OK) {
-                       ErrPrint("prepare: %s\n", sqlite3_errmsg(handle));
+                       /* LCOV_EXCL_START */
+                       SHORTCUT_ERR("prepare: %s\n", sqlite3_errmsg(handle));
                        free(language);
                        _close_db(&handle);
                        return SHORTCUT_ERROR_IO_ERROR;
+                       /* LCOV_EXCL_STOP */
                }
 
                ret = sqlite3_bind_text(stmt, 1, package_name, -1, SQLITE_TRANSIENT);
                if (ret != SQLITE_OK) {
-                       ErrPrint("bind text: %s\n", sqlite3_errmsg(handle));
+                       /* LCOV_EXCL_START */
+                       SHORTCUT_ERR("bind text: %s\n", sqlite3_errmsg(handle));
                        sqlite3_finalize(stmt);
                        free(language);
                        _close_db(&handle);
                        return SHORTCUT_ERROR_IO_ERROR;
+                       /* LCOV_EXCL_STOP */
                }
        } else {
                query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service";
                ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
                if (ret != SQLITE_OK) {
-                       ErrPrint("prepare: %s\n", sqlite3_errmsg(handle));
+                       /* LCOV_EXCL_START */
+                       SHORTCUT_ERR("prepare: %s\n", sqlite3_errmsg(handle));
                        free(language);
                        _close_db(&handle);
                        return SHORTCUT_ERROR_IO_ERROR;
+                       /* LCOV_EXCL_STOP */
                }
        }
 
        cnt = 0;
        *shortcut_list = NULL;
        while (SQLITE_ROW == sqlite3_step(stmt)) {
+               /* LCOV_EXCL_START */
                id = sqlite3_column_int(stmt, 0);
 
                package_name = (const char *)sqlite3_column_text(stmt, 1);
@@ -254,20 +413,26 @@ EAPI int shortcut_db_get_list(const char *package_name, GList **shortcut_list)
                shortcut = (shortcut_info_s *)calloc(sizeof(shortcut_info_s), 1);
                if (shortcut == NULL) {
                        free(i18n_name);
+                       free(i18n_icon);
                        break;
                }
                shortcut->package_name = strdup(package_name);
                shortcut->icon = strdup((i18n_icon != NULL ? i18n_icon : (char *)icon));
                shortcut->name = strdup((i18n_name != NULL ? i18n_name : (char *)name));
                shortcut->extra_key = strdup((char *)extra_key);
-               shortcut->extra_data = strdup((char *)extra_key);
+               shortcut->extra_data = strdup((char *)extra_data);
                *shortcut_list = g_list_append(*shortcut_list, shortcut);
 
-               free(i18n_name);
-               i18n_name = NULL;
+               if (i18n_name) {
+                       free(i18n_name);
+                       i18n_name = NULL;
+               }
 
-               free(i18n_icon);
-               i18n_icon = NULL;
+               if (i18n_icon) {
+                       free(i18n_icon);
+                       i18n_icon = NULL;
+               }
+               /* LCOV_EXCL_STOP */
        }
 
        sqlite3_reset(stmt);