diff options
Diffstat (limited to 'src/components/smart_objects')
21 files changed, 5226 insertions, 19 deletions
diff --git a/src/components/smart_objects/CMakeLists.txt b/src/components/smart_objects/CMakeLists.txt index 89f0dbdce..c1d599db6 100644 --- a/src/components/smart_objects/CMakeLists.txt +++ b/src/components/smart_objects/CMakeLists.txt @@ -1,21 +1,54 @@ +# Copyright (c) 2014, 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. + + +set(SMART_OBJECTS_SRC_DIR ${COMPONENTS_DIR}/smart_objects/src) + include_directories ( - ./include - ../utils/include/ + include + ${COMPONENTS_DIR}/utils/include/ ) set (SOURCES - ./src/smart_object.cc - ./src/smart_schema.cc - ./src/schema_item.cc - ./src/always_false_schema_item.cc - ./src/always_true_schema_item.cc - ./src/default_shema_item.cc - ./src/bool_schema_item.cc - ./src/number_schema_item.cc - ./src/enum_schema_item.cc - ./src/string_schema_item.cc - ./src/object_schema_item.cc - ./src/array_schema_item.cc + ${SMART_OBJECTS_SRC_DIR}/smart_object.cc + ${SMART_OBJECTS_SRC_DIR}/smart_schema.cc + ${SMART_OBJECTS_SRC_DIR}/schema_item.cc + ${SMART_OBJECTS_SRC_DIR}/always_false_schema_item.cc + ${SMART_OBJECTS_SRC_DIR}/always_true_schema_item.cc + ${SMART_OBJECTS_SRC_DIR}/default_shema_item.cc + ${SMART_OBJECTS_SRC_DIR}/bool_schema_item.cc + ${SMART_OBJECTS_SRC_DIR}/number_schema_item.cc + ${SMART_OBJECTS_SRC_DIR}/enum_schema_item.cc + ${SMART_OBJECTS_SRC_DIR}/string_schema_item.cc + ${SMART_OBJECTS_SRC_DIR}/object_schema_item.cc + ${SMART_OBJECTS_SRC_DIR}/array_schema_item.cc ) add_library("SmartObjects" ${SOURCES}) @@ -24,3 +57,7 @@ if(ENABLE_LOG) target_link_libraries("SmartObjects" log4cxx -L${LOG4CXX_LIBS_DIRECTORY}) endif() +if(BUILD_TESTS) + add_subdirectory(test) +endif() + diff --git a/src/components/smart_objects/include/smart_objects/number_schema_item.h b/src/components/smart_objects/include/smart_objects/number_schema_item.h index f5dd8ba42..fb4d287fe 100644 --- a/src/components/smart_objects/include/smart_objects/number_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/number_schema_item.h @@ -85,7 +85,10 @@ class TNumberSchemaItem : public CDefaultSchemaItem<NumberType> { TNumberSchemaItem(const TSchemaItemParameter<NumberType>& MinValue, const TSchemaItemParameter<NumberType>& MaxValue, const TSchemaItemParameter<NumberType>& DefaultValue); - bool isNumberType(SmartType type); + /** + * @brief Compares if param value type is correct + **/ + bool isValidNumberType(SmartType type); /** * @brief Minimum and Maximum allowed values. @@ -105,16 +108,27 @@ TNumberSchemaItem<NumberType>::create( } template<typename NumberType> -bool TNumberSchemaItem<NumberType>::isNumberType(SmartType type) { - return SmartType_Integer == type || SmartType_Double == type; +bool TNumberSchemaItem<NumberType>::isValidNumberType(SmartType type) { + NumberType value(0); + if ((SmartType_Double == type) && + (typeid(double) == typeid(value))) { + return true; + } else if ((SmartType_Integer == type) && + (typeid(int32_t) == typeid(value) || + typeid(uint32_t) == typeid(value) || + typeid(int64_t) == typeid(value))) { + return true; + } else { + return false; + } } template<typename NumberType> Errors::eType TNumberSchemaItem<NumberType>::validate(const SmartObject& Object) { - if (!isNumberType(Object.getType())) { + if (!isValidNumberType(Object.getType())) { return Errors::INVALID_VALUE; } - NumberType value; + NumberType value(0); if (typeid(int32_t) == typeid(value)) { value = Object.asInt(); } else if (typeid(uint32_t) == typeid(value)) { diff --git a/src/components/smart_objects/include/smart_objects/smart_object.h b/src/components/smart_objects/include/smart_objects/smart_object.h index 6a2b7b7f4..bd70b7ea1 100644 --- a/src/components/smart_objects/include/smart_objects/smart_object.h +++ b/src/components/smart_objects/include/smart_objects/smart_object.h @@ -114,6 +114,13 @@ typedef std::map<std::string, SmartObject> SmartMap; **/ typedef std::vector<uint8_t> SmartBinary; +typedef utils::SharedPtr<SmartObject> SmartObjectSPtr; + +/** + * @brief List of SmartObjects + */ +typedef std::vector<SmartObjectSPtr> SmartObjectList; + /** * @brief Main SmartObject class * diff --git a/src/components/smart_objects/test/AlwaysFalseSchemaItem_test.cc b/src/components/smart_objects/test/AlwaysFalseSchemaItem_test.cc new file mode 100644 index 000000000..cf1d107ba --- /dev/null +++ b/src/components/smart_objects/test/AlwaysFalseSchemaItem_test.cc @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" + +#include "smart_objects/smart_object.h" +#include "smart_objects/always_false_schema_item.h" + +namespace test { +namespace components { +namespace SmartObjects { +namespace SchemaItem { +using namespace NsSmartDeviceLink::NsSmartObjects; + +/** + * Test AlwaysFalseSchemaItem + **/ +TEST(test_AlwaysFalseSchemaItemTest, simple_test) { + SmartObject obj; + + ISchemaItemPtr item = CAlwaysFalseSchemaItem::create(); + + obj = 5; + int resultType = item->validate(obj); + EXPECT_EQ(Errors::ERROR, resultType); + EXPECT_EQ(5, obj.asInt()); + + obj = true; + resultType = item->validate(obj); + EXPECT_EQ(Errors::ERROR, resultType); + EXPECT_TRUE(obj.asBool()); + + obj = "Test"; + resultType = item->validate(obj); + EXPECT_EQ(Errors::ERROR, resultType); + EXPECT_EQ(std::string("Test"), obj.asString()); + + obj["First"] = "Some string"; + obj["Second"] = 555; + resultType = item->validate(obj["First"]); + EXPECT_EQ(Errors::ERROR, resultType); + resultType = item->validate(obj["Second"]); + EXPECT_EQ(Errors::ERROR, resultType); + resultType = item->validate(obj); + EXPECT_EQ(Errors::ERROR, resultType); + EXPECT_EQ(std::string("Some string"), obj["First"].asString()); + EXPECT_EQ(555, obj["Second"].asInt()); + + obj[0] = true; + obj[1] = false; + resultType = item->validate(obj[0]); + EXPECT_EQ(Errors::ERROR, resultType); + resultType = item->validate(obj[1]); + EXPECT_EQ(Errors::ERROR, resultType); + resultType = item->validate(obj); + EXPECT_EQ(Errors::ERROR, resultType); + EXPECT_TRUE(obj[0].asBool()); + EXPECT_FALSE(obj[1].asBool()); +} +} // namespace SchemaItem +} // namespace SmartObjects +} // namespace components +} // namespace test diff --git a/src/components/smart_objects/test/AlwaysTrueSchemaItem_test.cc b/src/components/smart_objects/test/AlwaysTrueSchemaItem_test.cc new file mode 100644 index 000000000..a29567293 --- /dev/null +++ b/src/components/smart_objects/test/AlwaysTrueSchemaItem_test.cc @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" + +#include "smart_objects/smart_object.h" +#include "smart_objects/always_true_schema_item.h" + +namespace test { +namespace components { +namespace SmartObjects { +namespace SchemaItem { + +using namespace NsSmartDeviceLink::NsSmartObjects; + +/** + * Test AlwaysTrueSchemaItem + **/ +TEST(test_AlwaysTrueSchemaItemTest, simple_test) { + SmartObject obj; + + ISchemaItemPtr item = CAlwaysTrueSchemaItem::create(); + + obj = 5; + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(5, obj.asInt()); + + obj = true; + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_TRUE(obj.asBool()); + + obj = "Test"; + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(std::string("Test"), obj.asString()); + + obj["First"] = "Some string"; + obj["Second"] = 555; + resultType = item->validate(obj["First"]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj["Second"]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(std::string("Some string"), obj["First"].asString()); + EXPECT_EQ(555, obj["Second"].asInt()); + + obj[0] = true; + obj[1] = false; + resultType = item->validate(obj[0]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj[1]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_TRUE(obj[0].asBool()); + EXPECT_FALSE(obj[1].asBool()); +} +} // namespace SchemaItem +} // namespace SmartObjects +} // namespace components +} // namespace test diff --git a/src/components/smart_objects/test/ArraySchemaItem_test.cc b/src/components/smart_objects/test/ArraySchemaItem_test.cc new file mode 100644 index 000000000..e8cad4012 --- /dev/null +++ b/src/components/smart_objects/test/ArraySchemaItem_test.cc @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" + +#include "smart_objects/smart_object.h" +#include "smart_objects/array_schema_item.h" +#include "smart_objects/string_schema_item.h" + +namespace test { +namespace components { +namespace SmartObjects { +namespace SchemaItem { + +/** + * Test ArraySchemaItem no schema item, no min and max size + **/ +TEST(test_no_default_value, test_ArraySchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CArraySchemaItem::create(); // No schema item, no min and max size + + obj[0] = 38; + obj[1] = true; + obj[2] = "New String"; + obj[3][0] = 39; + obj[3][1] = false; + obj[3][2] = "Another String"; + + EXPECT_EQ(38, obj[0].asInt()); + EXPECT_TRUE(obj[1].asBool()); + EXPECT_EQ(std::string("New String"), obj[2].asString()); + EXPECT_EQ(39, obj[3][0].asInt()); + EXPECT_FALSE(obj[3][1].asBool()); + EXPECT_EQ(std::string("Another String"), obj[3][2].asString()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj[0]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[1]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[2]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[3]); + EXPECT_EQ(Errors::OK, resultType); + + item->applySchema(obj); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj[0]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[1]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[2]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[3]); + EXPECT_EQ(Errors::OK, resultType); + + EXPECT_EQ(38, obj[0].asInt()); + EXPECT_TRUE(obj[1].asBool()); + EXPECT_EQ(std::string("New String"), obj[2].asString()); + EXPECT_EQ(39, obj[3][0].asInt()); + EXPECT_FALSE(obj[3][1].asBool()); + EXPECT_EQ(std::string("Another String"), obj[3][2].asString()); + + //Object - valid string + obj = "New valid string"; + ASSERT_EQ(std::string("New valid string"), obj.asString()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + //Obj - bool + obj = true; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + //Object - number + obj = 3.1415926; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); +} + +/** + * Test ArraySchemaItem with schema item + * + * Create ArraySchemaItem with schema item. Method validate should return true + * only if all array elements are valid schema item objects + **/ +TEST(test_item_with_default_value, test_ArraySchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CArraySchemaItem::create(); // No min and max size + + obj[0] = "Some String"; + obj[1] = "true"; + obj[2] = "New String"; + + EXPECT_EQ(std::string("Some String"), obj[0].asString()); + EXPECT_EQ(std::string("true"), obj[1].asString()); + EXPECT_EQ(std::string("New String"), obj[2].asString()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj[0]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[1]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[2]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + item->applySchema(obj); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj[0]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[1]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[2]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + EXPECT_EQ(std::string("Some String"), obj[0].asString()); + EXPECT_EQ(std::string("true"), obj[1].asString()); + EXPECT_EQ(std::string("New String"), obj[2].asString()); + + obj[3][0] = "39"; + obj[3][1] = "false"; + obj[3][2] = "Another String"; + + EXPECT_EQ(std::string("39"), obj[3][0].asString()); + EXPECT_EQ(std::string("false"), obj[3][1].asString()); + EXPECT_EQ(std::string("Another String"), obj[3][2].asString()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj[3]); + EXPECT_EQ(Errors::OK, resultType); + + obj[3][3] = "Another very very loooooong String"; + + resultType = item->validate(obj[3]); + EXPECT_EQ(Errors::OK, resultType); +} + +/** + * Test ArraySchemaItem with min size + **/ +TEST(test_array_with_min_size, test_ArraySchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CArraySchemaItem::create( + CStringSchemaItem::create(TSchemaItemParameter<size_t>(25)), + TSchemaItemParameter<size_t>(3)); + + obj[0] = "Some String"; + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + obj[1] = "true"; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + obj[2] = "New String"; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + EXPECT_EQ(std::string("Some String"), obj[0].asString()); + EXPECT_EQ(std::string("true"), obj[1].asString()); + EXPECT_EQ(std::string("New String"), obj[2].asString()); +} + +/** + * Test ArraySchemaItem with min size + **/ +TEST(test_array_with_max_size, test_ArraySchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CArraySchemaItem::create( + CStringSchemaItem::create(TSchemaItemParameter<size_t>(), + TSchemaItemParameter<size_t>(25)), + TSchemaItemParameter<size_t>(), TSchemaItemParameter<size_t>(3)); // No min size + + obj[0] = "Some String"; + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + obj[1] = "true"; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + obj[2] = "New String"; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + obj[3] = "Another String"; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + EXPECT_EQ(std::string("Some String"), obj[0].asString()); + EXPECT_EQ(std::string("true"), obj[1].asString()); + EXPECT_EQ(std::string("New String"), obj[2].asString()); + EXPECT_EQ(std::string("Another String"), obj[3].asString()); +} + +/** + * Test ArraySchemaItem with min and max size + **/ +TEST(test_array_with_min_and_max_size, test_ArraySchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CArraySchemaItem::create( + CStringSchemaItem::create(TSchemaItemParameter<size_t>(), + TSchemaItemParameter<size_t>(25)), + TSchemaItemParameter<size_t>(2), TSchemaItemParameter<size_t>(4)); + + obj[0] = "Some String"; + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + obj[1] = "true"; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + obj[2] = "New String"; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + obj[3] = "Another String"; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + obj[4] = "Out of array"; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + EXPECT_EQ(std::string("Some String"), obj[0].asString()); + EXPECT_EQ(std::string("true"), obj[1].asString()); + EXPECT_EQ(std::string("New String"), obj[2].asString()); + EXPECT_EQ(std::string("Another String"), obj[3].asString()); + EXPECT_EQ(std::string("Out of array"), obj[4].asString()); +} + +TEST(test_map_validate, test_ArraySchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CArraySchemaItem::create( + CStringSchemaItem::create(TSchemaItemParameter<size_t>(), + TSchemaItemParameter<size_t>(25)), + TSchemaItemParameter<size_t>(2), TSchemaItemParameter<size_t>(4)); + + obj["array"][0] = "Some String"; + + int resultType = item->validate(obj["array"]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + obj["array"][1] = "true"; + + resultType = item->validate(obj["array"]); + EXPECT_EQ(Errors::OK, resultType); + + obj["array"][2] = "New String"; + + resultType = item->validate(obj["array"]); + EXPECT_EQ(Errors::OK, resultType); + + obj["array"][3] = "Another String"; + + resultType = item->validate(obj["array"]); + EXPECT_EQ(Errors::OK, resultType); + + obj["array"][4] = "Out of array"; + + resultType = item->validate(obj["array"]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + EXPECT_EQ(std::string("Some String"), obj["array"][0].asString()); + EXPECT_EQ(std::string("true"), obj["array"][1].asString()); + EXPECT_EQ(std::string("New String"), obj["array"][2].asString()); + EXPECT_EQ(std::string("Another String"), obj["array"][3].asString()); + EXPECT_EQ(std::string("Out of array"), obj["array"][4].asString()); +} +} // namespace SchemaItem +} // namespace SmartObjects +} // namespace components +} // namespace test + diff --git a/src/components/smart_objects/test/BoolSchemaItem_test.cc b/src/components/smart_objects/test/BoolSchemaItem_test.cc new file mode 100644 index 000000000..c56dd9aa2 --- /dev/null +++ b/src/components/smart_objects/test/BoolSchemaItem_test.cc @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" + +#include "utils/shared_ptr.h" + +#include "smart_objects/smart_object.h" +#include "smart_objects/bool_schema_item.h" + +namespace test { +namespace components { +namespace SmartObjects { +namespace SchemaItem { +using NsSmartDeviceLink::NsSmartObjects::ISchemaItemPtr; + +/** + * Test BoolSchemaItem no default value + * + * Create SchemaItem without default value. Method setDefaultValue should always return false + * and leave SmartObject in previous state. + **/ +TEST(test_no_default_value, test_BoolSchemaItemTest) { + NsSmartDeviceLink::NsSmartObjects::SmartObject obj; + + ISchemaItemPtr item = + NsSmartDeviceLink::NsSmartObjects::CBoolSchemaItem::create(); // No default value + + obj = 5; + ASSERT_EQ(5, obj.asInt()); + + int resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + + obj = true; + ASSERT_TRUE(obj.asBool()); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + bool resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + EXPECT_TRUE(obj.asBool()); + + obj = "Test"; + ASSERT_EQ(std::string("Test"), obj.asString()); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); +} + +/** + * Test BoolSchemaItem with default value + * + * Create SchemaItem with default value. Method setDefaultValue should return true, + * Bool SmartObject should contain default value. + * Not bool SmartObject should converted to BoolObject and setted up by default value. + **/ +TEST(test_item_with_default_value, test_BoolSchemaItemTest) { + NsSmartDeviceLink::NsSmartObjects::SmartObject obj; + + ISchemaItemPtr item = + NsSmartDeviceLink::NsSmartObjects::CBoolSchemaItem::create( + NsSmartDeviceLink::NsSmartObjects::TSchemaItemParameter<bool>(false)); // Default value = false + + obj = 5; + ASSERT_EQ(5, obj.asInt()); + + int resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + + obj = true; + ASSERT_TRUE(obj.asBool()); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + bool resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_FALSE(obj.asBool()); + + obj = "Test"; + ASSERT_EQ(std::string("Test"), obj.asString()); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_FALSE(obj.asBool()); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + EXPECT_FALSE(obj.asBool()); +} + +TEST(test_map_validate, test_BoolSchemaItemTest) { + NsSmartDeviceLink::NsSmartObjects::SmartObject obj; + ISchemaItemPtr item = + NsSmartDeviceLink::NsSmartObjects::CBoolSchemaItem::create( + NsSmartDeviceLink::NsSmartObjects::TSchemaItemParameter<bool>(false)); // Default value = false + + obj["aa"] = true; + ASSERT_TRUE(obj["aa"].asBool()); + + int resultType = item->validate(obj["aa"]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + + bool resDefault = item->setDefaultValue(obj["aa"]); + EXPECT_TRUE(resDefault); + EXPECT_FALSE(obj["aa"].asBool()); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_FALSE(obj.asBool()); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + obj["ind"] = true; + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); +} + +TEST(test_array_validate, test_BoolSchemaItemTest) { + NsSmartDeviceLink::NsSmartObjects::SmartObject obj; + ISchemaItemPtr item = + NsSmartDeviceLink::NsSmartObjects::CBoolSchemaItem::create(); + + obj[0] = true; + obj[1] = false; + + ASSERT_TRUE(obj[0].asBool()); + ASSERT_FALSE(obj[1].asBool()); + + int resultType = item->validate(obj[0]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + resultType = item->validate(obj[1]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + + bool resDefault = item->setDefaultValue(obj[0]); + EXPECT_FALSE(resDefault); + EXPECT_TRUE(obj[0].asBool()); + + resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + EXPECT_FALSE(obj[1].asBool()); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + + obj = false; + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); +} +} // namespace SchemaItem" +} // namespace SmartObjects" +} // namespace components" +} // namespace test" diff --git a/src/components/smart_objects/test/CMakeLists.txt b/src/components/smart_objects/test/CMakeLists.txt new file mode 100644 index 000000000..fbcd78cdc --- /dev/null +++ b/src/components/smart_objects/test/CMakeLists.txt @@ -0,0 +1,68 @@ +# Copyright (c) 2014, 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. + +if(BUILD_TESTS) +add_definitions(-DUNIT_TESTS) + +include_directories ( + ${GMOCK_INCLUDE_DIRECTORY} + ${COMPONENTS_DIR}/smart_objects/include + ${COMPONENTS_DIR}/formatters/include/ + ${JSONCPP_INCLUDE_DIRECTORY} +) + +set(LIBRARIES + gmock_main + SmartObjects + formatters + jsoncpp +) + +set(SOURCES + ${COMPONENTS_DIR}/smart_objects/test/SmartObjectDraft_test.cc + ${COMPONENTS_DIR}/smart_objects/test/SmartObjectInvalid_test.cc + ${COMPONENTS_DIR}/smart_objects/test/SmartObjectStress_test.cc + ${COMPONENTS_DIR}/smart_objects/test/SmartObjectUnit_test.cc + ${COMPONENTS_DIR}/smart_objects/test/TSharedPtr_test.cc + ${COMPONENTS_DIR}/smart_objects/test/smart_object_performance_test.cc + ${COMPONENTS_DIR}/smart_objects/test/map_performance_test.cc + ${COMPONENTS_DIR}/smart_objects/test/main.cc + ${COMPONENTS_DIR}/smart_objects/test/BoolSchemaItem_test.cc + ${COMPONENTS_DIR}/smart_objects/test/NumberSchemaItem_test.cc + ${COMPONENTS_DIR}/smart_objects/test/StringSchemaItem_test.cc + ${COMPONENTS_DIR}/smart_objects/test/ArraySchemaItem_test.cc + ${COMPONENTS_DIR}/smart_objects/test/CObjectSchemaItem_test.cc + ${COMPONENTS_DIR}/smart_objects/test/AlwaysTrueSchemaItem_test.cc + ${COMPONENTS_DIR}/smart_objects/test/AlwaysFalseSchemaItem_test.cc +) + +create_test("smart_object_test" "${SOURCES}" "${LIBRARIES}") + +endif() diff --git a/src/components/smart_objects/test/CObjectSchemaItem_test.cc b/src/components/smart_objects/test/CObjectSchemaItem_test.cc new file mode 100644 index 000000000..56f365e5c --- /dev/null +++ b/src/components/smart_objects/test/CObjectSchemaItem_test.cc @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" +#include "smart_objects/smart_object.h" +#include "smart_objects/smart_schema.h" +#include "smart_objects/array_schema_item.h" +#include "smart_objects/bool_schema_item.h" +#include "smart_objects/string_schema_item.h" +#include "smart_objects/enum_schema_item.h" +#include "smart_objects/number_schema_item.h" +#include "smart_objects/schema_item_parameter.h" +#include "smart_objects/object_schema_item.h" +#include "formatters/generic_json_formatter.h" +#include "formatters/CSmartFactory.hpp" + +namespace formatters = NsSmartDeviceLink::NsJSONHandler::Formatters; +namespace smartobj = NsSmartDeviceLink::NsSmartObjects; + +using namespace NsSmartDeviceLink::NsSmartObjects; +using namespace NsSmartDeviceLink::NsJSONHandler::strings; + +namespace test { +namespace components { +namespace SmartObjects { +namespace SchemaItem { + +namespace FunctionID { +enum eType { + INVALID_ENUM = -1, + Function0 = 0, + Function1, + Function2, + Function3, + Function4, + Function5, + Function6 +}; +} // namespace FunctionID + +namespace ResultType { +enum eType { + INVALID_ENUM = -1, + APPLICATION_NOT_REGISTERED = 0, + SUCCESS, + TOO_MANY_PENDING_REQUESTS, + REJECTED, + INVALID_DATA, + OUT_OF_MEMORY, + ABORTED, + USER_DISALLOWED, + GENERIC_ERROR, + DISALLOWED +}; +} // namespace ResultType + +namespace Keys { +const char RESULT_CODE[] = "resultCode"; +const char INFO[] = "info"; +const char SUCCESS[] = "success"; +} + +class ObjectSchemaItemTest : public ::testing::Test { + protected: + ISchemaItemPtr schema_item; + // Create SmartObjectSchema for test object + void SetUp() { + std::set<FunctionID::eType> function_values; + function_values.insert(FunctionID::Function0); + function_values.insert(FunctionID::Function1); + function_values.insert(FunctionID::Function2); + function_values.insert(FunctionID::Function3); + function_values.insert(FunctionID::Function4); + function_values.insert(FunctionID::Function5); + function_values.insert(FunctionID::Function6); + + std::set<ResultType::eType> resultCode_values; + resultCode_values.insert(ResultType::APPLICATION_NOT_REGISTERED); + resultCode_values.insert(ResultType::SUCCESS); + resultCode_values.insert(ResultType::TOO_MANY_PENDING_REQUESTS); + resultCode_values.insert(ResultType::REJECTED); + resultCode_values.insert(ResultType::INVALID_DATA); + resultCode_values.insert(ResultType::OUT_OF_MEMORY); + resultCode_values.insert(ResultType::ABORTED); + resultCode_values.insert(ResultType::USER_DISALLOWED); + resultCode_values.insert(ResultType::GENERIC_ERROR); + resultCode_values.insert(ResultType::DISALLOWED); + + CObjectSchemaItem::Members paramsMembersMap; + paramsMembersMap[S_FUNCTION_ID] = CObjectSchemaItem::SMember( + TEnumSchemaItem<FunctionID::eType>::create(function_values), true); + paramsMembersMap[S_CORRELATION_ID] = CObjectSchemaItem::SMember( + TNumberSchemaItem<int>::create(), true); + paramsMembersMap[S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember( + TNumberSchemaItem<int>::create(TSchemaItemParameter<int>(1), + TSchemaItemParameter<int>(2)), + true); + + CObjectSchemaItem::Members schemaMembersMap; + schemaMembersMap[Keys::RESULT_CODE] = CObjectSchemaItem::SMember( + TEnumSchemaItem<ResultType::eType>::create(resultCode_values), false); + schemaMembersMap[Keys::INFO] = CObjectSchemaItem::SMember( + CStringSchemaItem::create(TSchemaItemParameter<size_t>(0), + TSchemaItemParameter<size_t>(10)), + false); + schemaMembersMap[Keys::SUCCESS] = CObjectSchemaItem::SMember( + CBoolSchemaItem::create(), false); + + CObjectSchemaItem::Members rootMembersMap; + rootMembersMap[S_PARAMS] = CObjectSchemaItem::SMember( + CObjectSchemaItem::create(paramsMembersMap), true); + rootMembersMap[S_MSG_PARAMS] = CObjectSchemaItem::SMember( + CObjectSchemaItem::create(schemaMembersMap), true); + + schema_item = CObjectSchemaItem::create(rootMembersMap); + } +}; + +TEST_F(ObjectSchemaItemTest, validation_correct) { + SmartObject obj; + obj[S_PARAMS][S_FUNCTION_ID] = 0; + obj[S_PARAMS][S_CORRELATION_ID] = 0XFF0; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 1; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 0; + obj[S_MSG_PARAMS][Keys::INFO] = "0123456789"; + obj[S_MSG_PARAMS][Keys::SUCCESS] = true; + + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); +} + +TEST_F(ObjectSchemaItemTest, validation_correct_skip_not_mandatory) { + SmartObject obj; + obj[S_PARAMS][S_FUNCTION_ID] = 1; + obj[S_PARAMS][S_CORRELATION_ID] = -0xFF1; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 1; + // skip non-mandatory obj[S_MSG_PARAMS][Keys::INFO] + obj[S_MSG_PARAMS][Keys::SUCCESS] = false; + + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); +} + +TEST_F(ObjectSchemaItemTest, validation_invalid_param) { + SmartObject obj; + obj[S_PARAMS] = "some parameters"; + obj[S_MSG_PARAMS] = "some message parameters"; + + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); + + obj[S_PARAMS][S_FUNCTION_ID] = "some function"; + obj[S_PARAMS][S_CORRELATION_ID] = "some correlation id"; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 3; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = "some result"; + obj[S_MSG_PARAMS][Keys::SUCCESS] = 0xABC; + + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); + + obj[S_PARAMS][S_FUNCTION_ID] = 1; + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); + + obj[S_PARAMS][S_CORRELATION_ID] = -0xFF1; + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); + + obj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); + + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 1; + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); + + obj[S_MSG_PARAMS][Keys::SUCCESS] = false; + + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); +} +TEST_F(ObjectSchemaItemTest, validation_invalid_not_mandatory_param) { + SmartObject obj; + obj[S_PARAMS][S_FUNCTION_ID] = 0; + obj[S_PARAMS][S_CORRELATION_ID] = 0XFF0; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 1; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 0; + obj[S_MSG_PARAMS][Keys::SUCCESS] = true; + + // invalid non-mandatory obj[S_MSG_PARAMS][Keys::INFO] + obj[S_MSG_PARAMS][Keys::INFO] = 0x10; + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); + + // invalid non-mandatory obj[S_MSG_PARAMS][Keys::INFO] + obj[S_MSG_PARAMS][Keys::INFO] = true; + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); + + // invalid non-mandatory obj[S_MSG_PARAMS][Keys::INFO] + obj[S_MSG_PARAMS][Keys::INFO] = SmartObject(); + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); + + obj[S_MSG_PARAMS][Keys::INFO] = "info"; + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); +} + +TEST_F(ObjectSchemaItemTest, validation_missing_mandatory) { + SmartObject obj; + // missed obj[S_PARAMS][S_FUNCTION_ID] + // missed obj[S_PARAMS][S_CORRELATION_ID] + // missed obj[S_PARAMS][S_PROTOCOL_VERSION] + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 2; + obj[S_MSG_PARAMS][Keys::INFO] = "123"; + obj[S_MSG_PARAMS][Keys::SUCCESS] = false; + + EXPECT_EQ(Errors::MISSING_MANDATORY_PARAMETER, schema_item->validate(obj)); + + obj[S_PARAMS][S_FUNCTION_ID] = 2; + // S_CORRELATION_ID and S_PROTOCOL_VERSION is still missed + EXPECT_EQ(Errors::MISSING_MANDATORY_PARAMETER, schema_item->validate(obj)); + + obj[S_PARAMS][S_CORRELATION_ID] = 0XFF2; + // S_PROTOCOL_VERSION is still missed + EXPECT_EQ(Errors::MISSING_MANDATORY_PARAMETER, schema_item->validate(obj)); + + obj[S_PARAMS][S_PROTOCOL_VERSION] = 1; + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); +} + +TEST_F(ObjectSchemaItemTest, validation_unexpected_param) { + const char* fake1 = "FAKE_PARAM1"; + const char* fake2 = "FAKE_PARAM2"; + const char* fake3 = "FAKE_PARAM3"; + + SmartObject obj; + obj[S_PARAMS][S_FUNCTION_ID] = 0; + obj[S_PARAMS][S_CORRELATION_ID] = 0XFF; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 1; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 2; + obj[S_MSG_PARAMS][Keys::INFO] = "123"; + obj[S_MSG_PARAMS][Keys::SUCCESS] = true; + + obj[fake1] = SmartObject(static_cast<int64_t>(0)); + // any fake parameter is OK + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); + + obj[S_PARAMS][fake2] = SmartObject("123"); + // any fake parameters are OK + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); + + obj[S_MSG_PARAMS][fake3] = true; + // any fake parameters are OK + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); +} + +TEST_F(ObjectSchemaItemTest, validation_unexpected_param_remove) { + const char* fake1 = "FAKE_PARAM1"; + const char* fake2 = "FAKE_PARAM2"; + const char* fake3 = "FAKE_PARAM3"; + + SmartObject obj = SmartObject(SmartType::SmartType_Map); + obj[S_PARAMS][S_FUNCTION_ID] = 0; + obj[S_PARAMS][S_CORRELATION_ID] = 0XFF; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 1; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 2; + obj[S_MSG_PARAMS][Keys::INFO] = "123"; + obj[S_MSG_PARAMS][Keys::SUCCESS] = true; + + obj[fake1] = SmartObject(static_cast<int64_t>(0)); + obj[S_PARAMS][fake2] = SmartObject("123"); + obj[S_MSG_PARAMS][fake3] = true; + + // Check apply schema + schema_item->applySchema(obj); + + EXPECT_TRUE(obj.keyExists(fake1)); + EXPECT_TRUE(obj[S_PARAMS].keyExists(fake2)); + EXPECT_TRUE(obj[S_MSG_PARAMS].keyExists(fake3)); + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); + + // all fake parameters are removed on unapply schema + schema_item->unapplySchema(obj); + + EXPECT_FALSE(obj.keyExists(fake1)); + EXPECT_FALSE(obj[S_PARAMS].keyExists(fake2)); + EXPECT_FALSE(obj[S_MSG_PARAMS].keyExists(fake3)); + + obj[fake1] = SmartObject(static_cast<int64_t>(0)); + obj[S_PARAMS][fake2] = SmartObject("123"); + obj[S_MSG_PARAMS][fake3] = true; + + // Check unapply schema + schema_item->unapplySchema(obj); + // all fake parameters are removed on apply schema + EXPECT_FALSE(obj.keyExists(fake1)); + EXPECT_FALSE(obj[S_PARAMS].keyExists(fake2)); + EXPECT_FALSE(obj[S_MSG_PARAMS].keyExists(fake3)); + // Invalide state after enum convertion + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); +} + +TEST_F(ObjectSchemaItemTest, validation_empty_params) { + SmartObject obj; + obj[S_PARAMS][S_FUNCTION_ID] = 1; + obj[S_PARAMS][S_CORRELATION_ID] = 0xFF; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + obj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + // S_MSG_PARAMS has only fake parameter + obj[S_MSG_PARAMS]["FAKE_PARAM1"] = SmartObject(); + obj[S_MSG_PARAMS]["FAKE_PARAM2"] = SmartObject(0x1); + obj[S_MSG_PARAMS]["FAKE_PARAM3"] = SmartObject("2"); + + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); + + schema_item->applySchema(obj); + EXPECT_EQ(Errors::OK, schema_item->validate(obj)); + + schema_item->unapplySchema(obj); + // Invalide state after enum convertion + EXPECT_EQ(Errors::INVALID_VALUE, schema_item->validate(obj)); +} + +TEST_F(ObjectSchemaItemTest, test_strings_to_enum_conversion) { + SmartObject object; + object[S_PARAMS][S_FUNCTION_ID] = SmartObject(); + object[S_PARAMS][S_CORRELATION_ID] = 0XFF0; + object[S_PARAMS][S_PROTOCOL_VERSION] = 1; + object[S_MSG_PARAMS][Keys::RESULT_CODE] = SmartObject(); + object[S_MSG_PARAMS][Keys::INFO] = "0123456789"; + object[S_MSG_PARAMS][Keys::SUCCESS] = true; + + typedef EnumConversionHelper<ResultType::eType>::CStringToEnumMap Results; + const Results results = + EnumConversionHelper<ResultType::eType>::cstring_to_enum_map(); + + typedef EnumConversionHelper<FunctionID::eType>::CStringToEnumMap Functions; + const Functions functions = + EnumConversionHelper<FunctionID::eType>::cstring_to_enum_map(); + + for (Results::const_iterator res_it = results.begin(); + res_it != results.end(); ++res_it) { + for (Functions::const_iterator func_it = functions.begin(); + func_it != functions.end(); ++func_it) { + const char* const function_str = func_it->first; + const char* const result_type_str = res_it->first; + const FunctionID::eType function_type = func_it->second; + const ResultType::eType result_type = res_it->second; + + object[S_PARAMS][S_FUNCTION_ID] = function_str; + object[S_MSG_PARAMS][Keys::RESULT_CODE] = result_type_str; + + // S_FUNCTION_ID and RESULT_CODE are not converted to int + EXPECT_NE(Errors::OK, schema_item->validate(object)); + + schema_item->applySchema(object); + EXPECT_EQ(Errors::OK, schema_item->validate(object)); + + // check conversion result + EXPECT_EQ(function_type, object[S_PARAMS][S_FUNCTION_ID].asInt()); + EXPECT_EQ(result_type, object[S_MSG_PARAMS][Keys::RESULT_CODE].asInt()); + + schema_item->unapplySchema(object); + // S_FUNCTION_ID and RESULT_CODE are string + EXPECT_NE(Errors::OK, schema_item->validate(object)); + + // check conversion result + EXPECT_EQ(function_str, object[S_PARAMS][S_FUNCTION_ID].asString()); + EXPECT_EQ(result_type_str, + object[S_MSG_PARAMS][Keys::RESULT_CODE].asString()); + } + } +} +// ---------------------------------------------------------------------------- +}// namespace SchemaItem +} // namespace SmartObjects +} // namespace components +} // namespace test + +namespace NsSmartDeviceLink { +namespace NsSmartObjects { + +namespace FunctionID = test::components::SmartObjects::SchemaItem::FunctionID; +typedef EnumConversionHelper<FunctionID::eType> FunctionConvertor; + +template<> +const FunctionConvertor::EnumToCStringMap FunctionConvertor::enum_to_cstring_map_ = + FunctionConvertor::InitEnumToCStringMap(); + +template<> +const FunctionConvertor::CStringToEnumMap FunctionConvertor::cstring_to_enum_map_ = + FunctionConvertor::InitCStringToEnumMap(); + +template<> +const char* const FunctionConvertor::cstring_values_[] = + { "Function0", "Function1", "Function2", "Function3", "Function4", + "Function5", "Function6" }; + +template<> +const FunctionID::eType FunctionConvertor::enum_values_[] = { + FunctionID::Function0, FunctionID::Function1, FunctionID::Function2, + FunctionID::Function3, FunctionID::Function4, FunctionID::Function5, + FunctionID::Function6 }; + +// ---------------------------------------------------------------------------- + +namespace ResultType = test::components::SmartObjects::SchemaItem::ResultType; +typedef EnumConversionHelper<ResultType::eType> ResultTypeConvertor; + +template<> +const ResultTypeConvertor::EnumToCStringMap ResultTypeConvertor::enum_to_cstring_map_ = + ResultTypeConvertor::InitEnumToCStringMap(); + +template<> +const ResultTypeConvertor::CStringToEnumMap ResultTypeConvertor::cstring_to_enum_map_ = + ResultTypeConvertor::InitCStringToEnumMap(); + +template<> +const char* const ResultTypeConvertor::cstring_values_[] = { + "APPLICATION_NOT_REGISTERED", "SUCCESS", "TOO_MANY_PENDING_REQUESTS", + "REJECTED", "INVALID_DATA", "OUT_OF_MEMORY", "ABORTED", "USER_DISALLOWED", + "GENERIC_ERROR", "DISALLOWED" }; + +template<> +const ResultType::eType ResultTypeConvertor::enum_values_[] = { + ResultType::APPLICATION_NOT_REGISTERED, ResultType::SUCCESS, + ResultType::TOO_MANY_PENDING_REQUESTS, ResultType::REJECTED, + ResultType::INVALID_DATA, ResultType::OUT_OF_MEMORY, ResultType::ABORTED, + ResultType::USER_DISALLOWED, ResultType::GENERIC_ERROR, + ResultType::DISALLOWED }; +} // namespace NsSmartObjects +} // namespace NsSmartDeviceLink diff --git a/src/components/smart_objects/test/EnumSchemaItem_test.cc b/src/components/smart_objects/test/EnumSchemaItem_test.cc new file mode 100644 index 000000000..e99e2f4e6 --- /dev/null +++ b/src/components/smart_objects/test/EnumSchemaItem_test.cc @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" + +#include "smart_objects/smart_object.h" +#include "smart_objects/enum_schema_item.h" +#include "smart_objects/string_schema_item.h" + +#include <string> + +namespace test { +namespace components { +namespace SmartObjects { +namespace SchemaItem { + +using namespace NsSmartDeviceLink::NsSmartObjects; +namespace TestType { +enum eType { + INVALID_ENUM = -1, + USER_EXIT = 0, + IGNITION_OFF, + BLUETOOTH_OFF, + USB_DISCONNECTED, + TOO_MANY_REQUESTS, + MASTER_RESET, + FACTORY_DEFAULTS, + APP_UNAUTHORIZED +}; +} + +class EnumSchemaItemTest : public ::testing::Test { + protected: + EnumSchemaItemTest() { + testEnum.insert(TestType::USER_EXIT); + testEnum.insert(TestType::IGNITION_OFF); + testEnum.insert(TestType::BLUETOOTH_OFF); + testEnum.insert(TestType::USB_DISCONNECTED); + testEnum.insert(TestType::TOO_MANY_REQUESTS); + testEnum.insert(TestType::MASTER_RESET); + testEnum.insert(TestType::FACTORY_DEFAULTS); + testEnum.insert(TestType::APP_UNAUTHORIZED); + } + + virtual void SetUp() { + } + + std::set<TestType::eType> testEnum; +}; + +/** + * Test EnumSchemaItem + * + * Create SchemaItem with default value. Method setDefaultValue should return true, + * SmartObject should contain default value. + * Not Enum SmartObject should converted to intObject and setted up by the default value. + **/ +TEST_F(EnumSchemaItemTest, test_item_with_default_value) { + SmartObject obj; + ISchemaItemPtr item = TEnumSchemaItem<TestType::eType>::create( + testEnum, + TSchemaItemParameter<TestType::eType>(TestType::FACTORY_DEFAULTS)); + + //Object - valid enum + obj = TestType::BLUETOOTH_OFF; + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + bool resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(TestType::FACTORY_DEFAULTS, obj.asInt()); + + //Obj - bool + obj = true; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(TestType::FACTORY_DEFAULTS, obj.asInt()); + + //Object - number + obj = 3.1415926; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(TestType::FACTORY_DEFAULTS, obj.asInt()); + + //Object - string + obj = "Some string"; + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(TestType::FACTORY_DEFAULTS, obj.asInt()); +} + +/** + * Test EnumSchemaItem with default value + * + * Create SchemaItem without default value. Method setDefaultValue should return false, + * SmartObject should contain previous value. + **/ +TEST_F(EnumSchemaItemTest, test_item_without_default_value) { + SmartObject obj; + + ISchemaItemPtr item = TEnumSchemaItem<TestType::eType>::create( + testEnum, TSchemaItemParameter<TestType::eType>()); + + //Object - valid enum + obj = TestType::BLUETOOTH_OFF; + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + bool resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + EXPECT_EQ(TestType::BLUETOOTH_OFF, obj.asInt()); + + //Obj - bool + obj = true; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + EXPECT_TRUE(obj.asBool()); + + //Object - number + obj = 3.1415926; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + EXPECT_EQ(3.1415926, obj.asDouble()); + + //Object - string + obj = "Some string"; + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + EXPECT_EQ(std::string("Some string"), obj.asString()); + + //Object - int in range of enum + obj = 6; + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object - int out of enum range + obj = 15; + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); +} + +/** + * Test apply and unapply EnumSchemaItem + **/ +TEST_F(EnumSchemaItemTest, test_apply_unapply_schema) { + SmartObject obj; + + ISchemaItemPtr item = TEnumSchemaItem<TestType::eType>::create( + testEnum, + TSchemaItemParameter<TestType::eType>(TestType::FACTORY_DEFAULTS)); + + //Object - valid enum + obj = TestType::BLUETOOTH_OFF; + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + bool resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(TestType::FACTORY_DEFAULTS, obj.asInt()); + + item->unapplySchema(obj); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + EXPECT_EQ(std::string("FACTORY_DEFAULTS"), obj.asString()); + + item->applySchema(obj); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(TestType::FACTORY_DEFAULTS, obj.asInt()); + + obj = "TOO_MANY_REQUESTS"; + item->applySchema(obj); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(TestType::TOO_MANY_REQUESTS, obj.asInt()); + + obj = "ENOUGH_REQUESTS"; + item->applySchema(obj); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + EXPECT_EQ(std::string("ENOUGH_REQUESTS"), obj.asString()); +} + +} +} +} +} + +namespace NsSmartDeviceLink { +namespace NsSmartObjects { + +template<> +const EnumConversionHelper< + test::components::SmartObjects::SchemaItem::TestType::eType>::EnumToCStringMap EnumConversionHelper< + test::components::SmartObjects::SchemaItem::TestType::eType>::enum_to_cstring_map_ = + EnumConversionHelper< + test::components::SmartObjects::SchemaItem::TestType::eType>::InitEnumToCStringMap(); + +template<> +const EnumConversionHelper< + test::components::SmartObjects::SchemaItem::TestType::eType>::CStringToEnumMap EnumConversionHelper< + test::components::SmartObjects::SchemaItem::TestType::eType>::cstring_to_enum_map_ = + EnumConversionHelper< + test::components::SmartObjects::SchemaItem::TestType::eType>::InitCStringToEnumMap(); + +template<> +const char* const EnumConversionHelper< + test::components::SmartObjects::SchemaItem::TestType::eType>::cstring_values_[] = + { "USER_EXIT", "IGNITION_OFF", "BLUETOOTH_OFF", "USB_DISCONNECTED", + "TOO_MANY_REQUESTS", "MASTER_RESET", "FACTORY_DEFAULTS", + "APP_UNAUTHORIZED" }; + +template<> +const test::components::SmartObjects::SchemaItem::TestType::eType EnumConversionHelper< + test::components::SmartObjects::SchemaItem::TestType::eType>::enum_values_[] = + { test::components::SmartObjects::SchemaItem::TestType::USER_EXIT, + test::components::SmartObjects::SchemaItem::TestType::IGNITION_OFF, + test::components::SmartObjects::SchemaItem::TestType::BLUETOOTH_OFF, + test::components::SmartObjects::SchemaItem::TestType::USB_DISCONNECTED, + test::components::SmartObjects::SchemaItem::TestType::TOO_MANY_REQUESTS, + test::components::SmartObjects::SchemaItem::TestType::MASTER_RESET, + test::components::SmartObjects::SchemaItem::TestType::FACTORY_DEFAULTS, + test::components::SmartObjects::SchemaItem::TestType::APP_UNAUTHORIZED }; + +} +} diff --git a/src/components/smart_objects/test/NumberSchemaItem_test.cc b/src/components/smart_objects/test/NumberSchemaItem_test.cc new file mode 100644 index 000000000..6e372593f --- /dev/null +++ b/src/components/smart_objects/test/NumberSchemaItem_test.cc @@ -0,0 +1,780 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" +#include "smart_objects/smart_object.h" +#include "smart_objects/number_schema_item.h" + +namespace test { +namespace components { +namespace SmartObjects { +namespace SchemaItem { + +using NsSmartDeviceLink::NsSmartObjects::ISchemaItemPtr; + +/** + * Test NumberSchemaItem as INT with no default value + * + * Create SchemaItem without default value. Method setDefaultValue should always return false + * and leave SmartObject in previous state. + **/ +TEST(test_int_no_default_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<int>::create(); // No default value, no min, no max + + //Object int + obj = 5; + ASSERT_EQ(5, obj.asInt()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Obj bool + obj = true; + ASSERT_TRUE(obj.asBool()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + //Set default value + bool resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + EXPECT_TRUE(obj.asBool()); + + //Obj string + obj = "Test"; + ASSERT_EQ(std::string("Test"), obj.asString()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); +} + +/** + * Test NumberSchemaItem as INT with setted min value + **/ +TEST(test_int_min_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<int>::create( + TSchemaItemParameter<int>(10)); // No default value, no max value + + //Object int correct + obj = 15; + ASSERT_EQ(15, obj.asInt()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object int incorrect + obj = 9; + ASSERT_EQ(9, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Object int correct + obj = 10; + ASSERT_EQ(10, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); +} + +/** + * Test NumberSchemaItem as INT with setted max value + **/ +TEST(test_int_max_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<int>::create( + TSchemaItemParameter<int>(), TSchemaItemParameter<int>(749)); // No default value, no min value + + //Object int correct + obj = 749; + ASSERT_EQ(749, obj.asInt()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object int incorrect + obj = 750; + ASSERT_EQ(750, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Object int correct + obj = -750; + ASSERT_EQ(-750, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); +} + +/** + * Test NumberSchemaItem as INT with setted min and max value + **/ +TEST(test_int_min_max_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<int>::create( + TSchemaItemParameter<int>(-949), TSchemaItemParameter<int>(749)); // No default value + + //Object int correct + obj = 749; + ASSERT_EQ(749, obj.asInt()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object int incorrect + obj = 750; + ASSERT_EQ(750, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Object int correct + obj = -949; + ASSERT_EQ(-949, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object int incorrect + obj = -950; + ASSERT_EQ(-950, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + +} + +/** + * Test NumberSchemaItem as INT with correct default value + **/ +TEST(test_int_correct_default_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<int>::create( + TSchemaItemParameter<int>(-12000), TSchemaItemParameter<int>(100), + TSchemaItemParameter<int>(-38)); + + //Object int correct + obj = -12000; + ASSERT_EQ(-12000, obj.asInt()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object int incorrect + obj = -12001; + ASSERT_EQ(-12001, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Object int correct + obj = 100; + ASSERT_EQ(100, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object int incorrect + obj = 101; + ASSERT_EQ(101, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Set default value + bool resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(-38, obj.asInt()); + + //Object string + obj = "string"; + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(-38, obj.asInt()); +} + +/** + * Test NumberSchemaItem as INT with default value out of range + **/ +TEST(test_int_default_value_out_of_range, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<int>::create( + TSchemaItemParameter<int>(90), TSchemaItemParameter<int>(100), + TSchemaItemParameter<int>(50)); // Default value out of range + + //Object int correct + obj = 90; + ASSERT_EQ(90, obj.asInt()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object int incorrect + obj = 89; + ASSERT_EQ(89, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Object int correct + obj = 100; + ASSERT_EQ(100, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object int incorrect + obj = 101; + ASSERT_EQ(101, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Set default value + bool resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + EXPECT_EQ(50, obj.asInt()); + + //Object string + obj = "string"; + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + EXPECT_EQ(50, obj.asInt()); +} + +TEST(test_int_map_validate, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<int>::create( + TSchemaItemParameter<int>(-120), TSchemaItemParameter<int>(100), + TSchemaItemParameter<int>(-38)); + + obj["min"] = -120; + obj["out_of_min"] = -121; + obj["max"] = 100; + obj["out_of_max"] = 101; + + int resultType = item->validate(obj["min"]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj["max"]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj["out_of_min"]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + resultType = item->validate(obj["out_of_max"]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + //Set default value + bool resDefault = item->setDefaultValue(obj["aa"]); + EXPECT_TRUE(resDefault); + EXPECT_EQ(-38, obj["aa"].asInt()); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(-38, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + resultType = item->validate(obj["min"]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); +} + +TEST(test_int_array_validate, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<int>::create( + TSchemaItemParameter<int>(-120), TSchemaItemParameter<int>(100), + TSchemaItemParameter<int>(-38)); + + obj[0] = -121; + obj[1] = -120; + obj[2] = 100; + obj[3] = 101; + + int resultType = item->validate(obj[0]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OUT_OF_RANGE, + resultType); + + resultType = item->validate(obj[1]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + resultType = item->validate(obj[2]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + resultType = item->validate(obj[3]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OUT_OF_RANGE, + resultType); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + + bool resDefault = item->setDefaultValue(obj[0]); + EXPECT_TRUE(resDefault); + EXPECT_EQ(-38, obj[0].asInt()); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(-38, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + resultType = item->validate(obj[0]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); +} + +/** + * Test NumberSchemaItem as DOUBLE with no default value + * + * Create SchemaItem without default value. Method setDefaultValue should always return false + * and leave SmartObject in previous state. + **/ +TEST(test_double_no_default_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<double>::create(); // No default value, no min, no max + + //Object int + obj = 5.79; + ASSERT_EQ(5.79, obj.asDouble()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Obj bool + obj = true; + ASSERT_TRUE(obj.asBool()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + //Set default value + bool resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + EXPECT_TRUE(obj.asBool()); + + //Obj string + obj = "Test"; + ASSERT_EQ(std::string("Test"), obj.asString()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + //Set default value + resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); +} + +/** + * Test NumberSchemaItem as DOUBLE with setted min value + **/ +TEST(test_double_min_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<double>::create( + TSchemaItemParameter<double>(10.0)); // No default value, no max value + + //Object double correct + obj = 10.000001; + ASSERT_EQ(10.000001, obj.asDouble()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object double incorrect + obj = 9.999999; + ASSERT_EQ(9.999999, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + /* + //Object int + obj = 10; + ASSERT_EQ(10, obj.asInt()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType);*/ +} + +/** + * Test NumberSchemaItem as DOUBLE with setted max value + **/ +TEST(test_double_max_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<double>::create( + TSchemaItemParameter<double>(), TSchemaItemParameter<double>(749.0)); // No default value, no min value + + //Object double correct + obj = 749.0; + ASSERT_EQ(749.0, obj.asDouble()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object double incorrect + obj = 749.0001; + ASSERT_EQ(749.0001, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Object double correct + obj = -750.0; + ASSERT_EQ(-750.0, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); +} + +/** + * Test NumberSchemaItem as DOUBLE with setted min and max value + **/ +TEST(test_double_min_max_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<double>::create( + TSchemaItemParameter<double>(-949.0), + TSchemaItemParameter<double>(749.0)); // No default value + + //Object double correct + obj = 749.0; + ASSERT_EQ(749.0, obj.asDouble()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object double incorrect + obj = 749.001; + ASSERT_EQ(749.001, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Object double correct + obj = -949.0; + ASSERT_EQ(-949.0, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object double incorrect + obj = -949.00001; + ASSERT_EQ(-949.00001, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + +} + +/** + * Test NumberSchemaItem as DOUBLE with correct default value + **/ +TEST(test_double_correct_default_value, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<double>::create( + TSchemaItemParameter<double>(-12000.0), + TSchemaItemParameter<double>(100.0), TSchemaItemParameter<double>(-38.0)); + + //Object double correct + obj = -12000.0; + ASSERT_EQ(-12000.0, obj.asDouble()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object double incorrect + obj = -12000.01; + ASSERT_EQ(-12000.01, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Object double correct + obj = 100.0; + ASSERT_EQ(100.0, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object double incorrect + obj = 100.001; + ASSERT_EQ(100.001, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Set default value + bool resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(-38.0, obj.asDouble()); + + //Object string + obj = "string"; + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(-38.0, obj.asDouble()); +} + +/** + * Test NumberSchemaItem as DOUBLE with default value out of range + **/ +TEST(test_double_default_value_out_of_range, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<double>::create( + TSchemaItemParameter<double>(90.0), TSchemaItemParameter<double>(100.0), + TSchemaItemParameter<double>(50.0)); // Default value out of range + + //Object double correct + obj = 90.0; + ASSERT_EQ(90.0, obj.asDouble()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object double incorrect + obj = 89.999; + ASSERT_EQ(89.999, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Object double correct + obj = 100.0; + ASSERT_EQ(100.0, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + //Object double incorrect + obj = 100.001; + ASSERT_EQ(100.001, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + //Set default value + bool resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + EXPECT_EQ(50.0, obj.asDouble()); + + //Object string + obj = "string"; + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + EXPECT_EQ(50.0, obj.asDouble()); +} + +TEST(test_double_map_validate, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<double>::create( + TSchemaItemParameter<double>(-120.0), TSchemaItemParameter<double>(100.0), + TSchemaItemParameter<double>(-38.0)); + + obj["min"] = -120.0; + obj["out_of_min"] = -120.001; + obj["max"] = 100.0; + obj["out_of_max"] = 100.001; + + int resultType = item->validate(obj["min"]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj["max"]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj["out_of_min"]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + resultType = item->validate(obj["out_of_max"]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + bool resDefault = item->setDefaultValue(obj["aa"]); + EXPECT_TRUE(resDefault); + EXPECT_EQ(-38.0, obj["aa"].asDouble()); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(-38.0, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + + resultType = item->validate(obj["min"]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); +} + +TEST(test_double_array_validate, test_NumberSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + + SmartObject obj; + + ISchemaItemPtr item = TNumberSchemaItem<double>::create( + TSchemaItemParameter<double>(-120.0), TSchemaItemParameter<double>(100.0), + TSchemaItemParameter<double>(-38.0)); + + obj[0] = -120.001; + obj[1] = -120.0; + obj[2] = 100.0; + obj[3] = 100.000001; + + int resultType = item->validate(obj[0]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OUT_OF_RANGE, + resultType); + + resultType = item->validate(obj[1]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + resultType = item->validate(obj[2]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + resultType = item->validate(obj[3]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OUT_OF_RANGE, + resultType); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + + bool resDefault = item->setDefaultValue(obj[0]); + EXPECT_TRUE(resDefault); + EXPECT_EQ(-38.0, obj[0].asDouble()); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(-38.0, obj.asDouble()); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::OK, resultType); + + resultType = item->validate(obj[0]); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); + + resultType = item->validate(obj); + EXPECT_EQ(NsSmartDeviceLink::NsSmartObjects::Errors::INVALID_VALUE, + resultType); +} +} // namespace SchemaItem +} // namespace SmartObjects +} // namespace components +} // namespace test diff --git a/src/components/smart_objects/test/SmartObjectConvertionTime_test.cc b/src/components/smart_objects/test/SmartObjectConvertionTime_test.cc new file mode 100644 index 000000000..11a1ed3d2 --- /dev/null +++ b/src/components/smart_objects/test/SmartObjectConvertionTime_test.cc @@ -0,0 +1,714 @@ +//TODO +//this test file should be refactored. Now it doesn't test anything. +//Previously it tests equality of objects but should test time for object's conversion +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" + +#include "utils/shared_ptr.h" + +#include "smart_objects/smart_object.h" +#include "smart_objects/smart_schema.h" +#include "smart_objects/schema_item.h" +#include "formatters/CFormatterJsonSDLRPCv2.hpp" +#include "formatters/CFormatterJsonSDLRPCv1.hpp" +#include "smart_objects/array_schema_item.h" +#include "smart_objects/bool_schema_item.h" +#include "smart_objects/object_schema_item.h" +#include "smart_objects/string_schema_item.h" +#include "smart_objects/enum_schema_item.h" +#include "smart_objects/number_schema_item.h" +#include "smart_objects/schema_item_parameter.h" + +#include <string> +#include <time.h> + +namespace test { +namespace components { +namespace SmartObjects { +namespace SmartObjectConvertionTimeTest { + +using namespace NsSmartDeviceLink::NsJSONHandler::strings; +using namespace NsSmartDeviceLink::NsSmartObjects; + +namespace TestType { +enum eType { + INVALID_ENUM = -1, + APPLICATION_NOT_REGISTERED = 0, + SUCCESS, + TOO_MANY_PENDING_REQUESTS, + REJECTED, + INVALID_DATA, + OUT_OF_MEMORY, + ABORTED, + USER_DISALLOWED, + GENERIC_ERROR, + DISALLOWED +}; +} + +namespace FunctionIdTest { +enum eType { + INVALID_ENUM = -1, + RegisterAppInterface, + UnregisterAppInterface, + SetGlobalProperties, +}; +} + +namespace MessageTypeTest { +enum eType { + INVALID_ENUM = -1, + request, + response, + notification +}; +} + +class SmartObjectConvertionTimeTest : public ::testing::Test { + protected: + + double getConvertionTimeToJsonV2Format(const SmartObject& srcObj, + std::string& jsonString) { + timespec convertionStartTime, convertionEndTime; + clock_gettime(CLOCK_REALTIME, &convertionStartTime); + + // SmartObjects --> JSON + NsSmartDeviceLink::NsJSONHandler::Formatters::CFormatterJsonSDLRPCv2::toString( + srcObj, jsonString); + + clock_gettime(CLOCK_REALTIME, &convertionEndTime); + + return static_cast<double>(convertionEndTime.tv_sec + - convertionStartTime.tv_sec) + + static_cast<double>(convertionEndTime.tv_nsec + - convertionStartTime.tv_nsec) * 1e-9; + } + + double getConvertionTimeFromJsonV2Format(std::string& jsonString, + SmartObject& dstObj) { + timespec convertionStartTime, convertionEndTime; + clock_gettime(CLOCK_REALTIME, &convertionStartTime); + + // JSON --> SmartObjects + NsSmartDeviceLink::NsJSONHandler::Formatters::CFormatterJsonSDLRPCv2::fromString< + FunctionIdTest::eType, MessageTypeTest::eType>( + jsonString, dstObj, FunctionIdTest::RegisterAppInterface, + MessageTypeTest::request, 13); + + clock_gettime(CLOCK_REALTIME, &convertionEndTime); + return static_cast<double>(convertionEndTime.tv_sec + - convertionStartTime.tv_sec) + + static_cast<double>(convertionEndTime.tv_nsec + - convertionStartTime.tv_nsec) * 1e-9; + } + + double getConvertionTimeToJsonV1Format(const SmartObject& srcObj, + std::string& jsonString) { + timespec convertionStartTime, convertionEndTime; + clock_gettime(CLOCK_REALTIME, &convertionStartTime); + + // SmartObjects --> JSON + NsSmartDeviceLink::NsJSONHandler::Formatters::CFormatterJsonSDLRPCv1::toString( + srcObj, jsonString); + + clock_gettime(CLOCK_REALTIME, &convertionEndTime); + return static_cast<double>(convertionEndTime.tv_sec + - convertionStartTime.tv_sec) + + static_cast<double>(convertionEndTime.tv_nsec + - convertionStartTime.tv_nsec) * 1e-9; + } + + double getConvertionTimeFromJsonV1Format(std::string& jsonString, + SmartObject& dstObj) { + timespec convertionStartTime, convertionEndTime; + clock_gettime(CLOCK_REALTIME, &convertionStartTime); + + // JSON --> SmartObjects + NsSmartDeviceLink::NsJSONHandler::Formatters::CFormatterJsonSDLRPCv1::fromString< + FunctionIdTest::eType, MessageTypeTest::eType>(jsonString, dstObj); + + clock_gettime(CLOCK_REALTIME, &convertionEndTime); + return static_cast<double>(convertionEndTime.tv_sec + - convertionStartTime.tv_sec) + + static_cast<double>(convertionEndTime.tv_nsec + - convertionStartTime.tv_nsec) * 1e-9; + } + + void calculateConvertionTime(SmartObject& srcObj, SmartObject& dstObj) { + std::string jsonString; + double convertionToTime = 0.0; + double convertionFromTime = 0.0; + const int cycles = 1; + + for (int i = 0; i < cycles; i++) { + convertionToTime += getConvertionTimeToJsonV1Format(srcObj, jsonString); +// printf("%s\n", jsonString.c_str()); + convertionFromTime += getConvertionTimeFromJsonV1Format(jsonString, + dstObj); + } + printf( + "Format V1. Convertion TO time = %.8f, Convertion FROM time = %.8f\n", + convertionToTime / cycles, convertionFromTime / cycles); + + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 1; // adjust protocol version + + srcObj.getSchema().applySchema(dstObj); + // The objects are different after remove non-schemed fields +// EXPECT_TRUE(srcObj == dstObj); + + convertionToTime = 0.0; + convertionFromTime = 0.0; + for (int i = 0; i < cycles; i++) { + convertionToTime += getConvertionTimeToJsonV2Format(srcObj, jsonString); + convertionFromTime += getConvertionTimeFromJsonV2Format(jsonString, + dstObj); + } + printf( + "Format V2. Convertion TO time = %.8f, Convertion FROM time = %.8f\n", + convertionToTime / cycles, convertionFromTime / cycles); + + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; // adjust protocol version + + dstObj.getSchema().applySchema(dstObj); + // The objects are different after remove non-schemed fields +// EXPECT_TRUE(srcObj == dstObj); + } + + void calculateConvertionTimeWithJsonStringOutput(const SmartObject& srcObj, + SmartObject& dstObj) { + std::string jsonString; + double convertionToTime = getConvertionTimeToJsonV1Format(srcObj, + jsonString); + double convertionFromTime = getConvertionTimeFromJsonV1Format(jsonString, + dstObj); + printf("\nJSON string V1 = %s", jsonString.c_str()); + printf( + "\nFormat V1. Convertion TO time = %.8f, Convertion FROM time = %.8f\n", + convertionToTime, convertionFromTime); + + convertionToTime = getConvertionTimeToJsonV2Format(srcObj, jsonString); + convertionFromTime = getConvertionTimeFromJsonV2Format(jsonString, dstObj); + printf("\nJSON string V2 = %s", jsonString.c_str()); + printf( + "\nFormat V2. Convertion TO time = %.8f, Convertion FROM time = %.8f\n", + convertionToTime, convertionFromTime); + } + + // The basic Schema just for enum conversion (FunctionId and MessageType) + CSmartSchema initBasicObjectSchema() { + std::set<FunctionIdTest::eType> functionId_allowedEnumSubsetValues; + functionId_allowedEnumSubsetValues.insert( + FunctionIdTest::RegisterAppInterface); + functionId_allowedEnumSubsetValues.insert( + FunctionIdTest::UnregisterAppInterface); + functionId_allowedEnumSubsetValues.insert( + FunctionIdTest::SetGlobalProperties); + + std::set<MessageTypeTest::eType> messageType_allowedEnumSubsetValues; + messageType_allowedEnumSubsetValues.insert(MessageTypeTest::request); + messageType_allowedEnumSubsetValues.insert(MessageTypeTest::response); + messageType_allowedEnumSubsetValues.insert(MessageTypeTest::notification); + + ISchemaItemPtr functionId_SchemaItem = + TEnumSchemaItem<FunctionIdTest::eType>::create( + functionId_allowedEnumSubsetValues); + + ISchemaItemPtr messageType_SchemaItem = TEnumSchemaItem< + MessageTypeTest::eType>::create(messageType_allowedEnumSubsetValues); + + CObjectSchemaItem::Members paramsMembersMap; + paramsMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_FUNCTION_ID] = + CObjectSchemaItem::SMember(functionId_SchemaItem, true); + paramsMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_MESSAGE_TYPE] = + CObjectSchemaItem::SMember(messageType_SchemaItem, true); + paramsMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_CORRELATION_ID] = + CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + + std::map<std::string, CObjectSchemaItem::SMember> rootMembersMap; + rootMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS] = + CObjectSchemaItem::SMember(CObjectSchemaItem::create(paramsMembersMap), + true); + + return CSmartSchema(CObjectSchemaItem::create(rootMembersMap)); + } + + //Create SmartObjectSchema for test object + CSmartSchema initObjectSchema() { + std::set<TestType::eType> resultCode_allowedEnumSubsetValues; + resultCode_allowedEnumSubsetValues.insert( + TestType::APPLICATION_NOT_REGISTERED); + resultCode_allowedEnumSubsetValues.insert(TestType::SUCCESS); + resultCode_allowedEnumSubsetValues.insert( + TestType::TOO_MANY_PENDING_REQUESTS); + resultCode_allowedEnumSubsetValues.insert(TestType::REJECTED); + resultCode_allowedEnumSubsetValues.insert(TestType::INVALID_DATA); + resultCode_allowedEnumSubsetValues.insert(TestType::OUT_OF_MEMORY); + resultCode_allowedEnumSubsetValues.insert(TestType::ABORTED); + resultCode_allowedEnumSubsetValues.insert(TestType::USER_DISALLOWED); + resultCode_allowedEnumSubsetValues.insert(TestType::GENERIC_ERROR); + resultCode_allowedEnumSubsetValues.insert(TestType::DISALLOWED); + + std::set<FunctionIdTest::eType> functionId_allowedEnumSubsetValues; + functionId_allowedEnumSubsetValues.insert( + FunctionIdTest::RegisterAppInterface); + functionId_allowedEnumSubsetValues.insert( + FunctionIdTest::UnregisterAppInterface); + functionId_allowedEnumSubsetValues.insert( + FunctionIdTest::SetGlobalProperties); + + std::set<MessageTypeTest::eType> messageType_allowedEnumSubsetValues; + messageType_allowedEnumSubsetValues.insert(MessageTypeTest::request); + messageType_allowedEnumSubsetValues.insert(MessageTypeTest::response); + messageType_allowedEnumSubsetValues.insert(MessageTypeTest::notification); + + ISchemaItemPtr success_SchemaItem = CBoolSchemaItem::create( + TSchemaItemParameter<bool>()); + + ISchemaItemPtr resultCode_SchemaItem = + TEnumSchemaItem<TestType::eType>::create( + resultCode_allowedEnumSubsetValues, + TSchemaItemParameter<TestType::eType>()); + + ISchemaItemPtr info_SchemaItem = CStringSchemaItem::create( + TSchemaItemParameter<size_t>(0), TSchemaItemParameter<size_t>(1000), + TSchemaItemParameter<std::string>()); + + ISchemaItemPtr tryAgainTime_SchemaItem = TNumberSchemaItem<int>::create( + TSchemaItemParameter<int>(0), TSchemaItemParameter<int>(2000000000), + TSchemaItemParameter<int>()); + + std::map<std::string, CObjectSchemaItem::SMember> schemaMembersMap; + + schemaMembersMap["success"] = CObjectSchemaItem::SMember(success_SchemaItem, + true); + schemaMembersMap["resultCode"] = CObjectSchemaItem::SMember( + resultCode_SchemaItem, true); + schemaMembersMap["info"] = CObjectSchemaItem::SMember(info_SchemaItem, + false); + schemaMembersMap["tryAgainTime"] = CObjectSchemaItem::SMember( + tryAgainTime_SchemaItem, true); + + std::map<std::string, CObjectSchemaItem::SMember> paramsMembersMap; + paramsMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_FUNCTION_ID] = + CObjectSchemaItem::SMember( + TEnumSchemaItem<FunctionIdTest::eType>::create( + functionId_allowedEnumSubsetValues), + true); + paramsMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_MESSAGE_TYPE] = + CObjectSchemaItem::SMember( + TEnumSchemaItem<MessageTypeTest::eType>::create( + messageType_allowedEnumSubsetValues), + true); + paramsMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_CORRELATION_ID] = + CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + paramsMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_VERSION] = + CObjectSchemaItem::SMember( + TNumberSchemaItem<int>::create(TSchemaItemParameter<int>(1), + TSchemaItemParameter<int>(2)), + true); + paramsMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_TYPE] = + CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + + std::map<std::string, CObjectSchemaItem::SMember> rootMembersMap; + rootMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_MSG_PARAMS] = + CObjectSchemaItem::SMember(CObjectSchemaItem::create(schemaMembersMap), + true); + rootMembersMap[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS] = + CObjectSchemaItem::SMember(CObjectSchemaItem::create(paramsMembersMap), + true); + return CSmartSchema(CObjectSchemaItem::create(rootMembersMap)); + } +}; + +TEST_F(SmartObjectConvertionTimeTest, test_int_object_convertion) { + SmartObject srcObj, dstObj; + CSmartSchema schema = initObjectSchema(); + + srcObj.setSchema(schema); + dstObj.setSchema(schema); + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 1; + srcObj[S_MSG_PARAMS]["value"] = 5; + + printf("\n INT value.\n"); + calculateConvertionTime(srcObj, dstObj); +} + +TEST_F(SmartObjectConvertionTimeTest, test_double_object_convertion) { + SmartObject srcObj, dstObj; + CSmartSchema schema = initObjectSchema(); + + srcObj.setSchema(schema); + dstObj.setSchema(schema); + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["value1"] = 3.1415926; + srcObj[S_MSG_PARAMS]["value2"] = 32.6; + srcObj[S_MSG_PARAMS]["value3"] = 33.945; + srcObj[S_MSG_PARAMS]["value4"] = -12.5487698; + srcObj[S_MSG_PARAMS]["value5"] = 0.61287346; + + printf("\n Double value.\n"); + calculateConvertionTime(srcObj, dstObj); +} + +TEST_F(SmartObjectConvertionTimeTest, test_some_object_convertion) { + SmartObject srcObj, dstObj; + CSmartSchema schema = initObjectSchema(); + + srcObj.setSchema(schema); + dstObj.setSchema(schema); + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["appId"] = "APP ID"; + srcObj[S_MSG_PARAMS]["appName"] = "APP NAME"; + srcObj[S_MSG_PARAMS]["appType"][0] = "SYSTEM"; + srcObj[S_MSG_PARAMS]["appType"][1] = "COMMUNICATION"; + srcObj[S_MSG_PARAMS]["hmiDisplayLanguageDesired"] = "RU-RU"; + srcObj[S_MSG_PARAMS]["isMediaApplication"] = true; + srcObj[S_MSG_PARAMS]["languageDesired"] = "EN-US"; + srcObj[S_MSG_PARAMS]["ngnMediaScreenAppName"] = "SCREEN NAME"; + srcObj[S_MSG_PARAMS]["syncMsgVersion"]["majorVersion"] = 2; + srcObj[S_MSG_PARAMS]["syncMsgVersion"]["minorVersion"] = 10; + srcObj[S_MSG_PARAMS]["ttsName"][0]["text"] = "ABC"; + srcObj[S_MSG_PARAMS]["ttsName"][0]["type"] = "TEXT"; + srcObj[S_MSG_PARAMS]["vrSynonyms"][0] = "Synonym1"; + srcObj[S_MSG_PARAMS]["vrSynonyms"][1] = "Synonym2"; + srcObj[S_MSG_PARAMS]["null"] = SmartObject(); + srcObj[S_MSG_PARAMS]["double"] = -0.1234; + + printf("\n Random object.\n"); + calculateConvertionTime(srcObj, dstObj); +} + +TEST_F(SmartObjectConvertionTimeTest, test_map_object_convertion) { + SmartObject srcObj, dstObj, mapObj, innerObj; + CSmartSchema schema = initObjectSchema(); + + srcObj.setSchema(schema); + dstObj.setSchema(schema); + + // First iteration + mapObj["request"]["name"] = "My Request"; + mapObj["request"]["id"] = 123; + mapObj["response"]["name"] = "My Response"; + mapObj["response"]["id"] = 456; + mapObj["we"]["need"]["to"]["go"]["deeper"] = true; + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["value"] = mapObj; + + printf("\n MAP object.\n"); + calculateConvertionTime(srcObj, dstObj); + + // Second iteration + innerObj = mapObj; + mapObj["request"]["value"] = innerObj; + mapObj["response"]["value"] = innerObj; + mapObj["we"]["need"]["to"]["go"]["deeper"]["value"] = innerObj; + srcObj[S_MSG_PARAMS]["value"] = mapObj; + + printf("\n Complex MAP object.\n"); + calculateConvertionTime(srcObj, dstObj); + + // Third iteration + innerObj = mapObj; + mapObj["request"]["value"] = innerObj; + mapObj["response"]["value"] = innerObj; + mapObj["we"]["need"]["to"]["go"]["deeper"]["value"] = innerObj; + srcObj[S_MSG_PARAMS]["value"] = mapObj; + + printf("\n Very Complex MAP object.\n"); + calculateConvertionTime(srcObj, dstObj); + + // Last iteration + innerObj = mapObj; + mapObj["request"]["value"] = innerObj; + mapObj["response"]["value"] = innerObj; + mapObj["we"]["need"]["to"]["go"]["deeper"]["value"] = innerObj; + srcObj[S_MSG_PARAMS]["value"] = mapObj; + + printf("\n Very Very Complex MAP object.\n"); + calculateConvertionTime(srcObj, dstObj); +} + +TEST_F(SmartObjectConvertionTimeTest, test_array_convertion) { + SmartObject srcObj, dstObj, arrayObj, innerObj; + CSmartSchema schema = initObjectSchema(); + int arraySize = 10; + + srcObj.setSchema(schema); + dstObj.setSchema(schema); + + // First iteration + for (int i = 0; i < arraySize; i++) { + arrayObj[i] = rand(); + } + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["array"] = arrayObj; + + printf("\n Array object [%d].\n", arraySize); + calculateConvertionTime(srcObj, dstObj); + + // Second iteration + printf("\n Array object [%d x %d].\n", arraySize, arraySize); + innerObj = arrayObj; + for (int i = 0; i < arraySize; i++) { + arrayObj[i] = innerObj; + } + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["array"] = arrayObj; + + calculateConvertionTime(srcObj, dstObj); + + // Third iteration + printf("\n Array object [%d x %d x %d].\n", arraySize, arraySize, arraySize); + innerObj = arrayObj; + for (int i = 0; i < arraySize; i++) { + arrayObj[i] = innerObj; + } + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["array"] = arrayObj; + + calculateConvertionTime(srcObj, dstObj); + + // Fourth iteration + printf("\n Array object [%d x %d x %d x %d].\n", arraySize, arraySize, + arraySize, arraySize); + innerObj = arrayObj; + for (int i = 0; i < arraySize; i++) { + arrayObj[i] = innerObj; + } + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["array"] = arrayObj; + + calculateConvertionTime(srcObj, dstObj); + + // Last iteration + printf("\n Array object [%d x %d x %d x %d x %d].\n", arraySize, arraySize, + arraySize, arraySize, arraySize); + innerObj = arrayObj; + for (int i = 0; i < arraySize; i++) { + arrayObj[i] = innerObj; + } + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["array"] = arrayObj; + + calculateConvertionTime(srcObj, dstObj); +} + +TEST_F(SmartObjectConvertionTimeTest, test_object_with_enum_convertion) { + SmartObject srcObj, dstObj; + CSmartSchema schema = initObjectSchema(); + + srcObj.setSchema(schema); + dstObj.setSchema(schema); + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["success"] = true; + srcObj[S_MSG_PARAMS]["resultCode"] = 2; + srcObj[S_MSG_PARAMS]["info"] = "Some string"; + srcObj[S_MSG_PARAMS]["tryAgainTime"] = 322; + srcObj.setSchema(schema); + + printf("\n Object with enum.\n"); + calculateConvertionTime(srcObj, dstObj); +} + +TEST_F(SmartObjectConvertionTimeTest, test_object_without_enum_convertion) { + SmartObject srcObj, dstObj; + CSmartSchema schema = initObjectSchema(); + + srcObj.setSchema(schema); + dstObj.setSchema(schema); + + srcObj[S_PARAMS][S_MESSAGE_TYPE] = MessageTypeTest::request; + srcObj[S_PARAMS][S_FUNCTION_ID] = FunctionIdTest::RegisterAppInterface; + srcObj[S_PARAMS][S_CORRELATION_ID] = 13; + srcObj[S_PARAMS][S_PROTOCOL_TYPE] = 0; + srcObj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + srcObj[S_MSG_PARAMS]["success"] = true; + srcObj[S_MSG_PARAMS]["resultCode"] = 2; + srcObj[S_MSG_PARAMS]["info"] = "Some string"; + srcObj[S_MSG_PARAMS]["tryAgainTime"] = 322; + + printf("\n Object without enum.\n"); + calculateConvertionTime(srcObj, dstObj); +} + +} +} +} +} + +namespace NsSmartDeviceLink { +namespace NsSmartObjects { + +template<> +const EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::eType>::EnumToCStringMap EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::eType>::enum_to_cstring_map_ = + EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::eType>::InitEnumToCStringMap(); + +template<> +const EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::eType>::CStringToEnumMap EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::eType>::cstring_to_enum_map_ = + EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::eType>::InitCStringToEnumMap(); + +template<> +const char* const EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::eType>::cstring_values_[] = + { "APPLICATION_NOT_REGISTERED", "SUCCESS", "TOO_MANY_PENDING_REQUESTS", + "REJECTED", "INVALID_DATA", "OUT_OF_MEMORY", "ABORTED", + "USER_DISALLOWED", "GENERIC_ERROR", "DISALLOWED" }; + +template<> +const test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::eType EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::eType>::enum_values_[] = + { + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::APPLICATION_NOT_REGISTERED, + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::SUCCESS, + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::TOO_MANY_PENDING_REQUESTS, + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::REJECTED, + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::INVALID_DATA, + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::OUT_OF_MEMORY, + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::ABORTED, + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::USER_DISALLOWED, + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::GENERIC_ERROR, + test::components::SmartObjects::SmartObjectConvertionTimeTest::TestType::DISALLOWED }; + +template<> +const EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::eType>::EnumToCStringMap EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::eType>::enum_to_cstring_map_ = + EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::eType>::InitEnumToCStringMap(); + +template<> +const EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::eType>::CStringToEnumMap EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::eType>::cstring_to_enum_map_ = + EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::eType>::InitCStringToEnumMap(); + +template<> +const char* const EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::eType>::cstring_values_[] = + { "RegisterAppInterface", "UnregisterAppInterface", "SetGlobalProperties" }; + +template<> +const test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::eType EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::eType>::enum_values_[] = + { + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::RegisterAppInterface, + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::UnregisterAppInterface, + test::components::SmartObjects::SmartObjectConvertionTimeTest::FunctionIdTest::SetGlobalProperties }; + +template<> +const EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::eType>::EnumToCStringMap EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::eType>::enum_to_cstring_map_ = + EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::eType>::InitEnumToCStringMap(); + +template<> +const EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::eType>::CStringToEnumMap EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::eType>::cstring_to_enum_map_ = + EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::eType>::InitCStringToEnumMap(); + +template<> +const char* const EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::eType>::cstring_values_[] = + { "request", "response", "notification" }; + +template<> +const test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::eType EnumConversionHelper< + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::eType>::enum_values_[] = + { + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::request, + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::response, + test::components::SmartObjects::SmartObjectConvertionTimeTest::MessageTypeTest::notification }; + +} +} diff --git a/src/components/smart_objects/test/SmartObjectDraft_test.cc b/src/components/smart_objects/test/SmartObjectDraft_test.cc new file mode 100644 index 000000000..85c97c262 --- /dev/null +++ b/src/components/smart_objects/test/SmartObjectDraft_test.cc @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2014, 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 <vector> + +#include "gmock/gmock.h" + +#include "smart_objects/smart_object.h" + +using ::testing::ElementsAre; +using ::testing::ContainerEq; + +namespace test { +namespace components { +namespace SmartObjects { +namespace SmartObjectDraftTest { + +using NsSmartDeviceLink::NsSmartObjects::SmartObject; +using NsSmartDeviceLink::NsSmartObjects::SmartType; + +TEST(SmartObjectsDraftTest, primitive_types) { + SmartObject obj; + + obj = true; + ASSERT_TRUE(obj.asBool()); + ASSERT_EQ(SmartType::SmartType_Boolean, obj.getType()); + + obj = 5; + ASSERT_EQ(5, obj.asInt()); + ASSERT_EQ(SmartType::SmartType_Integer, obj.getType()); + + obj = 'A'; + ASSERT_DOUBLE_EQ('A', obj.asChar()); + ASSERT_EQ(SmartType::SmartType_Character, obj.getType()); + + obj = "Test"; + ASSERT_EQ(std::string("Test"), obj.asString()); + ASSERT_EQ(SmartType::SmartType_String, obj.getType()); + + obj = 6.0; + ASSERT_DOUBLE_EQ(6.0, obj.asDouble()); + ASSERT_EQ(SmartType::SmartType_Double, obj.getType()); +} + +TEST(SmartObjectsDraftTest, test_map_access) { + SmartObject obj; + + obj["aa"] = true; + ASSERT_TRUE(obj["aa"].asInt()); + ASSERT_EQ(SmartType::SmartType_Map, obj.getType()); + + obj["aa"]["fds"]["Fsdf"] = 123; + ASSERT_EQ(123, obj["aa"]["fds"]["Fsdf"].asInt()); + ASSERT_EQ(SmartType::SmartType_Map, obj.getType()); +} + +TEST(SmartObjectsDraftTest, test_array_access) { + SmartObject obj; + + obj[0] = 5; + obj[-1] = 6; // Appending new item to array + + ASSERT_EQ(5, obj[0].asInt()); + ASSERT_EQ(6, obj[1].asInt()); + ASSERT_EQ(SmartType::SmartType_Array, obj.getType()); +} + +TEST(SmartObjectsDraftTest, test_public_interface) { + SmartObject obj; + + // ---- INTEGER ---- // + obj = 1; + ASSERT_EQ(1, obj.asInt()); + + // ---- unsigned int ---- // + obj = static_cast<unsigned int>(100); + ASSERT_EQ(100u, obj.asUInt()); + + // ---- DOUBLE ---- // + obj = 3.14; + ASSERT_EQ(3.14, obj.asDouble()); + + // ---- CHAR ---- // + obj = 'a'; + ASSERT_EQ('a', obj.asChar()); + + // ---- BOOL ---- // + obj = true; + ASSERT_TRUE(obj.asBool()); + + // ---- CHAR* ---- // + obj = "Hello, world"; + ASSERT_EQ(std::string("Hello, world"), obj.asString()); + + // ---- STD::STRING ---- // + obj = std::string("Hello, world"); + ASSERT_EQ(std::string("Hello, world"), obj.asString()); + + // ---- Binary ---- // + NsSmartDeviceLink::NsSmartObjects::SmartBinary binaryData; + binaryData.push_back('\0'); + binaryData.push_back('a'); + obj = binaryData; + ASSERT_THAT(obj.asBinary(), ElementsAre('\0', 'a')); + + // ---- ARRAY ---- // + obj[0] = 1; + obj[1] = true; + obj[2] = 'a'; + obj[3] = 3.14; + + ASSERT_EQ(1, obj[0].asInt()); + ASSERT_TRUE(obj[1].asBool()); + ASSERT_EQ('a', obj[2].asChar()); + ASSERT_EQ(3.14, obj[3].asDouble()); + + // ---- DEEP ARRAY ---- // + obj[0] = 1; + obj[1][0] = 3.14; + obj[1][1][0] = true; + + ASSERT_EQ(1, obj[0].asInt()); + ASSERT_EQ(3.14, obj[1][0].asDouble()); + ASSERT_TRUE(obj[1][1][0].asBool()); + + // ---- MAP ---- // + obj["name"] = "My name"; + obj["count"] = 10; + obj["isValid"] = true; + + ASSERT_EQ(std::string("My name"), obj["name"].asString()); + ASSERT_EQ(10, obj["count"].asInt()); + ASSERT_TRUE(obj["isValid"].asBool()); + + // ---- DEEP MAP ---- // + obj["request"]["name"] = "My Request"; + obj["request"]["id"] = 123; + obj["response"]["name"] = "My Response"; + obj["response"]["id"] = 456; + obj["we"]["need"]["to"]["go"]["deeper"] = true; + + ASSERT_EQ(std::string("My Request"), obj["request"]["name"].asString()); + ASSERT_EQ(123, obj["request"]["id"].asInt()); + ASSERT_EQ(std::string("My Response"), obj["response"]["name"].asString()); + ASSERT_EQ(456, obj["response"]["id"].asInt()); + ASSERT_TRUE(obj["we"]["need"]["to"]["go"]["deeper"].asBool()); +} + +TEST(SmartObjectsDraftTest, test_helper_methods) { + SmartObject obj; + + // ---- INTEGER ---- // + obj = 1; + ASSERT_EQ(1, obj.asInt()); + + // ---- unsigned int ---- // + obj = static_cast<unsigned int>(100); + ASSERT_EQ(100u, obj.asUInt()); + + // ---- DOUBLE ---- // + obj = 3.14; + ASSERT_EQ(3.14, obj.asDouble()); + //TEST_COMPONENTS_SMART_OBJECTS_SMARTOBJECTDRAFTTEST_H_ + // ---- CHAR ---- // + obj = 'a'; + ASSERT_EQ('a', obj.asChar()); + + // ---- BOOL ---- // + obj = true; + ASSERT_TRUE(obj.asBool()); + + // ---- STD::STRING ---- // + obj = std::string("Hello, world"); + ASSERT_EQ(std::string("Hello, world"), obj.asString()); + + // ---- Binary ---- // + NsSmartDeviceLink::NsSmartObjects::SmartBinary binaryData; + binaryData.push_back('\0'); + binaryData.push_back('a'); + obj = binaryData; + ASSERT_THAT(obj.asBinary(), ElementsAre('\0', 'a')); +} + +TEST(SmartObjectsDraftTest, compare_empty_objects_by_types) { + ASSERT_EQ(SmartObject(), SmartObject()); + + std::vector<SmartType> smart_types; + smart_types.push_back(SmartType::SmartType_Null); + smart_types.push_back(SmartType::SmartType_Boolean); + smart_types.push_back(SmartType::SmartType_Integer); + smart_types.push_back(SmartType::SmartType_Character); + smart_types.push_back(SmartType::SmartType_String); + smart_types.push_back(SmartType::SmartType_Double); + smart_types.push_back(SmartType::SmartType_Map); + smart_types.push_back(SmartType::SmartType_Array); + smart_types.push_back(SmartType::SmartType_Binary); + smart_types.push_back(SmartType::SmartType_Invalid); + + for (size_t i = 0u; i < smart_types.size(); ++i) { + const SmartType type_i = smart_types[i]; + for (size_t j = 0u; j < smart_types.size(); ++j) { + const SmartType type_j = smart_types[i]; + if (type_i == type_j) { + ASSERT_EQ(SmartObject(type_i), SmartObject(type_j)); + ASSERT_EQ(SmartObject(type_j), SmartObject(type_i)); + } else { + ASSERT_NE(SmartObject(type_i), SmartObject(type_j)); + ASSERT_EQ(SmartObject(type_j), SmartObject(type_i)); + } + } + } +} + +TEST(SmartObjectsDraftTest, compare_integer_type) { + SmartObject value = SmartObject(0xFFFFF); + SmartObject same_value = SmartObject(static_cast<int64_t>(value.asInt())); + + ASSERT_EQ(value, same_value); + ASSERT_EQ(same_value, value); + + SmartObject other_value = SmartObject(0x00000); + + ASSERT_NE(value, other_value); + ASSERT_NE(other_value, value); + + ASSERT_NE(other_value, same_value); + ASSERT_NE(same_value, other_value); + + ASSERT_NE(value, SmartObject()); + ASSERT_NE(other_value, SmartObject()); + ASSERT_NE(same_value, SmartObject()); +} + +TEST(SmartObjectsDraftTest, compare_double_type) { + SmartObject value = SmartObject(6.0); + SmartObject same_value = SmartObject(6.0); + + ASSERT_EQ(value, same_value); + ASSERT_EQ(same_value, value); + + SmartObject other_value = SmartObject(6.0000001); + + ASSERT_NE(value, other_value); + ASSERT_NE(other_value, value); + + ASSERT_NE(other_value, same_value); + ASSERT_NE(same_value, other_value); + + ASSERT_NE(value, SmartObject()); + ASSERT_NE(other_value, SmartObject()); + ASSERT_NE(same_value, SmartObject()); +} + +TEST(SmartObjectsDraftTest, compare_bool_type) { + SmartObject value = SmartObject(true); + SmartObject same_value = SmartObject(true); + + ASSERT_EQ(value, same_value); + ASSERT_EQ(same_value, value); + + SmartObject other_value = SmartObject(false); + + ASSERT_NE(value, other_value); + ASSERT_NE(other_value, value); + + ASSERT_NE(other_value, same_value); + ASSERT_NE(same_value, other_value); + + ASSERT_NE(value, SmartObject()); + ASSERT_NE(other_value, SmartObject()); + ASSERT_NE(same_value, SmartObject()); +} + +TEST(SmartObjectsDraftTest, compare_string_type) { + SmartObject value = SmartObject("Test string"); + SmartObject same_value = SmartObject(std::string("Test string")); + + ASSERT_EQ(value, same_value); + ASSERT_EQ(same_value, value); + + SmartObject other_value = SmartObject("Other string"); + + ASSERT_NE(value, other_value); + ASSERT_NE(other_value, value); + + ASSERT_NE(other_value, same_value); + ASSERT_NE(same_value, other_value); + + ASSERT_NE(value, SmartObject()); + ASSERT_NE(other_value, SmartObject()); + ASSERT_NE(same_value, SmartObject()); +} + +TEST(SmartObjectsDraftTest, compare_map_type) { + SmartObject value; + value["KEY1"] = "VALUE1"; + value["KEY2"] = 0; + value["KEY3"] = false; + + SmartObject same_value; + same_value["KEY1"] = "VALUE1"; + same_value["KEY2"] = 0; + same_value["KEY3"] = false; + + ASSERT_EQ(value, same_value); + ASSERT_EQ(same_value, value); + + SmartObject other_value; + other_value["KEY1"] = "VALUE1"; + other_value["KEY2"] = 0; + // no KEY3 field + + SmartObject other_value2; + other_value2["KEY1"] = "VALUE1"; + other_value2["KEY2"] = 0; + // other ype of KEY3 field + other_value2["KEY3"] = "VALUE3"; + + ASSERT_NE(value, other_value); + ASSERT_NE(other_value, value); + + ASSERT_NE(value, other_value2); + ASSERT_NE(other_value2, value); + + ASSERT_NE(value, SmartObject()); + ASSERT_NE(same_value, SmartObject()); + ASSERT_NE(other_value, SmartObject()); + ASSERT_NE(other_value2, SmartObject()); +} +// TODO(Ezamakhov): add test for conversion string/int/double +}// namespace SmartObjectDraftTest +} // namespace SmartObjects +} // namespace components +} // namespace test diff --git a/src/components/smart_objects/test/SmartObjectInvalid_test.cc b/src/components/smart_objects/test/SmartObjectInvalid_test.cc new file mode 100644 index 000000000..6a3caf295 --- /dev/null +++ b/src/components/smart_objects/test/SmartObjectInvalid_test.cc @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" + +#include "smart_objects/smart_object.h" + +namespace test { +namespace components { +namespace SmartObjects { +namespace SmartObjectInvalidTest { +using namespace NsSmartDeviceLink::NsSmartObjects; + +TEST(test_SmartObjectInvalidTest, simple_type_can_be_set_in_constructor) { + SmartObject objMap(SmartType_Map); + ASSERT_EQ(SmartType_Map, objMap.getType()); + + SmartObject objArray(SmartType_Array); + ASSERT_EQ(SmartType_Array, objArray.getType()); + + SmartObject objInt(SmartType_Integer); + ASSERT_EQ(SmartType_Integer, objInt.getType()); + + SmartObject objDouble(SmartType_Double); + ASSERT_EQ(SmartType_Double, objDouble.getType()); + + SmartObject objBoolean(SmartType_Boolean); + ASSERT_EQ(SmartType_Boolean, objBoolean.getType()); + + SmartObject objChar(SmartType_Character); + ASSERT_EQ(SmartType_Character, objChar.getType()); + + SmartObject objString(SmartType_String); + ASSERT_EQ(SmartType_String, objString.getType()); + + SmartObject objBinary(SmartType_Binary); + ASSERT_EQ(SmartType_Binary, objBinary.getType()); + + SmartObject objInvalid(SmartType_Invalid); + ASSERT_EQ(SmartType_Invalid, objInvalid.getType()); + + SmartObject objNullConstructor(SmartType_Null); + ASSERT_EQ(SmartType_Null, objNullConstructor.getType()); + + SmartObject objNullDefault; + ASSERT_EQ(SmartType_Null, objNullDefault.getType()); +} + +TEST(test_SmartObjectInvalidTest, invalid_object_remains_invalid) { + SmartObject obj(SmartType_Invalid); + ASSERT_EQ(SmartType_Invalid, obj.getType()); + + obj = 1; + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_int_value, obj.asInt()); + + // ---- unsigned int ---- // + obj = static_cast<unsigned int>(100); + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_unsigned_int_value, obj.asUInt()); + + // ---- DOUBLE ---- // + obj = 3.14; + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_double_value, obj.asDouble()); + + // ---- CHAR ---- // + obj = 'a'; + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_char_value, obj.asChar()); + + // ---- BOOL ---- // + obj = true; + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_bool_value, obj.asBool()); + + // ---- CHAR* ---- // + obj = "Hello, world"; + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_string_value, obj.asString()); + + // ---- STD::STRING ---- // + obj = std::string("Hello, world"); + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_string_value, obj.asString()); + + // ---- BINARY ---- // + NsSmartDeviceLink::NsSmartObjects::SmartBinary binaryData; + binaryData.push_back('\0'); + binaryData.push_back('a'); + obj = binaryData; + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); + + // ---- ARRAY ---- // + obj[0] = 1; + obj[1] = true; + obj[2] = 'a'; + obj[3] = 3.14; + + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_int_value, obj[0].asInt()); + ASSERT_EQ(invalid_bool_value, obj[1].asBool()); + ASSERT_EQ(invalid_char_value, obj[2].asChar()); + ASSERT_EQ(invalid_double_value, obj[3].asDouble()); + + // ---- DEEP ARRAY ---- // + obj[0] = 1; + obj[1][0] = 3.14; + obj[1][1][0] = true; + + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_int_value, obj[0].asInt()); + ASSERT_EQ(invalid_double_value, obj[1][0].asDouble()); + ASSERT_EQ(invalid_bool_value, obj[1][1][0].asBool()); + + // ---- MAP ---- // + obj["name"] = "My name"; + obj["count"] = 10; + obj["isValid"] = true; + + ASSERT_EQ(SmartType_Invalid, obj.getType()); + ASSERT_EQ(invalid_string_value, obj["name"].asString()); + ASSERT_EQ(invalid_int_value, obj["count"].asInt()); + ASSERT_EQ(invalid_bool_value, obj["isValid"].asBool()); + + // ---- DEEP MAP ---- // + obj["request"]["name"] = "My Request"; + obj["request"]["id"] = 123; + obj["response"]["name"] = "My Response"; + obj["response"]["id"] = 456; + obj["we"]["need"]["to"]["go"]["deeper"] = true; + + ASSERT_EQ(SmartType_Invalid, obj.getType()); + + ASSERT_EQ(invalid_string_value, obj["request"]["name"].asString()); + ASSERT_EQ(invalid_int_value, obj["request"]["id"].asInt()); + ASSERT_EQ(invalid_string_value, obj["response"]["name"].asString()); + ASSERT_EQ(invalid_int_value, obj["response"]["id"].asInt()); + ASSERT_EQ(invalid_bool_value, + obj["we"]["need"]["to"]["go"]["deeper"].asBool()); +} +} // namespace SmartObjectInvalidTest +} // namespace SmartObjects +} // namespace components +} // namespace test diff --git a/src/components/smart_objects/test/SmartObjectStress_test.cc b/src/components/smart_objects/test/SmartObjectStress_test.cc new file mode 100644 index 000000000..4fb7b2efc --- /dev/null +++ b/src/components/smart_objects/test/SmartObjectStress_test.cc @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2014, 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 <sstream> +#include "gmock/gmock.h" +#include "smart_objects/smart_object.h" + +//#define NO_INCLUSIVE_MAPS +//#define COPY_SUB_OBJECTS_WORKAROUND + +namespace test { +namespace components { +namespace SmartObjects { +namespace SmartObjectStressTest { + +using namespace NsSmartDeviceLink::NsSmartObjects; + +class StressTestHelper : public ::testing::Test { + private: + char get_random_char() const { + return static_cast<char>('A' + (rand() % 52)); + } + + std::string to_string(const int value) const { + std::ostringstream oss; + oss << value; + return oss.str(); + } + + std::string to_string(const double value) const { + // Content is the same as in SmartObject::convert_double_to_string + std::stringstream ss; + ss << std::fixed << std::setprecision(10) << value; //convert double to string w fixed notation, hi precision + std::string s = ss.str(); //output to std::string + s.erase(s.find_last_not_of('0') + 1, std::string::npos); //remove trailing 000s (123.1200 => 123.12, 123.000 => 123.) + if (s[s.size() - 1] == '.') { + s.erase(s.end() - 1); //remove dangling decimal (123. => 123) + } + return s; + } + + std::string to_string(const char ch) const { + char buff[2]; + sprintf(buff, "%c", ch); + return std::string(buff); + } + + std::string to_string(const bool b) const { + return std::string((b) ? "true" : "false"); + } + + protected: + typedef std::map<std::string, std::string> VerificationMap; + VerificationMap mVerifyMap; + + std::vector<std::string> split(const std::string &s, char delim) const { + std::vector < std::string > elems; + + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + elems.push_back(item); + } + + return elems; + } + + std::string generate_key(const char *pPrefix, const int index) const { + char buff[32]; + sprintf(buff, "%s%d", pPrefix, index); + return std::string(buff); + } + + void makeRandomObject(SmartObject &obj, const int size, + std::string key_path) { + int type_id = rand() % 8; + + switch (type_id) { + case 0: // int + { + int iVal = rand(); + obj = iVal; + mVerifyMap[key_path] = to_string(iVal); + //std::cout << "Created int, value: " << iVal << std::endl; + break; + } + case 1: // bool + { + bool bVal = static_cast<bool>(rand() % 2); + obj = bVal; + mVerifyMap[key_path] = to_string(bVal); + //std::cout << "Created bool, value: " << to_string(bVal) << std::endl; + break; + } + case 2: // double + { + double dVal = 100.0 / (rand() % 200); + obj = dVal; + mVerifyMap[key_path] = to_string(dVal); + //std::cout << "Created double, value: " << dVal << std::endl; + break; + } + case 3: // char + { + char cVal = get_random_char(); + obj = cVal; + mVerifyMap[key_path] = to_string(cVal); + //std::cout << "Created char, value: " << cVal << std::endl; + break; + } + case 4: // string + { + std::string strVal(rand() % 200, get_random_char()); + obj = strVal; // string with random char filled random size + mVerifyMap[key_path] = strVal; + //std::cout << "Created string, value: " << strVal << std::endl; + break; + } + case 5: // map + if (size <= 0) + break; + + //std::cout << "Creating a map with size: " << size << std::endl; + mVerifyMap[key_path] = "map"; + for (int i = 0; i < size; i++) { + std::string key = generate_key("M", i); +#ifdef NO_INCLUSIVE_MAPS + obj[key] = key; +#else + obj[key] = SmartObject(); + makeRandomObject(obj[key], size - 1, key_path + key + ' '); // recursion +#endif // MAP_WORKAROUND + } + break; + case 6: // array + if (size <= 0) + break; + + //std::cout << "Creating an array with size: " << size << std::endl; + mVerifyMap[key_path] = "array"; + for (int i = 0; i < size; i++) { + obj[i] = SmartObject(); // just init it as an array + makeRandomObject(obj[i], size - 1, + key_path + generate_key("A", i) + ' '); // recursion + } + break; + case 7: // binary + int dataSize = rand() % 200; + char randomChar = get_random_char(); + std::string strDataVal(dataSize, randomChar); + std::string strVal("c:"); + strVal += strDataVal; + + NsSmartDeviceLink::NsSmartObjects::SmartBinary binaryVal(dataSize, + randomChar); + + obj = binaryVal; // string with binary data filled with random chars + mVerifyMap[key_path] = strVal; + //std::cout << "Created string, value: " << strVal << std::endl; + break; + } + } + + SmartObject get_object(SmartObject &rootObj, const std::string &path) const { + std::vector < std::string > obj_tokens; + SmartObject lastObj = rootObj; + + obj_tokens = split(path, ' '); + + for (size_t i = 0; i < obj_tokens.size(); i++) { + if (obj_tokens[i][0] == 'A') // array + { + int index = atoi(&(obj_tokens[i].c_str()[1])); // get integer skipping first char +#ifdef COPY_SUB_OBJECTS_WORKAROUND + lastObj = SmartObject(lastObj[index]); +#else + lastObj = lastObj[index]; // go to the child object +#endif + } else if (obj_tokens[i][0] == 'M') // map + { +#ifdef COPY_SUB_OBJECTS_WORKAROUND + lastObj = SmartObject(lastObj[obj_tokens[i]]); +#else + lastObj = lastObj[obj_tokens[i]]; // go to the child object +#endif + } else { + //FAIL(); + EXPECT_TRUE(false); + } + } + return lastObj; + } +}; + +/* + * The test creates the initial SmartObject and use it as an array for the next SmartObjects. + * Each next SmartObject is randomly assigned to some type. + * If one of the object happens to be a container it fills it with SmartObject of random type. The amount of these + * objects is the size of the parent container -1. + * The iteration continues until all nodes are simple SmartObjects (not arrays or maps) + */ +TEST_F(StressTestHelper, StressTest) { + SmartObject objects; + + const int size = 11; + + for (int i = 0; i < size; i++) { + SmartObject obj; + + makeRandomObject(obj, size - 1, generate_key("A", i) + ' '); + + objects[i] = obj; + } + + for (VerificationMap::const_iterator it = mVerifyMap.begin(); + it != mVerifyMap.end(); it++) { + std::string value(it->second); + SmartObject obj = get_object(objects, it->first); + + // Binary data check + if (!value.compare(0, 2, "c:")) { + std::string etalonData = value.substr(2); + + ASSERT_EQ(NsSmartDeviceLink::NsSmartObjects::SmartType_Binary, + obj.getType()); + + NsSmartDeviceLink::NsSmartObjects::SmartBinary binaryData = + obj.asBinary(); + ASSERT_EQ(etalonData.size(), binaryData.size()); + + for (size_t i = 0; i < etalonData.size(); ++i) { + { + std::string etalonData = value.substr(2); + + ASSERT_EQ(NsSmartDeviceLink::NsSmartObjects::SmartType_Binary, + obj.getType()); + + NsSmartDeviceLink::NsSmartObjects::SmartBinary binaryData = obj + .asBinary(); + ASSERT_EQ(etalonData.size(), binaryData.size()); + + for (size_t i = 0; i < etalonData.size(); ++i) { + ASSERT_EQ(etalonData.at(i), binaryData.at(i)); + } + continue; + } + + ASSERT_EQ(etalonData.at(i), binaryData.at(i)); + } + continue; + } + +#ifdef NO_INCLUSIVE_MAPS + if (!value.compare("map")) + { + std::vector<std::string> path = split(it->first, ' '); + + std::string map_value = path[path.size()-1]; + ASSERT_EQ(map_value, static_cast<std::string>(obj)); + continue; + } +#endif + if (value.compare("map") && value.compare("array")) { + //std::cout << "Verification key: " << it->first << " Value: " << value << std::endl; + //std::cout << "Object Value: " << static_cast<std::string>(obj) << std::endl; + + if (!value.compare("true")) { + ASSERT_TRUE(obj.asBool()); + } else if (!value.compare("false")) { + ASSERT_FALSE(obj.asBool()); + } else { + ASSERT_EQ(value, obj.asString())<< "Object value is not correct. Object path: " << it->first; + } + } + } +} + +TEST_F(StressTestHelper, ExtraManualDebugTest) { + SmartObject obj; + + obj[0] = false; + obj[1] = 0.869495; + obj[2] = true; + obj[3] = 'Q'; + obj[4] = true; + obj[5] = 3.704; + obj[6] = SmartObject(); + obj[6][0] = + std::string( + "ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt"); + obj[6][1] = 'K'; + obj[6][2] = 0.735294; + obj[6][3] = 'I'; + obj[6][4] = SmartObject(); + obj[6][4]["M0"] = 0.59432; + SmartObject & refObj = obj[6][4]; + refObj["M1"]["M0"]["M0"][0] = true; + + // FIXME: Figure out why there's a trailing zero while converting from double to string + ASSERT_EQ("0.59432", get_object(obj, "A6 A4 M0").asString()); + ASSERT_TRUE(get_object(obj, "A6 A4 M1 M0 M0 A0").asBool()); +} + +} +} +} +} diff --git a/src/components/smart_objects/test/SmartObjectUnit_test.cc b/src/components/smart_objects/test/SmartObjectUnit_test.cc new file mode 100644 index 000000000..d1d790f9d --- /dev/null +++ b/src/components/smart_objects/test/SmartObjectUnit_test.cc @@ -0,0 +1,584 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" +#include "smart_objects/smart_object.h" + +namespace test { +namespace components { +namespace SmartObjects { +namespace SmartObjectUnitTest { + +using namespace NsSmartDeviceLink::NsSmartObjects; + +class TestHelper : public ::testing::Test { + protected: + + void makeMapObject(SmartObject& obj, const int size) const { + char i_key[8], j_key[8], k_key[8], value[8]; + + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + for (int k = 0; k < size; k++) { + sprintf(i_key, "i_%d", i); + sprintf(j_key, "j_%d", j); + sprintf(k_key, "k_%d", k); + sprintf(value, "%d", i + j + k); + obj[i_key][j_key][k_key] = value; + } + } + + void checkMapObject(SmartObject& obj, const int size) const { + char i_key[8], j_key[8], k_key[8], value[8]; + + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + for (int k = 0; k < size; k++) { + sprintf(i_key, "i_%d", i); + sprintf(j_key, "j_%d", j); + sprintf(k_key, "k_%d", k); + sprintf(value, "%d", i + j + k); + + ASSERT_EQ(std::string(value), obj[i_key][j_key][k_key].asString())<< + "Wrong value in the map at [" << i_key << "][" << j_key << "][" << k_key << "]"; + } + } + + void makeArrayObject(SmartObject& obj, int size, int base = 0) { + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + for (int k = 0; k < size; k++) { + obj[i][j][k] = base + i + j + k; + } + } + + void checkArrayObject(SmartObject& obj, int size, int base = 0) { + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + for (int k = 0; k < size; k++) { + ASSERT_EQ(base + i + j + k, obj[i][j][k].asInt()) << + "Wrong value in the array at index: " << i << ", " << j << ", " << k; + } + } + }; + + /* + * Tests different types sequentially + */ +TEST(BasicMixtedTypes, test_SmartObjectUnitTest) { + SmartObject obj; + + ASSERT_EQ(invalid_int_value, obj.asInt())<< "Wrong cast to int just after construction"; + + obj = 10; + ASSERT_EQ(10, obj.asInt())<< "Wrong cast to int"; + + obj = "some string"; + ASSERT_EQ("some string", obj.asString())<< "Wrong cast to std::string"; + + obj = false; + ASSERT_FALSE(obj.asBool())<< "Wrong cast to bool"; + + obj = 'A'; + ASSERT_EQ('A', obj.asChar())<< "Wrong cast to char"; + + obj = 3.14; + ASSERT_EQ(3.14, obj.asDouble())<< "Wrong cast to double"; + + // array test + for (int i = 0; i < 100; i++) { + obj[i] = i; + ASSERT_EQ(i, obj[i].asInt()); + } + + // map test + for (int i = 0; i < 100; i++) { + char key[8]; + sprintf(key, "%d", i); + obj[key] = i; + ASSERT_EQ(i, obj[key].asInt()); + } +} + +TEST_F(TestHelper, BasicArrayTest) { + SmartObject obj; + + ASSERT_EQ(invalid_int_value, + obj[0].asInt())<< "Wrong value at accessing non existent index"; + ASSERT_EQ(invalid_int_value, + obj["non_existent_key"].asInt())<< "Wrong value at accessing non existent key"; + + obj[0] = 1; + ASSERT_EQ(1, obj[0].asInt())<< "Wrong value at 0 index"; + obj[1] = 2; + ASSERT_EQ(2, obj[1].asInt())<< "Wrong value at 1 index"; + + obj[0][0] = 3; + obj[1][0] = 1; + ASSERT_EQ(3, obj[0][0].asInt())<< "Wrong value at index 0, 0"; + + obj[0][0][0] = 4; + obj[0][1][0] = 5; + ASSERT_EQ(4, obj[0][0][0].asInt())<< "Wrong value at index 0, 0, 0"; + + const int size = 32; + makeArrayObject(obj, size); + + checkArrayObject(obj, size); +} + +TEST_F(TestHelper, BasicMapTest) { + SmartObject obj; + + ASSERT_EQ(invalid_int_value, + obj["non_existent_key"].asInt())<< "Wrong value for non existent key"; + + obj["abc"]["def"]["ghi"] = 5; + ASSERT_EQ(5, obj["abc"]["def"]["ghi"].asInt())<< "Wrong value for triple map"; + + obj["123"]["456"]["789"] = "string test"; + + ASSERT_EQ("string test", obj["123"]["456"]["789"].asString())<< + "Wrong value for triple map"; + + const int size = 32; + + makeMapObject(obj, size); + + checkMapObject(obj, size); +} + +TEST(ConstructorsTest, test_SmartObjectUnitTest) { + SmartObject objInt(5678); + ASSERT_EQ(5678, objInt.asInt())<< "Wrong constructor with int param"; + + const char* c_str = "test c_string"; + SmartObject obj_c_str(c_str); + ASSERT_EQ("test c_string", obj_c_str.asString())<< "Wrong constructor with c_str param"; + + SmartObject obj_std_str(std::string("test std_string")); + ASSERT_EQ(std::string("test std_string"), obj_std_str.asString()); + + SmartObject obj_char('R'); + ASSERT_EQ('R', obj_char.asChar())<< "Wrong constructor with char param"; + + SmartObject obj_double(-0.4321); + ASSERT_EQ(-0.4321, obj_double.asDouble())<< "Wrong constructor with double param"; + + SmartObject obj_bool(true); + ASSERT_TRUE(obj_bool.asBool())<< "Wrong constructor with bool param"; + + SmartObject src_obj; + + src_obj["key_1"] = "value_1"; // FIXME: String assignment crashes test + src_obj["key_2"]["sub_key_1"] = "value_2"; + + SmartObject dst_obj(src_obj); + ASSERT_EQ("value_1", dst_obj["key_1"].asString())<< "Copy constructor is not correct"; + ASSERT_EQ("value_2", dst_obj["key_2"]["sub_key_1"].asString())<< + "Copy constructor is not correct"; +} + +TEST(FromString, TypeConversion) { + { + // String to bool + SmartObject obj; + ASSERT_EQ(invalid_bool_value, obj.asBool()); + obj = "true"; + ASSERT_EQ(invalid_bool_value, obj.asBool()); + obj = "false"; + ASSERT_EQ(invalid_bool_value, obj.asBool()); + obj = true; + ASSERT_TRUE(obj.asBool()); + } + { + // String to int + SmartObject obj; + ASSERT_EQ(invalid_int_value, obj.asInt()); + obj = "0"; + ASSERT_EQ(0, obj.asInt()); + obj = "-34323"; + ASSERT_EQ(-34323, obj.asInt()); + obj = "+1234"; + ASSERT_EQ(1234, obj.asInt()); + obj = "3232.0"; + ASSERT_EQ(invalid_int_value, obj.asInt()); + obj = "123wtf"; + ASSERT_EQ(invalid_int_value, obj.asInt()); + obj = ""; + ASSERT_EQ(invalid_int_value, obj.asInt()); + obj = " 123 "; + ASSERT_EQ(invalid_int_value, obj.asInt()); + obj = " 123"; + ASSERT_EQ(123, obj.asInt()); + } + { + // String to char + SmartObject obj; + ASSERT_EQ(invalid_char_value, obj.asChar()); + obj = "C"; + ASSERT_EQ('C', obj.asChar()); + obj = "\n"; + ASSERT_EQ('\n', obj.asChar()); + obj = " A"; + ASSERT_EQ(invalid_char_value, obj.asChar()); + obj = ""; + ASSERT_EQ(invalid_char_value, obj.asChar()); + } + { + // String to double + SmartObject obj; + ASSERT_EQ(invalid_double_value, obj.asDouble()); + obj = "1234"; + ASSERT_EQ(1234, obj.asDouble()); + obj = "-0.1234"; + ASSERT_EQ(-0.1234, obj.asDouble()); + obj = ".54321"; + ASSERT_EQ(.54321, obj.asDouble()); + obj = "123.45.6"; + ASSERT_EQ(invalid_double_value, obj.asDouble()); + obj = "123 wtf"; + ASSERT_EQ(invalid_double_value, obj.asDouble()); + obj = " 0.5"; + ASSERT_EQ(0.5, obj.asDouble()); + } + { + // String to Map + SmartObject obj; + ASSERT_EQ(invalid_int_value, obj["key"].asInt()); + obj = "this is not a map"; + ASSERT_EQ(invalid_char_value, obj["some_key"].asChar()); + } + { + // String to Array + SmartObject obj; + ASSERT_EQ(invalid_bool_value, obj[0].asBool()); + obj = "this is not an array"; + ASSERT_EQ(invalid_double_value, obj[0].asDouble()); + } + { + // String to Binary + SmartObject obj; + ASSERT_EQ(invalid_binary_value, obj.asBinary()); + obj = "this is not an array"; + ASSERT_EQ(invalid_binary_value, obj.asBinary()); + } +} + +TEST(FromBool, TypeConversion) { + SmartObject obj; + + obj = true; + + ASSERT_EQ(invalid_string_value, obj.asString()); + ASSERT_TRUE(obj.asBool()); + ASSERT_EQ(1, obj.asInt()); + ASSERT_EQ(invalid_char_value, obj.asChar()); + ASSERT_EQ(1.0, obj.asDouble()); + ASSERT_EQ(invalid_int_value, obj["key"].asInt()); + ASSERT_EQ(invalid_char_value, obj[0].asChar()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); + + obj = false; + + ASSERT_EQ(invalid_string_value, obj.asString()); + ASSERT_FALSE(obj.asBool()); + ASSERT_EQ(0, obj.asBool()); + ASSERT_EQ(invalid_char_value, obj.asChar()); + ASSERT_EQ(0, obj.asDouble()); + ASSERT_EQ(invalid_int_value, obj["key"].asInt()); + ASSERT_EQ(invalid_char_value, obj[0].asChar()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); +} + +TEST(FromInt, TypeConversion) { + SmartObject obj; + + obj = 123; + + ASSERT_EQ("123", obj.asString()); + ASSERT_TRUE(obj.asBool()); + ASSERT_EQ(invalid_char_value, obj.asChar()); + ASSERT_EQ(123.0, obj.asDouble()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); + + obj = 5; + ASSERT_EQ("5", obj.asString()); + ASSERT_EQ(invalid_char_value, obj.asChar()); + + obj = 0; + ASSERT_EQ("0", obj.asString()); + ASSERT_FALSE(obj.asBool()); + + obj = 1; + ASSERT_TRUE(obj.asBool()); + + obj = -1234; + ASSERT_EQ(-1234, obj.asInt()); + ASSERT_EQ("-1234", obj.asString()); + ASSERT_EQ(-1234.0, obj.asDouble()); + ASSERT_EQ(invalid_char_value, obj.asChar()); + ASSERT_TRUE(obj.asBool()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); +} + +TEST(FromChar, TypeConversion) { + SmartObject obj; + + obj = '1'; + + ASSERT_EQ("1", obj.asString()); + ASSERT_EQ(invalid_int_value, obj.asInt()); + ASSERT_EQ('1', obj.asChar()); + ASSERT_EQ(invalid_double_value, obj.asDouble()); + ASSERT_EQ(invalid_int_value, obj["key"].asInt()); + ASSERT_EQ(invalid_char_value, obj[0].asChar()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); + + obj = '0'; + + ASSERT_EQ("0", obj.asString()); + ASSERT_EQ(invalid_int_value, obj.asInt()); + ASSERT_EQ('0', obj.asChar()); + ASSERT_EQ(invalid_double_value, obj.asDouble()); + ASSERT_EQ(invalid_int_value, obj["key"].asInt()); + ASSERT_EQ(invalid_char_value, obj[0].asChar()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); +} + +TEST(FromDouble, TypeConversion) { + SmartObject obj; + + obj = 0.1; + ASSERT_EQ("0.1", obj.asString()); // FIXME: result 0.100000 + ASSERT_EQ(0, obj.asInt()); + ASSERT_EQ(invalid_char_value, obj.asChar()); + ASSERT_EQ(0.1, obj.asDouble()); + ASSERT_TRUE(obj.asBool()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); + + obj = 0.9; + ASSERT_EQ("0.9", obj.asString()); + ASSERT_EQ(0, obj.asInt()); + ASSERT_TRUE(obj.asBool()); + + obj = -12323.999; + ASSERT_EQ("-12323.999", obj.asString()); + ASSERT_EQ(-12323, obj.asInt()); + ASSERT_TRUE(obj.asBool()); + + obj = 0.0; + ASSERT_EQ("0", obj.asString()); + ASSERT_EQ(0, obj.asInt()); + ASSERT_FALSE(obj.asBool()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); +} + +TEST(FromMap, TypeConversion) { + SmartObject obj; + + obj["key1"] = 123; + + ASSERT_EQ(invalid_string_value, obj.asString()); + ASSERT_EQ(invalid_int_value, obj.asInt()); + ASSERT_EQ(invalid_char_value, obj.asChar()); + ASSERT_EQ(invalid_double_value, obj.asDouble()); + ASSERT_EQ(123, obj["key1"].asInt()); + ASSERT_EQ(invalid_char_value, obj[0].asChar()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); +} + +TEST(FromArray, TypeConversion) { + SmartObject obj; + + obj[0] = 'A'; + obj[1] = -123; + + ASSERT_EQ(invalid_string_value, obj.asString()); + ASSERT_EQ(invalid_int_value, obj.asInt()); + ASSERT_EQ(invalid_char_value, obj.asChar()); + ASSERT_EQ(invalid_double_value, obj.asDouble()); + ASSERT_EQ('A', obj[0].asChar()); + ASSERT_EQ(invalid_int_value, obj["key1"].asInt()); + ASSERT_EQ(invalid_binary_value, obj.asBinary()); +} + +TEST_F(TestHelper, AssignmentTest) { + SmartObject objSrc, objDst; + + objSrc = -6; + objDst = 7; + objDst = objSrc; + ASSERT_EQ(-6, objDst.asInt())<< "Wrong assignment for int object"; + + objSrc = "Some test string"; + objDst = "Other string"; + objDst = objSrc; + ASSERT_EQ("Some test string", + objDst.asString())<< "Wrong assignment for std::string object"; + + objSrc = 0.5; + objDst = 4; + objDst = objSrc; + ASSERT_EQ(0.5, objDst.asDouble())<< "Wrong assignment for double object"; + + objSrc = true; + objDst = false; + objDst = objSrc; + ASSERT_TRUE(objDst.asBool())<< "Wrong assignment for bool object"; + + const int size = 32; + makeMapObject(objSrc, size); + objDst["a"]["b"] = 4; + objDst = objSrc; + checkMapObject(objDst, size); + + makeArrayObject(objSrc, size, 5); + makeArrayObject(objDst, 23, 6); + objDst = objSrc; + checkArrayObject(objDst, size, 5); +} + +TEST_F(TestHelper, SizeTest) { + SmartObject obj; + + ASSERT_EQ(0u, obj.length())<< "Wrong size for the uninitialized object"; + + obj = 1234; + ASSERT_EQ(0u, obj.length())<< "Wrong size for the int object"; + + std::string str("Some test very long string"); + obj = str; + ASSERT_EQ(str.size(), obj.length())<< + "The size of the object containing string is not correct"; + + obj = true; + ASSERT_EQ(0u, obj.length())<< "Wrong size of the true"; + + obj = 0.1234; + ASSERT_EQ(0u, obj.length())<< "Wrong size of the double"; + + obj = 'A'; + ASSERT_EQ(0u, obj.length())<< "Wrong size of the char"; + + makeMapObject(obj, 12); + ASSERT_EQ(12u, obj.length())<< "Wrong size of the object containing map"; + + makeArrayObject(obj, 21); + ASSERT_EQ(21u, obj.length())<< "Wrong size of the object containing array"; +} + +TEST(CopyObjectsTest, SmartObjectTest) { + SmartObject obj; + + obj[0] = "test string"; + + obj = obj[0]; + + ASSERT_EQ("test string", obj.asString()); + + obj["abc"] = "new test string"; + obj = obj["abc"]; + + ASSERT_EQ("new test string", obj.asString()); +} + +TEST(CopyConstructorTest, SmartObjectTest) { + SmartObject srcObj; + + srcObj[0] = "test string"; + + SmartObject dstObj = srcObj[0]; + + ASSERT_EQ("test string", dstObj.asString()); +} + +TEST(MapEraseTest, SmartObjectTest) { + SmartObject srcObj; + + srcObj["one"] = 1; + srcObj["two"] = 2; + srcObj["three"] = 3; + + ASSERT_EQ(3u, srcObj.length()); + ASSERT_EQ(2, srcObj["two"].asInt()); + + ASSERT_TRUE(srcObj.erase("two")); + ASSERT_FALSE(srcObj.erase("two")); + + ASSERT_EQ(2u, srcObj.length()); + ASSERT_EQ(-1, srcObj["two"].asInt()); + // The element "two" was accessed in the previous line so the element has been created + ASSERT_EQ(3u, srcObj.length()); + + srcObj["two"] = 2; + + ASSERT_EQ(1, srcObj["one"].asInt()); + ASSERT_EQ(2, srcObj["two"].asInt()); + ASSERT_EQ(3, srcObj["three"].asInt()); + + ASSERT_TRUE(srcObj.erase("one")); + + ASSERT_EQ(2u, srcObj.length()); + + ASSERT_TRUE(srcObj.erase("two")); + + ASSERT_EQ(1u, srcObj.length()); + + ASSERT_TRUE(srcObj.erase("three")); + + ASSERT_EQ(0u, srcObj.length()); + + srcObj["one"]["two"]["three"]["0"] = "1"; + srcObj["one"]["two"]["three"]["1"] = "2"; + + ASSERT_EQ(1u, srcObj.length()); + ASSERT_EQ(1u, srcObj["one"].length()); + ASSERT_EQ(1u, srcObj["one"]["two"].length()); + ASSERT_EQ(2u, srcObj["one"]["two"]["three"].length()); + + ASSERT_TRUE(srcObj["one"]["two"]["three"].erase("0")); + ASSERT_FALSE(srcObj["one"]["two"]["three"].erase("0")); + + ASSERT_EQ(1u, srcObj["one"]["two"]["three"].length()); + + ASSERT_TRUE(srcObj["one"].erase("two")); + ASSERT_EQ(0u, srcObj["one"].length()); + + srcObj = 1234; // not a map + ASSERT_FALSE(srcObj.erase("one")); +} +// TODO: Add a test to check accessing an array at strange indexes. +}// namespace SmartObjectUnitTest +} // namespace SmartObjects +} // namespace components +} // namespace test diff --git a/src/components/smart_objects/test/StringSchemaItem_test.cc b/src/components/smart_objects/test/StringSchemaItem_test.cc new file mode 100644 index 000000000..5fe179a7e --- /dev/null +++ b/src/components/smart_objects/test/StringSchemaItem_test.cc @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2014, 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 "gmock/gmock.h" + +#include "smart_objects/smart_object.h" +#include "smart_objects/string_schema_item.h" + +namespace test { +namespace components { +namespace SmartObjects { +namespace SchemaItem { + +/** + * Test StringSchemaItem no default value + * + * Create SchemaItem without default value. Method setDefaultValue should always return false + * and leave SmartObject in previous state. + **/ +TEST(test_no_default_value, test_StringSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CStringSchemaItem::create(); // No default value, no max length + + //Object - valid string + obj = "New valid string"; + ASSERT_EQ(std::string("New valid string"), obj.asString()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + bool resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + EXPECT_EQ(std::string("New valid string"), obj.asString()); + + //Obj - bool + obj = true; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + EXPECT_TRUE(obj.asBool()); + + //Object - number + obj = 3.1415926; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resDefault = item->setDefaultValue(obj); + EXPECT_FALSE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + EXPECT_EQ(3.1415926, obj.asDouble()); +} + +/** + * Test StringSchemaItem with default value + * + * Create SchemaItem with default value. Method setDefaultValue should return true, + * String SmartObject should contain default value. + * Not string SmartObject should converted to StringObject and setted up by the default value. + **/ +TEST(test_item_with_default_value, test_StringSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CStringSchemaItem::create( + TSchemaItemParameter<size_t>(), TSchemaItemParameter<size_t>(), + TSchemaItemParameter<std::string>("Default string")); // Default value, no max length + + //Object - valid string + obj = "New valid string"; + ASSERT_EQ(std::string("New valid string"), obj.asString()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + bool resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(std::string("Default string"), obj.asString()); + + //Obj - bool + obj = true; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(std::string("Default string"), obj.asString()); + + //Object - number + obj = 3.1415926; + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + EXPECT_EQ(std::string("Default string"), obj.asString()); +} + +/** + * Test StringSchemaItem with max length + **/ +TEST(test_item_with_max_length, test_StringSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CStringSchemaItem::create( + TSchemaItemParameter<size_t>(0), TSchemaItemParameter<size_t>(25), + TSchemaItemParameter<std::string>("Default string")); + + //Object - valid string + obj = "New valid string"; + ASSERT_EQ(std::string("New valid string"), obj.asString()); + + int resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); + bool resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(std::string("Default string"), obj.asString()); + + //Object - too long string + obj = "New very very loooooong string"; + ASSERT_EQ(std::string("New very very loooooong string"), obj.asString()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(std::string("Default string"), obj.asString()); + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); +} + +TEST(test_map_validate, test_StringSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CStringSchemaItem::create( + TSchemaItemParameter<size_t>(0), TSchemaItemParameter<size_t>(25), + TSchemaItemParameter<std::string>("Default string")); + + obj["str"] = "New valid string"; + obj["long"] = "New very very loooooong string"; + obj["bool"] = true; + obj["num"] = 3.14; + + int resultType = item->validate(obj["str"]); + EXPECT_EQ(Errors::OK, resultType); + + resultType = item->validate(obj["long"]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + resultType = item->validate(obj["bool"]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resultType = item->validate(obj["num"]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + bool resDefault = item->setDefaultValue(obj["str"]); + EXPECT_TRUE(resDefault); + EXPECT_EQ(std::string("Default string"), obj["str"].asString()); + + resDefault = item->setDefaultValue(obj["bool"]); + EXPECT_TRUE(resDefault); + EXPECT_EQ(std::string("Default string"), obj["bool"].asString()); + + resDefault = item->setDefaultValue(obj["num"]); + EXPECT_TRUE(resDefault); + EXPECT_EQ(std::string("Default string"), obj["num"].asString()); + + resultType = item->validate(obj["str"]); + EXPECT_EQ(Errors::OK, resultType); + + resultType = item->validate(obj["long"]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + resultType = item->validate(obj["bool"]); + EXPECT_EQ(Errors::OK, resultType); + + resultType = item->validate(obj["num"]); + EXPECT_EQ(Errors::OK, resultType); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(std::string("Default string"), obj.asString()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); +} + +TEST(test_array_validate, test_StringSchemaItemTest) { + using namespace NsSmartDeviceLink::NsSmartObjects; + SmartObject obj; + + ISchemaItemPtr item = CStringSchemaItem::create( + TSchemaItemParameter<size_t>(0), TSchemaItemParameter<size_t>(25), + TSchemaItemParameter<std::string>("Default string")); + + obj[0] = "New valid string"; + obj[1] = "New very very loooooong string"; + obj[2] = true; + obj[3] = 3.14; + obj[4] = "New valid string"; + + int resultType = item->validate(obj[0]); + EXPECT_EQ(Errors::OK, resultType); + + resultType = item->validate(obj[1]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + + resultType = item->validate(obj[2]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resultType = item->validate(obj[3]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + resultType = item->validate(obj[4]); + EXPECT_EQ(Errors::OK, resultType); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + + bool resDefault = item->setDefaultValue(obj[0]); + EXPECT_TRUE(resDefault); + resDefault = item->setDefaultValue(obj[2]); + EXPECT_TRUE(resDefault); + resDefault = item->setDefaultValue(obj[4]); + EXPECT_TRUE(resDefault); + + //Set default value for non-initialized element + resDefault = item->setDefaultValue(obj[5]); + EXPECT_TRUE(resDefault); + + EXPECT_EQ(std::string("Default string"), obj[0].asString()); + EXPECT_EQ(std::string("Default string"), obj[2].asString()); + EXPECT_EQ(std::string("Default string"), obj[4].asString()); + EXPECT_EQ(std::string("Default string"), obj[5].asString()); + + resultType = item->validate(obj[0]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj[1]); + EXPECT_EQ(Errors::OUT_OF_RANGE, resultType); + resultType = item->validate(obj[2]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj[3]); + EXPECT_EQ(Errors::INVALID_VALUE, resultType); + resultType = item->validate(obj[4]); + EXPECT_EQ(Errors::OK, resultType); + resultType = item->validate(obj[5]); + EXPECT_EQ(Errors::OK, resultType); + + resDefault = item->setDefaultValue(obj); + EXPECT_TRUE(resDefault); + EXPECT_EQ(std::string("Default string"), obj.asString()); + + resultType = item->validate(obj); + EXPECT_EQ(Errors::OK, resultType); +} +} // namespace SchemaItem +} // namespace SmartObjects +} // namespace components +} // namespace test diff --git a/src/components/smart_objects/test/TSharedPtr_test.cc b/src/components/smart_objects/test/TSharedPtr_test.cc new file mode 100644 index 000000000..3943d2b24 --- /dev/null +++ b/src/components/smart_objects/test/TSharedPtr_test.cc @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2014, 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 <stdlib.h> +#include <vector> +#include "gmock/gmock.h" +#include "utils/shared_ptr.h" + +namespace test { +namespace components { +namespace utils { +namespace SharedPtrTest { +class CMockObject { + public: + CMockObject(int id); + ~CMockObject(void); + int getId(void) const; + + MOCK_METHOD0(destructor, void ()); + +private: + int mId; +}; + +class CExtendedMockObject : public CMockObject { + public: + CExtendedMockObject(int id); +}; +} // namespace CMockObject +} // namespace SmartObjects +} // namespace components +} // namespace test + +test::components::utils::SharedPtrTest::CMockObject::CMockObject(int id) + : mId(id) { +} + +test::components::utils::SharedPtrTest::CMockObject::~CMockObject(void) { + destructor(); +} + +int test::components::utils::SharedPtrTest::CMockObject::getId(void) const { + return mId; +} + +test::components::utils::SharedPtrTest::CExtendedMockObject::CExtendedMockObject( + int id) + : CMockObject(id) { +} + +typedef utils::SharedPtr<test::components::utils::SharedPtrTest::CMockObject> tMockObjectPtr; +typedef utils::SharedPtr< + test::components::utils::SharedPtrTest::CExtendedMockObject> tExtendedMockObjectPtr; + +TEST(SharedPtrTest, Constructor) { + test::components::utils::SharedPtrTest::CMockObject* object1 = + new test::components::utils::SharedPtrTest::CMockObject(1); + test::components::utils::SharedPtrTest::CMockObject* object2 = + new test::components::utils::SharedPtrTest::CMockObject(2); + + EXPECT_CALL(*object1, destructor()).Times(0); + EXPECT_CALL(*object2, destructor()).Times(0); + + tMockObjectPtr p1(object1); + ASSERT_EQ(1, p1->getId()); + + tMockObjectPtr p2(p1); + ASSERT_EQ(1, p2->getId()); + + tMockObjectPtr p3 = p2; + ASSERT_EQ(1, p3->getId()); + + tMockObjectPtr p4 = object2; + ASSERT_EQ(2, p4->getId()); + + p3 = p4; + ASSERT_EQ(2, p3->getId()); + + EXPECT_CALL(*object1, destructor()); + EXPECT_CALL(*object2, destructor()); +} + +TEST(SharedPtrTest, PointerTypeCast) { + test::components::utils::SharedPtrTest::CExtendedMockObject* object1 = + new test::components::utils::SharedPtrTest::CExtendedMockObject(1); + test::components::utils::SharedPtrTest::CExtendedMockObject* object2 = + new test::components::utils::SharedPtrTest::CExtendedMockObject(2); + + EXPECT_CALL(*object1, destructor()).Times(0); + EXPECT_CALL(*object2, destructor()).Times(0); + + tExtendedMockObjectPtr ep1(object1); + ASSERT_EQ(1, ep1->getId()); + + tMockObjectPtr p1(ep1); + ASSERT_EQ(1, p1->getId()); + + tExtendedMockObjectPtr ep2(object2); + ASSERT_EQ(2, ep2->getId()); + + p1 = ep2; + ASSERT_EQ(2, p1->getId()); + + EXPECT_CALL(*object1, destructor()); + EXPECT_CALL(*object2, destructor()); +} + +TEST(SharedPtrTest, AddedOperators) { + test::components::utils::SharedPtrTest::CExtendedMockObject* object1 = + new test::components::utils::SharedPtrTest::CExtendedMockObject(1); + test::components::utils::SharedPtrTest::CExtendedMockObject* object2 = + new test::components::utils::SharedPtrTest::CExtendedMockObject(2); + + EXPECT_CALL(*object1, destructor()).Times(0); + EXPECT_CALL(*object2, destructor()).Times(0); + + tExtendedMockObjectPtr ep1(object1); + tMockObjectPtr p1(ep1); + tExtendedMockObjectPtr ep2(object2); + p1 = ep2; + + ASSERT_EQ(2, p1->getId()); + ASSERT_EQ(2, (*p1).getId()); + + ASSERT_FALSE(!p1); + + utils::SharedPtr<int> p3(new int(10)); + ASSERT_EQ(10, *p3); + ASSERT_FALSE(!p3); + + utils::SharedPtr<int> p2; + ASSERT_TRUE(!p2); + + p2.reset(new int); + ASSERT_FALSE(!p2); + *p2 = 3; + ASSERT_EQ(3, *p2); + + EXPECT_CALL(*object1, destructor()); + EXPECT_CALL(*object2, destructor()); +} + +TEST(SharedPtrTest, StressTest) { + const size_t cNumIterations = 1024U * 1024U; + + size_t objectCreated = 0U; + size_t pointersCopied = 0U; + + std::vector<tMockObjectPtr> objects; + + for (size_t i = 0U; i < cNumIterations; ++i) { + if ((true == objects.empty()) || (0 == rand() % 256)) { + test::components::utils::SharedPtrTest::CMockObject* object = + new test::components::utils::SharedPtrTest::CMockObject(0); + EXPECT_CALL(*object, destructor()); + + objects.push_back(object); + + ++objectCreated; + } else { + size_t objectIndex = static_cast<size_t>(rand()) % objects.size(); + + if (rand() % 2) { + objects.push_back(objects[objectIndex]); + + ++pointersCopied; + } else { + objects.erase(objects.begin() + objectIndex); + } + } + } + printf("%zu objects created, %zu pointers copied\n", objectCreated, + pointersCopied); +} diff --git a/src/components/smart_objects/test/main.cc b/src/components/smart_objects/test/main.cc new file mode 100644 index 000000000..59fa20e8b --- /dev/null +++ b/src/components/smart_objects/test/main.cc @@ -0,0 +1,7 @@ +#include "gmock/gmock.h"
+
+int main(int argc, char** argv) {
+ testing::InitGoogleMock(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
diff --git a/src/components/smart_objects/test/map_performance_test.cc b/src/components/smart_objects/test/map_performance_test.cc new file mode 100644 index 000000000..e7e9ccffa --- /dev/null +++ b/src/components/smart_objects/test/map_performance_test.cc @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014, 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 <vector> +#include <map> + +#include "gmock/gmock.h" + +typedef std::string Key; +typedef std::vector<std::string> Value; +typedef std::map<Key, Value> Map; + +namespace { +void MakeMapObject(Map &obj, const int size) { + char i_key[8], j_key[8]; + + Value array; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + sprintf(j_key, "j_%d", j); + array.push_back(j_key); + } + + sprintf(i_key, "i_%d", i); + obj[i_key] = array; + } +} +} + +TEST(SmartObjectPerformanceTest, SmartObjectMapPerformance) { + Map object; + MakeMapObject(object, 100); + + for (Map::const_iterator i = object.begin(); i != object.end(); ++i) { + printf("%s - ", i->first.c_str()); + const Value& value = i->second; + + Value::const_iterator item = std::find(value.begin(), value.end(), "j_9"); + if (item != value.end()) { + printf("%s\n", item->c_str()); + } else { + printf("none...\n"); + } + } +} diff --git a/src/components/smart_objects/test/smart_object_performance_test.cc b/src/components/smart_objects/test/smart_object_performance_test.cc new file mode 100644 index 000000000..72b6c1fa6 --- /dev/null +++ b/src/components/smart_objects/test/smart_object_performance_test.cc @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014, 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 <set> + +#include "gmock/gmock.h" + +#include "smart_objects/smart_object.h" + +using namespace NsSmartDeviceLink::NsSmartObjects; + +namespace { +void MakeMapObject(SmartObject &obj, const int size) { + char i_key[8], j_key[8]; + + SmartObject array; + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + sprintf(j_key, "j_%d", j); + array[-1] = j_key; + } + + sprintf(i_key, "i_%d", i); + obj[i_key] = array; + } +} +} + +TEST(SmartObjectPerformanceTest, SmartObjectPerformance) { + SmartObject object; + MakeMapObject(object, 100); + + std::set < std::string > keys = object.enumerate(); + for (std::set<std::string>::iterator i = keys.begin(); i != keys.end(); ++i) { + printf("%s - ", i->c_str()); + SmartArray* array = object[*i].asArray(); + + SmartArray::iterator item = std::find(array->begin(), array->end(), "j_9"); + if (item != array->end()) { + printf("%s\n", item->asString().c_str()); + } else { + printf("none...\n"); + } + } +} |
