template<typename T> class Enum;
template<typename T, size_t minsize, size_t maxsize> class Array;
template<typename T, size_t minsize, size_t maxsize> class Map;
+template<typename T> class Nullable;
template<typename T> class Mandatory;
template<typename T> class Optional;
public:
bool is_initialized() const;
bool is_valid() const;
- bool is_null() const;
- void set_to_null();
protected:
enum ValueState {
kUninitialized,
- kNull,
kInvalid,
kValid
};
const Map<T, minsize, maxsize>& field,
Json::Value* json_value);
template<class T>
+ static void WriteJsonField(const char* field_name,
+ const Nullable<T>& field,
+ Json::Value* json_value);
+ template<class T>
static void WriteJsonField(const char* field_name, const Optional<T>& field,
Json::Value* json_value);
template<class T>
};
template<typename T>
+class Nullable : public T {
+ public:
+ // Methods
+ Nullable();
+ // Need const and non-const versions to beat all-type accepting constructor
+ explicit Nullable(Json::Value* value);
+ explicit Nullable(const Json::Value* value);
+ template<typename U>
+ explicit Nullable(const U& value);
+ template<typename U>
+ Nullable(const Json::Value* value, const U& def_value);
+ template<typename U>
+ Nullable& operator=(const U& new_val);
+ Json::Value ToJsonValue() const;
+
+ bool is_valid() const;
+ bool is_initialized() const;
+ bool is_null() const;
+ void set_to_null();
+ private:
+ bool marked_null_;
+};
+
+template<typename T>
class Mandatory : public T {
public:
// Methods
bool is_valid() const;
bool is_initialized() const;
- bool is_null() const;
private:
T value_;
};
return value_state_ == kValid;
}
-inline bool PrimitiveType::is_null() const {
- return value_state_ == kNull;
-}
-
-inline void PrimitiveType::set_to_null() {
- value_state_ = kNull;
-}
-
/*
* Boolean class
*/
}
/*
+ * Nullable class
+ */
+template<typename T>
+Nullable<T>::Nullable()
+ : marked_null_(false) {
+}
+
+template<typename T>
+template<typename U>
+Nullable<T>::Nullable(const U& value)
+ : T(value),
+ marked_null_(false) {
+}
+
+template<typename T>
+template<typename U>
+Nullable<T>& Nullable<T>::operator=(const U& new_val) {
+ this->T::operator=(new_val);
+ return *this;
+}
+
+template<typename T>
+bool Nullable<T>::is_valid() const {
+ return is_null() || T::is_valid();
+}
+
+template<typename T>
+bool Nullable<T>::is_initialized() const {
+ return is_null() || T::is_initialized();
+}
+
+template<typename T>
+bool Nullable<T>::is_null() const {
+ return marked_null_;
+}
+
+template<typename T>
+void Nullable<T>::set_to_null() {
+ marked_null_ = true;
+}
+
+/*
* Mandatory class
*/
template<typename T>
return value_.is_initialized();
}
-template<typename T>
-bool Optional<T>::is_null() const {
- return value_.is_null();
-}
-
} // namespace rpc
bool (Json::Value::*type_check)() const) {
if (!value) {
return kUninitialized;
- }
- if (value->isNull()) {
- return kNull;
} else if ((value->*type_check)()) {
return kValid;
} else {
// static
template<class T>
void CompositeType::WriteJsonField(const char* field_name,
+ const Nullable<T>& field,
+ Json::Value* json_value) {
+ (*json_value)[field_name] = field.ToJsonValue();
+}
+
+// static
+template<class T>
+void CompositeType::WriteJsonField(const char* field_name,
const Optional<T>& field,
Json::Value* json_value) {
if (field.is_initialized()) {
template<typename T, size_t minsize, size_t maxsize>
Json::Value Array<T, minsize, maxsize>::ToJsonValue() const {
+ if (is_null()) {
+ return Json::Value::null;
+ }
Json::Value array(Json::arrayValue);
array.resize(this->size());
for (size_t i = 0; i != this->size(); ++i) {
template<typename T, size_t minsize, size_t maxsize>
Json::Value Map<T, minsize, maxsize>::ToJsonValue() const {
+ if (is_null()) {
+ return Json::Value::null;
+ }
Json::Value map(Json::objectValue);
for (typename MapType::const_iterator i = this->begin(); i != this->end(); ++i) {
map[i->first] = i->second.ToJsonValue();
}
template<typename T>
+Nullable<T>::Nullable(const Json::Value* value)
+ : T(value),
+ marked_null_(value != NULL && value->isNull()){
+}
+
+template<typename T>
+Nullable<T>::Nullable(Json::Value* value)
+ : T(value),
+ marked_null_(value != NULL && value->isNull()){
+}
+
+template<typename T>
+template<typename U>
+Nullable<T>::Nullable(const Json::Value* value, const U& def_value)
+ : T(value, def_value),
+ marked_null_(value != NULL && value->isNull()) {
+}
+
+template<typename T>
+inline Json::Value Nullable<T>::ToJsonValue() const {
+ return marked_null_ ? Json::Value::null : T::ToJsonValue();
+}
+
+template<typename T>
template<typename U>
Mandatory<T>::Mandatory(const Json::Value* value, const U& def_value)
: T(value, def_value) {
# --- components tests
add_subdirectory(./components)
add_subdirectory(./thirdPartyLibs)
-
-#add_subdirectory(./tools)
+add_subdirectory(${CMAKE_SOURCE_DIR}/src/components/policy/test/policy ./policy)
+add_subdirectory(./tools)
include_directories (
- ../src/thirdPartyLibs/gmock-1.6.0/include
+ ../src/thirdPartyLibs/gmock-1.7.0/include
../src/thirdPartyLibs/jsoncpp/include/
- ../src/thirdPartyLibs/gmock-1.6.0/gtest/include
+ ../src/thirdPartyLibs/gmock-1.7.0/gtest/include
../src/thirdPartyLibs/MessageBroker/include
../src/appMain
../src/components/application_manager/include
- ../src/components/policies/include
../src/components/hmi_message_handler/include
../src/components/request_watchdog/include
../src/components/media_manager/include
# ${GLIB_glib_2_INCLUDE_DIR}
)
-set(LIBRARIES
- MediaManager
+if (BUILD_TESTS_WITH_HMI)
+ set(LIBRARIES
+ test_App_Manager
ApplicationManager
- gtest
- gtest_main
- gmock
- gmock_main
- formatters
- HMI_API
- v4_protocol_v1_2_no_extra
- SmartObjects
- RequestWatchdog
- policies
- ProtocolHandler
- Utils
- ConfigProfile
- #test_JSONHandler_v4_protocol_v2_0_revP
- #test_json_handler
- #test_SmartObjectTest
- #test_FormattersCommandsTest
- #test_UtilsTest
- #test_RequestWatchdogTest
- #test_ProtocolHandlerTest
- #test_JSONCPPTest
- connectionHandler
- MOBILE_API
- jsoncpp
- TransportManager
- HMIMessageHandler
- MessageBroker
- MessageBrokerClient
- MessageBrokerServer
- encryption
- bluetooth
- pthread
- avahi-client
- avahi-common
- ${LibXML2_LIBRARIES} -lxml2
- # rt
- # ${GSTREAMER_gstreamer_LIBRARY}
- Resumption
+ MediaManager
+ gtest
+ gtest_main
+ gmock
+ gmock_main
+ formatters
+ HMI_API
+ v4_protocol_v1_2_no_extra
+ SmartObjects
+ RequestWatchdog
+ policies
+ ProtocolHandler
+ Utils
+ ConfigProfile
+ #test_JSONHandler_v4_protocol_v2_0_revP
+ #test_json_handler
+ #test_SmartObjectTest
+ #test_FormattersCommandsTest
+ #test_UtilsTest
+ #test_RequestWatchdogTest
+ #test_ProtocolHandlerTest
+ #test_JSONCPPTest
+ #test_MobileMessageHandlerTest
+ connectionHandler
+ MOBILE_API
+ jsoncpp
+#################################################
+ TransportManager
+ HMIMessageHandler
+ MessageBroker
+ MessageBrokerClient
+ MessageBrokerServer
+ encryption
+ bluetooth
+ pthread
+ avahi-client
+ avahi-common
+ ${LibXML2_LIBRARIES} -lxml2
+ # rt
+ # ${GSTREAMER_gstreamer_LIBRARY}
+ Resumption
+ )
+else(BUILD_TESTS_WITH_HMI)
+set(LIBRARIES
+ MediaManager
+ ApplicationManager
+ gtest
+ gtest_main
+ gmock
+ gmock_main
+ formatters
+ HMI_API
+ v4_protocol_v1_2_no_extra
+ SmartObjects
+ RequestWatchdog
+ #policy
+ ProtocolHandler
+ Utils
+ ConfigProfile
+ #test_JSONHandler_v4_protocol_v2_0_revP
+ #test_json_handler
+ #test_SmartObjectTest
+ #test_FormattersCommandsTest
+ #test_UtilsTest
+ #test_RequestWatchdogTest
+ #test_ProtocolHandlerTest
+ #test_JSONCPPTest
+ #test_MobileMessageHandlerTest
+ connectionHandler
+ MOBILE_API
+ jsoncpp
+#################################################
+ TransportManager
+ HMIMessageHandler
+ MessageBroker
+ MessageBrokerClient
+ MessageBrokerServer
+ encryption
+ bluetooth
+ pthread
+ avahi-client
+ avahi-common
+ ${LibXML2_LIBRARIES} -lxml2
+ # rt
+ # ${GSTREAMER_gstreamer_LIBRARY}
+ Resumption
)
+endif(BUILD_TESTS_WITH_HMI)
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ list(APPEND LIBRARIES dl)
+endif()
+
if (BUILD_USB_SUPPORT)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
endif()
add_executable("test_suit" "./test_suit.cc")
+target_link_libraries("test_suit" ${LIBRARIES})
-if (BUILD_TESTS_WITH_HMI)
- target_link_libraries("test_suit" test_App_Manager ${LIBRARIES})
-else (BUILD_TESTS_WITH_HMI)
- target_link_libraries("test_suit" ${LIBRARIES})
-endif (BUILD_TESTS_WITH_HMI)
# vim: set ts=2 sw=2 et:
TEST(ValidatedTypesJson, BooleanNullTest) {
Boolean boolean(&Value::null);
ASSERT_TRUE(boolean.is_initialized());
- ASSERT_TRUE(boolean.is_null());
ASSERT_FALSE(boolean.is_valid());
}
Value* novalue = NULL;
Boolean boolean(novalue);
ASSERT_FALSE(boolean.is_initialized());
- ASSERT_FALSE(boolean.is_null());
ASSERT_FALSE(boolean.is_valid());
}
TEST(ValidatedTypesJson, IntegerNullTest) {
Integer<int32_t, -5, 192> integer(&Value::null);
ASSERT_TRUE(integer.is_initialized());
- ASSERT_TRUE(integer.is_null());
ASSERT_FALSE(integer.is_valid());
}
Value* novalue = NULL;
Integer<int32_t, -5, 192> integer(novalue);
ASSERT_FALSE(integer.is_initialized());
- ASSERT_FALSE(integer.is_null());
ASSERT_FALSE(integer.is_valid());
}
TEST(ValidatedTypesJson, FloatNullTest) {
Float<1, 7> flt(&Value::null);
ASSERT_TRUE(flt.is_initialized());
- ASSERT_TRUE(flt.is_null());
ASSERT_FALSE(flt.is_valid());
}
Value* novalue = NULL;
Float<1, 7> flt(novalue);
ASSERT_FALSE(flt.is_initialized());
- ASSERT_FALSE(flt.is_null());
ASSERT_FALSE(flt.is_valid());
}
TEST(ValidatedTypesJson, StringNullTest) {
String<1, 42> str(&Value::null);
ASSERT_TRUE(str.is_initialized());
- ASSERT_TRUE(str.is_null());
ASSERT_FALSE(str.is_valid());
}
Value* novalue = NULL;
String<1, 500> str(novalue);
ASSERT_FALSE(str.is_initialized());
- ASSERT_FALSE(str.is_null());
ASSERT_FALSE(str.is_valid());
}
TEST(ValidatedTypesJson, EnumNullTest) {
Enum<TestEnum> enm(&Value::null);
ASSERT_TRUE(enm.is_initialized());
- ASSERT_TRUE(enm.is_null());
ASSERT_FALSE(enm.is_valid());
}
Value* novalue = NULL;
Enum<TestEnum> enm(novalue);
ASSERT_FALSE(enm.is_initialized());
- ASSERT_FALSE(enm.is_null());
ASSERT_FALSE(enm.is_valid());
}
Value* none = NULL;
Optional< Boolean > optional_bool;
*optional_bool = Boolean(none);
- ASSERT_FALSE(optional_bool.is_null());
ASSERT_FALSE(optional_bool.is_initialized());
// It is ok for Optional value to be absent
ASSERT_TRUE(optional_bool.is_valid());
TEST(ValidatedTypesJson, OptionalBoolFromNullValueTest) {
Optional< Boolean > optional_bool;
*optional_bool = Boolean(&Value::null);
- ASSERT_TRUE(optional_bool.is_null());
ASSERT_TRUE(optional_bool.is_initialized());
// Optional values should not be absent
ASSERT_FALSE(optional_bool.is_valid());
Value* none = NULL;
Mandatory< Boolean > mandatory_bool;
mandatory_bool = Boolean(none);
- ASSERT_FALSE(mandatory_bool.is_null());
ASSERT_FALSE(mandatory_bool.is_initialized());
ASSERT_FALSE(mandatory_bool.is_valid());
}
+TEST(ValidatedTypesJson, NullableIntFromNullValueTest) {
+ Nullable< Integer<int8_t, 1, 15> > nullable_int(&Value::null);
+ ASSERT_TRUE(nullable_int.is_initialized());
+ ASSERT_TRUE(nullable_int.is_valid());
+ ASSERT_TRUE(nullable_int.is_null());
+}
+
+TEST(ValidatedTypesJson, NullableIntFromNonNullValueTest) {
+ Value json(3);
+ Nullable< Integer<int8_t, 1, 15> > nullable_int(&json);
+ ASSERT_TRUE(nullable_int.is_initialized());
+ ASSERT_TRUE(nullable_int.is_valid());
+ ASSERT_FALSE(nullable_int.is_null());
+ ASSERT_EQ(3, nullable_int);
+}
+
+TEST(ValidatedTypesJson, NullableIntFromAbsentValueTest) {
+ Value* noval = NULL;
+ Nullable< Integer<int8_t, 1, 15> > nullable_int(noval);
+ ASSERT_FALSE(nullable_int.is_initialized());
+ ASSERT_FALSE(nullable_int.is_valid());
+ ASSERT_FALSE(nullable_int.is_null());
+}
+
TEST(ValidatedTypesJson, OptionalIntFromJsonTest) {
Value int_value(42);
Optional< Integer<int64_t, 42, 43> > optional_int;
ASSERT_FALSE(te.is_valid());
}
+TEST(ValidatedTypes, TestNullableConstructor) {
+ Nullable< Integer<int8_t, 2, 10> >nullable_int;
+ ASSERT_FALSE(nullable_int.is_initialized());
+ ASSERT_FALSE(nullable_int.is_null());
+ ASSERT_FALSE(nullable_int.is_valid());
+ nullable_int = 5;
+ ASSERT_TRUE(nullable_int.is_initialized());
+ ASSERT_FALSE(nullable_int.is_null());
+ ASSERT_TRUE(nullable_int.is_valid());
+ nullable_int.set_to_null();
+ ASSERT_TRUE(nullable_int.is_initialized());
+ ASSERT_TRUE(nullable_int.is_null());
+ ASSERT_TRUE(nullable_int.is_valid());
+}
+
+TEST(ValidatedTypes, TestOptionalNullableConstructor) {
+ Optional< Nullable< Integer<int8_t, 2, 10> > > optional_nullable_int;
+ ASSERT_FALSE(optional_nullable_int.is_initialized());
+ ASSERT_FALSE(optional_nullable_int->is_null());
+ ASSERT_TRUE(optional_nullable_int.is_valid());
+ ASSERT_FALSE(optional_nullable_int);
+
+ *optional_nullable_int = 9;
+ ASSERT_TRUE(optional_nullable_int.is_initialized());
+ ASSERT_FALSE(optional_nullable_int->is_null());
+ ASSERT_TRUE(optional_nullable_int.is_valid());
+ ASSERT_EQ(9, *optional_nullable_int);
+ ASSERT_TRUE(optional_nullable_int);
+
+ optional_nullable_int->set_to_null();
+ ASSERT_TRUE(optional_nullable_int.is_initialized());
+ ASSERT_TRUE(optional_nullable_int->is_null());
+ ASSERT_TRUE(optional_nullable_int.is_valid());
+}
+
+TEST(ValidatedTypes, TestMandatoryNullableConstructor) {
+ Mandatory< Nullable< Integer<int8_t, 2, 10> > > mandatory_nullable_int;
+ ASSERT_FALSE(mandatory_nullable_int.is_initialized());
+ ASSERT_FALSE(mandatory_nullable_int.is_null());
+ ASSERT_FALSE(mandatory_nullable_int.is_valid());
+
+ mandatory_nullable_int = 9;
+ ASSERT_TRUE(mandatory_nullable_int.is_initialized());
+ ASSERT_FALSE(mandatory_nullable_int.is_null());
+ ASSERT_TRUE(mandatory_nullable_int.is_valid());
+ ASSERT_EQ(9, mandatory_nullable_int);
+
+ mandatory_nullable_int.set_to_null();
+ ASSERT_TRUE(mandatory_nullable_int.is_initialized());
+ ASSERT_TRUE(mandatory_nullable_int.is_null());
+ ASSERT_TRUE(mandatory_nullable_int.is_valid());
+}
+
TEST(ValidatedTypes, TestMandatoryConstructor) {
Mandatory< Integer<int8_t, 2, 10> > mandatory_int;
ASSERT_FALSE(mandatory_int.is_initialized());
TEST_F(GeneratedInterfaceTests, TestFactory) {
testing::StrictMock<TestRequestHandlerMock> mock;
Json::Value json_value;
- request::Request* req = request::NewFromJson(json_value, kAddSubMenuID);
+ request::Request* req = request::NewFromJson(&json_value, kAddSubMenuID);
request::AddSubMenu& add_sub_menu_ref =
static_cast<request::AddSubMenu&>(*req);
EXPECT_CALL(mock, HandleAddSubMenu(testing::Ref(add_sub_menu_ref)))
req->HandleWith(&mock);
}
+TEST_F(GeneratedInterfaceTests, TestNullableStructMember) {
+ TestStructWithNullableParam with_nullable;
+ ASSERT_FALSE(with_nullable.is_initialized());
+ ASSERT_FALSE(with_nullable.is_valid());
+ ASSERT_FALSE(with_nullable.nullableInt.is_valid());
+ ASSERT_FALSE(with_nullable.nullableInt.is_null());
+ with_nullable.nullableInt.set_to_null();
+ ASSERT_TRUE(with_nullable.is_valid());
+ ASSERT_TRUE(with_nullable.is_initialized());
+ ASSERT_TRUE(with_nullable.nullableInt.is_null());
+ ASSERT_TRUE(with_nullable.nullableInt.is_valid());
+ ASSERT_TRUE(with_nullable.nullableInt.is_initialized());
+}
+
+TEST_F(GeneratedInterfaceTests, TestNullableStructMemberNullInitializationFromJson) {
+ const char* input_json =
+ "{\"nullableInt\":null}\n";
+ Value json_value = JsonValue(input_json);
+ TestStructWithNullableParam with_nullable(&json_value);
+ ASSERT_TRUE(with_nullable.is_initialized());
+ ASSERT_TRUE(with_nullable.is_valid());
+ ASSERT_TRUE(with_nullable.nullableInt.is_null());
+ std::string result = writer.write(with_nullable.ToJsonValue());
+ ASSERT_EQ(input_json, result);
+}
+
+TEST_F(GeneratedInterfaceTests, TestNullableStructMemberInitializationFromJson) {
+ const char* input_json =
+ "{\"nullableInt\":3}\n";
+ Value json_value = JsonValue(input_json);
+ TestStructWithNullableParam with_nullable(&json_value);
+ ASSERT_TRUE(with_nullable.is_initialized());
+ ASSERT_TRUE(with_nullable.is_valid());
+ ASSERT_FALSE(with_nullable.nullableInt.is_null());
+ ASSERT_EQ(3, with_nullable.nullableInt);
+ std::string result = writer.write(with_nullable.ToJsonValue());
+ ASSERT_EQ(input_json, result);
+}
+
+TEST_F(GeneratedInterfaceTests, TestNullableEnumInitialization) {
+ TestStructWithNullableStructParam strct_with_nullable;
+ strct_with_nullable.nullableEnum = IT_DYNAMIC;
+ strct_with_nullable.nonNullableEnum = IT_STATIC;
+ ASSERT_TRUE(strct_with_nullable.is_initialized());
+ ASSERT_TRUE(strct_with_nullable.is_valid());
+ std::string result = writer.write(strct_with_nullable.ToJsonValue());
+ const char* awaited_json1 = "{\"nonNullableEnum\":\"STATIC\",\"nullableEnum\":\"DYNAMIC\"}\n";
+ ASSERT_EQ(awaited_json1, result);
+
+ strct_with_nullable.nullableEnum.set_to_null();
+ ASSERT_TRUE(strct_with_nullable.is_initialized());
+ ASSERT_TRUE(strct_with_nullable.is_valid());
+ result = writer.write(strct_with_nullable.ToJsonValue());
+ const char* awaited_json2 = "{\"nonNullableEnum\":\"STATIC\",\"nullableEnum\":null}\n";
+ ASSERT_EQ(awaited_json2, result);
+}
+
+TEST_F(GeneratedInterfaceTests, TestStructWithNullableTypedef) {
+ StructWithNullableTypedef swntd;
+ ASSERT_FALSE(swntd.is_initialized());
+ ASSERT_FALSE(swntd.is_valid());
+ swntd.nullableTdResult = R_SUCCESS;
+ ASSERT_TRUE(swntd.is_initialized());
+ ASSERT_TRUE(swntd.is_valid());
+ ASSERT_EQ(R_SUCCESS, swntd.nullableTdResult);
+
+ swntd.nullableTdResult.set_to_null();
+ const char* awaited_json = "{\"nullableTdResult\":null}\n";
+ std::string result = writer.write(swntd.ToJsonValue());
+ ASSERT_EQ(awaited_json, result);
+}
+
+TEST_F(GeneratedInterfaceTests, TestNullingStructWithNullableMapOfNullableInts) {
+ StructWithNullableMapOfNullableInts nmoni;
+ ASSERT_FALSE(nmoni.is_initialized());
+ ASSERT_FALSE(nmoni.is_valid());
+ ASSERT_FALSE(nmoni.nullableMap.is_null());
+ nmoni.nullableMap.set_to_null();
+ ASSERT_TRUE(nmoni.is_initialized());
+ ASSERT_TRUE(nmoni.is_valid());
+ ASSERT_TRUE(nmoni.nullableMap.is_null());
+ const char* awaited_json = "{\"nullableMap\":null}\n";
+ std::string result = writer.write(nmoni.ToJsonValue());
+ ASSERT_EQ(awaited_json, result);
+}
+
+TEST_F(GeneratedInterfaceTests, TestNullingValueInStructWithNullableMapOfNullableInts) {
+ StructWithNullableMapOfNullableInts nmoni;
+ ASSERT_FALSE(nmoni.is_initialized());
+ ASSERT_FALSE(nmoni.is_valid());
+ ASSERT_FALSE(nmoni.nullableMap.is_null());
+ nmoni.nullableMap["Hello"].set_to_null();
+
+ ASSERT_TRUE(nmoni.is_initialized());
+ ASSERT_TRUE(nmoni.is_valid());
+ ASSERT_FALSE(nmoni.nullableMap.is_null());
+ ASSERT_TRUE(nmoni.nullableMap["Hello"].is_null());
+ const char* awaited_json = "{\"nullableMap\":{\"Hello\":null}}\n";
+ std::string result = writer.write(nmoni.ToJsonValue());
+ ASSERT_EQ(awaited_json, result);
+}
+
} // namespace test
</param>
</struct>
+ <struct name="TestStructWithNullableParam">
+ <param name="nullableInt" nullable="true" type="Integer" minavlue="0" maxvalue="42" />
+ </struct>
+
+ <struct name="TestStructWithNullableStructParam">
+ <param name="nullableEnum" nullable="true" type="ImageType"/>
+ <param name="nonNullableEnum" nullable="true" type="ImageType"/>
+ </struct>
+
<enum name="FunctionID" internal_scope="base">
<description>Enumeration linking function names with function IDs in AppLink protocol.</description>
<description>Assumes enumeration starts at value 0.</description>
Test typedef over enum
</description>
</typedef>
+
+ <struct name="StructWithNullableTypedef">
+ <description>
+ Test struct having nullable typedef as a param
+ </description>
+ <param name="nullableTdResult" type="TdResult" nullable="true"/>
+ </struct>
+
+ <struct name="StructWithNullableMapOfNullableInts">
+ <param name="nullableMap" type="Integer" minvalue="0" maxvalue="42" map="true" minsize="1" maxsize="5" nullable="true" null_values_allowed="true" />
+ </struct>
+
<typedef name="TdResultArray" type="TdResult" array="true" minsize="1" maxsize="10">
<description>
Test typedef over array
virtual void GenerateCodeForEnum(const Enum* enm);
virtual void GenerateCodeForArray(const Array* array);
virtual void GenerateCodeForMap(const Map* map);
+ virtual void GenerateCodeForNullable(const NullableType* nullable);
virtual void GenerateCodeForStruct(const Struct* strct);
virtual void GenerateCodeForTypedef(const Typedef* tdef);
+
private:
const Interface* interface_;
const TypePreferences* preferences_;
virtual void GenerateCodeForEnum(const Enum* enm);
virtual void GenerateCodeForArray(const Array* array);
virtual void GenerateCodeForMap(const Map* map);
+ virtual void GenerateCodeForNullable(const NullableType* nullable);
virtual void GenerateCodeForStruct(const Struct* strct);
virtual void GenerateCodeForTypedef(const Typedef* tdef);
private:
- // Wraps type declaration with "Mandatory" or "Optional" templates
- // returns true if type name was wrapped (and thus fully generated).
- bool MaybeWrapWithAvailabilitySpecifier(const Type* type);
-private:
const Interface* interface_;
const TypePreferences* preferences_;
- bool skip_availaiblity_specifier_;
- bool mandatory_;
std::stringstream os_;
};
virtual void GenerateCodeForEnum(const Enum* enm);
virtual void GenerateCodeForArray(const Array* array);
virtual void GenerateCodeForMap(const Map* map);
+ virtual void GenerateCodeForNullable(const NullableType* nullable);
virtual void GenerateCodeForStruct(const Struct* strct);
virtual void GenerateCodeForTypedef(const Typedef* tdef);
private:
virtual void GenerateCodeForArray(const Array* array);
virtual void GenerateCodeForMap(const Map* map);
virtual void GenerateCodeForEnum(const Enum* enm);
+ virtual void GenerateCodeForNullable(const NullableType* nullable);
virtual void GenerateCodeForStruct(const Struct* strct);
virtual void GenerateCodeForTypedef(const Typedef* tdef);
private:
true));
}
+void IncludeTypeHelper::GenerateCodeForNullable(const NullableType* nullable) {
+ nullable->type()->Apply(this);
+}
+
void IncludeTypeHelper::GenerateCodeForStruct(const Struct* strct) {
cpp_file_->Include(CppFile::Header(
GetTypeInterfaceName(strct) + "/types.h",
factory_type_(factory_type) {
Add(MessageFactoryFunction::Parameter(
serialization_type == kJson ? "json" : "reader",
- serialization_type == kJson ? "const Json::Value&": "dbus::MessageReader*"));
+ serialization_type == kJson ? "const Json::Value*": "dbus::MessageReader*"));
Add(MessageFactoryFunction::Parameter("function_id", "FunctionID"));
}
void StructTypeIsInitializedMethod::DefineBody(std::ostream* os) const {
const Struct::FieldsList& fields = strct_->fields();
- *os << "return" << '\n';
- Indent indent1(*os), indent2(*os);
for (size_t i = 0; i != fields.size(); ++i) {
const Struct::Field& field = fields[i];
- strmfmt(*os, "{0}.is_initialized() || ", field.name());
+ strmfmt(*os, "if ({0}.is_initialized()) return true;\n", field.name());
if ((i % 2) == 1) {
*os << endl;
}
}
- *os << "false;" << endl;
+ *os << "return false;\n";
}
} // namespace codegen
void StructTypeIsValidMethod::DefineBody(std::ostream* os) const {
const Struct::FieldsList& fields = strct_->fields();
- *os << "return" << '\n';
- Indent indent1(*os), indent2(*os);
for (size_t i = 0; i != fields.size(); ++i) {
const Struct::Field& field = fields[i];
- strmfmt(*os, "{0}.is_valid() && ", field.name());
- if ((i % 2) == 1) {
- *os << '\n';
- }
+ strmfmt(*os, "if (!{0}.is_valid()) return false;\n", field.name());
}
- *os << func_names::kAdditionalValidation << "();" << endl;
+ *os << "return "<< func_names::kAdditionalValidation << "();\n";
}
StructTypeAdditionalValidationMethod::StructTypeAdditionalValidationMethod(
: CppFunction(strct->name(), func_names::kAdditionalValidation, "bool",
kConst),
strct_(strct) {
-
}
StructTypeAdditionalValidationMethod::~StructTypeAdditionalValidationMethod() {
os_ << map_decl_end;
}
+void TypeNameGenerator::GenerateCodeForNullable(const NullableType* nullable) {
+ // Just generate a type name without special qualifiers
+ nullable->type()->Apply(this);
+}
+
void TypeNameGenerator::GenerateCodeForStruct(const Struct* strct) {
const char* struct_decl_begin = prefer_reference_type_ ? "const " : "";
const char* struct_decl_end = prefer_reference_type_ ? "&" : "";
const Type* type,
Availability availability)
: interface_(interface),
- preferences_(preferences),
- skip_availaiblity_specifier_(availability == kUnspecified),
- mandatory_(availability == kMandatory) {
- if (!skip_availaiblity_specifier_) {
- // Arrays, map and typedefs of arrays and maps doesn't need to be marked as
- // optional or mandatory because their minimal size indicates whether
- // container contents is optional
- skip_availaiblity_specifier_ = TypeProperties(type).is_container();
+ preferences_(preferences) {
+ bool wrap_with_availability = availability != kUnspecified;
+ // Arrays, map and typedefs of arrays and maps doesn't need to be marked as
+ // optional or mandatory because their minimal size indicates whether
+ // container contents is optional
+ if (TypeProperties(type).is_container()) {
+ wrap_with_availability = false;
+ }
+
+ if (wrap_with_availability) {
+ os_ << (availability == kMandatory ? "Mandatory< " : "Optional < ");
}
type->Apply(this);
+ if (wrap_with_availability) {
+ os_ << " >";
+ }
}
RpcTypeNameGenerator::~RpcTypeNameGenerator() {
}
void RpcTypeNameGenerator::GenerateCodeForBoolean(const Boolean* boolean) {
- if (MaybeWrapWithAvailabilitySpecifier(boolean)) {
- } else {
- os_ << "Boolean";
- }
+ os_ << "Boolean";
}
void RpcTypeNameGenerator::GenerateCodeForInteger(const Integer* integer) {
- if (!MaybeWrapWithAvailabilitySpecifier(integer)) {
- const char* int_type = StdIntTypeFromRagne(*preferences_, integer->range());
- strmfmt(os_, "Integer<{0}, {1}, {2}>", int_type, integer->range().min(),
- integer->range().max());
- }
+ const char* int_type = StdIntTypeFromRagne(*preferences_, integer->range());
+ strmfmt(os_, "Integer<{0}, {1}, {2}>", int_type, integer->range().min(),
+ integer->range().max());
}
void RpcTypeNameGenerator::GenerateCodeForFloat(const Float* flt) {
- if (!MaybeWrapWithAvailabilitySpecifier(flt)) {
- const Fraction& minval = flt->range().min_fract();
- const Fraction& maxval = flt->range().max_fract();
- strmfmt(os_, "Float<{0}, {1}", minval.numer(), maxval.numer());
- if (minval.denumer() == 1 && maxval.denumer() == 1) {
- os_ << ">";
- } else {
- strmfmt(os_, ", {0}, {1}>", minval.denumer(), maxval.denumer());
- }
+ const Fraction& minval = flt->range().min_fract();
+ const Fraction& maxval = flt->range().max_fract();
+ strmfmt(os_, "Float<{0}, {1}", minval.numer(), maxval.numer());
+ if (minval.denumer() == 1 && maxval.denumer() == 1) {
+ os_ << ">";
+ } else {
+ strmfmt(os_, ", {0}, {1}>", minval.denumer(), maxval.denumer());
}
}
void RpcTypeNameGenerator::GenerateCodeForString(const String* string) {
- if (!MaybeWrapWithAvailabilitySpecifier(string)) {
- strmfmt(os_, "String<{0}, {1}>", string->length_range().min(),
- string->length_range().max());
- }
+ strmfmt(os_, "String<{0}, {1}>", string->length_range().min(),
+ string->length_range().max());
}
void RpcTypeNameGenerator::GenerateCodeForEnum(const Enum* enm) {
- if (!MaybeWrapWithAvailabilitySpecifier(enm)) {
- strmfmt(os_, "Enum<{0}>", TypeNamespacePrefix(interface_, enm) + enm->name());
- }
+ strmfmt(os_, "Enum<{0}>", TypeNamespacePrefix(interface_, enm) + enm->name());
}
void RpcTypeNameGenerator::GenerateCodeForArray(const Array* array) {
strmfmt(os_, ", {0}, {1} >", map->range().min(), map->range().max());
}
-void RpcTypeNameGenerator::GenerateCodeForStruct(const Struct* strct) {
- if (!MaybeWrapWithAvailabilitySpecifier(strct)) {
- os_ << TypeNamespacePrefix(interface_, strct) + strct->name();
- }
+void RpcTypeNameGenerator::GenerateCodeForNullable(
+ const NullableType* nullable) {
+ os_ << "Nullable < ";
+ nullable->type()->Apply(this);
+ os_ << " >";
}
-void RpcTypeNameGenerator::GenerateCodeForTypedef(const Typedef* tdef) {
- if (!MaybeWrapWithAvailabilitySpecifier(tdef)) {
- os_ << TypeNamespacePrefix(interface_, tdef) + tdef->name();
- }
+void RpcTypeNameGenerator::GenerateCodeForStruct(const Struct* strct) {
+ os_ << TypeNamespacePrefix(interface_, strct) + strct->name();
}
-bool RpcTypeNameGenerator::MaybeWrapWithAvailabilitySpecifier(const Type* type) {
- if (skip_availaiblity_specifier_) {
- return false;
- } else {
- skip_availaiblity_specifier_ = true;
- os_ << (mandatory_ ? "Mandatory< " : "Optional < ");
- type->Apply(this);
- os_ << " >";
- return true;
- }
+void RpcTypeNameGenerator::GenerateCodeForTypedef(const Typedef* tdef) {
+ os_ << TypeNamespacePrefix(interface_, tdef) + tdef->name();
}
TypeProperties::TypeProperties(const Type* type)
container_ = true;
}
+void TypeProperties::GenerateCodeForNullable(const NullableType* nullable) {
+ nullable->type()->Apply(this);
+}
+
void TypeProperties::GenerateCodeForStruct(const Struct* strct) {
}
};
/*
- * Typedef type
+ * Nullable type decorator
*/
+class NullableType : public Type {
+ public:
+ // Methods
+ NullableType(const Type* type);
+ const Type* type() const;
+ bool operator<(const NullableType& that) const;
+ // codegen::Type methods
+ virtual TypeCodeGenerator* Apply(TypeCodeGenerator* code_generator) const;
+ virtual const ConstantsCreator* SupportsConstants() const;
+ private:
+ const Type* type_;
+};
+/*
+ * Typedef type
+ */
class Typedef : public Type {
public:
Typedef(const Interface* interface,
class Array;
class Map;
class Struct;
+class NullableType;
class Typedef;
class ConstantsCreator;
virtual void GenerateCodeForEnum(const Enum* enm);
virtual void GenerateCodeForArray(const Array* array);
virtual void GenerateCodeForMap(const Map* map);
+ virtual void GenerateCodeForNullable(const NullableType* nullable);
virtual void GenerateCodeForStruct(const Struct* strct);
virtual void GenerateCodeForTypedef(const Typedef* tdef);
virtual ~TypeCodeGenerator();
// if |get_array| is true array is created, otherwise map is created
// Returns false and prints to cerr on error
bool GetContainer(const pugi::xml_node& params, const Type** type,
- bool get_array);
- bool GetNonArray(const pugi::xml_node& params, const Type** type);
+ bool get_array, bool container_nullable);
+ bool GetNonArray(const pugi::xml_node& params,
+ const Type** type,
+ bool nullable);
+ bool GetNullable(const Type* original_type, const Type** type);
bool GetEnum(const std::string& name, const Type** type) const;
bool GetStruct(const std::string& name, const Type** type) const;
bool GetTypedef(const std::string& name, const Type** type) const;
bool IsRegisteredEnum(const std::string& enum_name) const;
bool IsRegisteredStruct(const std::string& struct_name) const;
bool IsRegisteredTypedef(const std::string& typedef_name) const;
+ // Returns true if given type is defined in external interface
bool IsExternalType(const std::string& full_type_name) const;
private:
// fields
const ModelFilter* model_filter_;
std::set<Array> arrays_;
std::set<Map> maps_;
+ std::set<NullableType> nullables_;
EnumList enums_;
utils::StdContainerDeleter<EnumList> enums_deleter_;
EnumByName enum_by_name_;
platform_(platform){
}
+NullableType::NullableType(const Type* type)
+ : type_(type) {
+}
+
+const Type* NullableType::type() const {
+ return type_;
+}
+
+bool NullableType::operator<(const NullableType& that) const {
+ // Simple pointer comparison should be enough here
+ if (type_ != that.type_) {
+ return type_ < that.type_;
+ }
+}
+
+TypeCodeGenerator* NullableType::Apply(
+ TypeCodeGenerator* code_generator) const {
+ code_generator->GenerateCodeForNullable(this);
+ return code_generator;
+}
+
+const ConstantsCreator* NullableType::SupportsConstants() const {
+ return type_->SupportsConstants();
+}
+
Typedef::Typedef(const Interface* interface,
const std::string& name,
const Type* type,
return description_;
}
-
const Interface& Typedef::interface() const {
return *interface_;
}
void TypeCodeGenerator::GenerateCodeForMap(const Map* map) {
}
+void TypeCodeGenerator::GenerateCodeForNullable(
+ const NullableType* nullable) {
+}
+
void TypeCodeGenerator::GenerateCodeForStruct(const Struct* strct) {
}
bool TypeRegistry::GetCompositeType(const pugi::xml_node& params, const Type** type) {
bool is_array = params.attribute("array").as_bool(false);
bool is_map = params.attribute("map").as_bool(false);
+ bool is_nullable = params.attribute("nullable").as_bool(false);
if (is_array && is_map) {
strmfmt(std::cerr, "Entity {0} has both map and array attributes specified",
params.attribute("name").as_string(""));
return false;
}
if (is_map) {
- return GetContainer(params, type, false);
+ return GetContainer(params, type, false, is_nullable);
} else if (is_array) {
- return GetContainer(params, type, true);
+ return GetContainer(params, type, true, is_nullable);
} else {
- return GetNonArray(params, type);
+ return GetNonArray(params, type, is_nullable);
}
}
}
bool TypeRegistry::GetContainer(const pugi::xml_node& params, const Type** type,
- bool get_array) {
+ bool get_array, bool container_nullable) {
const Type* element_type = NULL;
- if (GetNonArray(params, &element_type)) {
+ bool null_values_allowed =
+ params.attribute("null_values_allowed").as_bool(false);
+ if (GetNonArray(params, &element_type, null_values_allowed)) {
assert(element_type);
std::string minsize_str = params.attribute("minsize").as_string("0");
std::string maxsize_str = params.attribute("maxsize").as_string("0");
*type = &*maps_.insert(Map(element_type, Map::Range(minsize, maxsize)))
.first;
}
- return true;
+ if (container_nullable) {
+ return GetNullable(*type, type);
+ } else {
+ return true;
+ }
} else {
std::cerr << "Incorrect array size range: " << minsize_str << ", "
<< maxsize_str << std::endl;
}
bool TypeRegistry::GetNonArray(const pugi::xml_node& params,
- const Type** type) {
+ const Type** type, bool nullable) {
+ bool type_found = false;
pugi::xml_attribute type_name = params.attribute("type");
if (type_name) {
std::string type_name_str = type_name.value();
BuiltinTypeRegistry::BuiltInType builtin_type = builtin_type_registry_
->BuiltInTypeByName(type_name_str);
if (BuiltinTypeRegistry::kNotABuiltInType != builtin_type) {
- return builtin_type_registry_->GetType(builtin_type, params, type);
+ type_found = builtin_type_registry_->GetType(builtin_type, params, type);
} else if (IsExternalType(type_name_str)) {
- return GetExternalType(type_name_str, type);
+ type_found = GetExternalType(type_name_str, type);
} else if (*type = GetType(type_name_str)) {
- return true;
+ type_found = true;
} else {
std::cerr << "Unregistered type: " << type_name_str << std::endl;
- return false;
+ type_found = false;
}
} else {
std::cerr << "Absent type name" << std::endl;
- return false;
+ type_found = false;
}
+
+ if (type_found && nullable) {
+ type_found = GetNullable(*type, type);
+ }
+ return type_found;
+}
+
+bool TypeRegistry::GetNullable(const Type* original_type,
+ const Type** type) {
+ std::set<NullableType>::const_iterator inserted =
+ nullables_.insert(NullableType(original_type)).first;
+ *type = &*inserted;
+ return true;
}
bool TypeRegistry::GetEnum(const std::string& name, const Type** type) const {