diff options
author | Anton Hrytsevich <AGritsevich@luxoft.com> | 2016-05-28 16:19:39 +0300 |
---|---|---|
committer | Levchenko <slevchenko@SLevchenko-lws-unq> | 2016-08-04 17:30:29 +0300 |
commit | 3d6ded95790263fb9c434703ab346bec18542ebe (patch) | |
tree | d492e3921ea0a1bf6fe39fcb0cf6b138ffc8c827 | |
parent | f0ab94ebeed8a82e355ca6838e4b427831789288 (diff) | |
download | sdl_core-3d6ded95790263fb9c434703ab346bec18542ebe.tar.gz |
AppLaunchData common implementation
Related issue : APPLINK-24892
11 files changed, 2032 insertions, 2 deletions
diff --git a/src/components/application_manager/include/application_manager/app_launch/app_launch_data.h b/src/components/application_manager/include/application_manager/app_launch/app_launch_data.h index 7c875520aa..0d52384018 100644 --- a/src/components/application_manager/include/application_manager/app_launch/app_launch_data.h +++ b/src/components/application_manager/include/application_manager/app_launch/app_launch_data.h @@ -81,8 +81,8 @@ class AppLaunchData { /** * @brief select from DB all records with this dev_mac * @param app_data - data to inserting - * @param dev_apps - pointer to vector with result of select - * @return true in success cases and false othrewise + * @param dev_apps - + * @return vector of pointers on results of select */ virtual std::vector<ApplicationDataPtr> GetApplicationDataByDevice( const std::string& dev_mac) = 0; diff --git a/src/components/application_manager/include/application_manager/app_launch/app_launch_data_db.h b/src/components/application_manager/include/application_manager/app_launch/app_launch_data_db.h new file mode 100644 index 0000000000..92d6bbd9ef --- /dev/null +++ b/src/components/application_manager/include/application_manager/app_launch/app_launch_data_db.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_DATA_DB_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_DATA_DB_H_ +#include <memory> +#include "application_manager/app_launch/app_launch_data_impl.h" +#include "application_manager/app_launch_settings.h" +#include "utils/macro.h" +#ifdef __QNX__ +#include "utils/qdb_wrapper/sql_database.h" +#include "utils/qdb_wrapper/sql_query.h" +#else // linux +#include "utils/sqlite_wrapper/sql_database.h" +#include "utils/sqlite_wrapper/sql_query.h" +#endif + +namespace app_launch { + +const std::string kDatabaseName = "resumption"; + +/** + * @brief Show should database be saved in a disk file or in memory + */ +enum DbStorage { In_Memory_Storage = 0, In_File_Storage }; + +/** + * @brief class contains logic for representation application + * launch_app data in data base + */ +class AppLaunchDataDB : public AppLaunchDataImpl { + public: + /** + * @brief Constructor of AppLaunchDataDB + * @param settings - setting of AppLaunch + */ + AppLaunchDataDB(const AppLaunchSettings& settings, + DbStorage db_storage = In_File_Storage); + + /** + * @brief allows to destroy AppLaunchDataDB object + */ + ~AppLaunchDataDB(); + + /** + * @brief Creates or opens DB and initialize it + * @return false if DB doesn't initialize + * otherwise returns true + */ + bool Init(); + + /** + * @brief delete App_launch table in DB, after calling this + * one, it should again call init + * @return true in success cases and false othrewise + */ + bool Clear() OVERRIDE; + + /** + * @brief Write database to file system + */ + bool Persist() OVERRIDE; + + /** + * @return current count of records + * AppLaunch in DB + */ + uint32_t GetCurentNumberOfAppData() const; + + /** + * @param app_data - searching fields in object + * @return true in case application data already existed + * and false othrewise + */ + bool IsAppDataAlreadyExisted(const ApplicationData& app_data) const OVERRIDE; + + /** + * @brief returns pointer to data base + */ + utils::dbms::SQLDatabase* db() const; + + enum ApplicationDataDBIndexes { + result_query = 0, + device_mac_index = 0, + application_id_index, + bundle_id_index, + timestamp_index + }; + + private: + /** + * @brief update time stamp + * @param app_data - data to update + * @return true in success cases and false othrewise + */ + bool RefreshAppSessionTime(const ApplicationData& app_data) OVERRIDE; + + /** + * @brief insert new data to DB + * @param app_data - data to inserting + * @return true in success cases and false othrewise + */ + bool AddNewAppData(const ApplicationData& app_data) OVERRIDE; + + /** + * @brief select from DB all records with this dev_mac + * @param app_data - data to inserting + * @return vector of ponter on founded records + */ + std::vector<ApplicationDataPtr> GetAppDataByDevMac( + const std::string& dev_mac) const OVERRIDE; + /** + * @brief delete record with oldest timestamp + * @return true in success cases and false othrewise + */ + bool DeleteOldestAppData() OVERRIDE; + + /** + * @brief write DB to file + * @return true in success cases and false othrewise + */ + bool WriteDb(); + + /** + * @brief returns pointer to data base + */ + std::auto_ptr<utils::dbms::SQLDatabase> db_; + + /** + * @brief indicate initializing status of DB + */ + bool init_successeful_; + + DISALLOW_COPY_AND_ASSIGN(AppLaunchDataDB); +}; + +} // namespace app_launch + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_DATA_DB_H_ diff --git a/src/components/application_manager/include/application_manager/app_launch/app_launch_data_impl.h b/src/components/application_manager/include/application_manager/app_launch/app_launch_data_impl.h new file mode 100644 index 0000000000..111ff25ab2 --- /dev/null +++ b/src/components/application_manager/include/application_manager/app_launch/app_launch_data_impl.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_DATA_IMPL_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_DATA_IMPL_H_ + +#include "application_manager/app_launch/app_launch_data.h" +#include "application_manager/app_launch_settings.h" + +namespace app_launch { + +class AppLaunchDataImpl : public AppLaunchData { + public: + /** + * @brief Constructor of AppLaunchDataImpl + * @param settings - setting of AppLaunch + */ + AppLaunchDataImpl(const AppLaunchSettings& settings); + + /** + * @brief allows to destroy AppLaunchDataImpl object + */ + virtual ~AppLaunchDataImpl(); + + /** + * @brief insert new data to DB + * @param app_data - data to inserting + * @return true in success cases and false othrewise + */ + virtual bool AddApplicationData(const ApplicationData& app_data); + + /** + * @brief select from DB all records with this dev_mac + * @param app_data - data to inserting + * @return return vector of pointers on founded records + */ + std::vector<ApplicationDataPtr> GetApplicationDataByDevice( + const std::string& dev_mac) OVERRIDE; + + /** + * @brief Persist saves resumption data on file system + */ + virtual bool Persist() = 0; + + /** + * @return max count of iOS device that can be connected + */ + virtual uint32_t get_max_number_iOS_devs() const { + return kMaxNumberOfiOSdevice; + } + + /** + * @brief all AppLaunch settings + */ + const AppLaunchSettings& settings_; + + private: + /** + * @param app_data - searching filled in object + * @return true in case application data already existed + * and false othrewise + */ + virtual bool IsAppDataAlreadyExisted( + const ApplicationData& app_data) const = 0; + + /** + * @brief update time stamp + * @param app_data - data to update + * @return true in success cases and false othrewise + */ + virtual bool RefreshAppSessionTime(const ApplicationData& app_data) = 0; + + /** + * @brief insert new data to DB + * @param app_data - data to inserting + * @return true in success cases and false othrewise + */ + virtual bool AddNewAppData(const ApplicationData& app_data) = 0; + + /** + * @brief select from DB all records with this dev_mac + * @param app_data - data to inserting + * @return vector of ponter on founded records + */ + virtual std::vector<ApplicationDataPtr> GetAppDataByDevMac( + const std::string& dev_mac) const = 0; + + /** + * @brief delete record with oldest timestamp + * @return true in success cases and false othrewise + */ + virtual bool DeleteOldestAppData() = 0; + + /** + * @return current count of records + * AppLaunch in DB + */ + virtual uint32_t GetCurentNumberOfAppData() const = 0; + + /** + * @brief max count of iOS device that can be connected + */ + const uint32_t kMaxNumberOfiOSdevice; +}; +} // namespace app_launch + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_DATA_IMPL_H_ diff --git a/src/components/application_manager/include/application_manager/app_launch/app_launch_data_json.h b/src/components/application_manager/include/application_manager/app_launch/app_launch_data_json.h new file mode 100644 index 0000000000..61117e552b --- /dev/null +++ b/src/components/application_manager/include/application_manager/app_launch/app_launch_data_json.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_DATA_JSON_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_DATA_JSON_H_ + +#include "application_manager/app_launch/app_launch_data_impl.h" +#include "smart_objects/smart_object.h" +#include "resumption/last_state.h" +#include "utils/lock.h" +#include "utils/macro.h" + +namespace app_launch { + +enum { NotFound = -1 }; +/** + * @brief class contains logic for representation application launch_app data in + * json file + */ +class AppLaunchDataJson : public AppLaunchDataImpl { + public: + /** + * @brief Constructor of AppLaunchDataJson object + */ + AppLaunchDataJson(const AppLaunchSettings& settings, + resumption::LastState& last_state); + /** + * @brief allows to destroy AppLaunchDataJson object + */ + ~AppLaunchDataJson(); + + /** + * @brief Write Json to file system + */ + bool Persist() OVERRIDE; + + /** + * @brief delete App_launch table in DB, after calling this + * one, it should again call init + * @return true in success cases and false othrewise + */ + virtual bool Clear(); + + /** + * @return current count of records + * AppLaunch in DB + */ + uint32_t GetCurentNumberOfAppData() const; + + /** + * @param app_data - searching filled in object + * @return true in case application data already existed + * and false othrewise + */ + virtual bool IsAppDataAlreadyExisted(const ApplicationData& app_data) const; + + /** + * @param app_data - searching filled in object + * @param founded_index - referenceto index of founded record + * in case it wasn't found it'll be -1 + * @return pointer to json list object + */ + Json::Value& GetApplicationListAndIndex(const ApplicationData& app_data, + int32_t& founded_index) const; + + private: + /** + * @brief update time stamp + * @param app_data - data to update + * @return true in success cases and false othrewise + */ + virtual bool RefreshAppSessionTime(const ApplicationData& app_data); + + /** + * @brief insert new data to DB + * @param app_data - data to inserting + * @return true in success cases and false othrewise + */ + virtual bool AddNewAppData(const ApplicationData& app_data); + + /** + * @brief select from DB all records with this dev_mac + * @param app_data - data to inserting + * @return vector of pointer on founded records + */ + std::vector<ApplicationDataPtr> GetAppDataByDevMac( + const std::string& dev_mac) const OVERRIDE; + + /** + * @return pointer to LastState functionality + */ + resumption::LastState& last_state() const { + return last_state_; + } + + /** + * @brief delete record with oldest timestamp + * @return true in success cases and false othrewise + */ + bool DeleteOldestAppData(); + + /** + * @return pointer to AppLaunch data block in Json file + */ + Json::Value& GetSavedApplicationDataList() const; + + /** + * @return pointer to AppLaunch records block in Json file + */ + Json::Value& GetApplicationData() const; + + /** + * @brief lock to protected common data + */ + mutable sync_primitives::Lock app_launch_json_lock_; + + /** + * @brief ponter to Last State object + */ + resumption::LastState& last_state_; + + DISALLOW_COPY_AND_ASSIGN(AppLaunchDataJson); +}; + +} // namespace app_launch + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_DATA_JSON_H_ diff --git a/src/components/application_manager/include/application_manager/app_launch/app_launch_sql_queries.h b/src/components/application_manager/include/application_manager/app_launch/app_launch_sql_queries.h new file mode 100644 index 0000000000..d70af6bba4 --- /dev/null +++ b/src/components/application_manager/include/application_manager/app_launch/app_launch_sql_queries.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_SQL_QUERY_H_ +#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_SQL_QUERY_H_ + +#include <string> + +namespace app_launch { + +extern const std::string kCreateSchema; +extern const std::string kDropSchema; +extern const std::string kFindApplicationData; +extern const std::string kDeleteOldestAppData; +extern const std::string kGetNumberOfApplicationData; +extern const std::string kGetApplicationDataByDevID; +extern const std::string kAddApplicationData; +extern const std::string kRefreshApplicationDataSessionTime; + +} // namespace app_launch + +#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_APP_LAUNCH_APP_LAUNCH_SQL_QUERY_H_ diff --git a/src/components/application_manager/src/app_launch/app_launch_data_db.cc b/src/components/application_manager/src/app_launch/app_launch_data_db.cc new file mode 100644 index 0000000000..f3adfc749b --- /dev/null +++ b/src/components/application_manager/src/app_launch/app_launch_data_db.cc @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <string> +#include <unistd.h> + +#include "application_manager/app_launch/app_launch_data_db.h" +#include "application_manager/application_manager_impl.h" +#include "application_manager/app_launch/app_launch_sql_queries.h" +#include "application_manager/smart_object_keys.h" +#include "application_manager/message_helper.h" +#include "utils/make_shared.h" + +namespace app_launch { +CREATE_LOGGERPTR_GLOBAL(logger_, "AppLaunch") + +AppLaunchDataDB::AppLaunchDataDB(const AppLaunchSettings& settings, + DbStorage db_storage) + : AppLaunchDataImpl(settings) { + if (db_storage == In_File_Storage) { + db_.reset(new utils::dbms::SQLDatabase(kDatabaseName)); +#ifndef __QNX__ + std::string path = settings_.app_storage_folder(); + if (!path.empty()) { + db()->set_path(path + "/"); + } + } else if (db_storage == In_Memory_Storage) { + db_.reset(new utils::dbms::SQLDatabase()); +#endif // __QNX__ + DCHECK(db_.get()); + } else { + LOG4CXX_AUTO_TRACE(logger_); + LOG4CXX_ERROR(logger_, "Get not existed type of database storage"); + } + + // Connect to resumption DB + init_successeful_ = Init(); +} + +AppLaunchDataDB::~AppLaunchDataDB() { + db()->Close(); +} + +bool AppLaunchDataDB::Init() { + LOG4CXX_AUTO_TRACE(logger_); + + if (!db()->Open()) { + LOG4CXX_ERROR(logger_, "Failed opening database."); + LOG4CXX_INFO(logger_, "Starting opening retries."); + const uint16_t attempts = settings_.app_launch_max_retry_attempt(); + LOG4CXX_DEBUG(logger_, "Total attempts number is: " << attempts); + bool is_opened = false; + const uint16_t open_attempt_timeout_ms = + settings_.app_launch_retry_wait_time(); + const useconds_t sleep_interval_mcsec = open_attempt_timeout_ms * 1000u; + LOG4CXX_DEBUG(logger_, + "Open attempt timeout(ms) is: " << open_attempt_timeout_ms); + for (size_t i = 0u; i < attempts; ++i) { + usleep(sleep_interval_mcsec); + LOG4CXX_INFO(logger_, "Attempt: " << i + 1); + if (db()->Open()) { + LOG4CXX_INFO(logger_, "Database opened."); + is_opened = true; + break; + } + } + if (!is_opened) { + LOG4CXX_ERROR(logger_, + "Open retry sequence failed. Tried " + << attempts << " attempts with " + << open_attempt_timeout_ms + << " open timeout(ms) for each."); + return false; + } + } +#ifndef __QNX__ + if (!db()->IsReadWrite()) { + LOG4CXX_ERROR(logger_, "There are no read/write permissions for database"); + return false; + } +#endif // __QNX__ + + utils::dbms::SQLQuery query(db()); + if (!query.Exec(kCreateSchema)) { + LOG4CXX_ERROR( + logger_, + "Failed creating schema of database: " << query.LastError().text()); + return false; + } + + return true; +} + +bool AppLaunchDataDB::Persist() { + LOG4CXX_AUTO_TRACE(logger_); + bool retVal = false; + + if (!init_successeful_) { + LOG4CXX_ERROR(logger_, + "AppLaunch data base was not successfully " + "initialize, AppLaunch won't work!"); + return retVal; + } + + if ((retVal = WriteDb())) { + LOG4CXX_DEBUG(logger_, "App_lauch had been successfully saved."); + } else { + LOG4CXX_WARN(logger_, "Fail to save app_launch data."); + } + + return retVal; +} + +bool AppLaunchDataDB::IsAppDataAlreadyExisted( + const ApplicationData& app_data) const { + LOG4CXX_AUTO_TRACE(logger_); + bool retVal = false; + + if (!init_successeful_) { + LOG4CXX_ERROR(logger_, + "AppLaunch data base was not successfully " + "initialize, AppLaunch won't work!"); + return retVal; + } + + utils::dbms::SQLQuery query(db()); + + if (!query.Prepare(kFindApplicationData)) { + LOG4CXX_WARN(logger_, + "Problem with verification queries 'kFindApplicationData'"); + return retVal; + } + + query.Bind(device_mac_index, app_data.device_mac_); + query.Bind(application_id_index, app_data.mobile_app_id_); + query.Bind(bundle_id_index, app_data.bundle_id_); + + if (query.Exec()) { + retVal = query.GetBoolean(result_query); + } else { + LOG4CXX_WARN(logger_, + "Failed execute query 'kGetNumberOfApplicationData'. Reson: " + << query.LastError().text()); + } + + return retVal; +} + +bool AppLaunchDataDB::RefreshAppSessionTime(const ApplicationData& app_data) { + LOG4CXX_AUTO_TRACE(logger_); + bool retVal = false; + + if (!init_successeful_) { + LOG4CXX_ERROR(logger_, + "AppLaunch data base was not successfully " + "initialize, AppLaunch won't work!"); + return retVal; + } + + utils::dbms::SQLQuery query(db()); + + if (!query.Prepare(kRefreshApplicationDataSessionTime)) { + LOG4CXX_WARN(logger_, + "Problem with verification queries " + "'kRefreshApplicationDataSessionTime'"); + return retVal; + } + + query.Bind(device_mac_index, app_data.device_mac_); + query.Bind(application_id_index, app_data.mobile_app_id_); + query.Bind(bundle_id_index, app_data.bundle_id_); + + if (query.Exec()) { + LOG4CXX_DEBUG(logger_, "Dare&time last session were updated successfully"); + retVal = WriteDb(); + } else { + LOG4CXX_WARN(logger_, + "Failed execute query 'kGetNumberOfApplicationData'. Reson: " + << query.LastError().text()); + } + + return retVal; +} + +bool AppLaunchDataDB::AddNewAppData(const ApplicationData& app_data) { + LOG4CXX_AUTO_TRACE(logger_); + bool retVal = false; + + if (!init_successeful_) { + LOG4CXX_ERROR(logger_, + "AppLaunch data base was not successfully " + "initialize, AppLaunch won't work!"); + return retVal; + } + + utils::dbms::SQLQuery query(db()); + + if (!query.Prepare(kAddApplicationData)) { + LOG4CXX_WARN(logger_, + "Problem with verification queries 'kAddApplicationData'"); + return retVal; + } + + query.Bind(device_mac_index, app_data.device_mac_); + query.Bind(application_id_index, app_data.mobile_app_id_); + query.Bind(bundle_id_index, app_data.bundle_id_); + + retVal = query.Exec(); + if (retVal) { + LOG4CXX_DEBUG(logger_, "New application data was added successfully"); + retVal = WriteDb(); + } else { + LOG4CXX_WARN(logger_, + "Failed execute query 'kGetNumberOfApplicationData'. Reson: " + << query.LastError().text()); + } + + return retVal; +} + +std::vector<ApplicationDataPtr> AppLaunchDataDB::GetAppDataByDevMac( + const std::string& dev_mac) const { + LOG4CXX_AUTO_TRACE(logger_); + std::vector<ApplicationDataPtr> dev_apps; + + if (!init_successeful_) { + LOG4CXX_ERROR(logger_, + "AppLaunch data base was not successfully " + "initialize, AppLaunch won't work!"); + return dev_apps; + } + + utils::dbms::SQLQuery query(db()); + + if (!query.Prepare(kGetApplicationDataByDevID)) { + LOG4CXX_WARN( + logger_, + "Problem with verification queries 'kGetApplicationDataByDevID'"); + return dev_apps; + } + + query.Bind(device_mac_index, dev_mac); + const bool retVal = query.Exec(); + if (retVal) { + LOG4CXX_INFO(logger_, + "Values of ignition off counts were updated successfully"); + do { + const std::string device_mac = query.GetString(device_mac_index); + const std::string mobile_app_id = query.GetString(application_id_index); + const std::string bundle_id = query.GetString(bundle_id_index); + dev_apps.push_back(utils::MakeShared<ApplicationData>( + mobile_app_id, bundle_id, device_mac)); + } while (query.Next()); + LOG4CXX_DEBUG(logger_, "All application data has been successfully loaded"); + } else { + LOG4CXX_WARN(logger_, + "Failed execute query 'kGetNumberOfApplicationData'. Reson: " + << query.LastError().text()); + } + + return dev_apps; +} + +bool AppLaunchDataDB::Clear() { + LOG4CXX_AUTO_TRACE(logger_); + bool retVal = false; + + utils::dbms::SQLQuery query(db()); + retVal = query.Exec(kDropSchema); + + if (retVal) { + LOG4CXX_INFO(logger_, "App_Launch table had been cleared successfully"); + retVal = WriteDb(); + init_successeful_ = false; + } else { + LOG4CXX_WARN(logger_, + "Failed dropping database: " << query.LastError().text()); + } + + return retVal; +} + +uint32_t AppLaunchDataDB::GetCurentNumberOfAppData() const { + LOG4CXX_AUTO_TRACE(logger_); + uint32_t number_of_app_data = 0u; + + if (!init_successeful_) { + LOG4CXX_ERROR(logger_, + "AppLaunch data base was not successfully " + "initialize, AppLaunch won't work!"); + return number_of_app_data; + } + + utils::dbms::SQLQuery query(db()); + + if (!query.Prepare(kGetNumberOfApplicationData)) { + LOG4CXX_WARN( + logger_, + "Problem with verification queries 'kGetNumberOfApplicationData'"); + return number_of_app_data; + } + + if (query.Exec()) { + LOG4CXX_INFO(logger_, + "Values of ignition off counts were updated successfully"); + + number_of_app_data = query.GetInteger(result_query); + LOG4CXX_DEBUG(logger_, + "Total cout saved mobile applications is " + << number_of_app_data); + } else { + LOG4CXX_WARN(logger_, + "Failed execute query 'kGetNumberOfApplicationData'. Reson: " + << query.LastError().text()); + } + + return number_of_app_data; +} + +bool AppLaunchDataDB::DeleteOldestAppData() { + LOG4CXX_AUTO_TRACE(logger_); + bool retVal = false; + + if (!init_successeful_) { + LOG4CXX_ERROR(logger_, + "AppLaunch data base was not successfully " + "initialize, AppLaunch won't work!"); + return retVal; + } + + utils::dbms::SQLQuery query(db()); + + if (!query.Prepare(kDeleteOldestAppData)) { + LOG4CXX_WARN(logger_, + "Problem with verification queries 'kDeleteOldestAppData'"); + return retVal; + } + + if ((retVal = query.Exec())) { + LOG4CXX_INFO(logger_, + "Values of ignition off counts were updated successfully"); + retVal = WriteDb(); + } else { + LOG4CXX_WARN(logger_, + "Failed execute query 'kGetNumberOfApplicationData'. Reson: " + << query.LastError().text()); + } + + return retVal; +} + +bool AppLaunchDataDB::WriteDb() { + LOG4CXX_AUTO_TRACE(logger_); + return db_->Backup(); +} + +utils::dbms::SQLDatabase* AppLaunchDataDB::db() const { +#ifdef __QNX__ + std::auto_ptr<utils::dbms::SQLDatabase> db_qnx( + new utils::dbms::SQLDatabase(kDatabaseName)); + db_qnx.get()->Open(); + return db_qnx.get(); +#else + return db_.get(); +#endif // __QNX__ +} + +} // namespace resumption diff --git a/src/components/application_manager/src/app_launch/app_launch_data_impl.cc b/src/components/application_manager/src/app_launch/app_launch_data_impl.cc new file mode 100644 index 0000000000..c095cc9d94 --- /dev/null +++ b/src/components/application_manager/src/app_launch/app_launch_data_impl.cc @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "application_manager/app_launch/app_launch_data_impl.h" +#include "utils/logger.h" + +namespace app_launch { + +CREATE_LOGGERPTR_GLOBAL(logger_, "AppLaunch") + +AppLaunchDataImpl::AppLaunchDataImpl(const AppLaunchSettings& settings) + : settings_(settings) + , kMaxNumberOfiOSdevice(settings.max_number_of_ios_device()) {} + +AppLaunchDataImpl::~AppLaunchDataImpl() {} + +bool AppLaunchDataImpl::AddApplicationData(const ApplicationData& app_data) { + LOG4CXX_AUTO_TRACE(logger_); + bool retVal = true; + + if (app_data.device_mac_.empty() == false && + app_data.mobile_app_id_.empty() == false && + app_data.bundle_id_.empty() == false) { + if (IsAppDataAlreadyExisted(app_data)) { + LOG4CXX_INFO(logger_, "This application data already existed"); + retVal &= RefreshAppSessionTime(app_data); + } else { + if (GetCurentNumberOfAppData() >= get_max_number_iOS_devs()) { + LOG4CXX_INFO(logger_, + "Max number of application data have. It will be deleted " + "the oldest one"); + retVal &= DeleteOldestAppData(); + } + retVal &= AddNewAppData(app_data); + LOG4CXX_INFO(logger_, "Added new application data to DB"); + } + } else { + retVal = false; + } + return retVal; +} + +std::vector<ApplicationDataPtr> AppLaunchDataImpl::GetApplicationDataByDevice( + const std::string& dev_mac) { + LOG4CXX_AUTO_TRACE(logger_); + std::vector<ApplicationDataPtr> apps = GetAppDataByDevMac(dev_mac); + + if (apps.empty()) { + LOG4CXX_DEBUG(logger_, "No application founded by mac" << dev_mac); + } + + return apps; +} + +} // namespace app_launch diff --git a/src/components/application_manager/src/app_launch/app_launch_data_json.cc b/src/components/application_manager/src/app_launch/app_launch_data_json.cc new file mode 100644 index 0000000000..dc5474e280 --- /dev/null +++ b/src/components/application_manager/src/app_launch/app_launch_data_json.cc @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <algorithm> +#include "application_manager/app_launch/app_launch_data_json.h" +#include "application_manager/smart_object_keys.h" +#include "smart_objects/smart_object.h" +#include "utils/make_shared.h" +#include "utils/date_time.h" +#include "json/json.h" + +namespace app_launch { + +CREATE_LOGGERPTR_GLOBAL(logger_, "AppLaunch") + +AppLaunchDataJson::AppLaunchDataJson(const AppLaunchSettings& settings, + resumption::LastState& last_state) + : AppLaunchDataImpl(settings) + , app_launch_json_lock_(true) + , last_state_(last_state) {} + +AppLaunchDataJson::~AppLaunchDataJson() {} + +Json::Value& AppLaunchDataJson::GetSavedApplicationDataList() const { + using namespace application_manager; + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock autolock(app_launch_json_lock_); + Json::Value& app_launch = GetApplicationData(); + if (!app_launch.isMember(strings::app_launch_list)) { + app_launch[strings::app_launch_list] = Json::Value(Json::arrayValue); + LOG4CXX_WARN(logger_, "app_list section is missed"); + } + Json::Value& app_launch_list = app_launch[strings::app_launch_list]; + if (!app_launch_list.isArray()) { + LOG4CXX_ERROR(logger_, "app_launch_list type INVALID rewrite"); + app_launch_list = Json::Value(Json::arrayValue); + } + return app_launch_list; +} + +Json::Value& AppLaunchDataJson::GetApplicationData() const { + using namespace application_manager; + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock autolock(app_launch_json_lock_); + Json::Value& dictionary = last_state().dictionary; + if (!dictionary.isMember(strings::app_launch)) { + last_state().dictionary[strings::app_launch] = + Json::Value(Json::objectValue); + LOG4CXX_WARN(logger_, "app_launch section is missed"); + } + Json::Value& app_launch = dictionary[strings::app_launch]; + if (!app_launch.isObject()) { + LOG4CXX_ERROR(logger_, "resumption type INVALID rewrite"); + app_launch = Json::Value(Json::objectValue); + } + return app_launch; +} + +Json::Value& AppLaunchDataJson::GetApplicationListAndIndex( + const ApplicationData& app_data, int32_t& founded_index) const { + using namespace application_manager; + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock autolock(app_launch_json_lock_); + + Json::Value& apps_list = GetSavedApplicationDataList(); + const Json::ArrayIndex size = apps_list.size(); + + for (Json::ArrayIndex idx = 0; idx != size; ++idx) { + if (apps_list[idx].isMember(strings::device_id) && + apps_list[idx].isMember(strings::bundle_id) && + apps_list[idx].isMember(strings::app_id) && + apps_list[idx].isMember(strings::app_launch_last_session)) { + const std::string deviceID = + apps_list[idx][strings::device_id].asString(); + const std::string bundleID = + apps_list[idx][strings::bundle_id].asString(); + const std::string appID = apps_list[idx][strings::app_id].asString(); + + if (deviceID == app_data.device_mac_ && + bundleID == app_data.bundle_id_ && + appID == app_data.mobile_app_id_) { + founded_index = idx; + } + } + } + + return apps_list; +} + +bool AppLaunchDataJson::IsAppDataAlreadyExisted( + const ApplicationData& app_data) const { + LOG4CXX_AUTO_TRACE(logger_); + + int32_t index = NotFound; + GetApplicationListAndIndex(app_data, index); + return index == NotFound ? false : true; +} + +bool AppLaunchDataJson::RefreshAppSessionTime(const ApplicationData& app_data) { + using namespace application_manager; + using namespace date_time; + LOG4CXX_AUTO_TRACE(logger_); + bool retVal = false; + + int32_t index = NotFound; + Json::Value& json_data_list = GetApplicationListAndIndex(app_data, index); + if (index != NotFound) { + if (json_data_list.empty() == false) { + json_data_list[index][strings::app_launch_last_session] = + static_cast<Json::Value::UInt64>(DateTime::getCurrentTime().tv_sec); + retVal = true; + } + } + return retVal; +} + +bool AppLaunchDataJson::AddNewAppData(const ApplicationData& app_data) { + using namespace application_manager; + using namespace date_time; + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock autolock(app_launch_json_lock_); + + Json::Value& json_app_data = + GetSavedApplicationDataList().append(Json::Value()); + json_app_data[strings::device_id] = app_data.device_mac_; + json_app_data[strings::app_id] = app_data.mobile_app_id_; + json_app_data[strings::bundle_id] = app_data.bundle_id_; + json_app_data[strings::app_launch_last_session] = + static_cast<Json::Value::UInt64>(DateTime::getCurrentTime().tv_sec); + + LOG4CXX_DEBUG(logger_, + "New application data saved. Detatils device_id: " + << app_data.device_mac_ + << ", app_id: " << app_data.mobile_app_id_ + << ", bundle_id: " << app_data.bundle_id_ << "."); + + return true; +} + +std::vector<ApplicationDataPtr> AppLaunchDataJson::GetAppDataByDevMac( + const std::string& dev_mac) const { + using namespace application_manager; + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock autolock(app_launch_json_lock_); + std::vector<ApplicationDataPtr> dev_apps; + const Json::Value& apps_list = GetSavedApplicationDataList(); + const Json::ArrayIndex size = apps_list.size(); + + for (Json::ArrayIndex idx = 0; idx != size; ++idx) { + if (apps_list[idx].isMember(strings::device_id) && + apps_list[idx].isMember(strings::bundle_id) && + apps_list[idx].isMember(strings::app_id) && + apps_list[idx].isMember(strings::app_launch_last_session)) { + const std::string deviceMac = + apps_list[idx][strings::device_id].asString(); + const std::string bundleID = + apps_list[idx][strings::bundle_id].asString(); + const std::string appID = apps_list[idx][strings::app_id].asString(); + + if (deviceMac == dev_mac) { + dev_apps.push_back( + utils::MakeShared<ApplicationData>(appID, bundleID, deviceMac)); + } + } + } + + return dev_apps; +} + +bool AppLaunchDataJson::Clear() { + LOG4CXX_AUTO_TRACE(logger_); + + GetSavedApplicationDataList().clear(); + + LOG4CXX_DEBUG(logger_, + "Application launch JSON section successfully cleared."); + + return true; +} + +uint32_t AppLaunchDataJson::GetCurentNumberOfAppData() const { + LOG4CXX_AUTO_TRACE(logger_); + + uint32_t list_size = GetSavedApplicationDataList().size(); + + LOG4CXX_DEBUG(logger_, + "Successfully was gotten app_launch list. Size: " << list_size); + + return list_size; +} + +bool AppLaunchDataJson::DeleteOldestAppData() { + using namespace application_manager; + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock autolock(app_launch_json_lock_); + std::vector<uint64_t> temp_array; + std::vector<Json::Value> temp_json_list; + Json::Value& apps_list = GetSavedApplicationDataList(); + const Json::ArrayIndex size = apps_list.size(); + + // Search oldest record in Json + // for it collect all timestaps in vector + for (Json::ArrayIndex idx = 0; idx != size; ++idx) { + if (apps_list[idx].isMember(strings::device_id) && + apps_list[idx].isMember(strings::bundle_id) && + apps_list[idx].isMember(strings::app_id) && + apps_list[idx].isMember(strings::app_launch_last_session)) { + temp_array.push_back( + apps_list[idx][strings::app_launch_last_session].asUInt64()); + } + } + + // Calc oldest one and found index of it in Json + const int32_t oldest_index = + (std::min_element(temp_array.begin(), temp_array.end()) - + temp_array.begin()); + + // Copy in temporary vector Json list without oldest record + int32_t i = 0; + for (Json::Value::iterator it = GetSavedApplicationDataList().begin(); + it != GetSavedApplicationDataList().end(); + ++it, i++) { + if ((*it).isMember(strings::device_id) && + (*it).isMember(strings::bundle_id) && (*it).isMember(strings::app_id) && + (*it).isMember(strings::app_launch_last_session)) { + if (i == oldest_index) { + continue; + } + temp_json_list.push_back((*it)); + } + } + + // Clear Json list + GetSavedApplicationDataList().clear(); + + // Copy to Json new list without oldest one + for (std::vector<Json::Value>::iterator it = temp_json_list.begin(); + it != temp_json_list.end(); + ++it) { + GetSavedApplicationDataList().append((*it)); + } + + LOG4CXX_DEBUG( + logger_, "Oldest application launch data had been successfully deleted."); + + return true; +} + +bool AppLaunchDataJson::Persist() { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock autolock(app_launch_json_lock_); + last_state().SaveToFileSystem(); + return true; +} + +} // app_launch diff --git a/src/components/application_manager/src/app_launch/app_launch_sql_queries.cc b/src/components/application_manager/src/app_launch/app_launch_sql_queries.cc new file mode 100644 index 0000000000..950bcd44fa --- /dev/null +++ b/src/components/application_manager/src/app_launch/app_launch_sql_queries.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "application_manager/app_launch/app_launch_sql_queries.h" + +namespace app_launch { + +const std::string kCreateSchema = + "CREATE TABLE IF NOT EXISTS `app_launch`( " + " `deviceMac` TEXT, " + " `appID` TEXT," + " `bundleID` TEXT," + " `last_session` DATETIME, " + " PRIMARY KEY(`deviceMac`, `appID`, `bundleID`)" + " ); "; + +const std::string kDropSchema = "DROP TABLE IF EXISTS `app_launch`; "; + +const std::string kAddApplicationData = + "INSERT INTO `app_launch`" + "(`deviceMac`, `appID`, `bundleID`, `last_session`)" + "VALUES " + "(?, ?, ?, STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW'));"; + +const std::string kFindApplicationData = + " SELECT COUNT(*)" + "FROM `app_launch`" + "WHERE `deviceMac` = ? AND `appID` = ? AND `bundleID` = ?;"; + +const std::string kDeleteOldestAppData = + "DELETE FROM `app_launch`" + "WHERE `last_session` IN (" + "SELECT MIN(`last_session`)" + "FROM `app_launch`);"; + +const std::string kGetNumberOfApplicationData = + "SELECT COUNT (*)" + "FROM `app_launch` ;"; + +const std::string kGetApplicationDataByDevID = + "SELECT *" + "FROM `app_launch`" + "WHERE `deviceMac` = ?;"; + +const std::string kRefreshApplicationDataSessionTime = + "UPDATE `app_launch`" + "SET `last_session` = STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')" + "WHERE `deviceMac` = ? AND appID = ? AND bundleID = ?;"; + +} // namespace resumption diff --git a/src/components/application_manager/test/app_launch/app_launch_data_db_test.cc b/src/components/application_manager/test/app_launch/app_launch_data_db_test.cc new file mode 100644 index 0000000000..25cd1adfe6 --- /dev/null +++ b/src/components/application_manager/test/app_launch/app_launch_data_db_test.cc @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <algorithm> +#include <sstream> +#include <memory> +#include "gtest/gtest.h" +#include "utils/macro.h" +#include "sql_database.h" +#include "sql_query.h" +#include "utils/make_shared.h" +#include "utils/file_system.h" +#include "application_manager/mock_app_launch_settings.h" +#include "application_manager/app_launch/app_launch_data_db.h" +#include "application_manager/app_launch/app_launch_sql_queries.h" + +namespace test { +namespace components { +namespace test_app_launch { + +using namespace file_system; +using namespace app_launch; + +using ::testing::ReturnRef; +using ::testing::Return; +using ::testing::NiceMock; + +class AppLaunchDataDBTest : public ::testing::Test { + protected: + virtual void SetUp() { + utils::dbms::SQLQuery query(test_db()); + EXPECT_TRUE(query.Prepare(kCreateSchema)); + EXPECT_TRUE(query.Exec()); + printf("Create table\n"); + } + + virtual void TearDown() { + utils::dbms::SQLQuery query(test_db()); + EXPECT_TRUE(query.Prepare(kDropSchema)); + EXPECT_TRUE(query.Exec()); + printf("Delete table\n"); + } + + static void SetUpTestCase() { + NiceMock<MockAppLaunchSettings> mock_app_launch_settings_; + std::string curr_dir = file_system::CurrentWorkingDirectory(); + ON_CALL(mock_app_launch_settings_, app_storage_folder()) + .WillByDefault(ReturnRef(curr_dir)); + ON_CALL(mock_app_launch_settings_, max_number_of_ios_device()) + .WillByDefault(Return(15u)); + ON_CALL(mock_app_launch_settings_, app_launch_max_retry_attempt()) + .WillByDefault(Return(5u)); + ON_CALL(mock_app_launch_settings_, app_launch_retry_wait_time()) + .WillByDefault(Return(500u)); + if (is_in_file) { + res_db_.reset( + new AppLaunchDataDB(mock_app_launch_settings_, In_File_Storage)); + } else { + res_db_.reset( + new AppLaunchDataDB(mock_app_launch_settings_, In_Memory_Storage)); + } + test_db_ = (res_db_->db()); + + EXPECT_TRUE(test_db()->Open()); + EXPECT_TRUE(test_db()->IsReadWrite()); + } + + // Memory keep and clear AppLaunchDataDb + static utils::dbms::SQLDatabase* test_db_; + + static void TearDownTestCase() { + DeleteFile(kDatabaseName + ".sqlite"); + } + + static utils::dbms::SQLDatabase* test_db() { + return test_db_; + } + + static std::auto_ptr<AppLaunchDataDB> res_db_; + + AppLaunchDataDB* res_db() { + return res_db_.get(); + } + + const std::string kGetSsession = + " SELECT * FROM `app_launch` WHERE `deviceMac` = ? AND `appID` = ? AND " + "`bundleID` = ?;"; + const std::string kCheckTablesExist = + "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND " + "name='app_launch';"; + + const std::string kInsertTimestamp = + "UPDATE 'app_launch' " + "SET 'last_session' = ' 1666-06-16 06:06:06.666 '" + "WHERE `deviceMac` = ? AND `appID` = ? " + "AND `bundleID` = ?;"; + + // Write BD to file or memory + static const bool is_in_file = false; + + public: + void AddApplicationDataWithIncreaseTable(const ApplicationData& data); + void AddApplicationDataWithoutIncreaseTable(const ApplicationData& data); + std::string GetApplicationData(const ApplicationData& in_data, + ApplicationData& out_data); + std::string AddCounter(const std::string& inp, int32_t val); + void AddApplicationData_Expect_FALSE(const ApplicationData& data); +}; + +utils::dbms::SQLDatabase* AppLaunchDataDBTest::test_db_ = NULL; +std::auto_ptr<AppLaunchDataDB> AppLaunchDataDBTest::res_db_; + +void AppLaunchDataDBTest::AddApplicationDataWithIncreaseTable( + const ApplicationData& data) { + uint32_t sizeBeforeAdding = res_db()->GetCurentNumberOfAppData(); + EXPECT_TRUE(res_db()->AddApplicationData(data)); + + uint32_t sizeAfterAdding = res_db()->GetCurentNumberOfAppData(); + EXPECT_EQ(sizeBeforeAdding + 1u, sizeAfterAdding); +} + +void AppLaunchDataDBTest::AddApplicationDataWithoutIncreaseTable( + const ApplicationData& data) { + uint32_t sizeBeforeAdding = res_db()->GetCurentNumberOfAppData(); + EXPECT_TRUE(res_db()->AddApplicationData(data)); + + uint32_t sizeAfterAdding = res_db()->GetCurentNumberOfAppData(); + EXPECT_EQ(sizeBeforeAdding, sizeAfterAdding); +} + +std::string AppLaunchDataDBTest::GetApplicationData( + const ApplicationData& in_data, ApplicationData& out_data) { + utils::dbms::SQLQuery query(test_db()); + uint32_t sizeBeforeAdding = res_db()->GetCurentNumberOfAppData(); + EXPECT_TRUE(query.Prepare(kGetSsession)); + query.Bind(AppLaunchDataDB::device_mac_index, in_data.device_mac_); + query.Bind(AppLaunchDataDB::application_id_index, in_data.mobile_app_id_); + query.Bind(AppLaunchDataDB::bundle_id_index, in_data.bundle_id_); + EXPECT_TRUE(query.Exec()); + + uint32_t sizeAfterAdding = res_db()->GetCurentNumberOfAppData(); + + EXPECT_EQ(sizeBeforeAdding, sizeAfterAdding); + + out_data.device_mac_ = query.GetString(AppLaunchDataDB::device_mac_index); + out_data.mobile_app_id_ = + query.GetString(AppLaunchDataDB::application_id_index); + out_data.bundle_id_ = query.GetString(AppLaunchDataDB::bundle_id_index); + // Timestamp + return query.GetString(AppLaunchDataDB::timestamp_index); +} + +std::string AppLaunchDataDBTest::AddCounter(const std::string& inp, + int32_t val) { + std::stringstream ss; + ss << inp << val; + return ss.str(); +} + +TEST_F(AppLaunchDataDBTest, Init) { + utils::dbms::SQLQuery query_checks(test_db()); + EXPECT_TRUE(query_checks.Prepare(kCheckTablesExist)); + EXPECT_TRUE(query_checks.Exec()); + EXPECT_EQ(1u, query_checks.GetUInteger(0)); +} + +TEST_F(AppLaunchDataDBTest, SaveAndGetData) { + ApplicationData data("mobile_app_id", "bundle_id", "device_mac"); + AddApplicationDataWithIncreaseTable(data); + ApplicationData recoveredData("", "", ""); + GetApplicationData(data, recoveredData); + EXPECT_TRUE(data == recoveredData); +} + +TEST_F(AppLaunchDataDBTest, NotAddEmptyAppData) { + ApplicationData data1("", "bundle_id", "device_mac"); + ApplicationData data2("mobile_app_id", "", "device_mac"); + ApplicationData data3("mobile_app_id", "bundle_id", ""); + ApplicationData data4("", "", ""); + EXPECT_FALSE(res_db()->AddApplicationData(data1)); + EXPECT_FALSE(res_db()->AddApplicationData(data2)); + EXPECT_FALSE(res_db()->AddApplicationData(data3)); + EXPECT_FALSE(res_db()->AddApplicationData(data4)); + EXPECT_EQ(0u, res_db()->GetCurentNumberOfAppData()); +} + +TEST_F(AppLaunchDataDBTest, SaveOneAndGetAnotherData) { + ApplicationData data("mobile_app_id", "bundle_id", "device_mac"); + ApplicationData recoverData = data; + AddApplicationDataWithIncreaseTable(data); + recoverData.device_mac_ += "test"; + GetApplicationData(recoverData, recoverData); + EXPECT_FALSE(data == recoverData); +} + +TEST_F(AppLaunchDataDBTest, MaxCount) { + const uint32_t mac_ios_devs = res_db()->get_max_number_iOS_devs(); + for (uint32_t i = 0; i < mac_ios_devs; i++) { + ApplicationData data(AddCounter("mobile_app_id_", i), + AddCounter("bundle_id_", i), + "device_mac"); + AddApplicationDataWithIncreaseTable(data); + } + + utils::dbms::SQLQuery query(test_db()); + ApplicationData changedRecord("mobile_app_id_0", "bundle_id_0", "device_mac"); + EXPECT_TRUE(query.Prepare(kInsertTimestamp)); + query.Bind(AppLaunchDataDB::device_mac_index, changedRecord.device_mac_); + query.Bind(AppLaunchDataDB::application_id_index, + changedRecord.mobile_app_id_); + query.Bind(AppLaunchDataDB::bundle_id_index, changedRecord.bundle_id_); + EXPECT_TRUE(query.Exec()); + + uint32_t size_max = res_db()->GetCurentNumberOfAppData(); + EXPECT_EQ(mac_ios_devs, size_max); + EXPECT_TRUE(res_db()->AddApplicationData(ApplicationData( + "mobile_app_id_last", "bundle_id_last", "device_mac_last"))); + uint32_t size_after_max = res_db()->GetCurentNumberOfAppData(); + EXPECT_EQ(size_max, size_after_max); + EXPECT_FALSE(res_db()->IsAppDataAlreadyExisted(changedRecord)); +} + +namespace { +bool ApplicationDataComporator(const ApplicationDataPtr& left, + const ApplicationDataPtr& right) { + return (left->device_mac_ < right->device_mac_ && + left->mobile_app_id_ < right->mobile_app_id_ && + left->bundle_id_ < right->bundle_id_); +} +} // namespace + +TEST_F(AppLaunchDataDBTest, SelectMultipleData) { + std::vector<ApplicationDataPtr> input_data1; + std::vector<ApplicationDataPtr> input_data2; + std::vector<ApplicationDataPtr> output_data1; + std::vector<ApplicationDataPtr> output_data2; + const std::string device_mac_1 = "device_mac_1"; + const std::string device_mac_2 = "device_mac_2"; + + uint32_t half_part = res_db()->get_max_number_iOS_devs() / 2u; + + for (uint32_t i = 0; i < half_part; i++) { + const std::string mobile_app_id = AddCounter("d1_mobile_app_id_", i); + const std::string bundle_id = AddCounter("d1_bundle_id_", i); + + ApplicationDataPtr app_data = utils::MakeShared<ApplicationData>( + mobile_app_id, bundle_id, device_mac_1); + AddApplicationDataWithIncreaseTable(*app_data); + input_data1.push_back(app_data); + } + + for (uint32_t i = 0; i < half_part; i++) { + const std::string mobile_app_id = AddCounter("d2_mobile_app_id_", i); + const std::string bundle_id = AddCounter("d2_bundle_id_", i); + + ApplicationDataPtr app_data = utils::MakeShared<ApplicationData>( + mobile_app_id, bundle_id, device_mac_2); + AddApplicationDataWithIncreaseTable(*app_data); + input_data2.push_back(app_data); + } + + output_data1 = res_db()->GetApplicationDataByDevice(device_mac_1); + output_data2 = res_db()->GetApplicationDataByDevice(device_mac_2); + + EXPECT_EQ(half_part, output_data1.size()); + EXPECT_EQ(half_part, output_data2.size()); + + std::sort( + output_data1.begin(), output_data1.end(), ApplicationDataComporator); + std::sort( + output_data2.begin(), output_data2.end(), ApplicationDataComporator); + std::sort(input_data1.begin(), input_data1.end(), ApplicationDataComporator); + std::sort(input_data2.begin(), input_data2.end(), ApplicationDataComporator); + + for (uint32_t i = 0; i < output_data1.size(); i++) { + EXPECT_TRUE(*output_data1[i] == *input_data1[i]); + } + + for (uint32_t i = 0; i < output_data2.size(); i++) { + EXPECT_TRUE(*output_data2[i] == *input_data2[i]); + } +} + +// Most be last cause after it AppLaunchDataDBTest +// requeste manual Init call +TEST_F(AppLaunchDataDBTest, DeleteAllTableDataTwice) { + for (uint32_t i = 0; i < res_db()->get_max_number_iOS_devs(); i++) { + ApplicationData data(AddCounter("mobile_app_id_", i), + AddCounter("bundle_id_", i), + "device_mac"); + AddApplicationDataWithIncreaseTable(data); + } + + uint32_t full_size = res_db()->GetCurentNumberOfAppData(); + + EXPECT_EQ(full_size, res_db()->get_max_number_iOS_devs()); + EXPECT_TRUE(res_db()->Clear()); // delete data + EXPECT_EQ(0u, res_db()->GetCurentNumberOfAppData()); + EXPECT_TRUE(res_db()->Clear()); // second time delete data + EXPECT_EQ(0u, res_db()->GetCurentNumberOfAppData()); +} + +} // namespace test_app_launch +} // namespace components +} // namespace test diff --git a/src/components/application_manager/test/app_launch/app_launch_data_json_test.cc b/src/components/application_manager/test/app_launch/app_launch_data_json_test.cc new file mode 100644 index 0000000000..aee8456d58 --- /dev/null +++ b/src/components/application_manager/test/app_launch/app_launch_data_json_test.cc @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2016, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <algorithm> +#include <sstream> +#include <memory> +#include "json/json.h" +#include "gtest/gtest.h" +#include "utils/macro.h" +#include "utils/make_shared.h" +#include "utils/file_system.h" +#include "utils/date_time.h" +#include "resumption/last_state.h" +#include "smart_objects/smart_object.h" +#include "application_manager/smart_object_keys.h" +#include "application_manager/mock_app_launch_settings.h" +#include "application_manager/app_launch/app_launch_data_json.h" + +namespace test { +namespace components { +namespace test_app_launch { + +using ::testing::_; +using ::testing::Return; +using ::testing::NiceMock; + +namespace am = application_manager; +using namespace Json; +using namespace file_system; + +using namespace app_launch; + +const std::string kAppStorageFolder = "app_storage_folder"; +const std::string kAppStorageFile = "./app_info.dat"; +const std::string kAppInfoStorage = "app_info_storage"; + +class AppLaunchDataJsonTest : public ::testing::Test { + private: + virtual void SetUp() { + ::file_system::DeleteFile(kAppStorageFile); + test_last_state_ = std::auto_ptr<resumption::LastState>( + new resumption::LastState(kAppStorageFolder, kAppInfoStorage)); + ASSERT_TRUE(::file_system::CreateFile(kAppStorageFile)); + + NiceMock<MockAppLaunchSettings> mock_app_launch_settings_; + ON_CALL(mock_app_launch_settings_, max_number_of_ios_device()) + .WillByDefault(Return(15u)); + + res_json_.reset( + new AppLaunchDataJson(mock_app_launch_settings_, *test_last_state_)); + } + + public: + void TearDown() OVERRIDE { + res_json_.get()->Clear(); + } + + static void SetUpTestCase() {} + + static void TearDownTestCase() { + ::file_system::DeleteFile(kAppStorageFile); + ::file_system::RemoveDirectory(kAppStorageFolder); + } + + AppLaunchDataJson* res_json() { + return res_json_.get(); + } + + void AddApplicationDataWithIncreaseTable(const ApplicationData& data); + void AddApplicationDataWithoutIncreaseTable(const ApplicationData& data); + TimevalStruct GetApplicationData_EXPECT_TRUE(const ApplicationData& in_data, + ApplicationData& out_data); + void GetApplicationData_EXPECT_FALSE(const ApplicationData& in_data); + std::string AddCounter(const std::string& inp, int32_t val); + + std::auto_ptr<resumption::LastState> test_last_state_; + std::auto_ptr<AppLaunchDataJson> res_json_; + void SetTimestamp(const ApplicationData& in_data, TimevalStruct& timestamp); +}; + +void AppLaunchDataJsonTest::AddApplicationDataWithIncreaseTable( + const ApplicationData& data) { + uint32_t sizeBeforeAdding = res_json()->GetCurentNumberOfAppData(); + + EXPECT_TRUE(res_json()->AddApplicationData(data)); + + uint32_t sizeAfterAdding = res_json()->GetCurentNumberOfAppData(); + + EXPECT_EQ(sizeBeforeAdding + 1u, sizeAfterAdding); +} + +void AppLaunchDataJsonTest::AddApplicationDataWithoutIncreaseTable( + const ApplicationData& data) { + uint32_t sizeBeforeAdding = res_json()->GetCurentNumberOfAppData(); + + EXPECT_TRUE(res_json()->AddApplicationData(data)); + + uint32_t sizeAfterAdding = res_json()->GetCurentNumberOfAppData(); + + EXPECT_EQ(sizeBeforeAdding, sizeAfterAdding); +} + +TimevalStruct AppLaunchDataJsonTest::GetApplicationData_EXPECT_TRUE( + const ApplicationData& in_data, ApplicationData& out_data) { + uint32_t sizeBeforeGetting = res_json()->GetCurentNumberOfAppData(); + + int32_t index = NotFound; + Json::Value& json_data_list = + res_json()->GetApplicationListAndIndex(in_data, index); + EXPECT_FALSE(index == NotFound); + + uint32_t sizeAfterGetting = res_json()->GetCurentNumberOfAppData(); + + EXPECT_EQ(sizeBeforeGetting, sizeAfterGetting); + out_data.device_mac_ = + json_data_list[index][am::strings::device_id].asString(); + out_data.mobile_app_id_ = + json_data_list[index][am::strings::app_id].asString(); + out_data.bundle_id_ = + json_data_list[index][am::strings::bundle_id].asString(); + // time stamp + TimevalStruct tmVal = {0}; + tmVal.tv_sec = + json_data_list[index][am::strings::app_launch_last_session].asUInt64(); + return tmVal; +} + +void AppLaunchDataJsonTest::GetApplicationData_EXPECT_FALSE( + const ApplicationData& in_data) { + uint32_t sizeBeforeGetting = res_json()->GetCurentNumberOfAppData(); + + int32_t index = NotFound; + res_json()->GetApplicationListAndIndex(in_data, index); + EXPECT_TRUE(index == NotFound); + + uint32_t sizeAfterGetting = res_json()->GetCurentNumberOfAppData(); + + EXPECT_EQ(sizeBeforeGetting, sizeAfterGetting); +} + +void AppLaunchDataJsonTest::SetTimestamp(const ApplicationData& in_data, + TimevalStruct& timestamp) { + uint32_t sizeBeforeGetting = res_json()->GetCurentNumberOfAppData(); + + int32_t index = NotFound; + Json::Value& json_data_list = + res_json()->GetApplicationListAndIndex(in_data, index); + EXPECT_FALSE(index == NotFound); + + uint32_t sizeAfterGetting = res_json()->GetCurentNumberOfAppData(); + + EXPECT_FALSE(index == NotFound); + + EXPECT_EQ(sizeBeforeGetting, sizeAfterGetting); + // time stamp + json_data_list[index][am::strings::app_launch_last_session] = + static_cast<Json::Value::UInt64>(timestamp.tv_sec); +} + +std::string AppLaunchDataJsonTest::AddCounter(const std::string& inp, + int32_t val) { + std::stringstream ss; + ss << inp << val; + return ss.str(); +} + +TEST_F(AppLaunchDataJsonTest, SaveAndGetData) { + ApplicationData data("mobile_app_id", "bundle_id", "device_mac"); + AddApplicationDataWithIncreaseTable(data); + ApplicationData recoveredData("", "", ""); + GetApplicationData_EXPECT_TRUE(data, recoveredData); + EXPECT_TRUE(data == recoveredData); +} + +TEST_F(AppLaunchDataJsonTest, NotAddEmptyAppData) { + ApplicationData data1("", "bundle_id", "device_mac"); + ApplicationData data2("mobile_app_id", "", "device_mac"); + ApplicationData data3("mobile_app_id", "bundle_id", ""); + ApplicationData data4("", "", ""); + EXPECT_FALSE(res_json()->AddApplicationData(data1)); + EXPECT_FALSE(res_json()->AddApplicationData(data2)); + EXPECT_FALSE(res_json()->AddApplicationData(data3)); + EXPECT_FALSE(res_json()->AddApplicationData(data4)); + EXPECT_EQ(0u, res_json()->GetCurentNumberOfAppData()); +} + +TEST_F(AppLaunchDataJsonTest, SaveOneAndGetAnotherData) { + ApplicationData data("mobile_app_id", "bundle_id", "device_mac"); + ApplicationData recoverData = data; + AddApplicationDataWithIncreaseTable(data); + recoverData.device_mac_ += "test"; + GetApplicationData_EXPECT_FALSE(recoverData); +} + +TEST_F(AppLaunchDataJsonTest, RefreshTimestamp) { + ApplicationData data("mobile_app_id", "bundle_id", "device_mac"); + AddApplicationDataWithIncreaseTable(data); + ApplicationData recoveredData("", "", ""); + TimevalStruct timestamp1 = + GetApplicationData_EXPECT_TRUE(data, recoveredData); + TimevalStruct tm = {0, 0}; + SetTimestamp(data, tm); + TimevalStruct timestamp2 = + GetApplicationData_EXPECT_TRUE(data, recoveredData); + EXPECT_NE(timestamp1.tv_sec, timestamp2.tv_sec); + AddApplicationDataWithoutIncreaseTable(data); // again insert the same + TimevalStruct timestamp3 = + GetApplicationData_EXPECT_TRUE(data, recoveredData); + EXPECT_TRUE(data == recoveredData); + EXPECT_NE(timestamp2.tv_sec, timestamp3.tv_sec); +} + +TEST_F(AppLaunchDataJsonTest, MaxCount) { + const uint32_t max_ios_devs = res_json()->get_max_number_iOS_devs(); + for (uint32_t i = 0; i < max_ios_devs; i++) { + ApplicationData data(AddCounter("mobile_app_id_", i), + AddCounter("bundle_id_", i), + "device_mac"); + AddApplicationDataWithIncreaseTable(data); + } + + // insert new time stamp + ApplicationData changedRecord("mobile_app_id_0", "bundle_id_0", "device_mac"); + TimevalStruct tm = {0, 0}; + SetTimestamp(changedRecord, tm); + + uint32_t size_max = res_json()->GetCurentNumberOfAppData(); + EXPECT_EQ(max_ios_devs, size_max); + EXPECT_TRUE(res_json()->AddApplicationData(ApplicationData( + "mobile_app_id_last", "bundle_id_last", "device_mac_last"))); + uint32_t size_after_max = res_json()->GetCurentNumberOfAppData(); + EXPECT_EQ(size_max, size_after_max); + EXPECT_FALSE(res_json()->IsAppDataAlreadyExisted(changedRecord)); +} + +TEST_F(AppLaunchDataJsonTest, DeleteAllJsonDataTwice) { + for (uint32_t i = 0; i < res_json()->get_max_number_iOS_devs(); i++) { + ApplicationData data(AddCounter("mobile_app_id_", i), + AddCounter("bundle_id_", i), + "device_mac"); + AddApplicationDataWithIncreaseTable(data); + } + + uint32_t full_size = res_json()->GetCurentNumberOfAppData(); + + EXPECT_EQ(full_size, res_json()->get_max_number_iOS_devs()); + EXPECT_TRUE(res_json()->Clear()); // delete data + EXPECT_EQ(0u, res_json()->GetCurentNumberOfAppData()); + EXPECT_TRUE(res_json()->Clear()); // second time delete data + EXPECT_EQ(0u, res_json()->GetCurentNumberOfAppData()); +} + +namespace { +bool ApplicationDataComporator(const ApplicationDataPtr& left, + const ApplicationDataPtr& right) { + return (left->device_mac_ < right->device_mac_ && + left->mobile_app_id_ < right->mobile_app_id_ && + left->bundle_id_ < right->bundle_id_); +} +} // namespace + +TEST_F(AppLaunchDataJsonTest, SelectMultipleData) { + std::vector<ApplicationDataPtr> input_data1; + std::vector<ApplicationDataPtr> input_data2; + std::vector<ApplicationDataPtr> output_data1; + std::vector<ApplicationDataPtr> output_data2; + const std::string device_mac_1 = "device_mac_1"; + const std::string device_mac_2 = "device_mac_2"; + uint32_t half_part = res_json()->get_max_number_iOS_devs() / 2u; + + for (uint32_t i = 0; i < half_part; i++) { + const std::string mobile_app_id = AddCounter("d1_mobile_app_id_", i); + const std::string bundle_id = AddCounter("d1_bundle_id_", i); + + ApplicationDataPtr app_data = utils::MakeShared<ApplicationData>( + mobile_app_id, bundle_id, device_mac_1); + AddApplicationDataWithIncreaseTable(*app_data); + input_data1.push_back(app_data); + } + + for (uint32_t i = 0; i < half_part; i++) { + const std::string mobile_app_id = AddCounter("d2_mobile_app_id_", i); + const std::string bundle_id = AddCounter("d2_bundle_id_", i); + + ApplicationDataPtr app_data = utils::MakeShared<ApplicationData>( + mobile_app_id, bundle_id, device_mac_2); + AddApplicationDataWithIncreaseTable(*app_data); + input_data2.push_back(app_data); + } + + output_data1 = res_json()->GetApplicationDataByDevice(device_mac_1); + output_data2 = res_json()->GetApplicationDataByDevice(device_mac_2); + + EXPECT_EQ(half_part, output_data1.size()); + EXPECT_EQ(half_part, output_data2.size()); + + std::sort( + output_data1.begin(), output_data1.end(), ApplicationDataComporator); + std::sort( + output_data2.begin(), output_data2.end(), ApplicationDataComporator); + std::sort(input_data1.begin(), input_data1.end(), ApplicationDataComporator); + std::sort(input_data2.begin(), input_data2.end(), ApplicationDataComporator); + + for (uint32_t i = 0; i < output_data1.size(); i++) { + EXPECT_TRUE(*output_data1[i] == *input_data1[i]); + } + + for (uint32_t i = 0; i < output_data2.size(); i++) { + EXPECT_TRUE(*output_data2[i] == *input_data2[i]); + } +} + +} // namespace app_launch +} // namespace components +} // namespace test |