diff options
Diffstat (limited to 'src/components/smart_objects/test/CObjectSchemaItem_test.cc')
-rw-r--r-- | src/components/smart_objects/test/CObjectSchemaItem_test.cc | 453 |
1 files changed, 453 insertions, 0 deletions
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 0000000000..56f365e5c4 --- /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 |