diff options
author | Yaroslav Mamykin (GitHub) <33784535+YarikMamykin@users.noreply.github.com> | 2019-09-20 23:21:40 +0300 |
---|---|---|
committer | Jacob Keeler <jacob.keeler@livioradio.com> | 2019-09-20 16:21:40 -0400 |
commit | 5c7eef2b59c419be127da1bd0cc267884ee94182 (patch) | |
tree | 4fdc68001b57e6819414525f9fa76b04c6343ea4 | |
parent | e833e65ec42ee9a99eb4488e5bff4f23d9789768 (diff) | |
download | sdl_core-5c7eef2b59c419be127da1bd0cc267884ee94182.tar.gz |
Fix merge module data incorrect behavior (#3017)
* Fix MergeModuleData invalid behavior
* Rework MergeModuleData and MergeArray logic
* Add unit tests
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h | 23 | ||||
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc | 92 | ||||
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc | 82 | ||||
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/interior_data_cache_test.cc | 46 | ||||
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_helpers_test.cc | 285 | ||||
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/CMakeLists.txt | 81 | ||||
-rw-r--r-- | src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/resource_allocation_manager_impl_test.cc (renamed from src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager_impl_test.cc) | 0 |
8 files changed, 521 insertions, 92 deletions
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h index 7b249cb4b8..eed860fc7f 100644 --- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_helpers.h @@ -146,6 +146,29 @@ class RCHelpers { */ static void RemoveRedundantGPSDataFromIVDataMsg( smart_objects::SmartObject& msg_params); + + /** + * @brief MergeModuleData all keys and values from first parameter and + * update and append keys and values from the second + * @param data1 - initial data + * @param data2 - updated data + * @return updated data1 with data2 keys and values + */ + static smart_objects::SmartObject MergeModuleData( + const smart_objects::SmartObject& data1, + const smart_objects::SmartObject& data2); + + /** + * @brief MergeArray merge two arrays if their elements contain an `id` + * parameter + * @param data1 - initial data + * @param data2 - updated data + * @return updated data1 with any values in data2 if the arrays can be merged, + * otherwise data2 + */ + static smart_objects::SmartObject MergeArray( + const smart_objects::SmartObject& data1, + const smart_objects::SmartObject& data2); }; } // namespace rc_rpc_plugin diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc index bcbc3ab11b..3e50818210 100644 --- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc @@ -35,6 +35,7 @@ #include <iostream> #include <thread> #include "application_manager/smart_object_keys.h" +#include "rc_rpc_plugin/rc_helpers.h" #include "utils/date_time.h" #include "utils/logger.h" @@ -46,95 +47,6 @@ InteriorDataCacheImpl::InteriorDataCacheImpl() {} InteriorDataCacheImpl::~InteriorDataCacheImpl() {} -/** - * @brief MergeModuleData all keys and values from first parameter and - * update and append keys and values from the second - * @param data1 - initial data - * @param data2 - updated data - * @return updated data1 with data2 keys and values - */ -smart_objects::SmartObject MergeModuleData( - const smart_objects::SmartObject& data1, - const smart_objects::SmartObject& data2); - -/** - * @brief MergeArray merge two arrays if their elements contain an `id` - * parameter - * @param data1 - initial data - * @param data2 - updated data - * @return updated data1 with any values in data2 if the arrays can be merged, - * otherwise data2 - */ -smart_objects::SmartObject MergeArray(const smart_objects::SmartObject& data1, - const smart_objects::SmartObject& data2); - -smart_objects::SmartObject MergeModuleData( - const smart_objects::SmartObject& data1, - const smart_objects::SmartObject& data2) { - smart_objects::SmartObject result = data1; - auto it = data2.map_begin(); - for (; it != data2.map_end(); ++it) { - const std::string& key = it->first; - smart_objects::SmartObject& value = it->second; - if (!result.keyExists(key) || value.getType() != result[key].getType()) { - result[key] = value; - continue; - } - - // Merge maps and arrays with `id` param included, replace other types - if (value.getType() == smart_objects::SmartType::SmartType_Map) { - value = MergeModuleData(result[key], value); - } else if (value.getType() == smart_objects::SmartType::SmartType_Array) { - value = MergeArray(result[key], value); - } - result[key] = value; - } - return result; -} - -smart_objects::SmartObject MergeArray(const smart_objects::SmartObject& data1, - const smart_objects::SmartObject& data2) { - // Merge data only in the case where each value in the array is an Object with - // an ID included, otherwise replace - bool array_contains_objects = - !data2.empty() && - data2.getElement(0).getType() != smart_objects::SmartType::SmartType_Map; - bool can_merge_arrays = - array_contains_objects && - data2.getElement(0).keyExists(application_manager::strings::id); - if (!can_merge_arrays) { - return data2; - } - - smart_objects::SmartObject result = data1; - smart_objects::SmartArray* result_array = result.asArray(); - smart_objects::SmartArray* data_array = data2.asArray(); - auto data_it = data_array->begin(); - auto find_by_id = [](smart_objects::SmartArray* array, - const smart_objects::SmartObject& id) - -> smart_objects::SmartArray::iterator { - auto it = std::find_if(array->begin(), - array->end(), - [&id](smart_objects::SmartObject& obj) -> bool { - return obj[application_manager::strings::id] == id; - }); - return it; - }; - - for (; data_it != data_array->end(); ++data_it) { - const smart_objects::SmartObject element_id = - (*data_it)[application_manager::strings::id]; - auto result_it = find_by_id(result_array, element_id); - - if (result_it != result_array->end()) { - *result_it = MergeModuleData(*result_it, *data_it); - } else { - result_array->push_back(*data_it); - } - } - return result; -} - void InteriorDataCacheImpl::Add(const ModuleUid& module, const smart_objects::SmartObject& module_data) { LOG4CXX_TRACE( @@ -146,7 +58,7 @@ void InteriorDataCacheImpl::Add(const ModuleUid& module, cached_data_[module] = module_data; return; } - cached_data_[module] = MergeModuleData(it->second, module_data); + cached_data_[module] = RCHelpers::MergeModuleData(it->second, module_data); } smart_objects::SmartObject InteriorDataCacheImpl::Retrieve( diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc index e9e6620e25..8cf20948cf 100644 --- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_helpers.cc @@ -276,4 +276,86 @@ void RCHelpers::RemoveRedundantGPSDataFromIVDataMsg( location_data = new_location_data; } } + +smart_objects::SmartObject RCHelpers::MergeModuleData( + const smart_objects::SmartObject& data1, + const smart_objects::SmartObject& data2) { + if (data1.getType() != smart_objects::SmartType::SmartType_Map || + data2.getType() != smart_objects::SmartType::SmartType_Map) { + return data2; + } + + smart_objects::SmartObject result = data1; + + for (auto it = data2.map_begin(); it != data2.map_end(); ++it) { + const std::string& key = it->first; + smart_objects::SmartObject& value = it->second; + if (!result.keyExists(key) || value.getType() != result[key].getType()) { + result[key] = value; + continue; + } + + // Merge maps and arrays with `id` param included, replace other types + if (value.getType() == smart_objects::SmartType::SmartType_Map) { + value = MergeModuleData(result[key], value); + } else if (value.getType() == smart_objects::SmartType::SmartType_Array) { + value = MergeArray(result[key], value); + } + result[key] = value; + } + return result; +} + +smart_objects::SmartObject RCHelpers::MergeArray( + const smart_objects::SmartObject& data1, + const smart_objects::SmartObject& data2) { + // Merge data only in the case where each value in the array is an Object with + // an ID included, otherwise replace + + if (data1.getType() != smart_objects::SmartType::SmartType_Array || + data2.getType() != smart_objects::SmartType::SmartType_Array || + data2.empty()) { + return data2; + } + + auto& data2_array = *data2.asArray(); + for (const auto& data_item : data2_array) { + if (data_item.getType() != smart_objects::SmartType_Map || + !data_item.keyExists(application_manager::strings::id)) { + return data2; + } + } + + smart_objects::SmartObject result = data1; + smart_objects::SmartArray* result_array = result.asArray(); + + auto find_by_id = [](smart_objects::SmartArray* array, + const smart_objects::SmartObject& id) + -> smart_objects::SmartArray::iterator { + return std::find_if(array->begin(), + array->end(), + [&id](const smart_objects::SmartObject& obj) -> bool { + return id == obj[application_manager::strings::id]; + }); + }; + + auto merge = [&result_array, + &find_by_id](const smart_objects::SmartObject& data) -> void { + auto element_id = data[application_manager::strings::id]; + auto result_it = find_by_id(result_array, element_id); + + if (result_array->end() != result_it) { + *result_it = RCHelpers::MergeModuleData(*result_it, data); + } else { + result_array->push_back(data); + } + }; + + for (const auto& data : data2_array) { + merge(data); + } + + return result; +} + } // namespace rc_rpc_plugin diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt index 00ddcd7379..bd46bdf11f 100644 --- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/CMakeLists.txt @@ -41,11 +41,10 @@ include_directories ( ) set (RC_TEST_SOURCES -${CMAKE_CURRENT_SOURCE_DIR}/resource_allocation_manager_impl_test.cc ${CMAKE_CURRENT_SOURCE_DIR}/interior_data_cache_test.cc ${CMAKE_CURRENT_SOURCE_DIR}/rc_consent_manager_impl_test.cc ${CMAKE_CURRENT_SOURCE_DIR}/grid_test.cc -${CMAKE_CURRENT_SOURCE_DIR}/mock_rc_helpers.cc +${CMAKE_CURRENT_SOURCE_DIR}/rc_helpers_test.cc ) set(RC_COMMANDS_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/commands) @@ -71,3 +70,4 @@ endif() create_test("rc_commands_test" "${SOURCES}" "${LIBRARIES}" ) create_test("rc_plugin_test" "${RC_TEST_SOURCES}" "${LIBRARIES}") +add_subdirectory(resource_allocation_manager) diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/interior_data_cache_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/interior_data_cache_test.cc index e8d9f6e45d..40a6bdf41d 100644 --- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/interior_data_cache_test.cc +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/interior_data_cache_test.cc @@ -29,6 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#include "application_manager/smart_object_keys.h" #include "gtest/gtest.h" #include "rc_rpc_plugin/interior_data_cache_impl.h" @@ -38,6 +39,8 @@ class InteriorDataCacheTest : public ::testing::Test {}; namespace { const uint32_t time_frame_alowed_requests = 1; +const std::string kValueKey = "value"; +const std::string kArray = "array"; } // namespace TEST_F(InteriorDataCacheTest, @@ -177,4 +180,47 @@ TEST_F(InteriorDataCacheTest, Exist2ModuleTypesRemoveOneAnotherOneLeft) { EXPECT_EQ(data2, retrieved_data2); } +TEST_F(InteriorDataCacheTest, CheckCacheDataMerge) { + using namespace smart_objects; + const std::string module_type_key = "random_module_type"; + const std::string module_id = "random_module_id"; + rc_rpc_plugin::ModuleUid module(module_type_key, module_id); + + auto gen_smart_object = [](const std::string& id, + const std::string& value) -> SmartObject { + SmartObject result(SmartType_Map); + result[application_manager::strings::id] = id; + result[kValueKey] = value; + return result; + }; + + SmartObject data1; + SmartObject data1_array(SmartType_Array); + (*data1_array.asArray()) = SmartArray{gen_smart_object("id1", "value1"), + gen_smart_object("id2", "value2")}; + data1[kArray] = data1_array; + + SmartObject data2(SmartType_Map); + SmartObject data2_array(SmartType_Array); + (*data2_array.asArray()) = SmartArray{gen_smart_object("id1", "value3"), + gen_smart_object("id3", "value4")}; + data2[kArray] = data2_array; + + SmartObject expected_data(SmartType_Map); + SmartObject expected_array(SmartType_Array); + (*expected_array.asArray()) = SmartArray{gen_smart_object("id1", "value3"), + gen_smart_object("id2", "value2"), + gen_smart_object("id3", "value4")}; + expected_data[kArray] = expected_array; + + rc_rpc_plugin::InteriorDataCacheImpl cache; + cache.Add(module, data1); + cache.Add(module, data2); + + const auto retrieved_data = cache.Retrieve(module); + + EXPECT_TRUE(cache.Contains(module)); + EXPECT_EQ(expected_data, retrieved_data); +} + } // namespace rc_rpc_plugin_test diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_helpers_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_helpers_test.cc new file mode 100644 index 0000000000..21876c4c19 --- /dev/null +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/rc_helpers_test.cc @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2019, 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 "rc_rpc_plugin/rc_helpers.h" +#include <map> +#include <memory> +#include <string> +#include <type_traits> +#include <vector> +#include "gtest/gtest.h" +#include "rc_rpc_plugin/rc_module_constants.h" + +namespace { +const std::string kKeyId = "id"; +const std::string kKeyStatus = "status"; +const std::string kKeyDensity = "density"; +const std::string kKeyValue = "value"; +const std::string kArray = "array"; +} // namespace + +namespace rc_rpc_plugin_test { + +using namespace rc_rpc_plugin; +using namespace smart_objects; + +class RCHelpersTest : public ::testing::Test { + public: + /** + * @brief Generates smart object with next structure: + * { + * "status": "status<n>", + * "value": "value<n>", + * "id": "id<n>" + * } + * where <n> is number specified with 'object_number' param. + * + * @param int object_number - number of object + * @param bool use_id_key - defines, whether "id" key must be added to smart + * object + * + * @return smart_objects::SmartObject - generated smart object + */ + smart_objects::SmartObject gen_smart_object(int object_number, + bool use_id_key) { + smart_objects::SmartObject result(smart_objects::SmartType_Map); + result[kKeyStatus] = kKeyStatus + std::to_string(object_number); + result[kKeyValue] = kKeyValue + std::to_string(object_number); + if (use_id_key) { + result[kKeyId] = kKeyId + std::to_string(object_number); + } + return result; + } +}; + +TEST_F(RCHelpersTest, + MergeModuleData_OneOfParamsNotSmartMap_ExpectDataReplacedWithNewOne) { + SmartObject data1(SmartType_Map); + SmartObject data2(SmartType_Array); + + const auto result = RCHelpers::MergeModuleData(data1, data2); + EXPECT_NE(result, data1); + EXPECT_EQ(result, data2); +} + +TEST_F(RCHelpersTest, + MergeModuleData_FirstObjectDontContainKey_ExpectDataAppendedWithNewOne) { + SmartObject data1(SmartType_Map); + SmartObject data2(SmartType_Map); + + std::map<std::string, std::string> expected_keys_values = { + {"key1", "value1"}, {"key2", "value2"}}; + auto it = expected_keys_values.begin(); + + data1[it->first] = it->second; + ++it; + data2[it->first] = it->second; + + const auto result = RCHelpers::MergeModuleData(data1, data2); + for (auto& item : expected_keys_values) { + EXPECT_TRUE(result.keyExists(item.first)); + EXPECT_EQ(result[item.first], expected_keys_values[item.first]); + } +} + +TEST_F( + RCHelpersTest, + MergeModuleData_SecondObjectContainsDifferentValueType_ExpectDataReplacedWithNewOne) { + SmartObject data1(SmartType_Map); + SmartObject data2(SmartType_Map); + + data1["key1"] = "value1"; + data2["key1"] = 30; + + const auto result = RCHelpers::MergeModuleData(data1, data2); + EXPECT_EQ(data2["key1"], result["key1"]); +} + +TEST_F(RCHelpersTest, MergeModuleData_Recursive) { + SmartObject data1(SmartType_Map); + SmartObject data2(SmartType_Map); + + data1["key1"]["subkey1"] = "subvalue1"; + data2["key1"]["subkey2"] = 30; + + const auto result = RCHelpers::MergeModuleData(data1, data2); + EXPECT_EQ(result["key1"]["subkey1"], data1["key1"]["subkey1"]); + EXPECT_EQ(result["key1"]["subkey2"], data2["key1"]["subkey2"]); +} + +TEST_F( + RCHelpersTest, + MergeModuleData_MergeObjectsThatContainArrays_ExpectDataReplacedWithNewOne) { + SmartObject data1(SmartType_Map); + SmartObject data1_array(SmartType_Array); + (*data1_array.asArray()) = + SmartArray{gen_smart_object(1, true), gen_smart_object(2, false)}; + data1[kArray] = data1_array; + + SmartObject data2(SmartType_Map); + SmartObject data2_array(SmartType_Array); + (*data2_array.asArray()) = + SmartArray{gen_smart_object(3, true), gen_smart_object(4, false)}; + data2[kArray] = data2_array; + + SmartObject expected_result(SmartType_Map); + SmartObject expected_result_array(SmartType_Array); + (*expected_result_array.asArray()) = + SmartArray{data2[kArray].getElement(0), data2[kArray].getElement(1)}; + + expected_result[kArray] = expected_result_array; + + const auto result = RCHelpers::MergeModuleData(data1, data2); + EXPECT_EQ(expected_result, result); +} + +TEST_F(RCHelpersTest, + MergeArray_OneOfParamsNotSmartArray_ExpectDataReplacedWithSecond) { + SmartObject data1(SmartType_Array); + SmartObject data2(SmartType_Map); + + const auto result = RCHelpers::MergeArray(data1, data2); + EXPECT_NE(result, data1); + EXPECT_EQ(result, data2); +} + +TEST_F(RCHelpersTest, MergeArray_FirstArrayEmpty_ExpectDataReplacedWithSecond) { + SmartObject data1(SmartType_Array); + SmartObject data2(SmartType_Array); + for (int object : {0, 1}) { + data2.asArray()->emplace(data2.asArray()->begin(), SmartObject(object)); + } + + ASSERT_EQ(0u, data1.length()); + ASSERT_EQ(2u, data2.length()); + + const auto result = RCHelpers::MergeArray(data1, data2); + EXPECT_NE(result, data1); + EXPECT_EQ(result, data2); +} + +TEST_F(RCHelpersTest, + MergeArray_SecondArrayEmpty_ExpectDataReplacedWithSecond) { + SmartObject data1(SmartType_Array); + for (int object : {0, 1}) { + data1.asArray()->emplace(data1.asArray()->begin(), SmartObject(object)); + } + SmartObject data2(SmartType_Array); + + ASSERT_EQ(2u, data1.length()); + ASSERT_EQ(0u, data2.length()); + + const auto result = RCHelpers::MergeArray(data1, data2); + EXPECT_NE(result, data1); + EXPECT_EQ(result, data2); +} + +TEST_F(RCHelpersTest, MergeArray_SimpleArrays_ExpectDataReplacedWithSecond) { + SmartObject data1(SmartType_Array); + for (int object : {0, 1, 2, 3, 4, 5}) { + data1.asArray()->emplace(data1.asArray()->begin(), SmartObject(object)); + } + + SmartObject data2(SmartType_Array); + for (int object : {0, 1}) { + data2.asArray()->emplace(data2.asArray()->begin(), SmartObject(object)); + } + + ASSERT_EQ(6u, data1.length()); + ASSERT_EQ(2u, data2.length()); + + const auto result = RCHelpers::MergeArray(data1, data2); + EXPECT_NE(result, data1); + EXPECT_EQ(result, data2); +} + +TEST_F(RCHelpersTest, + MergeArray_ObjectsHaveNotEqualIds_ExpectDataAppendedWithNewOne) { + SmartObject data1 = gen_smart_object(1, true); + SmartObject data2 = gen_smart_object(2, true); + + SmartObject array1(SmartType_Array); + array1.asArray()->push_back(data1); + SmartObject array2(SmartType_Array); + array2.asArray()->push_back(data2); + + SmartObject expected_array(SmartType_Array); + expected_array.asArray()->push_back(data1); + expected_array.asArray()->push_back(data2); + ASSERT_EQ(2u, expected_array.length()); + + const auto result = RCHelpers::MergeArray(array1, array2); + EXPECT_EQ(expected_array, result); +} + +TEST_F(RCHelpersTest, + MergeArray_SomeObjectsDontHaveIdKey_ExpectDataReplacedWithSecond) { + int object_number = 1; + + SmartObject array1(SmartType_Array); + array1.asArray()->push_back(gen_smart_object(object_number++, true)); + + SmartObject array2(SmartType_Array); + array2.asArray()->push_back(gen_smart_object(object_number++, false)); + array2.asArray()->push_back(gen_smart_object(object_number++, true)); + + const auto result = RCHelpers::MergeArray(array1, array2); + EXPECT_EQ(array2, result); +} + +TEST_F( + RCHelpersTest, + MergeArray_SomeObjectsHaveEqualIds_ExpectDataWithSameIdUpdateValueOnlyNewDataAdded) { + SmartObject temp = gen_smart_object(1, true); + + SmartObject data1(SmartType_Array); + auto& data1_array = *data1.asArray(); + + data1_array.push_back(temp); + data1_array.push_back(gen_smart_object(2, true)); + + SmartObject data2(SmartType_Array); + auto& data2_array = *data2.asArray(); + + temp[kKeyValue] = "CUSTOM VALUE"; + data2_array.push_back(temp); + data2_array.push_back(gen_smart_object(3, true)); + + SmartObject expected_result(SmartType_Array); + expected_result.asArray()->push_back(temp); + expected_result.asArray()->push_back(data1_array[1]); + expected_result.asArray()->push_back(data2_array[1]); + + const auto result = RCHelpers::MergeArray(data1, data2); + EXPECT_EQ(expected_result, result); +} + +} // namespace rc_rpc_plugin_test diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/CMakeLists.txt b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/CMakeLists.txt new file mode 100644 index 0000000000..c665e98448 --- /dev/null +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/CMakeLists.txt @@ -0,0 +1,81 @@ +# Copyright (c) 2019, 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 copyright holders nor the names of their 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(${CMAKE_SOURCE_DIR}/tools/cmake/helpers/sources.cmake) + +include_directories ( + ${GMOCK_INCLUDE_DIRECTORY} + ${COMPONENTS_DIR}/application_manager/test/include + ${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/include + ${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/test/include/ + ${COMPONENTS_DIR}/include/test/application_manager/ + ${COMPONENTS_DIR}/rc_rpc_plugin/test/include +) + +set (RESOURCE_ALLOC_MANAGER_TEST_SOURCES +${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_manager_impl.cc +${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/interior_data_cache_impl.cc +${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/resource_allocation_manager_impl.cc +${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_rpc_plugin.cc +${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_app_extension.cc +${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_consent_manager_impl.cc +${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_capabilities_manager_impl.cc +${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_command_factory.cc +${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/test/mock_rc_helpers.cc +${CMAKE_CURRENT_SOURCE_DIR}/resource_allocation_manager_impl_test.cc +) + +set(RC_COMMANDS_TEST_SOURCE_DIR ${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/test/commands) +set(RC_COMMANDS_SOURCE_DIR ${COMPONENTS_DIR}/application_manager/rpc_plugins/rc_rpc_plugin/src/commands) +collect_sources(COMMANDS_SOURCES "${RC_COMMANDS_TEST_DIR}" "${RC_COMMANDS_TEST_SOURCE_DIR}") + +set(LIBRARIES + ApplicationManager + connectionHandler + SmartObjects + ProtocolHandler + MessageHelper + connectionHandler + Utils + Resumption + jsoncpp + gmock_main + dl +) + +if(ENABLE_LOG) + list(APPEND LIBRARIES log4cxx -L${LOG4CXX_LIBS_DIRECTORY}) + list(APPEND LIBRARIES apr-1 -L${APR_LIBS_DIRECTORY}) + list(APPEND LIBRARIES aprutil-1 -L${APR_UTIL_LIBS_DIRECTORY}) + list(APPEND LIBRARIES expat -L${EXPAT_LIBS_DIRECTORY}) +endif() + +create_test("resource_allocation_manager_test" "${COMMANDS_SOURCES}" "${LIBRARIES}" "${RESOURCE_ALLOC_MANAGER_TEST_SOURCES}") + diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager_impl_test.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/resource_allocation_manager_impl_test.cc index 70ed832cb1..70ed832cb1 100644 --- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager_impl_test.cc +++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/test/resource_allocation_manager/resource_allocation_manager_impl_test.cc |