summaryrefslogtreecommitdiff
path: root/src/components/application_manager
diff options
context:
space:
mode:
authorAndrey Oleynik (GitHub) <dev-gh@users.noreply.github.com>2017-01-05 15:39:37 +0200
committerGitHub <noreply@github.com>2017-01-05 15:39:37 +0200
commit980a945110ed1f58000de4ad178dc877a9372b80 (patch)
treea93877c94bebce1ff198c3222cfd6cca56b4bf8a /src/components/application_manager
parent086097c4d8aac14cb425207f3392fe8ab3f28bf6 (diff)
parent059dae5f04ff38bd9f61827a9ed53b07e2adcbd7 (diff)
downloadsdl_core-980a945110ed1f58000de4ad178dc877a9372b80.tar.gz
Merge pull request #1149 from dev-gh/fix/Fix_max_requiests_constraint_check
Fixes logic of max requests per time scale constraint verification
Diffstat (limited to 'src/components/application_manager')
-rw-r--r--src/components/application_manager/include/application_manager/request_controller.h19
-rw-r--r--src/components/application_manager/include/application_manager/request_info.h82
-rw-r--r--src/components/application_manager/include/application_manager/request_tracker.h125
-rw-r--r--src/components/application_manager/src/request_controller.cc37
-rw-r--r--src/components/application_manager/src/request_info.cc60
-rw-r--r--src/components/application_manager/src/request_tracker.cc133
-rw-r--r--src/components/application_manager/test/CMakeLists.txt1
-rw-r--r--src/components/application_manager/test/request_info_test.cc101
-rw-r--r--src/components/application_manager/test/request_tracker_test.cc251
9 files changed, 537 insertions, 272 deletions
diff --git a/src/components/application_manager/include/application_manager/request_controller.h b/src/components/application_manager/include/application_manager/request_controller.h
index 479ebb217e..d3a5a0b821 100644
--- a/src/components/application_manager/include/application_manager/request_controller.h
+++ b/src/components/application_manager/include/application_manager/request_controller.h
@@ -49,6 +49,7 @@
#include "application_manager/request_info.h"
#include "application_manager/request_controller_settings.h"
+#include "application_manager/request_tracker.h"
namespace application_manager {
@@ -229,11 +230,15 @@ class RequestController {
void terminateWaitingForResponseAppRequests(const uint32_t& app_id);
/**
- * @brief Check Posibility to add new requests, or limits was exceeded
- * @param request - request to check possipility to Add
- * @return True if new request could be added, false otherwise
+ * @brief Checks whether all constraints are met before adding of request into
+ * processing queue. Verifies amount of pending requests, amount of requests
+ * per time scale for different HMI levels
+ * @param request - request to check constraints for
+ * @param level - HMI level in which request has been issued
+ * @return Appropriate result code of verification
*/
- TResult CheckPosibilitytoAdd(const RequestPtr request);
+ TResult CheckPosibilitytoAdd(const RequestPtr request,
+ const mobile_api::HMILevel::eType level);
/**
* @brief Check Posibility to add new requests, or limits was exceeded
@@ -274,6 +279,12 @@ class RequestController {
RequestInfoSet waiting_for_response_;
/**
+ * @brief Tracker verifying time scale and maximum requests amount in
+ * different HMI levels
+ */
+ RequestTracker request_tracker_;
+
+ /**
* @brief Set of HMI notifications with timeout.
*/
std::list<RequestPtr> notification_list_;
diff --git a/src/components/application_manager/include/application_manager/request_info.h b/src/components/application_manager/include/application_manager/request_info.h
index 193699be78..216eb86cc5 100644
--- a/src/components/application_manager/include/application_manager/request_info.h
+++ b/src/components/application_manager/include/application_manager/request_info.h
@@ -63,9 +63,7 @@ struct RequestInfo {
RequestInfo(RequestPtr request,
const RequestType requst_type,
const uint64_t timeout_msec)
- : request_(request)
- , timeout_msec_(timeout_msec)
- , hmi_level_(mobile_apis::HMILevel::INVALID_ENUM) {
+ : request_(request), timeout_msec_(timeout_msec) {
start_time_ = date_time::DateTime::getCurrentTime();
updateEndTime();
requst_type_ = requst_type;
@@ -106,14 +104,6 @@ struct RequestInfo {
return app_id_;
}
- mobile_apis::HMILevel::eType hmi_level() {
- return hmi_level_;
- }
-
- void set_hmi_level(const mobile_apis::HMILevel::eType& level) {
- hmi_level_ = level;
- }
-
RequestType requst_type() const {
return requst_type_;
}
@@ -135,7 +125,6 @@ struct RequestInfo {
uint64_t timeout_msec_;
TimevalStruct end_time_;
uint32_t app_id_;
- mobile_apis::HMILevel::eType hmi_level_;
RequestType requst_type_;
uint32_t correlation_id_;
};
@@ -234,34 +223,6 @@ class RequestInfoSet {
*/
const size_t Size();
- /**
- * @brief Check if this app is able to add new requests,
- * or limits was exceeded
- * @param app_id - application id
- * @param app_time_scale - time scale (seconds)
- * @param max_request_per_time_scale - maximum count of request
- * that should be allowed for app_time_scale seconds
- * @return True if new request could be added, false otherwise
- */
- bool CheckTimeScaleMaxRequest(uint32_t app_id,
- uint32_t app_time_scale,
- uint32_t max_request_per_time_scale);
-
- /**
- * @brief Check if this app is able to add new requests
- * in current hmi_level, or limits was exceeded
- * @param hmi_level - hmi level
- * @param app_id - application id
- * @param app_time_scale - time scale (seconds)
- * @param max_request_per_time_scale - maximum count of request
- * that should be allowed for app_time_scale seconds
- * @return True if new request could be added, false otherwise
- */
- bool CheckHMILevelTimeScaleMaxRequest(mobile_apis::HMILevel::eType hmi_level,
- uint32_t app_id,
- uint32_t app_time_scale,
- uint32_t max_request_per_time_scale);
-
private:
/*
* @brief Comparator of connection key for std::find_if function
@@ -329,47 +290,6 @@ struct TimeScale {
uint32_t app_id_;
};
-/**
-* @brief Structure used in std algorithms to determine amount of request
-* during time scale for application in defined hmi level
-*/
-struct HMILevelTimeScale {
- HMILevelTimeScale(const TimevalStruct& start,
- const TimevalStruct& end,
- const uint32_t& app_id,
- const mobile_apis::HMILevel::eType& hmi_level)
- : start_(start), end_(end), app_id_(app_id), hmi_level_(hmi_level) {}
-
- bool operator()(RequestInfoPtr setEntry) {
- if (!setEntry.valid()) {
- return false;
- }
-
- if (setEntry->app_id() != app_id_) {
- return false;
- }
-
- if (setEntry->hmi_level() != hmi_level_) {
- return false;
- }
-
- if (date_time::DateTime::getSecs(setEntry->start_time()) <
- date_time::DateTime::getSecs(start_) ||
- date_time::DateTime::getSecs(setEntry->start_time()) >
- date_time::DateTime::getSecs(end_)) {
- return false;
- }
-
- return true;
- }
-
- private:
- TimevalStruct start_;
- TimevalStruct end_;
- uint32_t app_id_;
- mobile_apis::HMILevel::eType hmi_level_;
-};
-
} // namespace request_controller
} // namespace application_manager
diff --git a/src/components/application_manager/include/application_manager/request_tracker.h b/src/components/application_manager/include/application_manager/request_tracker.h
new file mode 100644
index 0000000000..36ab3eaefb
--- /dev/null
+++ b/src/components/application_manager/include/application_manager/request_tracker.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2017, 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_REQUEST_TRACKER_H_
+#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_REQUEST_TRACKER_H_
+
+#include <string>
+#include <map>
+#include <vector>
+#include "application_manager/request_controller_settings.h"
+#include "interfaces/MOBILE_API.h"
+#include "utils/date_time.h"
+
+namespace application_manager {
+
+namespace request_controller {
+
+/**
+ * @brief The TrackResult enum defines results of application request tracking
+ */
+enum class TrackResult {
+ kSuccess,
+ kNoneLevelMaxRequestsExceeded,
+ kMaxRequestsExceeded
+};
+
+/**
+ * @brief The RequestTracker class tracks requests per time constraints.
+ * There are several parameters in configuration file defining maximum
+ * requests
+ * number and time scale for that number, so application must consider that,
+ * otherwise it will be disconnected and won't be registered till next
+ * ignition
+ * cycle.
+ */
+class RequestTracker {
+ public:
+ typedef uint32_t ApplicationID;
+
+ /**
+ * @brief RequestTracker class constructor
+ * @param settings Settings instance having time scale and maximum requests
+ * values
+ */
+ explicit RequestTracker(const RequestControlerSettings& settings);
+
+ /**
+ * @brief Tracks amount of requests per defined time considering HMI level
+ * Currently there is a separate restrictions can be set for NONE level.
+ * Other levels tracked by single constraint.
+ * @param app_id Unique application id
+ * @param level HMI level of request
+ * @return Success if constraints are not exceeded, otherwise - exceeded
+ * error code (depends on HMI level)
+ */
+ TrackResult Track(const ApplicationID& app_id,
+ const mobile_apis::HMILevel::eType level);
+
+ private:
+ typedef std::vector<TimevalStruct> RequestAddedAt;
+ typedef std::map<ApplicationID, RequestAddedAt> ApplicationsRequestsTracker;
+
+ /**
+ * @brief Checks whether maximum requests number is exceeded per defined
+ * time
+ * scale.
+ * @param app_id Unique application id
+ * @param time_scale Time scale defined in configuration file
+ * @param max_requests Maximum requests number defined in configuration file
+ * @param tracker Container tracking applications requests amount and their
+ * time of addition into processing
+ * @return
+ */
+ bool Track(const ApplicationID& app_id,
+ const uint32_t time_scale,
+ const uint32_t max_requests,
+ ApplicationsRequestsTracker& tracker);
+
+ /**
+ * @brief settings_ having time scale and maximum requests values
+ */
+ const RequestControlerSettings& settings_;
+
+ /**
+ * @brief Tracker for applications requests done in NONE level
+ */
+ ApplicationsRequestsTracker none_level_tracker_;
+
+ /**
+ * @brief Tracker for applications requests done in other than NONE level
+ */
+ ApplicationsRequestsTracker tracker_;
+};
+
+} // namespace request_controller
+} // namespace application_manager
+#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_REQUEST_TRACKER_H_
diff --git a/src/components/application_manager/src/request_controller.cc b/src/components/application_manager/src/request_controller.cc
index 3b3ea839d7..77a1853a39 100644
--- a/src/components/application_manager/src/request_controller.cc
+++ b/src/components/application_manager/src/request_controller.cc
@@ -49,6 +49,7 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "RequestController")
RequestController::RequestController(const RequestControlerSettings& settings)
: pool_state_(UNDEFINED)
, pool_size_(settings.thread_pool_size())
+ , request_tracker_(settings)
, timer_("AM RequestCtrlTimer",
new timer::TimerTaskImpl<RequestController>(
this, &RequestController::TimeoutThread))
@@ -101,42 +102,26 @@ void RequestController::DestroyThreadpool() {
}
RequestController::TResult RequestController::CheckPosibilitytoAdd(
- const RequestPtr request) {
+ const RequestPtr request, const mobile_apis::HMILevel::eType level) {
LOG4CXX_AUTO_TRACE(logger_);
- const uint32_t& app_hmi_level_none_time_scale =
- settings_.app_hmi_level_none_time_scale();
-
- // app_hmi_level_none_max_request_per_time_scale
- const uint32_t& hmi_level_none_count =
- settings_.app_hmi_level_none_time_scale_max_requests();
-
- const uint32_t& app_time_scale = settings_.app_time_scale();
-
- const uint32_t& max_request_per_time_scale =
- settings_.app_time_scale_max_requests();
-
- const uint32_t& pending_requests_amount = settings_.pending_requests_amount();
-
- if (!CheckPendingRequestsAmount(pending_requests_amount)) {
+ if (!CheckPendingRequestsAmount(settings_.pending_requests_amount())) {
LOG4CXX_ERROR(logger_, "Too many pending request");
return RequestController::TOO_MANY_PENDING_REQUESTS;
}
- if (!waiting_for_response_.CheckHMILevelTimeScaleMaxRequest(
- mobile_apis::HMILevel::HMI_NONE,
- request->connection_key(),
- app_hmi_level_none_time_scale,
- hmi_level_none_count)) {
+ const TrackResult track_result =
+ request_tracker_.Track(request->connection_key(), level);
+
+ if (TrackResult::kNoneLevelMaxRequestsExceeded == track_result) {
LOG4CXX_ERROR(logger_, "Too many application requests in hmi level NONE");
return RequestController::NONE_HMI_LEVEL_MANY_REQUESTS;
}
- if (!waiting_for_response_.CheckTimeScaleMaxRequest(
- request->connection_key(),
- app_time_scale,
- max_request_per_time_scale)) {
+
+ if (TrackResult::kMaxRequestsExceeded == track_result) {
LOG4CXX_ERROR(logger_, "Too many application requests");
return RequestController::TOO_MANY_REQUESTS;
}
+
return SUCCESS;
}
@@ -171,7 +156,7 @@ RequestController::TResult RequestController::addMobileRequest(
logger_,
"correlation_id : " << request->correlation_id()
<< "connection_key : " << request->connection_key());
- RequestController::TResult result = CheckPosibilitytoAdd(request);
+ RequestController::TResult result = CheckPosibilitytoAdd(request, hmi_level);
if (SUCCESS == result) {
AutoLock auto_lock_list(mobile_request_list_lock_);
mobile_request_list_.push_back(request);
diff --git a/src/components/application_manager/src/request_info.cc b/src/components/application_manager/src/request_info.cc
index 80b18a53c6..9a5828d939 100644
--- a/src/components/application_manager/src/request_info.cc
+++ b/src/components/application_manager/src/request_info.cc
@@ -268,66 +268,6 @@ void RequestInfoSet::CheckSetSizes() {
DCHECK(set_sizes_equal);
}
-bool RequestInfoSet::CheckTimeScaleMaxRequest(
- uint32_t app_id,
- uint32_t app_time_scale,
- uint32_t max_request_per_time_scale) {
- LOG4CXX_AUTO_TRACE(logger_);
- if (max_request_per_time_scale > 0 && app_time_scale > 0) {
- TimevalStruct end = date_time::DateTime::getCurrentTime();
- TimevalStruct start = {0, 0};
- start.tv_sec = end.tv_sec - app_time_scale;
-
- sync_primitives::AutoLock lock(this_lock_);
- TimeScale scale(start, end, app_id);
- const uint32_t count = std::count_if(time_sorted_pending_requests_.begin(),
- time_sorted_pending_requests_.end(),
- scale);
- if (count >= max_request_per_time_scale) {
- LOG4CXX_WARN(logger_,
- "Processing requests count " << count
- << " exceed application limit "
- << max_request_per_time_scale);
- return false;
- }
- LOG4CXX_DEBUG(logger_, "Requests count " << count);
- } else {
- LOG4CXX_DEBUG(logger_, "CheckTimeScaleMaxRequest disabled");
- }
- return true;
-}
-
-bool RequestInfoSet::CheckHMILevelTimeScaleMaxRequest(
- mobile_apis::HMILevel::eType hmi_level,
- uint32_t app_id,
- uint32_t app_time_scale,
- uint32_t max_request_per_time_scale) {
- LOG4CXX_AUTO_TRACE(logger_);
- if (max_request_per_time_scale > 0 && app_time_scale > 0) {
- TimevalStruct end = date_time::DateTime::getCurrentTime();
- TimevalStruct start = {0, 0};
- start.tv_sec = end.tv_sec - app_time_scale;
-
- sync_primitives::AutoLock lock(this_lock_);
- HMILevelTimeScale scale(start, end, app_id, hmi_level);
- const uint32_t count = std::count_if(time_sorted_pending_requests_.begin(),
- time_sorted_pending_requests_.end(),
- scale);
- if (count >= max_request_per_time_scale) {
- LOG4CXX_WARN(logger_,
- "Processing requests count "
- << count << " exceed application limit "
- << max_request_per_time_scale << " in hmi level "
- << hmi_level);
- return false;
- }
- LOG4CXX_DEBUG(logger_, "Requests count " << count);
- } else {
- LOG4CXX_DEBUG(logger_, "CheckHMILevelTimeScaleMaxRequest disabled");
- }
- return true;
-}
-
bool RequestInfoSet::AppIdCompararator::operator()(
const RequestInfoPtr value_compare) const {
switch (compare_type_) {
diff --git a/src/components/application_manager/src/request_tracker.cc b/src/components/application_manager/src/request_tracker.cc
new file mode 100644
index 0000000000..13b3d4d873
--- /dev/null
+++ b/src/components/application_manager/src/request_tracker.cc
@@ -0,0 +1,133 @@
+/*
+* Copyright (c) 2017, 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 "utils/logger.h"
+#include "utils/macro.h"
+#include "application_manager/request_tracker.h"
+#include "application_manager/message_helper.h"
+
+namespace application_manager {
+
+namespace request_controller {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "RequestController")
+
+RequestTracker::RequestTracker(const RequestControlerSettings& settings)
+ : settings_(settings) {}
+
+TrackResult RequestTracker::Track(const ApplicationID& app_id,
+ const mobile_apis::HMILevel::eType level) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ bool track_result = false;
+
+ LOG4CXX_DEBUG(logger_,
+ "Tracking request for level: "
+ << MessageHelper::StringifiedHMILevel(level));
+
+ if (mobile_apis::HMILevel::HMI_NONE == level) {
+ track_result = Track(app_id,
+ settings_.app_hmi_level_none_time_scale(),
+ settings_.app_hmi_level_none_time_scale_max_requests(),
+ none_level_tracker_);
+
+ return track_result ? TrackResult::kSuccess
+ : TrackResult::kNoneLevelMaxRequestsExceeded;
+ }
+
+ track_result = Track(app_id,
+ settings_.app_time_scale(),
+ settings_.app_time_scale_max_requests(),
+ tracker_);
+
+ return track_result ? TrackResult::kSuccess
+ : TrackResult::kMaxRequestsExceeded;
+}
+
+bool RequestTracker::Track(const ApplicationID& app_id,
+ const uint32_t time_scale,
+ const uint32_t max_requests,
+ ApplicationsRequestsTracker& tracker) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ using date_time::DateTime;
+
+ if (!time_scale || !max_requests) {
+ LOG4CXX_INFO(logger_, "Time scale request tracking is disabled.");
+ return true;
+ }
+
+ LOG4CXX_DEBUG(logger_,
+ "Time scale is: " << time_scale << ". Max requests number is: "
+ << max_requests);
+
+ LOG4CXX_DEBUG(logger_, "Tracking app id: " << app_id);
+ ApplicationsRequestsTracker::iterator it_app = tracker.find(app_id);
+
+ if (tracker.end() == it_app) {
+ LOG4CXX_DEBUG(logger_, "Adding new application into tracking.");
+ tracker[app_id].push_back(DateTime::getCurrentTime());
+ return true;
+ }
+
+ LOG4CXX_DEBUG(logger_,
+ "Amount of known requests is: " << it_app->second.size());
+
+ if (it_app->second.size() < max_requests) {
+ LOG4CXX_DEBUG(logger_, "Adding new request into tracking.");
+ tracker[app_id].push_back(DateTime::getCurrentTime());
+ return true;
+ }
+
+ LOG4CXX_DEBUG(logger_,
+ "Oldest request is added at: "
+ << DateTime::getmSecs(it_app->second.front())
+ << ". Current time is: "
+ << DateTime::getmSecs(DateTime::getCurrentTime())
+ << ". Time scale is: " << time_scale);
+
+ if (DateTime::calculateTimeSpan(it_app->second.front()) > time_scale) {
+ LOG4CXX_DEBUG(logger_, "Dropping oldest request, adding new one.");
+ ApplicationsRequestsTracker::mapped_type& times = tracker[app_id];
+
+ DCHECK_OR_RETURN(!times.empty(), false);
+
+ times.erase(times.begin());
+ times.push_back(DateTime::getCurrentTime());
+ return true;
+ }
+
+ LOG4CXX_DEBUG(logger_, "Requests amount per time scale is exceeded.");
+
+ return false;
+}
+
+} // namespace request_controller
+} // namespace application_manager
diff --git a/src/components/application_manager/test/CMakeLists.txt b/src/components/application_manager/test/CMakeLists.txt
index 4ce8760006..a7f5d8b243 100644
--- a/src/components/application_manager/test/CMakeLists.txt
+++ b/src/components/application_manager/test/CMakeLists.txt
@@ -52,6 +52,7 @@ if (BUILD_TESTS)
${AM_TEST_DIR}/mobile_message_handler_test.cc
${AM_TEST_DIR}/mobile_message_handler_v1_test.cc
${AM_TEST_DIR}/request_info_test.cc
+ ${AM_TEST_DIR}/request_tracker_test.cc
${AM_TEST_DIR}/resumption_sql_queries_test.cc
${AM_TEST_DIR}/event_engine_test.cc
${AM_TEST_DIR}/policy_event_observer_test.cc
diff --git a/src/components/application_manager/test/request_info_test.cc b/src/components/application_manager/test/request_info_test.cc
index 74c4041736..62d9897a18 100644
--- a/src/components/application_manager/test/request_info_test.cc
+++ b/src/components/application_manager/test/request_info_test.cc
@@ -177,107 +177,6 @@ TEST_F(RequestInfoTest, AddHMIRequests_RemoveAllRequests) {
EXPECT_EQ(0u, request_info_set_.Size());
}
-TEST_F(RequestInfoTest, CheckRequestsMaxCount) {
- const uint32_t app_hmi_level_time_scale = 100;
- const uint32_t hmi_level_count = 1000;
-
- // Count of added requests is less than max possible
- std::vector<utils::SharedPtr<TestRequestInfo> > requests;
- for (uint32_t i = 0; i < hmi_level_count - 1; ++i) {
- utils::SharedPtr<TestRequestInfo> request =
- CreateTestInfo(mobile_connection_key1_,
- i,
- request_info::RequestInfo::MobileRequest,
- date_time::DateTime::getCurrentTime(),
- default_timeout_);
-
- request->set_hmi_level(mobile_apis::HMILevel::HMI_FULL);
- requests.push_back(request);
- EXPECT_TRUE(request_info_set_.Add(request));
- }
- EXPECT_EQ(hmi_level_count - 1, request_info_set_.Size());
-
- EXPECT_TRUE(request_info_set_.CheckHMILevelTimeScaleMaxRequest(
- mobile_apis::HMILevel::HMI_FULL,
- mobile_connection_key1_,
- app_hmi_level_time_scale,
- hmi_level_count));
-
- // Adding new request is correct
- utils::SharedPtr<TestRequestInfo> new_request =
- CreateTestInfo(mobile_connection_key1_,
- hmi_level_count,
- request_info::RequestInfo::MobileRequest,
- date_time::DateTime::getCurrentTime(),
- default_timeout_);
- new_request->set_hmi_level(mobile_apis::HMILevel::HMI_FULL);
- EXPECT_TRUE(request_info_set_.Add(new_request));
- EXPECT_EQ(hmi_level_count, request_info_set_.Size());
-
- // Count of added requests is max
- EXPECT_FALSE(request_info_set_.CheckHMILevelTimeScaleMaxRequest(
- mobile_apis::HMILevel::HMI_FULL,
- mobile_connection_key1_,
- app_hmi_level_time_scale,
- hmi_level_count));
-
- utils::SharedPtr<TestRequestInfo> new_request2 =
- CreateTestInfo(mobile_connection_key1_,
- hmi_level_count + 1,
- request_info::RequestInfo::MobileRequest,
- date_time::DateTime::getCurrentTime(),
- default_timeout_);
-
- EXPECT_TRUE(request_info_set_.Add(new_request2));
-}
-
-TEST_F(RequestInfoTest, CheckMaxCountOfRequest) {
- const uint32_t app_hmi_level_time_scale = 100;
- const uint32_t hmi_level_count = 1000;
-
- // Count of added requests is less than max possible
- std::vector<utils::SharedPtr<TestRequestInfo> > requests;
- for (uint32_t i = 0; i < hmi_level_count - 1; ++i) {
- utils::SharedPtr<TestRequestInfo> request =
- CreateTestInfo(mobile_connection_key1_,
- i,
- request_info::RequestInfo::MobileRequest,
- date_time::DateTime::getCurrentTime(),
- default_timeout_);
- request->set_hmi_level(mobile_apis::HMILevel::HMI_FULL);
- requests.push_back(request);
- EXPECT_TRUE(request_info_set_.Add(request));
- }
- EXPECT_EQ(hmi_level_count - 1, request_info_set_.Size());
-
- EXPECT_TRUE(request_info_set_.CheckTimeScaleMaxRequest(
- mobile_connection_key1_, app_hmi_level_time_scale, hmi_level_count));
-
- // Adding new request is correct
- utils::SharedPtr<TestRequestInfo> new_request =
- CreateTestInfo(mobile_connection_key1_,
- hmi_level_count,
- request_info::RequestInfo::MobileRequest,
- date_time::DateTime::getCurrentTime(),
- default_timeout_);
- new_request->set_hmi_level(mobile_apis::HMILevel::HMI_FULL);
- EXPECT_TRUE(request_info_set_.Add(new_request));
- EXPECT_EQ(hmi_level_count, request_info_set_.Size());
-
- // Count of added requests is max
- EXPECT_FALSE(request_info_set_.CheckTimeScaleMaxRequest(
- mobile_connection_key1_, app_hmi_level_time_scale, hmi_level_count));
-
- utils::SharedPtr<TestRequestInfo> new_request2 =
- CreateTestInfo(mobile_connection_key1_,
- hmi_level_count + 1,
- request_info::RequestInfo::MobileRequest,
- date_time::DateTime::getCurrentTime(),
- default_timeout_);
-
- EXPECT_TRUE(request_info_set_.Add(new_request2));
-}
-
TEST_F(RequestInfoTest, AddMobileRequests_RemoveMobileRequests) {
utils::SharedPtr<TestRequestInfo> mobile_request1 =
CreateTestInfo(mobile_connection_key1_,
diff --git a/src/components/application_manager/test/request_tracker_test.cc b/src/components/application_manager/test/request_tracker_test.cc
new file mode 100644
index 0000000000..ee09e0a3e0
--- /dev/null
+++ b/src/components/application_manager/test/request_tracker_test.cc
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2017, 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 "gtest/gtest.h"
+#include "utils/macro.h"
+#include "application_manager/request_tracker.h"
+#include "application_manager/mock_request_controller_settings.h"
+#include "interfaces/MOBILE_API.h"
+#include "utils/lock.h"
+#include "utils/conditional_variable.h"
+
+namespace test {
+namespace components {
+namespace request_controller_test {
+
+using ::testing::Return;
+using ::testing::ReturnRef;
+
+class RequestTrackerTestClass : public ::testing::Test {
+ public:
+ RequestTrackerTestClass() : tracker_(mock_request_controller_settings_) {}
+
+ void SetDefaultConstraints() {
+ EXPECT_CALL(mock_request_controller_settings_,
+ app_hmi_level_none_time_scale())
+ .WillRepeatedly(ReturnRef(kDefaultAppHmiLevelNoneRequestsTimeScale));
+
+ EXPECT_CALL(mock_request_controller_settings_,
+ app_hmi_level_none_time_scale_max_requests())
+ .WillRepeatedly(ReturnRef(kDefaultAppHmiLevelNoneTimeScaleMaxRequests));
+
+ EXPECT_CALL(mock_request_controller_settings_, app_time_scale())
+ .WillRepeatedly(ReturnRef(kDefaultAppRequestsTimeScale));
+
+ EXPECT_CALL(mock_request_controller_settings_,
+ app_time_scale_max_requests())
+ .WillRepeatedly(ReturnRef(kDefaultAppTimeScaleMaxRequests));
+ }
+
+ protected:
+ application_manager_test::MockRequestControlerSettings
+ mock_request_controller_settings_;
+
+ application_manager::request_controller::RequestTracker tracker_;
+
+ const uint32_t kDefaultAppHmiLevelNoneRequestsTimeScale = 10u;
+ const uint32_t kDefaultAppHmiLevelNoneTimeScaleMaxRequests = 100u;
+ const uint32_t kDefaultAppTimeScaleMaxRequests = 5u;
+ const uint32_t kDefaultAppRequestsTimeScale = 200u;
+};
+
+TEST_F(RequestTrackerTestClass, TrackAppRequestInNone_ExpectSuccessTillLimit) {
+ const uint32_t app_id = 1u;
+ const mobile_apis::HMILevel::eType none_level =
+ mobile_apis::HMILevel::HMI_NONE;
+
+ SetDefaultConstraints();
+
+ for (uint32_t i = 0; i < kDefaultAppHmiLevelNoneTimeScaleMaxRequests; ++i) {
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id, none_level));
+ }
+
+ EXPECT_EQ(application_manager::request_controller::TrackResult::
+ kNoneLevelMaxRequestsExceeded,
+ tracker_.Track(app_id, none_level));
+}
+
+TEST_F(RequestTrackerTestClass,
+ TrackAppRequestInNone_NoLimits_ExpectAlwaysSuccess) {
+ const uint32_t no_limit = 0;
+
+ EXPECT_CALL(mock_request_controller_settings_,
+ app_hmi_level_none_time_scale())
+ .WillRepeatedly(ReturnRef(no_limit));
+
+ EXPECT_CALL(mock_request_controller_settings_,
+ app_hmi_level_none_time_scale_max_requests())
+ .WillRepeatedly(ReturnRef(no_limit));
+
+ const uint32_t app_id = 1u;
+ const mobile_apis::HMILevel::eType none_level =
+ mobile_apis::HMILevel::HMI_NONE;
+
+ for (uint32_t i = 0; i < kDefaultAppHmiLevelNoneTimeScaleMaxRequests; ++i) {
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id, none_level));
+ }
+
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id, none_level));
+}
+
+TEST_F(RequestTrackerTestClass,
+ TrackAppRequestInOtherThanNone_ExpectSuccessTillLimit) {
+ const uint32_t app_id = 1u;
+ mobile_apis::HMILevel::eType hmi_level =
+ mobile_apis::HMILevel::HMI_BACKGROUND;
+
+ SetDefaultConstraints();
+
+ for (uint32_t i = 0; i < kDefaultAppTimeScaleMaxRequests; ++i) {
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id, hmi_level));
+ if (i % 2) {
+ hmi_level = mobile_apis::HMILevel::HMI_FULL;
+ } else {
+ hmi_level = mobile_apis::HMILevel::HMI_LIMITED;
+ }
+ }
+
+ EXPECT_EQ(application_manager::request_controller::TrackResult::
+ kMaxRequestsExceeded,
+ tracker_.Track(app_id, hmi_level));
+}
+
+TEST_F(RequestTrackerTestClass,
+ TrackAppRequestInOtherThanNone_NoLimits_ExpectAlwaysSuccess) {
+ const uint32_t no_limit = 0;
+
+ EXPECT_CALL(mock_request_controller_settings_, app_time_scale())
+ .WillRepeatedly(ReturnRef(no_limit));
+
+ EXPECT_CALL(mock_request_controller_settings_, app_time_scale_max_requests())
+ .WillRepeatedly(ReturnRef(no_limit));
+
+ const uint32_t app_id = 1u;
+ mobile_apis::HMILevel::eType hmi_level =
+ mobile_apis::HMILevel::HMI_BACKGROUND;
+
+ for (uint32_t i = 0; i < kDefaultAppTimeScaleMaxRequests; ++i) {
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id, hmi_level));
+ if (i % 2) {
+ hmi_level = mobile_apis::HMILevel::HMI_FULL;
+ } else {
+ hmi_level = mobile_apis::HMILevel::HMI_LIMITED;
+ }
+ }
+
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id, hmi_level));
+}
+
+TEST_F(RequestTrackerTestClass,
+ TrackTwoAppsRequestInNone_ExpectSuccessTillLimit) {
+ const uint32_t app_id_1 = 1u;
+ const uint32_t app_id_2 = 2u;
+
+ const mobile_apis::HMILevel::eType none_level =
+ mobile_apis::HMILevel::HMI_NONE;
+
+ SetDefaultConstraints();
+
+ for (uint32_t i = 0; i < kDefaultAppHmiLevelNoneTimeScaleMaxRequests; ++i) {
+ if (i % 2) {
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id_1, none_level));
+ } else {
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id_2, none_level));
+ }
+ }
+
+ for (uint32_t i = 0; i < kDefaultAppHmiLevelNoneTimeScaleMaxRequests / 2;
+ ++i) {
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id_1, none_level));
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id_2, none_level));
+ }
+
+ EXPECT_EQ(application_manager::request_controller::TrackResult::
+ kNoneLevelMaxRequestsExceeded,
+ tracker_.Track(app_id_1, none_level));
+
+ EXPECT_EQ(application_manager::request_controller::TrackResult::
+ kNoneLevelMaxRequestsExceeded,
+ tracker_.Track(app_id_2, none_level));
+}
+
+TEST_F(RequestTrackerTestClass,
+ TrackAppRequestInNone_DoPause_TrackAgain_ExpectSuccessTillLimit) {
+ const uint32_t max_requests = 5;
+ const uint32_t time_scale_ms = 1;
+
+ sync_primitives::ConditionalVariable awaiter;
+ sync_primitives::Lock lock;
+ sync_primitives::AutoLock auto_lock(lock);
+
+ EXPECT_CALL(mock_request_controller_settings_,
+ app_hmi_level_none_time_scale())
+ .WillRepeatedly(ReturnRef(time_scale_ms));
+
+ EXPECT_CALL(mock_request_controller_settings_,
+ app_hmi_level_none_time_scale_max_requests())
+ .WillRepeatedly(ReturnRef(max_requests));
+
+ const uint32_t app_id = 1u;
+ const mobile_apis::HMILevel::eType none_level =
+ mobile_apis::HMILevel::HMI_NONE;
+
+ for (uint32_t i = 0; i < max_requests; ++i) {
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id, none_level));
+ }
+
+ awaiter.WaitFor(auto_lock, time_scale_ms * 2);
+
+ for (uint32_t i = 0; i < max_requests; ++i) {
+ EXPECT_EQ(application_manager::request_controller::TrackResult::kSuccess,
+ tracker_.Track(app_id, none_level));
+ }
+
+ EXPECT_EQ(application_manager::request_controller::TrackResult::
+ kNoneLevelMaxRequestsExceeded,
+ tracker_.Track(app_id, none_level));
+}
+
+} // namespace request_controller
+} // namespace components
+} // namespace test