diff options
Diffstat (limited to 'tools/InterfaceGenerator')
34 files changed, 7850 insertions, 0 deletions
diff --git a/tools/InterfaceGenerator/Generator.py b/tools/InterfaceGenerator/Generator.py new file mode 100755 index 000000000..5b5894bc0 --- /dev/null +++ b/tools/InterfaceGenerator/Generator.py @@ -0,0 +1,116 @@ +""" +Generator application that generates c++ interfaces code from xml description + +usage: Generator.py [-h] --parser-type {sdlrpcv2} + source-xml namespace output-dir + +SmartSchema interface generator + +positional arguments: + source-xml + namespace + output-dir + +optional arguments: + -h, --help show this help message and exit + --parser-type {sdlrpcv2} +""" + +import os.path +import argparse +import errno +import sys + +import generator.parsers.SDLRPCV1 +import generator.parsers.SDLRPCV2 +import generator.parsers.JSONRPC +import generator.generators.SmartFactorySDLRPC +import generator.generators.SmartFactoryJSONRPC + +from generator.parsers.RPCBase import ParseError +from generator.generators.SmartFactoryBase import GenerateError + +SUPPORTED_FORMATS = { + "sdlrpcv1": (generator.parsers.SDLRPCV1.Parser, + generator.generators.SmartFactorySDLRPC.CodeGenerator), + "sdlrpcv2": (generator.parsers.SDLRPCV2.Parser, + generator.generators.SmartFactorySDLRPC.CodeGenerator), + "jsonrpc": (generator.parsers.JSONRPC.Parser, + generator.generators.SmartFactoryJSONRPC.CodeGenerator) +} + + +def _create_parser(): + """Create parser for parsing command-line arguments. + + Returns an instance of argparse.ArgumentParser + + """ + + parser = argparse.ArgumentParser( + description="SmartSchema interface generator" + ) + parser.add_argument("source-xml") + parser.add_argument("namespace") + parser.add_argument("output-dir") + parser.add_argument("--parser-type", + choices=SUPPORTED_FORMATS.keys(), + required=True) + return parser + + +def _handle_fatal_error(error): + """Handle fatal error during parsing or code generation. + + Keyword arguments: + error -- base exception to handle. + + """ + + print(error.message) + print + sys.exit(errno.EINVAL) + + +def main(): + """Main function of the generator that does actual work.""" + + args = vars(_create_parser().parse_args()) + + src_xml = args["source-xml"] + src_xml_name = os.path.splitext(os.path.basename(src_xml))[0] + namespace = args["namespace"] + output_dir = args["output-dir"] + parser_type = args["parser_type"] + + print(""" +Generating interface source code with following parameters: + Source xml : {0} + Namespace : {1} + Output directory: {2} + Parser type : {3} +""".format(src_xml, namespace, output_dir, parser_type)) + + # Select required parser and code generator + parser = SUPPORTED_FORMATS[parser_type][0]() + code_generator = SUPPORTED_FORMATS[parser_type][1]() + + # Convert incoming xml to internal model + try: + interface = parser.parse(args["source-xml"]) + except ParseError as error: + _handle_fatal_error(error) + + # Generate SmartFactory source code from internal model + try: + code_generator.generate(interface, + src_xml_name, + namespace, + output_dir) + except GenerateError as error: + _handle_fatal_error(error) + + print("Done.") + +if __name__ == '__main__': + main() diff --git a/tools/InterfaceGenerator/generator/Model.py b/tools/InterfaceGenerator/generator/Model.py new file mode 100755 index 000000000..ee458d934 --- /dev/null +++ b/tools/InterfaceGenerator/generator/Model.py @@ -0,0 +1,326 @@ +"""Interface model. + +Interface model is represented by Interface class. +Parser must provide an instance of this model as a result of parsing +interface definition file. +Generator must take an instance of this model as input for generating +output files. +""" + +# In this module there are classes that are used as data container +# pylint: disable=R0903 + +import collections + + +class Boolean(object): + + """Boolean type. + + default_value -- default value + + """ + + def __init__(self, default_value=None): + self.default_value = default_value + + +class Integer(object): + + """Integer type. + + Instance variables: + min_value -- minimum allowed value + max_value -- maximum allowed value + default_value -- default value + + """ + + def __init__(self, min_value=None, max_value=None, default_value=None): + self.min_value = min_value + self.max_value = max_value + self.default_value = default_value + + +class Double(object): + + """Floating-point type. + + Instance variables: + min_value -- minimum allowed value + max_value -- maximum allowed value + default_value -- default value + + """ + + def __init__(self, min_value=None, max_value=None, default_value=None): + self.min_value = min_value + self.max_value = max_value + self.default_value = default_value + +class String(object): + + """String type. + + Instance variables: + min_length -- minimum string length + max_length -- maximum string length + default_value -- default value + + """ + + def __init__(self, min_length=None, max_length=None, default_value=None): + self.min_length = min_length + self.max_length = max_length + self.default_value = default_value + + +class Array(object): + + """Array type. + + Instance variables: + min_size -- minimum array size + max_size -- maximum array size + element_type -- type of array element + + """ + + def __init__(self, min_size=None, max_size=None, element_type=None): + self.min_size = min_size + self.max_size = max_size + self.element_type = element_type + + +class Issue(object): + + """Issue. + + Instance variables: + creator -- issue creator + value -- issue text + + """ + + def __init__(self, creator=None, value=None): + self.creator = creator + self.value = value + + +class InterfaceItemBase(object): + + """Base class for interface item. + + Instance variables: + name -- item name + description -- list of string description elements + design_description -- list of string design description elements + issues -- list of issues + todos -- list of string todo elements + platform -- optional platform (string or None) + default_value -- default value + scope -- optional scope: internal, partner or none (none by defaul, means public) + + """ + + def __init__(self, name, description=None, design_description=None, + issues=None, todos=None, platform=None, default_value=None, scope=None): + self.name = name + self.description = description if description is not None else [] + self.design_description = \ + design_description if design_description is not None else [] + self.issues = issues if issues is not None else [] + self.todos = todos if todos is not None else [] + self.platform = platform + self.default_value = default_value + self.scope = scope + + +class EnumElement(InterfaceItemBase): + + """Element of enumeration. + + Instance variables: + internal_name -- internal name of an element must be used by a + generator if it is provided (not None) + value -- optional element value + + """ + + def __init__(self, name, description=None, design_description=None, + issues=None, todos=None, platform=None, internal_name=None, + value=None): + super(EnumElement, self).__init__( + name, description=description, + design_description=design_description, issues=issues, todos=todos, + platform=platform) + self.internal_name = internal_name + self.value = value + + @property + def primary_name(self): + """Primary name of the EnumElement. + + Return the 'internal_name' property if presented or 'name' property + otherwise. + + """ + return self.name if self.internal_name is None else self.internal_name + + +class Enum(InterfaceItemBase): + + """Enumeration. + + Instance variables: + internal_scope -- optional internal scope + elements -- enumeration elements + + """ + + def __init__(self, name, description=None, design_description=None, + issues=None, todos=None, platform=None, internal_scope=None, + elements=None, scope=None): + super(Enum, self).__init__( + name, description=description, + design_description=design_description, issues=issues, todos=todos, + platform=platform, scope=scope) + + self.internal_scope = internal_scope + self.elements = \ + elements if elements is not None else collections.OrderedDict() + + +class EnumSubset(InterfaceItemBase): + + """Enumeration subset. + + Instance variables: + enum -- enumeration + allowed_elements -- dictionary of elements of enumeration + which are allowed in this subset + + """ + + def __init__(self, name, enum, description=None, design_description=None, + issues=None, todos=None, platform=None, + allowed_elements=None): + super(EnumSubset, self).__init__( + name, description=description, + design_description=design_description, issues=issues, todos=todos, + platform=platform) + + self.enum = enum + self.allowed_elements = \ + allowed_elements if allowed_elements is not None else {} + + +class Param(InterfaceItemBase): + + """Parameter. + + Instance variables: + is_mandatory -- boolean value indicating whether + this parameter is mandatory + param_type -- parameter type + default_value -- default value + + """ + + def __init__(self, name, param_type, description=None, + design_description=None, issues=None, todos=None, + platform=None, is_mandatory=True, default_value=None, scope=None): + super(Param, self).__init__( + name, description=description, + design_description=design_description, issues=issues, todos=todos, + platform=platform, default_value=default_value, scope=scope) + + self.is_mandatory = is_mandatory + self.param_type = param_type + self.default_value = default_value + + +class FunctionParam(Param): + + """Function parameter. + + Instance variables: + default_value -- optional default value of this parameter + + """ + + def __init__(self, name, param_type, description=None, + design_description=None, issues=None, todos=None, + platform=None, is_mandatory=True, default_value=None, scope=None): + super(FunctionParam, self).__init__( + name, param_type=param_type, description=description, + design_description=design_description, issues=issues, todos=todos, + platform=platform, is_mandatory=is_mandatory, default_value=default_value, scope=scope) + + self.default_value = default_value + + +class Struct(InterfaceItemBase): + + """Structure. + + Instance variables: + members -- dictionary of structure members (instances of Param class) + + """ + + def __init__(self, name, description=None, design_description=None, + issues=None, todos=None, platform=None, members=None, scope=None): + super(Struct, self).__init__( + name, description=description, + design_description=design_description, issues=issues, todos=todos, + platform=platform, scope=scope) + + self.members = \ + members if members is not None else collections.OrderedDict() + + +class Function(InterfaceItemBase): + + """Function. + + Instance variables: + function_id -- function identifier (EnumElement from Enum "FunctionID") + message_type -- message type (EnumElement from Enum "messageType") + params -- function parameters + + """ + + def __init__(self, name, function_id, message_type, description=None, + design_description=None, issues=None, todos=None, + platform=None, params=None, scope=None): + super(Function, self).__init__( + name, description=description, + design_description=design_description, issues=issues, todos=todos, + platform=platform, scope=scope) + + self.function_id = function_id + self.message_type = message_type + self.params = \ + params if params is not None else collections.OrderedDict() + + +class Interface(object): + + """Interface. + + Instance variables: + enums -- dictionary of enumerations + structs -- dictionary of structures + functions -- dictionary of functions + params -- dictionary of interface parameters (name, version, etc.) + + """ + + def __init__(self, enums=None, structs=None, functions=None, params=None): + self.enums = enums if enums is not None else collections.OrderedDict() + self.structs = \ + structs if structs is not None else collections.OrderedDict() + self.functions = \ + functions if functions is not None else collections.OrderedDict() + self.params = params if params is not None else {} diff --git a/tools/InterfaceGenerator/generator/__init__.py b/tools/InterfaceGenerator/generator/__init__.py new file mode 100755 index 000000000..380e81d9a --- /dev/null +++ b/tools/InterfaceGenerator/generator/__init__.py @@ -0,0 +1,2 @@ +"""Top-level application package. +""" diff --git a/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py new file mode 100755 index 000000000..2b372021c --- /dev/null +++ b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py @@ -0,0 +1,1684 @@ +"""SmartFactory code generator base. + +Base of code generator for SmartFactory that provides SmartSchema object in +accordance with given internal model. + +""" +# pylint: disable=W0402 +# pylint: disable=C0302 +import codecs +import collections +import os +import string +import uuid + +from generator import Model + + +class GenerateError(Exception): + + """Generate error. + + This exception is raised when SmartFactory generator is unable to create + output from given model. + + """ + + pass + + +class CodeGenerator(object): + + """Base SmartFactory generator. + + This class provides service which allows to generate pair of *.h and + *.cc files by given interface model. + + """ + + def __init__(self): + """Construct new object.""" + + self._generated_structs = [] + self._structs_add_code = u"" + + def generate(self, interface, filename, namespace, destination_dir): + """Generate SmartFactory source files. + + Generates source code files at destination directory in + accordance with given model in specified namespace. + + Keyword arguments: + interface -- model of the interface to generate source code for. + filename -- name of initial XML file. + namespace -- name of destination namespace. + destination_dir -- directory to create source files. + + """ + + namespace = unicode(namespace) + + if interface is None: + raise GenerateError("Given interface is None.") + + self._generated_structs = [] + self._structs_add_code = "" + + if "messageType" in interface.enums: + interface.enums["messageType"] = self._preprocess_message_type( + interface.enums["messageType"]) + + if not os.path.exists(destination_dir): + os.makedirs(destination_dir) + + namespace_open = u"" + namespace_close = u"" + + if namespace: + parts = namespace.split(u"::") + for part in parts: + namespace_open = u"".join( + [namespace_open, + self._namespace_open_template.substitute(name=part)]) + namespace_close = u"".join( + [namespace_close, + "}} // {0}\n".format(part)]) + + class_name = unicode(os.path.splitext(filename)[0]) + guard = u"__CSMARTFACTORY_{0}_{1}_H__".format( + class_name.upper(), + unicode(uuid.uuid1().hex.capitalize())) + header_file_name = u"".join("{0}.h".format(class_name)) + + with codecs.open(os.path.join(destination_dir, header_file_name), + encoding="utf-8", + mode="w") as f_h: + f_h.write(self._h_file_tempalte.substitute( + class_name=class_name, + guard=guard, + namespace_open=namespace_open, + enums_content=self._gen_enums( + interface.enums.values(), + interface.structs.values()), + namespace_close=namespace_close)) + + self._gen_struct_schema_items(interface.structs.values()) + + function_id_items = u"" + if "FunctionID" in interface.enums: + function_id = interface.enums["FunctionID"] + function_id_items = u"\n".join( + [self._impl_code_loc_decl_enum_insert_template.substitute( + var_name="function_id_items", + enum=function_id.name, + value=x.primary_name) + for x in function_id.elements.values()]) + + message_type_items = u"" + if "messageType" in interface.enums: + message_type = interface.enums["messageType"] + message_type_items = u"\n".join( + [self._impl_code_loc_decl_enum_insert_template.substitute( + var_name="message_type_items", + enum=message_type.name, + value=x.primary_name) + for x in message_type.elements.values()]) + + header_file_name = "".join("{0}_schema.h".format(class_name)) + guard = u"__CSMARTFACTORY_{0}_{1}_HPP__".format( + class_name.upper(), + unicode(uuid.uuid1().hex.capitalize())) + with codecs.open(os.path.join(destination_dir, header_file_name), + encoding="utf-8", + mode="w") as f_h: + f_h.write(self._hpp_schema_file_tempalte.substitute( + class_name=class_name, + guard=guard, + header_file_name=unicode("".join("{0}.h".format(class_name))), + namespace_open=namespace_open, + class_content=self._gen_h_class( + class_name, + interface.params, + interface.functions.values(), + interface.structs.values()), + namespace_close=namespace_close)) + + with codecs.open(os.path.join(destination_dir, + u"".join("{0}_schema.cc".format(class_name))), + encoding="utf-8", mode="w") as f_s: + f_s.write(self._cc_file_template.substitute( + header_file_name=unicode(header_file_name), + namespace=namespace, + class_name=class_name, + function_id_items=self._indent_code(function_id_items, 1), + message_type_items=self._indent_code(message_type_items, 1), + struct_schema_items=self._structs_add_code, + pre_function_schemas=self._gen_pre_function_schemas( + interface.functions.values()), + function_schemas=self._gen_function_schemas( + interface.functions.values()), + init_function_impls=self._gen_function_impls( + interface.functions.values(), + namespace, + class_name), + init_structs_impls=self._gen_sturct_impls( + interface.structs.values(), + namespace, + class_name), + enum_string_coversions=self._gen_enum_to_str_converters( + interface.enums.values(), + namespace))) + + def _preprocess_message_type(self, message_type): + """Preprocess message_type enum. + + In base class this method is unimplemented and will cause runtime + exception. This method must be overridden by the subclasses to + return message_type enum after preprocessing. + + Keyword arguments: + message_type -- message_type enum to preprocess. + + """ + + raise GenerateError("Unexpected call to the unimplemented function.") + + def _gen_enum_to_str_converters(self, enums, namespace): + """Generate enum to string converters. + + Generates part of source code with specific enum to string value + converting functions. + + Keyword arguments: + enums -- list of enums to generate string converting functions. + namespace -- namespace to address enums. + + Returns: + String value with enum to string converting functions. + + """ + + if enums is None: + raise GenerateError("Enums is None") + + return u"\n".join([self._enum_to_str_converter_template.substitute( + namespace=namespace, + enum=x.name, + cstringvalues=self._indent_code(self._gen_enum_cstring_values(x), 2), + enumvalues=self._indent_code(self._gen_enum_enum_values(x, namespace), 2)) + for x in enums]) + + def _gen_enum_cstring_values(self, enum): + """Generate list of c-string representing enum values. + Keyword arguments: + enum -- enum to generate string mapping. + Returns: + String value with c-string values. + """ + return u",\n".join(['"' + x.name + '"' for x in enum.elements.values()]) + + def _gen_enum_enum_values(self, enum, namespace): + """Generate list of all enum values. + Keyword arguments: + enum -- enum to generate the list. + namespace -- namespace to address enum. + Returns: + String value with enum values. + """ + return u",\n".join([namespace + "::" + enum.name + "::" + x.primary_name for x in enum.elements.values()]) + + def _gen_h_class(self, class_name, params, functions, structs): + """Generate source code of class for header file. + + Generates source code of class that should be used in the + header file. + + Keyword arguments: + class_name -- name of the class to generate. + params -- class parameters. + functions -- list of functions to generate methods for. + structs -- structures to generate methods for. + + Returns: + String with complete *.h file source code. + + """ + + return self._class_h_template.substitute( + comment=self._gen_class_comment(class_name, params), + class_name=class_name, + init_function_decls=self._gen_function_decls(functions), + init_struct_decls=self._gen_structs_decls(structs)) + + def _gen_structs_decls(self, structs): + """Generate method prototypes for structs for header file. + + Generates method prototypes for structs that should be used in the + header file. + + Keyword arguments: + structs -- list of structs to generate methods for. + + Returns: + String with structs init methods declarations source code. + + """ + + if structs is None: + raise GenerateError("Structs is None") + + return u"\n".join([self._indent_code( + self._gen_struct_decl(x), 1) for x in structs]) + + def _gen_struct_decl(self, struct): + """Generate method prototype for struct for header file. + + Generates method prototype for struct that should be used in the + header file. + + Keyword arguments: + struct -- struct to generate method for. + + Returns: + String with struct inin method declaration source code. + + """ + + return self._struct_decl_template.substitute( + comment=self._gen_comment(struct), + struct_name=struct.name) + + def _gen_function_decls(self, functions): + """Generate method prototypes for functions for header file. + + Generates method prototypes for functions that should be used in the + header file. + + Keyword arguments: + functions -- list of functions to generate methods for. + + Returns: + String with function init methods declarations source code. + + """ + + if functions is None: + raise GenerateError("Functions is None") + + return u"\n".join([self._indent_code( + self._gen_function_decl(x), 1) for x in functions]) + + def _gen_function_decl(self, function): + """Generate method prototype for function for header file. + + Generates method prototype for function that should be used in the + header file. + + Keyword arguments: + function -- function to generate method for. + + Returns: + String with function declaration source code. + + """ + + return self._function_decl_template.substitute( + comment=self._gen_comment(function), + function_id=function.function_id.primary_name, + message_type=function.message_type.primary_name) + + def _gen_struct_schema_items(self, structs): + """Generate struct schema items initialization code for source file. + + Generates struct schema items initialization code that should be used + in the source file. + + Keyword arguments: + structs -- list of structs to generate code for. + + Returns: + String with struct schema items initialization source code. + + """ + + if structs is None: + raise GenerateError("Structs is None") + + for struct in structs: + self._process_struct(struct) + + def _process_struct(self, struct): + """Process struct recursively to provide correct initialization. + + This method create source code for cc file that guarantees that + structures are initialized in right order (to resolve all + dependencies). + + Keyword arguments: + struct -- struct to process. + + """ + + if struct.name in self._generated_structs: + return + + for member in struct.members.values(): + self._process_struct_member(member) + + self._structs_add_code = u"\n".join( + [self._structs_add_code, self._indent_code( + self._gen_struct_schema_item(struct), 1)]) + self._generated_structs.append(struct.name) + + def _process_struct_member(self, member): + """Process struct member recursively to provide correct initialization. + + This method ensures that nested structs (if any) are generated. + + Keyword arguments: + member -- struct member to process. + + """ + + if type(member.param_type) is Model.Struct: + self._ensure_struct_generated(member.param_type) + + def _ensure_struct_generated(self, struct): + """Ensure that struct is already generated. + + If struct is already created this method returns otherwise it + runs generation of struct to resolve dependency. + + Keyword arguments: + struct -- struct to ensure existence. + + """ + + if struct.name in self._generated_structs: + return + + self._process_struct(struct) + + def _gen_struct_schema_item(self, struct): + """Generate struct schema item initialization code for source file. + + Generates struct schema item initialization code that should be used + in the source file. + + Keyword arguments: + struct -- struct to generate code for. + + Returns: + String with struct schema item initialization source code. + + """ + + return self._struct_schema_item_template.substitute(name=struct.name) + + def _gen_pre_function_schemas(self, functions): + """Generate specific code that goes before schema initialization. + + In base class this function is unimplemented and it will raise an + runtime exception. Subclasses must implement this function in order + to provide format-specific code that goes before schema initialization. + + Keyword arguments: + functions -- list of functions to generate code for. + + """ + + raise GenerateError("Unexpected call to the unimplemented function.") + + def _gen_function_schemas(self, functions): + """Generate functions initialization code for source file. + + Generates functions schema initialization code that should be used + in the source file. + + Keyword arguments: + functions -- list of functions to generate code for. + + Returns: + String with functions schema initialization source code. + + """ + + if functions is None: + raise GenerateError("Functions is None") + + return u"".join([self._indent_code( + self._gen_function_schema(x), 1) + for x in functions]) + + def _gen_function_schema(self, function): + """Generate function initialization code for source file. + + Generates function schema initialization code that should be used + in the source file. + + Keyword arguments: + function -- function to generate method for. + + Returns: + String with function schema initialization source code. + + """ + + return self._function_schema_template.substitute( + function_id=function.function_id.primary_name, + message_type=function.message_type.primary_name) + + def _gen_sturct_impls(self, structs, namespace, class_name): + """Generate structs implementation for source file. + + Generates implementation code of methods that provide schema items for + structs. This code should be used in the source file. + + Keyword arguments: + structs -- list of structs to generate methods for. + namespace -- name of destination namespace. + class_name -- name of the parent class. + + Returns: + String with structs implementation source code. + + """ + + if structs is None: + raise GenerateError("Structs is None") + + return u"\n".join([self._gen_struct_impl( + x, namespace, class_name) for x in structs]) + + def _gen_struct_impl(self, struct, namespace, class_name): + """Generate struct implementation for source file. + + Generates implementation code of method that provide schema item for + struct. This code should be used in the source file. + + Keyword arguments: + struct -- struct to generate method for. + namespace -- name of destination namespace. + class_name -- name of the parent class. + + Returns: + String with structs implementation source code. + + """ + + processed_enums = [] + return self._struct_impl_template.substitute( + namespace=namespace, + class_name=class_name, + struct_name=struct.name, + code=self._indent_code( + self._struct_impl_code_tempate.substitute( + schema_loc_decl=self._gen_schema_loc_decls( + struct.members.values(), processed_enums), + schema_items_decl=self._gen_schema_items_decls( + struct.members.values()), + schema_item_fill=self._gen_schema_items_fill( + struct.members.values())), + 1)) + + def _gen_schema_loc_decls(self, members, processed_enums): + """Generate local declarations of variables for schema. + + This method generates full set of required variables for + enums and enum subsets. + + Keyword arguments: + members -- struct/function members/params. + processed_enums -- list of already processed enums. + + Returns: + String with local declarations source code. + + """ + + result = u"" + for member in members: + if type(member.param_type) is Model.Enum and \ + member.param_type.name not in processed_enums: + local_var = self._gen_schema_loc_emum_var_name( + member.param_type) + result = u"\n".join( + [u"".join( + [result, self._impl_code_loc_decl_enum_template. + substitute( + type=member.param_type.name, + var_name=local_var)]), + u"\n".join( + [self._impl_code_loc_decl_enum_insert_template. + substitute( + var_name=local_var, + enum=member.param_type.name, + value=x.primary_name) + for x in member.param_type.elements.values()])]) + processed_enums.append(member.param_type.name) + result = u"".join([result, u"\n\n"]) if result else u"" + elif type(member.param_type) is Model.EnumSubset: + local_var = self._gen_schema_loc_emum_s_var_name(member.name) + result = u"\n".join( + [u"".join( + [result, self._impl_code_loc_decl_enum_template. + substitute( + type=member.param_type.enum.name, + var_name=local_var)]), + u"\n".join( + [self._impl_code_loc_decl_enum_insert_template. + substitute( + var_name=local_var, + enum=member.param_type.enum.name, + value=x.primary_name) + for x in member.param_type. + allowed_elements.values()])]) + result = u"".join([result, u"\n\n"]) if result else u"" + elif type(member.param_type) is Model.Array: + result = u"".join( + [result, self._gen_schema_loc_decls( + [Model.Param(name=member.param_type.element_type.name + if type(member.param_type.element_type) is + Model.EnumSubset else "", + param_type=member.param_type.element_type)], + processed_enums)]) + + return result + + def _gen_schema_items_decls(self, members): + """Generate schema items declarations. + + Generates declaration and initialization of schema items + which is uses as struct members/function parameters. + + Keyword arguments: + members -- list of struct members/function parameters. + + Returns: + String with schema items declaration source code. + + """ + + result = u"\n\n".join( + [self._gen_schema_item_decl(x) for x in members]) + + return u"".join([result, u"\n\n"]) if result else u"" + + def _gen_schema_item_decl(self, member): + """Generate schema item declaration. + + Generates declaration and initialization of schema item + which is uses as struct member/function parameter. + + Keyword arguments: + member -- struct member/function parameter. + + Returns: + String with schema item declaration source code. + + """ + + return self._impl_code_item_decl_temlate.substitute( + comment=self._gen_comment(member, False), + var_name=self._gen_schema_item_var_name(member), + item_decl=self._gen_schema_item_decl_code( + member.param_type, + member.name, + member.default_value)) + + def _gen_schema_item_decl_code(self, param, member_name, default_value): + + """Generate schema item initialization code. + + Generates type-specific code that initializes schema item + + Keyword arguments: + param -- value of parameter type. + mamber_name -- name of struct member/function parameter. + default_value -- default value (used only for function parameters). + + Returns: + String with schema item initialization source code. + + """ + code = u"" + if type(param) is Model.Boolean: + code = self._impl_code_bool_item_template.substitute( + params=self._gen_schema_item_param_values( + [[u"bool", None if param.default_value is None + else u"true" if param.default_value is True else u"false"]])) + elif type(param) is Model.Integer: + if param.max_value < 2 ** 31: + code = self._impl_code_integer_item_template.substitute( + type=u"int32_t", + params=self._gen_schema_item_param_values( + [[u"int32_t", param.min_value], + [u"int32_t", param.max_value], + [u"int32_t", param.default_value]])) + elif param.max_value < 2 ** 63: + code = self._impl_code_integer_item_template.substitute( + type=u"int64_t", + params=self._gen_schema_item_param_values( + [[u"int64_t", param.min_value], + [u"int64_t", str(param.max_value) + u"LL"], + [u"int64_t", param.default_value]])) + else: + raise GenerateError("Parameter value too large: " + str(param.max_value)) + elif type(param) is Model.Double: + code = self._impl_code_integer_item_template.substitute( + type=u"double", + params=self._gen_schema_item_param_values( + [[u"double", param.min_value], + [u"double", param.max_value], + [u"double", param.default_value]])) + elif type(param) is Model.String: + code = self._impl_code_string_item_template.substitute( + params=self._gen_schema_item_param_values( + [[u"size_t", param.min_length], + [u"size_t", param.max_length], + [u"std::string", u"".join( + [u'"', param.default_value, u'"']) if param.default_value + is not None else u""]])) + elif type(param) is Model.Array: + code = self._impl_code_array_item_template.substitute( + params=u"".join( + [u"".join( + [self._gen_schema_item_decl_code( + param.element_type, + param.element_type.name if type(param.element_type) + is Model.EnumSubset else u"", + None), + u", "]), + self._gen_schema_item_param_values( + [[u"size_t", param.min_size], + [u"size_t", param.max_size]])])) + elif type(param) is Model.Struct: + code = self._impl_code_struct_item_template.substitute( + name=param.name) + elif type(param) is Model.Enum: + code = self._impl_code_enum_item_template.substitute( + type=param.name, + params=u"".join( + [self._gen_schema_loc_emum_var_name(param), + u", ", + self._gen_schema_item_param_values( + [[u"".join([param.name, u"::eType"]), + u"".join([param.name, u"::", + default_value.primary_name]) if + default_value is not None else None]])])) + elif type(param) is Model.EnumSubset: + code = self._impl_code_enum_item_template.substitute( + type=param.enum.name, + params=u"".join( + [self._gen_schema_loc_emum_s_var_name(member_name), + u", ", + self._gen_schema_item_param_values( + [[u"".join([param.enum.name, u"::eType"]), + default_value.primary_name if default_value + is not None else None]])])) + else: + raise GenerateError("Unexpected type of parameter: " + + str(type(param))) + return code + + def _gen_schema_item_param_values(self, params): + """Generate values of schema item initialization parameters. + + Generates part of code which is used as schema item initialization + parameters. + + Keyword arguments: + params -- list of tuples which maps parameter type to parameter value. + + Returns: + String with schema item initialization parameters source code. + + """ + + result = u"" + for param in params: + value = self._impl_code_item_param_value_template.substitute( + type=param[0], + value=str(param[1] if param[1] is not None else "")) + result = u"".join([result, u"".join( + [u", ", value]) + if result else value]) + + return result + + def _gen_schema_items_fill(self, members): + """Generate schema items fill code. + + Generates source code that fills new schema with items. + + Keyword arguments: + members -- list of struct members/function parameters to process. + + Returns: + String with function schema items fill code. + + """ + + result = u"\n".join( + [self._gen_schema_item_fill(x) for x in members]) + + return u"".join([result, u"\n\n"]) if result else u"" + + def _gen_schema_params_fill(self, message_type_name): + """Generate schema params fill code. + + In the base class this method is not implemented (raises exception). + This method must be implemented by the subclasses to specify format + specific PARAMS for the function. + + Keyword arguments: + message_type_name -- Name of the messageType enum element. + + Returns: + String with function schema params fill code. + + """ + + raise GenerateError("Unexpected call to the unimplemented function.") + + def _gen_schema_item_fill(self, member): + """Generate schema item fill code. + + Generates source code that fills new schema with item. + + Keyword arguments: + member -- struct member/function parameter to process. + + Returns: + String with schema item fill code. + + """ + + return self._impl_code_item_fill_template.substitute( + name=member.name, + var_name=self._gen_schema_item_var_name(member), + is_mandatory=u"true" if member.is_mandatory is True else u"false") + + @staticmethod + def _gen_schema_item_var_name(member): + """Generate schema item variable name. + + Generates variable name for local declarations. + + Keyword arguments: + member -- struct member/function parameter to process. + + Returns: + String with schema item variable name. + + """ + + return u"".join([member.name, u"_SchemaItem"]) + + @staticmethod + def _gen_schema_loc_emum_var_name(param_type): + """Generate name of enum local variable. + + Generates name of local variable that defines allowed enum elements. + + Keyword arguments: + param_type -- parameter type object. + + Returns: + String with name of enum local variable. + + """ + + return u"".join([param_type.name, u"_all_enum_values"]) + + @staticmethod + def _gen_schema_loc_emum_s_var_name(member_name): + """Generate name of enum subset local variable. + + Generates name of local variable that defines allowed enum + subset elements. + + Keyword arguments: + param_type -- parameter type object. + + Returns: + String with name of enum subset local variable. + + """ + + return u"".join([member_name, "_allowed_enum_subset_values"]) + + def _gen_function_impls(self, functions, namespace, class_name): + """Generate functions implementation for source file. + + Generates implementation code of methods that provide schema for + functions. This code should be used in the source file. + + Keyword arguments: + functions -- list of functions to generate methods for. + namespace -- name of destination namespace. + class_name -- name of the parent class. + + Returns: + String with functions implementation source code. + + """ + + if functions is None: + raise GenerateError("Functions is None") + + return u"\n".join([self._gen_function_impl( + x, namespace, class_name) for x in functions]) + + def _gen_function_impl(self, function, namespace, class_name): + """Generate function implementation for source file. + + Generates implementation code of method that provides schema for + function. This code should be used in the source file. + + Keyword arguments: + function -- function to generate method for. + namespace -- name of destination namespace. + class_name -- name of the parent class. + + Returns: + String with function implementation source code. + + """ + + processed_enums = [] + return self._function_impl_template.substitute( + namespace=namespace, + class_name=class_name, + function_id=function.function_id.primary_name, + message_type=function.message_type.primary_name, + code=self._indent_code( + self._function_impl_code_tempate.substitute( + schema_loc_decl=self._gen_schema_loc_decls( + function.params.values(), processed_enums), + schema_items_decl=self._gen_schema_items_decls( + function.params.values()), + schema_item_fill=self._gen_schema_items_fill( + function.params.values()), + schema_params_fill=self._gen_schema_params_fill( + function.message_type.name)), + 1)) + + def _gen_enums(self, enums, structs): + """Generate enums for header file. + + Generates declaration of enumerations for the header file. + + Keyword arguments: + enums -- list of enums to generate. + + Returns: + String with enums declaration source code. + + """ + + if enums is None: + raise GenerateError("Enums is None") + + if structs is None: + raise GenerateError("Structs is None") + + if structs: + struct_id_enum_elements = collections.OrderedDict() + for struct in structs: + struct_id_enum_elements[struct.name] = Model.EnumElement( + name=struct.name) + return u"\n".join( + [self._gen_enum( + Model.Enum(name="StructIdentifiers", + elements=struct_id_enum_elements)), + u"\n".join([self._gen_enum(x) for x in enums])]) + + return u"\n".join([self._gen_enum(x) for x in enums]) + + def _gen_enum(self, enum): + """Generate enum for header file. + + Generates declaration of enumeration for the header file. + + Keyword arguments: + enum -- enum to generate. + + Returns: + String with enum declaration source code. + + """ + + enum_elements = enum.elements.values() + enum_elements.insert(0, Model.EnumElement( + name=u"INVALID_ENUM", + description=None, + design_description=None, + issues=None, + todos=None, + platform=None, + internal_name=None, + value=u"-1")) + return self._enum_template.substitute( + comment=self._gen_comment(enum), + name=enum.name, + enum_items=self._indent_code(self._gen_enum_elements( + enum_elements), 1)) + + def _gen_enum_elements(self, enum_elements): + """Generate enum elements for header file. + + Generates declaration of enumeration elements for the header file. + + Keyword arguments: + enum_elements -- list of enum elements to generate. + + Returns: + String with enum elements declaration source code. + + """ + + return u",\n\n".join([self._gen_enum_element(x) + for x in enum_elements]) + + def _gen_enum_element(self, enum_element): + """Generate enum element for header file. + + Generates declaration of enumeration element for the header file. + + Keyword arguments: + enum_element -- enum element to generate. + + Returns: + String with enum element declaration source code. + + """ + + if enum_element.value is not None: + return self._enum_element_with_value_template.substitute( + comment=self._gen_comment(enum_element), + name=enum_element.primary_name, + value=enum_element.value) + else: + return self._enum_element_with_no_value_template.substitute( + comment=self._gen_comment(enum_element), + name=enum_element.primary_name) + + def _gen_class_comment(self, class_name, params): + """Generate doxygen comment to the class for header file. + + Generates doxygen comment for the class that should be used in + the header file. + + Keyword arguments: + class_name -- name of the class. + params -- class parameters. + + Returns: + String with generated doxygen class comment. + + """ + + return self._class_comment_template.substitute( + class_name=class_name, + class_params=u"".join( + [u" * {0} - {1}\n".format(x[0], + x[1]) for x in params.items()]) + if params else u" * none\n") + + def _gen_comment(self, interface_item_base, use_doxygen=True): + """Generate doxygen comment for iterface_item_base for header file. + + Generates doxygen comment for any iterface_item_base for the header + file. + + Keyword arguments: + interface_item_base -- object to generate doxygen comment for. + use_doxygen -- Flag that indicates does function uses doxygen or not. + + Returns: + String with generated doxygen comment. + + """ + + brief_type_title = None + interface_item_base_classname = interface_item_base.__class__.__name__ + if interface_item_base_classname in self._model_types_briefs: + brief_type_title = \ + self._model_types_briefs[interface_item_base_classname] + else: + raise GenerateError("Unable to create comment for unknown type " + + interface_item_base_classname) + + name = interface_item_base.primary_name if \ + type(interface_item_base) is Model.EnumElement else \ + interface_item_base.name + brief_description = (u" * @brief {0}{1}.\n" if use_doxygen is + True else u"// {0}{1}.\n").format( + brief_type_title, + name) + + description = u"".join([(u" * {0}\n" if use_doxygen + is True else u"// {0}\n").format(x) + for x in self._normalize_multiline_comments( + interface_item_base.description)]) + if description is not u"": + description = u"".join([u" *\n" if use_doxygen + is True else u"//\n", description]) + + design_description = u"".join([(u" * {0}\n" if use_doxygen is + True else u"// {0}\n").format(x) + for x in + self._normalize_multiline_comments( + interface_item_base. + design_description)]) + if design_description is not u"": + design_description = u"".join([u" *\n" if use_doxygen is + True else "//\n", + design_description]) + + issues = u"".join([(u" * @note {0}\n" if use_doxygen is + True else u"// Note: {0}\n").format(x) + for x in self._normalize_multiline_comments( + [x.value for x in interface_item_base.issues])]) + if issues is not u"": + issues = u"".join([u" *\n" if use_doxygen is + True else u"//\n", issues]) + + todos = u"".join([(u" * @todo {0}\n" if use_doxygen is + True else u"// ToDo: {0}\n").format(x) + for x in self._normalize_multiline_comments( + interface_item_base.todos)]) + if todos is not u"": + todos = u"".join([u" *\n" if use_doxygen is + True else u"//\n", todos]) + + returns = u"" + if type(interface_item_base) is Model.Function: + returns = u"".join([u" *\n", self._function_return_comment]) + + template = self._comment_doxygen_template if use_doxygen is \ + True else self._comment_cc_template + + return template.substitute( + brief_description=brief_description, + description=description, + design_description=design_description, + issues=issues, + todos=todos, + returns=returns) + + def _indent_code(self, code, indent_level): + """Indent given source code. + + Indents given source code right by given indentation level. + + Keyword arguments: + code -- given source code. + indent_level -- desired indentation level. + + Returns: + String with processed code. + + """ + + code_lines = code.split("\n") + return u"".join( + [u"{0}{1}\n".format( + self._indent_template * indent_level, + x) if x is not u"" else u"\n" for x in code_lines]) + + @staticmethod + def _normalize_multiline_comments(initial_strings): + """Normalize multiline comments. + + Makes multiline comment clean of any line breaks creating additional + strings for the comment. + + Keyword arguments: + initial_strings -- initial list of strings to process. + + Returns: + New list of the strings (with contains no strings with line breaks). + + """ + + result = [] + for initial_string in initial_strings: + result = result + initial_string.splitlines() + return result + + _model_types_briefs = dict( + {u"EnumElement": u"", + u"Enum": u"Enumeration ", + u"Function": u"Method that generates schema for function ", + u"Struct": u"Method that generates schema item for structure ", + u"Param": u"Struct member ", + u"FunctionParam": u"Function parameter "}) + + _h_file_tempalte = string.Template( + u'''/**\n''' + u''' * @file ${class_name}.h\n''' + u''' * @brief Generated class ${class_name} header file.\n''' + u''' *\n''' + u''' * This class is a part of SmartObjects solution. It provides\n''' + u''' * factory functionallity which allows client to use ''' + u'''SmartSchemas\n''' + u''' * in accordance with definitions from ${class_name}.xml file\n''' + u''' */\n''' + u'''// Copyright (c) 2013, Ford Motor Company\n''' + u'''// All rights reserved.\n''' + u'''//\n''' + u'''// Redistribution and use in source and binary forms, ''' + u'''with or without\n''' + u'''// modification, are permitted provided that the following ''' + u'''conditions are met:\n''' + u'''//\n''' + u'''// Redistributions of source code must retain the above ''' + u'''copyright notice, this\n''' + u'''// list of conditions and the following disclaimer.\n''' + u'''//\n''' + u'''// Redistributions in binary form must reproduce ''' + u'''the above copyright notice,\n''' + u'''// this list of conditions and the following\n''' + u'''// disclaimer in the documentation and/or other materials ''' + u'''provided with the\n''' + u'''// distribution.\n''' + u'''//\n''' + u'''// Neither the name of the Ford Motor Company nor the names ''' + u'''of its contributors\n''' + u'''// may be used to endorse or promote products derived ''' + u'''from this software\n''' + u'''// without specific prior written permission.\n''' + u'''//\n''' + u'''// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND ''' + u'''CONTRIBUTORS "AS IS"\n''' + u'''// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ''' + u'''LIMITED TO, THE\n''' + u'''// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ''' + u'''A PARTICULAR PURPOSE\n''' + u'''// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ''' + u'''OR CONTRIBUTORS BE\n''' + u'''// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ''' + u'''EXEMPLARY, OR\n''' + u'''// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ''' + u'''PROCUREMENT OF\n''' + u'''// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ''' + u'''OR BUSINESS\n''' + u'''// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ''' + u'''WHETHER IN\n''' + u'''// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ''' + u'''OR OTHERWISE)\n''' + u'''// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ''' + u'''ADVISED OF THE\n''' + u'''// POSSIBILITY OF SUCH DAMAGE.\n\n''' + u'''#ifndef $guard\n''' + u'''#define $guard\n''' + u'''\n''' + u'''$namespace_open''' + u'''$enums_content''' + u'''$namespace_close''' + u'''#endif //$guard\n''' + u'''\n\n''') + + _hpp_schema_file_tempalte = string.Template( + u'''/**\n''' + u''' * @file ${class_name}.hpp\n''' + u''' * @brief Generated class ${class_name} header file.\n''' + u''' *\n''' + u''' * This class is a part of SmartObjects solution. It provides\n''' + u''' * factory functionallity which allows client to use ''' + u'''SmartSchemas\n''' + u''' * in accordance with definitions from ${class_name}.xml file\n''' + u''' */\n''' + u'''// Copyright (c) 2013, Ford Motor Company\n''' + u'''// All rights reserved.\n''' + u'''//\n''' + u'''// Redistribution and use in source and binary forms, ''' + u'''with or without\n''' + u'''// modification, are permitted provided that the following ''' + u'''conditions are met:\n''' + u'''//\n''' + u'''// Redistributions of source code must retain the above ''' + u'''copyright notice, this\n''' + u'''// list of conditions and the following disclaimer.\n''' + u'''//\n''' + u'''// Redistributions in binary form must reproduce ''' + u'''the above copyright notice,\n''' + u'''// this list of conditions and the following\n''' + u'''// disclaimer in the documentation and/or other materials ''' + u'''provided with the\n''' + u'''// distribution.\n''' + u'''//\n''' + u'''// Neither the name of the Ford Motor Company nor the names ''' + u'''of its contributors\n''' + u'''// may be used to endorse or promote products derived ''' + u'''from this software\n''' + u'''// without specific prior written permission.\n''' + u'''//\n''' + u'''// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND ''' + u'''CONTRIBUTORS "AS IS"\n''' + u'''// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ''' + u'''LIMITED TO, THE\n''' + u'''// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ''' + u'''A PARTICULAR PURPOSE\n''' + u'''// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ''' + u'''OR CONTRIBUTORS BE\n''' + u'''// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ''' + u'''EXEMPLARY, OR\n''' + u'''// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ''' + u'''PROCUREMENT OF\n''' + u'''// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ''' + u'''OR BUSINESS\n''' + u'''// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ''' + u'''WHETHER IN\n''' + u'''// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ''' + u'''OR OTHERWISE)\n''' + u'''// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ''' + u'''ADVISED OF THE\n''' + u'''// POSSIBILITY OF SUCH DAMAGE.\n\n''' + u'''#ifndef $guard\n''' + u'''#define $guard\n''' + u'''\n''' + u'''#include "formatters/CSmartFactory.hpp"\n''' + u'''#include "smart_objects/smart_schema.h"\n''' + u'''#include "smart_objects/schema_item.h"\n''' + u'''#include "utils/shared_ptr.h"\n''' + u'''#include "$header_file_name"\n''' + u'''\n''' + u'''$namespace_open''' + u'''\n\n''' + u'''$class_content''' + u'''\n\n''' + u'''$namespace_close''' + u'''\n''' + u'''#endif //$guard\n''' + u'''\n''') + + _namespace_open_template = string.Template( + u'''namespace $name {\n''') + + _cc_file_template = string.Template( + u'''/**\n''' + u''' * @file ${class_name}.cc\n''' + u''' * @brief Generated class ${class_name} source file.\n''' + u''' *\n''' + u''' * This class is a part of SmartObjects solution. It provides\n''' + u''' * factory functionallity which allows client to use ''' + u'''SmartSchemas\n''' + u''' * in accordance with definitions from ${class_name}.xml file\n''' + u''' */\n''' + u'''// Copyright (c) 2013, Ford Motor Company\n''' + u'''// All rights reserved.\n''' + u'''//\n''' + u'''// Redistribution and use in source and binary forms, ''' + u'''with or without\n''' + u'''// modification, are permitted provided that the following ''' + u'''conditions are met:\n''' + u'''//\n''' + u'''// Redistributions of source code must retain the above ''' + u'''copyright notice, this\n''' + u'''// list of conditions and the following disclaimer.\n''' + u'''//\n''' + u'''// Redistributions in binary form must reproduce ''' + u'''the above copyright notice,\n''' + u'''// this list of conditions and the following\n''' + u'''// disclaimer in the documentation and/or other materials ''' + u'''provided with the\n''' + u'''// distribution.\n''' + u'''//\n''' + u'''// Neither the name of the Ford Motor Company nor the names ''' + u'''of its contributors\n''' + u'''// may be used to endorse or promote products derived ''' + u'''from this software\n''' + u'''// without specific prior written permission.\n''' + u'''//\n''' + u'''// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND ''' + u'''CONTRIBUTORS "AS IS"\n''' + u'''// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ''' + u'''LIMITED TO, THE\n''' + u'''// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ''' + u''''A PARTICULAR PURPOSE\n''' + u'''// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER ''' + u'''OR CONTRIBUTORS BE\n''' + u'''// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ''' + u'''EXEMPLARY, OR\n''' + u'''// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ''' + u'''PROCUREMENT OF\n''' + u'''// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ''' + u'''OR BUSINESS\n''' + u'''// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ''' + u'''WHETHER IN\n''' + u'''// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ''' + u'''OR OTHERWISE)\n''' + u'''// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ''' + u'''ADVISED OF THE\n''' + u'''// POSSIBILITY OF SUCH DAMAGE.\n\n''' + u'''#include <map>\n''' + u'''#include <set>\n''' + u'''\n''' + u'''#include "$header_file_name"\n''' + u'''#include "smart_objects/always_true_schema_item.h"\n''' + u'''#include "smart_objects/always_false_schema_item.h"\n''' + u'''#include "smart_objects/array_schema_item.h"\n''' + u'''#include "smart_objects/bool_schema_item.h"\n''' + u'''#include "smart_objects/object_schema_item.h"\n''' + u'''#include "smart_objects/string_schema_item.h"\n''' + u'''#include "smart_objects/enum_schema_item.h"\n''' + u'''#include "smart_objects/number_schema_item.h"\n''' + u'''#include "smart_objects/schema_item_parameter.h"\n''' + u'''\n''' + u'''using namespace NsSmartDeviceLink::NsSmartObjects;\n''' + u'''\n''' + u'''$namespace::$class_name::$class_name()\n''' + u''' : NsSmartDeviceLink::NsJSONHandler::CSmartFactory<FunctionID::eType, ''' + u'''messageType::eType, StructIdentifiers::eType>() {\n''' + u''' TStructsSchemaItems struct_schema_items;\n''' + u''' InitStructSchemes(struct_schema_items);\n''' + u'''\n''' + u''' std::set<FunctionID::eType> function_id_items;\n''' + u'''${function_id_items}''' + u'''\n''' + u''' std::set<messageType::eType> message_type_items;\n''' + u'''${message_type_items}''' + u'''\n''' + u''' InitFunctionSchemes(struct_schema_items, function_id_items, ''' + u'''message_type_items);\n''' + u'''}\n''' + u'''\n''' + u'''utils::SharedPtr<ISchemaItem> $namespace::$class_name::''' + u'''ProvideObjectSchemaItemForStruct(\n''' + u''' const TStructsSchemaItems &struct_schema_items,\n''' + u''' const StructIdentifiers::eType struct_id) {\n''' + u''' const TStructsSchemaItems::const_iterator it = ''' + u'''struct_schema_items.find(struct_id);\n''' + u''' if (it != struct_schema_items.end()) {\n''' + u''' return it->second;\n''' + u''' }\n''' + u'''\n''' + u''' return NsSmartDeviceLink::NsSmartObjects::''' + u'''CAlwaysFalseSchemaItem::create();\n''' + u'''}\n''' + u'''\n''' + u'''void $namespace::$class_name::InitStructSchemes(\n''' + u''' TStructsSchemaItems &struct_schema_items) {''' + u'''$struct_schema_items''' + u'''}\n''' + u'''\n''' + u'''void $namespace::$class_name::InitFunctionSchemes(\n''' + u''' const TStructsSchemaItems &struct_schema_items,\n''' + u''' const std::set<FunctionID::eType> &function_id_items,\n''' + u''' const std::set<messageType::eType> &message_type_items) {\n''' + u'''$pre_function_schemas''' + u'''$function_schemas''' + u'''}\n''' + u'''\n''' + u'''//------------- Functions schemes initialization -------------\n''' + u'''\n''' + u'''$init_function_impls''' + u'''\n''' + u'''//----------- Structs schema items initialization ------------\n''' + u'''\n''' + u'''$init_structs_impls''' + u'''\n''' + u'''//-------------- String to value enum mapping ----------------\n''' + u'''\n''' + u'''namespace NsSmartDeviceLink {\n''' + u'''namespace NsSmartObjects {\n''' + u'''\n''' + u'''$enum_string_coversions''' + u'''\n''' + u'''} // NsSmartObjects\n''' + u'''} // NsSmartDeviceLink\n''' + u'''\n''') + + _enum_to_str_converter_template = string.Template( + u'''template<>\n''' + u'''const EnumConversionHelper<${namespace}::${enum}::eType>::''' + u'''EnumToCStringMap\n''' + u'''EnumConversionHelper<${namespace}::${enum}::eType>::''' + u'''enum_to_cstring_map_ =\n''' + u''' EnumConversionHelper<${namespace}::${enum}::eType>::''' + u'''InitEnumToCStringMap();\n''' + u'''\n''' + u'''template<>\n''' + u'''const EnumConversionHelper<${namespace}::${enum}::eType>::''' + u'''CStringToEnumMap\n''' + u'''EnumConversionHelper<${namespace}::${enum}::eType>::''' + u'''cstring_to_enum_map_ =\n''' + u''' EnumConversionHelper<${namespace}::${enum}::eType>::''' + u'''InitCStringToEnumMap();\n''' + u'''\n''' + u'''template<>\n''' + u'''const char* const\n''' + u'''EnumConversionHelper<${namespace}::${enum}::eType>::''' + u'''cstring_values_[] = {\n''' + u'''${cstringvalues}''' + u'''};\n''' + u'''\n''' + u'''template<>\n''' + u'''const ${namespace}::${enum}::eType\n''' + u'''EnumConversionHelper<${namespace}::${enum}::eType>::''' + u'''enum_values_[] = {\n''' + u'''${enumvalues}''' + u'''};\n''' + u'''\n''') + + _struct_schema_item_template = string.Template( + u'''utils::SharedPtr<ISchemaItem> struct_schema_item_${name} = ''' + u'''InitStructSchemaItem_${name}(struct_schema_items);\n''' + u'''struct_schema_items.insert(std::make_pair(''' + u'''StructIdentifiers::${name}, struct_schema_item_${name}));\n''' + u'''structs_schemes_.insert(std::make_pair(''' + u'''StructIdentifiers::${name}, CSmartSchema(''' + u'''struct_schema_item_${name})));''') + + _function_schema_template = string.Template( + u'''functions_schemes_.insert(std::make_pair(NsSmartDeviceLink::''' + u'''NsJSONHandler::''' + u'''SmartSchemaKey<FunctionID::eType, messageType::eType>''' + u'''(FunctionID::$function_id, messageType::$message_type), ''' + u'''InitFunction_${function_id}_${message_type}(''' + u'''struct_schema_items, function_id_items, message_type_items)));''') + + _struct_impl_template = string.Template( + u'''utils::SharedPtr<ISchemaItem> $namespace::$class_name::''' + u'''InitStructSchemaItem_${struct_name}(\n''' + u''' const TStructsSchemaItems &struct_schema_items) {\n''' + u'''$code''' + u'''}\n''') + + _struct_impl_code_tempate = string.Template( + u'''${schema_loc_decl}''' + u'''${schema_items_decl}''' + u'''CObjectSchemaItem::Members ''' + u'''schema_members;\n\n''' + u'''${schema_item_fill}''' + u'''return CObjectSchemaItem::create(schema_members);''') + + _impl_code_loc_decl_enum_template = string.Template( + u'''std::set<${type}::eType> ${var_name};''') + + _impl_code_loc_decl_enum_insert_template = string.Template( + u'''${var_name}.insert(${enum}::${value});''') + + _impl_code_item_decl_temlate = string.Template( + u'''${comment}''' + u'''utils::SharedPtr<ISchemaItem> ${var_name} = ${item_decl};''') + + _impl_code_integer_item_template = string.Template( + u'''TNumberSchemaItem<${type}>::create(${params})''') + + _impl_code_bool_item_template = string.Template( + u'''CBoolSchemaItem::create(${params})''') + + _impl_code_string_item_template = string.Template( + u'''CStringSchemaItem::create(${params})''') + + _impl_code_array_item_template = string.Template( + u'''CArraySchemaItem::create(${params})''') + + _impl_code_struct_item_template = string.Template( + u'''ProvideObjectSchemaItemForStruct(struct_schema_items, ''' + u'''StructIdentifiers::${name})''') + + _impl_code_enum_item_template = string.Template( + u'''TEnumSchemaItem<${type}::eType>::create(${params})''') + + _impl_code_item_param_value_template = string.Template( + u'''TSchemaItemParameter<$type>($value)''') + + _impl_code_item_fill_template = string.Template( + u'''schema_members["${name}"] = CObjectSchemaItem::''' + u'''SMember(${var_name}, ${is_mandatory});''') + + _function_impl_template = string.Template( + u'''CSmartSchema $namespace::$class_name::''' + u'''InitFunction_${function_id}_${message_type}(\n''' + u''' const TStructsSchemaItems &struct_schema_items,\n''' + u''' const std::set<FunctionID::eType> &function_id_items,\n''' + u''' const std::set<messageType::eType> &message_type_items) {\n''' + u'''$code''' + u'''}\n''') + + _function_impl_code_tempate = string.Template( + u'''${schema_loc_decl}''' + u'''${schema_items_decl}''' + u'''CObjectSchemaItem::Members ''' + u'''schema_members;\n\n''' + u'''${schema_item_fill}''' + u'''CObjectSchemaItem::Members ''' + u'''params_members;\n''' + u'''${schema_params_fill}''' + u'''\n''' + u'''CObjectSchemaItem::Members ''' + u'''root_members_map;\n''' + u'''root_members_map[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_MSG_PARAMS] = ''' + u'''CObjectSchemaItem::SMember(CObjectSchemaItem::''' + u'''create(schema_members), true);\n''' + u'''root_members_map[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_PARAMS] = ''' + u'''CObjectSchemaItem::SMember(CObjectSchemaItem::''' + u'''create(params_members), true);\n\n''' + u'''return CSmartSchema(CObjectSchemaItem::''' + u'''create(root_members_map));''') + + _class_h_template = string.Template( + u'''$comment\n''' + u'''class $class_name : public NsSmartDeviceLink::NsJSONHandler::''' + u'''CSmartFactory<FunctionID::eType, messageType::eType, ''' + u'''StructIdentifiers::eType> {\n''' + u''' public:\n''' + u''' /**\n''' + u''' * @brief Constructor.\n''' + u''' */\n''' + u''' $class_name();\n''' + u'''\n''' + u''' protected:\n''' + u''' /**\n''' + u''' * @brief Type that maps of struct IDs to schema items.\n''' + u''' */\n''' + u''' typedef std::map<const StructIdentifiers::eType, ''' + u'''utils::SharedPtr<NsSmartDeviceLink::NsSmartObjects::''' + u'''ISchemaItem> > TStructsSchemaItems;\n''' + u'''\n''' + u''' /**\n''' + u''' * @brief Helper that allows to make reference to struct\n''' + u''' *\n''' + u''' * @param struct_schema_items Struct schema items.\n''' + u''' * @param struct_id ID of structure to provide.\n''' + u''' *\n''' + u''' * @return utils::SharedPtr of strucute\n''' + u''' */\n''' + u''' static ''' + u'''utils::SharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> ''' + u'''ProvideObjectSchemaItemForStruct(\n''' + u''' const TStructsSchemaItems &struct_schema_items,\n''' + u''' const StructIdentifiers::eType struct_id);\n''' + u'''\n''' + u''' /**\n''' + u''' * @brief Initializes all struct schemes.\n''' + u''' */\n''' + u''' void InitStructSchemes(''' + u'''TStructsSchemaItems &struct_schema_items);\n''' + u'''\n''' + u''' /**\n''' + u''' * @brief Initializes all function schemes.\n''' + u''' *\n''' + u''' * @param struct_schema_items Struct schema items.\n''' + u''' * @param function_id_items Set of all elements ''' + u'''of FunctionID enum.\n''' + u''' * @param message_type_items Set of all elements ''' + u'''of messageType enum.\n''' + u''' */\n''' + u''' void InitFunctionSchemes(\n''' + u''' const TStructsSchemaItems &struct_schema_items,\n''' + u''' const std::set<FunctionID::eType> &function_id_items,\n''' + u''' const std::set<messageType::eType> ''' + u'''&message_type_items);\n''' + u'''\n''' + u'''$init_function_decls''' + u'''\n''' + u'''$init_struct_decls''' + u'''};''') + + _function_return_comment = u''' * @return NsSmartDeviceLink::''' \ + u'''NsSmartObjects::CSmartSchema\n''' + + _function_decl_template = string.Template( + u'''$comment\n''' + u'''static NsSmartDeviceLink::NsSmartObjects::CSmartSchema ''' + u'''InitFunction_${function_id}_${message_type}(\n''' + u''' const TStructsSchemaItems &struct_schema_items,\n''' + u''' const std::set<FunctionID::eType> &function_id_items,\n''' + u''' const std::set<messageType::eType> &message_type_items);''') + + _struct_decl_template = string.Template( + u'''$comment\n''' + u'''static ''' + u'''utils::SharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> ''' + u'''InitStructSchemaItem_${struct_name}(\n''' + u''' const TStructsSchemaItems &struct_schema_items);''') + + _class_comment_template = string.Template( + u'''/**\n''' + u''' * @brief Class $class_name.\n''' + u''' *\n''' + u''' * Params:\n''' + u'''$class_params''' + u''' */''') + + _comment_doxygen_template = string.Template( + u'''/**\n''' + u'''$brief_description''' + u'''$description''' + u'''$design_description''' + u'''$issues''' + u'''$todos''' + u'''$returns */''') + + _comment_cc_template = string.Template( + u'''$brief_description''' + u'''$description''' + u'''$design_description''' + u'''$issues''' + u'''$todos''' + u'''$returns''') + + _enum_template = string.Template( + u'''namespace $name {\n''' + u'''$comment\n''' + u'''enum eType {\n''' + u'''$enum_items};\n''' + u'''} // $name\n''') + + _enum_element_with_value_template = string.Template( + u'''$comment\n''' + u'''$name = $value''') + + _enum_element_with_no_value_template = string.Template( + u'''$comment\n''' + u'''$name''') + + _indent_template = u" " diff --git a/tools/InterfaceGenerator/generator/generators/SmartFactoryJSONRPC.py b/tools/InterfaceGenerator/generator/generators/SmartFactoryJSONRPC.py new file mode 100755 index 000000000..cf9887d39 --- /dev/null +++ b/tools/InterfaceGenerator/generator/generators/SmartFactoryJSONRPC.py @@ -0,0 +1,165 @@ +"""SmartFactory code generator for JSONRPC format. + +Defines JSONRPC format specific code generation rules. + +""" +import string + +from generator.generators import SmartFactoryBase +from generator import Model + + +class CodeGenerator(SmartFactoryBase.CodeGenerator): + + """JSONRPC SmartFactory generator. + + Defines special cases that affects base code generation to make JSONRPC + format-friendly code. + + """ + + def __init__(self): + """Construct new object.""" + + SmartFactoryBase.CodeGenerator.__init__(self) + + def _gen_pre_function_schemas(self, functions): + """Generate specific code that goes before schema initialization. + + JSON RPC generator generates code that adds specific schema for the + error_response and adds this schema for every available response. + + Keyword arguments: + functions -- list of functions to generate code for. + + Returns: + Source code with error_response schema initialization and adding to the + base SmartFactory.. + + """ + + code = u"" + for function in functions: + if unicode(function.message_type.primary_name) == u"response": + code = u"".join( + [code, self._error_response_insert_template.substitute( + function_id=function.function_id.primary_name)]) + + if code: + return self._indent_code( + u"".join([self._error_response_schema_template, code]), 1) + + return u"" + + def _preprocess_message_type(self, message_type): + """Preprocess message_type enum. + + JSON RPC generator needs to add new message_type "error_response" in + case if at least one response available. + + Keyword arguments: + message_type -- message_type enum to preprocess. + + Returns: + Preprocessed message_type enum. + + """ + + if "response" in message_type.elements: + message_type.elements[u"error_response"] = Model.EnumElement( + name=u"error_response") + + return message_type + + def _gen_schema_params_fill(self, message_type_name): + """Generate schema params fill code. + + Provides constant set of params for the function in accordance to the + JSONRPC format. + + Keyword arguments: + message_type_name -- Name of the messageType enum element. + + Returns: + String with function schema params fill code. + + """ + + return u"".join( + [self._base_params, + self._correlation_id_param + if unicode(message_type_name) != u"notification" else u"", + self._additional_response_params + if unicode(message_type_name) == u"response" else u""]) + + _error_response_insert_template = string.Template( + u'''functions_schemes_.insert(std::make_pair(''' + u'''NsSmartDeviceLink::NsJSONHandler::''' + u'''SmartSchemaKey<FunctionID::eType, messageType::eType>(''' + u'''FunctionID::${function_id}, messageType::error_response), ''' + u'''error_response_schema));\n''') + + _error_response_schema_template = ( + u'''CObjectSchemaItem::Members ''' + u'''params_members;\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(''' + u'''TEnumSchemaItem<FunctionID::eType>::create(''' + u'''function_id_items), true);\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(''' + u'''TEnumSchemaItem<messageType::eType>::create(''' + u'''message_type_items), true);\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(''' + u'''TNumberSchemaItem<int>::create(), true);\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(''' + u'''TNumberSchemaItem<int>::create(), true);\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(''' + u'''TNumberSchemaItem<int>::create(), true);\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::kCode] = CObjectSchemaItem::SMember(''' + u'''TNumberSchemaItem<int>::create(), true);\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::kMessage] = CObjectSchemaItem::SMember(''' + u'''CStringSchemaItem::create(), true);\n''' + u'''\n''' + u'''CObjectSchemaItem::Members root_members_map;\n''' + u'''root_members_map[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_PARAMS] = CObjectSchemaItem::SMember(''' + u'''CObjectSchemaItem::create(params_members), true);\n''' + u'''\n''' + u'''CSmartSchema error_response_schema(''' + u'''CObjectSchemaItem::create(root_members_map));\n''' + u'''\n''') + + _base_params = ( + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_FUNCTION_ID] = CObjectSchemaItem::''' + u'''SMember(TEnumSchemaItem<FunctionID::eType>::''' + u'''create(function_id_items), true);\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_MESSAGE_TYPE] = CObjectSchemaItem::''' + u'''SMember(TEnumSchemaItem<messageType::eType>::''' + u'''create(message_type_items), true);\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::''' + u'''SMember(TNumberSchemaItem<int>::create(), true);\n''' + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::''' + u'''SMember(TNumberSchemaItem<int>::create(), true);\n''' + ) + + _correlation_id_param = ( + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::S_CORRELATION_ID] = CObjectSchemaItem::''' + u'''SMember(TNumberSchemaItem<int>::create(), true);\n''' + ) + + _additional_response_params = ( + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' + u'''strings::kCode] = CObjectSchemaItem::''' + u'''SMember(TNumberSchemaItem<int>::create(), true);\n''' + ) diff --git a/tools/InterfaceGenerator/generator/generators/SmartFactorySDLRPC.py b/tools/InterfaceGenerator/generator/generators/SmartFactorySDLRPC.py new file mode 100755 index 000000000..b3fb61f4a --- /dev/null +++ b/tools/InterfaceGenerator/generator/generators/SmartFactorySDLRPC.py @@ -0,0 +1,92 @@ +"""SmartFactory code generator for SDLRPC format. + +Defines SDLRPC format specific code generation rules. + +""" +from generator.generators import SmartFactoryBase + + +class CodeGenerator(SmartFactoryBase.CodeGenerator): + + """SDLRPC SmartFactory generator. + + Defines special cases that affects base code generation to make SDLRPC + format-friendly code. + + """ + + def __init__(self): + """Construct new object.""" + + SmartFactoryBase.CodeGenerator.__init__(self) + + def _gen_pre_function_schemas(self, functions): + """Generate specific code that goes before schema initialization. + + In SDL RPC generator there is no need to generate any code before + schemas initialization. + + Keyword arguments: + functions -- list of functions to generate code for. + + Returns: + Empty string. + + """ + + return u"" + + def _preprocess_message_type(self, message_type): + """Preprocess message_type enum. + + In SDL RPC generator there is no need to preprocess message_type + enum values. + + Keyword arguments: + message_type -- message_type enum to preprocess. + + Returns: + Initial message_type enum without any modifications. + + """ + + return message_type + + def _gen_schema_params_fill(self, message_type_name): + """Generate schema params fill code. + + Provides constant set of params for the function in accordance to the + SDLRPC format (both v1 and v2). + + Keyword arguments: + message_type_name -- Name of the messageType enum element. + + Returns: + String with function schema params fill code. + + """ + + base_params = \ + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \ + u'''strings::S_FUNCTION_ID] = CObjectSchemaItem::''' \ + u'''SMember(TEnumSchemaItem<FunctionID::eType>::''' \ + u'''create(function_id_items), true);\n''' \ + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \ + u'''strings::S_MESSAGE_TYPE] = CObjectSchemaItem::''' \ + u'''SMember(TEnumSchemaItem<messageType::eType>::''' \ + u'''create(message_type_items), true);\n''' \ + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \ + u'''strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::''' \ + u'''SMember(TNumberSchemaItem<int>::create(), true);\n''' \ + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \ + u'''strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::''' \ + u'''SMember(TNumberSchemaItem<int>::create(), true);\n''' + + correlation_id_param = \ + u'''params_members[NsSmartDeviceLink::NsJSONHandler::''' \ + u'''strings::S_CORRELATION_ID] = CObjectSchemaItem::''' \ + u'''SMember(TNumberSchemaItem<int>::create(), true);\n''' + + return u"".join([base_params, correlation_id_param + if unicode(message_type_name) != + u"notification" else u""]) diff --git a/tools/InterfaceGenerator/generator/generators/__init__.py b/tools/InterfaceGenerator/generator/generators/__init__.py new file mode 100755 index 000000000..57e528dc8 --- /dev/null +++ b/tools/InterfaceGenerator/generator/generators/__init__.py @@ -0,0 +1,3 @@ +"""Package that contains generators from internal model representation to +different formats. +""" diff --git a/tools/InterfaceGenerator/generator/parsers/JSONRPC.py b/tools/InterfaceGenerator/generator/parsers/JSONRPC.py new file mode 100755 index 000000000..092f41ec1 --- /dev/null +++ b/tools/InterfaceGenerator/generator/parsers/JSONRPC.py @@ -0,0 +1,89 @@ +"""JSON RPC parser. + +Contains parser for JSON RPC XML format. + +""" + +from generator.parsers import RPCBase + + +class Parser(RPCBase.Parser): + + """JSON RPC parser.""" + + def __init__(self): + """Constructor.""" + super(Parser, self).__init__() + self._interface_name = None + + def _parse_root(self, root): + """Parse root XML element. + + This implementation parses root as interfaces element with multiple + interfaces in it. + + Keyword arguments: + root -- root element. + + """ + + self._params = root.attrib + self._interface_name = None + + for element in root: + if element.tag != "interface": + raise RPCBase.ParseError("Subelement '" + element.tag + + "' is unexpected in interfaces") + + if "name" not in element.attrib: + raise RPCBase.ParseError( + "Name is not specified for interface") + + self._interface_name = element.attrib["name"] + self._parse_interface(element, self._interface_name + "_") + + def _provide_enum_element_for_function(self, enum_name, element_name): + """Provide enum element for functions. + + This implementation replaces the underscore separating interface and + function name with dot and sets it as name of enum element leaving + the name with underscore as internal_name. For enums other than + FunctionID the base implementation is called. + + Returns EnumElement. + + """ + + name = element_name + internal_name = None + + if "FunctionID" == enum_name: + prefix_length = len(self._interface_name) + 1 + if element_name[:prefix_length] != self._interface_name + '_': + raise RPCBase.ParseError( + "Unexpected prefix for function id '" + + element_name + "'") + name = self._interface_name + "." + element_name[prefix_length:] + internal_name = element_name + + element = super(Parser, self)._provide_enum_element_for_function( + enum_name, + name) + + if internal_name is not None: + element.internal_name = internal_name + + return element + + def _check_function_param_name(self, function_param_name): + """Check function param name. + + This method is called to check whether the newly parsed function + parameter name conflicts with some predefined name. + """ + + if function_param_name in ['method', 'code']: + raise RPCBase.ParseError( + "'" + function_param_name + + "' is a predefined name and can't be used" + + " as a function parameter name") diff --git a/tools/InterfaceGenerator/generator/parsers/RPCBase.py b/tools/InterfaceGenerator/generator/parsers/RPCBase.py new file mode 100755 index 000000000..2b3db62d5 --- /dev/null +++ b/tools/InterfaceGenerator/generator/parsers/RPCBase.py @@ -0,0 +1,758 @@ +"""RPC XML base parser. + +Contains base parser for SDLRPC v1/v2 and JSON RPC XML format. + +""" + +import collections +import xml.etree.ElementTree + +from generator import Model + + +class ParseError(Exception): + + """Parse error. + + This exception is raised when XML contains errors and can't be parsed. + + """ + + pass + + +class Parser(object): + + """RPC XML Parser base. + + This class must not be used directly. One of its subclasses must be used + instead. + + """ + + def __init__(self): + """Constructor.""" + self._types = {} + self._enums = collections.OrderedDict() + self._structs = collections.OrderedDict() + self._functions = collections.OrderedDict() + self._params = {} + + def parse(self, filename): + """Parse XML. + + Returns an instance of generator.Model.Interface containing parsed + interface or raises ParseError if input XML contains errors + and can't be parsed. + + Keyword arguments: + filename -- name of input XML file. + + """ + + tree = xml.etree.ElementTree.parse(filename) + root = tree.getroot() + + self._enums = self._initialize_enums() + self._structs = collections.OrderedDict() + self._functions = collections.OrderedDict() + self._params = {} + + self._types = dict(self._enums.items()) + + self._parse_root(root) + + return Model.Interface(enums=self._enums, structs=self._structs, + functions=self._functions, params=self._params) + + def _initialize_enums(self): + """Initialize enums. + + The default implementation returns an OrderedDict with two empty + enums: "FunctionID" and "messageType". Required for formats where + these enums must be generated automatically according to the declared + in the XML functions. + + These enums are filled during the parsing of the functions. + + """ + return collections.OrderedDict( + [("FunctionID", Model.Enum(name="FunctionID")), + ("messageType", Model.Enum(name="messageType"))]) + + def _check_enum_name(self, enum): + """Check enum name. + + This method is called to check whether the newly parsed enum's name + conflicts with some predefined enum. + + This implementation raises an error if enum name is one of the + predefined enums "FunctionID" or "messageType" which must not be + declared explicitly in the XML. + + """ + if enum.name in ["FunctionID", "messageType"]: + raise ParseError( + "Enum '" + enum.name + + "' is generated automatically in SDLRPCV1 and" + " must not be declared in xml file") + + def _check_function_param_name(self, function_param_name): + """Check function param name. + + This method is called to check whether the newly parsed function + parameter name conflicts with some predefined name. + + This implementation doesn't check anything because there is no + predefined names in base RPC XML. + """ + + pass + + def _parse_root(self, root): + """Parse root XML element. + + Default implementation parses root as interface element without a + prefix. + + Keyword arguments: + root -- root element. + + """ + + self._parse_interface(root, "") + + def _parse_interface(self, interface, prefix): + """Parse interface element. + + Keyword arguments: + interface -- interface element. + prefix -- string prefix for all types of the interface. + + """ + if interface.tag != "interface": + raise ParseError("Invalid interface tag: " + interface.tag) + + params, subelements, attrib = self._parse_base_item(interface, "") + + for param in ["description", "design_description", "todos"]: + if 0 != len(params[param]): + attrib[param] = "\n".join(params[param]) + + if 0 != len(params["issues"]): + attrib["issues"] = "\n".join(i.value for i in params["issues"]) + + self._params = dict( + self._params.items() + + [(prefix + p[0], p[1]) for p in attrib.items()]) + + for element in subelements: + if element.tag == "enum": + enum = self._parse_enum(element, prefix) + self._check_enum_name(enum) + self._add_item(self._enums, enum) + self._add_type(enum) + elif element.tag == "struct": + struct = self._parse_struct(element, prefix) + self._add_item(self._structs, struct) + self._add_type(struct) + elif element.tag == "function": + function = self._parse_function(element, prefix) + self._add_item(self._functions, function, + (function.function_id, function.message_type)) + else: + raise ParseError("Unexpected element: " + element.tag) + + @staticmethod + def _add_item(items, item, key=None): + """Add new item in the items dictionary with given key. + + Performs additional check for presence in the dictionary and throws + ParseError exception if key already exist. + + """ + if key is None: + key = item.name + + if key in items: + raise ParseError(type(item).__name__ + " '" + str(key) + + "' is declared more than once") + items[key] = item + + def _add_type(self, _type): + """Add new type in the internal types dictionary. + + Performs additional check for presence type with same name in the + dictionary and throws ParseError exception if key already exist. + + """ + if _type.name in self._types: + raise ParseError("Type '" + _type.name + + "' is declared as both struct and enum") + + self._types[_type.name] = _type + + def _parse_enum(self, element, prefix): + """Parse element as enumeration. + + Returns an instance of generator.Model.Enum + + """ + params, subelements, attributes = \ + self._parse_base_item(element, prefix) + + internal_scope = None + scope = None + for attribute in attributes: + if attribute == "internal_scope": + internal_scope = attributes[attribute] + elif attribute == "scope": + scope = attributes[attribute] + else: + raise ParseError("Unexpected attribute '" + attribute + + "' in enum '" + params["name"] + "'") + params["internal_scope"] = internal_scope + params["scope"] = scope + + elements = collections.OrderedDict() + for subelement in subelements: + if subelement.tag == "element": + self._add_item(elements, self._parse_enum_element(subelement)) + else: + raise ParseError("Unexpected element '" + subelement.tag + + "' in enum '" + params["name"] + "'") + params["elements"] = elements + + # Magic usage is correct + # pylint: disable=W0142 + return Model.Enum(**params) + + def _parse_struct(self, element, prefix): + """Parse element as structure. + + Returns an instance of generator.Model.Struct + + """ + params, subelements, attrib = self._parse_base_item(element, prefix) + + scope = None + for attribute in attrib: + if attribute == "scope": + scope = attrib[attribute] + else: + raise ParseError("Unexpected attribute '" + attribute + + "' in struct '" + params["name"] + "'") + params["scope"] = scope + + members = collections.OrderedDict() + for subelement in subelements: + if subelement.tag == "param": + self._add_item(members, self._parse_param(subelement, prefix)) + else: + raise ParseError("Unexpected subelement '" + subelement.name + + "' in struct '" + params["name"] + "'") + params["members"] = members + + # Magic usage is correct + # pylint: disable=W0142 + return Model.Struct(**params) + + def _parse_function(self, element, prefix): + """Parse element as function. + + Returns an instance of generator.Model.Function + + """ + params, subelements, attributes = \ + self._parse_base_item(element, prefix) + + function_id, message_type = self._parse_function_id_type( + params["name"], + attributes) + + scope = None + for attribute in attributes: + if attribute == "scope": + scope = attributes[attribute] + + params["function_id"] = function_id + params["message_type"] = message_type + params["scope"] = scope + + function_params = collections.OrderedDict() + for subelement in subelements: + if subelement.tag == "param": + function_param = self._parse_function_param(subelement, + prefix) + self._check_function_param_name(function_param.name) + if function_param.name in function_params: + raise ParseError("Parameter '" + function_param.name + + "' is specified more than once" + + " for function '" + params["name"] + "'") + function_params[function_param.name] = function_param + else: + raise ParseError("Unexpected subelement '" + subelement.tag + + "' in function '" + params["name"] + "'") + params["params"] = function_params + + # Magic usage is correct + # pylint: disable=W0142 + return Model.Function(**params) + + def _parse_function_id_type(self, function_name, attrib): + """Parse function id and message type according to XML format. + + This implementation takes function name as function id and extracts + attribute "messagetype" as message type and searches them in enums + "FunctionID" and "messageType" adding the missing elements if + necessary. + + Returns function id and message type as an instances of EnumElement. + + """ + if "messagetype" not in attrib: + raise ParseError("No messagetype specified for function '" + + function_name + "'") + + function_id = self._provide_enum_element_for_function( + "FunctionID", + function_name) + + message_type = self._provide_enum_element_for_function( + "messageType", + self._extract_attrib(attrib, "messagetype")) + + return function_id, message_type + + def _provide_enum_element_for_function(self, enum_name, element_name): + """Provide enum element for functions. + + Search an element in an enum and add it if it is missing. + + Returns EnumElement. + + """ + if enum_name not in self._types: + raise ParseError("Enum '" + enum_name + + "' is not initialized") + + enum = self._types[enum_name] + + if not isinstance(enum, Model.Enum): + raise ParseError("'" + enum_name + "' is not an enum") + + if element_name not in enum.elements: + enum.elements[element_name] = Model.EnumElement(name=element_name) + + return enum.elements[element_name] + + def _parse_base_item(self, element, prefix): + """Parse element as base item. + + Returns an params, sub-elements and attributes of the element + + """ + params = {} + + description = [] + design_description = [] + issues = [] + todos = [] + subelements = [] + + if "name" not in element.attrib: + raise ParseError("Name is not specified for " + element.tag) + + params["name"] = prefix + element.attrib["name"] + attrib = dict(element.attrib.items()) + del attrib["name"] + + params["platform"] = self._extract_attrib(attrib, "platform") + + for subelement in element: + if subelement.tag == "description": + description.append(self._parse_simple_element(subelement)) + elif subelement.tag == "designdescription": + design_description.append( + self._parse_simple_element(subelement)) + elif subelement.tag == "todo": + todos.append(self._parse_simple_element(subelement)) + elif subelement.tag == "issue": + issues.append(self._parse_issue(subelement)) + else: + subelements.append(subelement) + + params["description"] = description + params["design_description"] = design_description + params["issues"] = issues + params["todos"] = todos + + return params, subelements, attrib + + @staticmethod + def _parse_simple_element(element): + """Parse element as simple element and returns it's text. + + Element is simple when it contains no subelements and attributes. + + Returns element text if present or empty string if not + + """ + if len(element) != 0: + raise ParseError("Unexpected subelements in '" + + element.tag + "'") + if len(element.attrib) != 0: + raise ParseError("Unexpected attributes in '" + + element.tag + "'") + return element.text if element.text is not None else "" + + @staticmethod + def _parse_issue(element): + """Parse element as issue. + + Issue must not contain subelements and attributes. + + Returns an instance of generator.Model.Issue + + """ + if len(element) != 0: + raise ParseError("Unexpected subelements in issue") + if "creator" not in element.attrib: + raise ParseError("No creator in issue") + if len(element.attrib) != 1: + raise ParseError("Unexpected attributes in issue") + + return Model.Issue( + creator=element.attrib["creator"], + value=element.text if element.text is not None else "") + + def _parse_enum_element(self, element): + """Parse element as element of enumeration. + + Returns an instance of generator.Model.EnumElement + + """ + params, subelements, attributes = self._parse_base_item(element, "") + + if len(subelements) != 0: + raise ParseError("Unexpected subelements in enum element") + + self._ignore_attribute(attributes, "hexvalue") + self._ignore_attribute(attributes, "scope") + self._ignore_attribute(attributes, "rootscreen") + + internal_name = None + value = None + for attribute in attributes: + if attribute == "internal_name": + internal_name = attributes[attribute] + elif attribute == "value": + try: + value = int(attributes[attribute]) + except: + raise ParseError("Invalid value for enum element: '" + + attributes[attribute] + "'") + params["internal_name"] = internal_name + params["value"] = value + + # Magic usage is correct + # pylint: disable=W0142 + return Model.EnumElement(**params) + + def _parse_param(self, element, prefix): + """Parse element as structure parameter. + + Returns an instance of generator.Model.Param + + """ + params, subelements, attrib = \ + self._parse_param_base_item(element, prefix) + + if len(attrib) != 0: + raise ParseError("""Unknown attribute(s) {0} in param {1} + """.format(attrib, params["name"])) + + if len(subelements) != 0: + raise ParseError("Unknown subelements in param '" + + params["name"] + "'") + + # Magic usage is correct + # pylint: disable=W0142 + return Model.Param(**params) + + def _parse_function_param(self, element, prefix): + """Parse element as function parameter. + + Returns an instance of generator.Model.FunctionParam + + """ + params, subelements, attrib = \ + self._parse_param_base_item(element, prefix) + + default_value = None + default_value_string = self._extract_attrib(attrib, "defvalue") + if default_value_string is not None: + param_type = params["param_type"] + if type(param_type) is Model.Boolean: + default_value = \ + self._get_bool_from_string(default_value_string) + elif type(param_type) is Model.Integer: + try: + default_value = int(default_value_string) + except: + raise ParseError("Invalid value for integer: '" + + default_value_string + "'") + elif type(param_type) is Model.Double: + try: + default_value = float(default_value_string) + except: + raise ParseError("Invalid value for float: '" + + default_value_string + "'") + elif type(param_type) is Model.String: + default_value = default_value_string + elif type(param_type) is Model.Enum or \ + type(param_type) is Model.EnumSubset: + if type(param_type) is Model.EnumSubset: + allowed_elements = param_type.allowed_elements + else: + allowed_elements = param_type.elements + if default_value_string not in allowed_elements: + raise ParseError("Default value '" + default_value_string + + "' for parameter '" + params["name"] + + "' is not a member of " + + type(param_type).__name__ + + "'" + params["name"] + "'") + default_value = allowed_elements[default_value_string] + else: + raise ParseError("Default value specified for " + + type(param_type).__name__) + params["default_value"] = default_value + + if len(attrib) != 0: + raise ParseError("Unexpected attributes in parameter '" + + params["name"] + "'") + + if len(subelements) != 0: + raise ParseError("Unexpected subelements in parameter '" + + params["name"] + "'") + + # Magic usage is correct + # pylint: disable=W0142 + return Model.FunctionParam(**params) + + def _parse_param_base_item(self, element, prefix): + """Parse base param items. + + Returns params, other subelements and attributes. + + """ + params, subelements, attrib = self._parse_base_item(element, "") + + params["is_mandatory"] = self._extract_optional_bool_attrib( + attrib, "mandatory", True) + + scope = self._extract_attrib(attrib, "scope") + if scope is not None: + params["scope"] = scope + + default_value = None; + param_type = None + type_name = self._extract_attrib(attrib, "type") + if type_name is None: + raise ParseError("Type is not specified for parameter '" + + params["name"] + "'") + if type_name == "Boolean": + default_value = self._extract_attrib( + attrib, "defvalue") + if default_value != None: + default_value = self._get_bool_from_string(default_value); + param_type = Model.Boolean(default_value=default_value) + elif type_name == "Integer" or \ + type_name == "Float": + min_value = self._extract_optional_number_attrib( + attrib, "minvalue", int if type_name == "Integer" else float) + max_value = self._extract_optional_number_attrib( + attrib, "maxvalue", int if type_name == "Integer" else float) + default_value = self._extract_optional_number_attrib( + attrib, "defvalue", int if type_name == "Integer" else float) + + param_type = \ + (Model.Integer if type_name == "Integer" else Model.Double)( + min_value=min_value, + max_value=max_value, + default_value=default_value) + elif type_name == "String": + min_length = self._extract_optional_number_attrib( + attrib, "minlength") + # if minlength is not defined default value is 1 + if min_length is None: + min_length = 1 + max_length = self._extract_optional_number_attrib( + attrib, "maxlength") + default_value = self._extract_attrib(attrib, "defvalue") + param_type = Model.String(min_length=min_length, max_length=max_length, default_value=default_value) + else: + if 1 == type_name.count("."): + custom_type_name = type_name.replace(".", "_") + else: + custom_type_name = prefix + type_name + + if custom_type_name in self._types: + param_type = self._types[custom_type_name] + default_value = self._extract_attrib(attrib, "defvalue") + if default_value != None: + if default_value not in param_type.elements: + raise ParseError("Default value '" + default_value + + "' for parameter '" + params["name"] + + "' is not a member of " + + type(param_type).__name__ + + "'" + params["name"] + "'") + default_value = param_type.elements[default_value] + else: + raise ParseError("Unknown type '" + type_name + "'") + + if self._extract_optional_bool_attrib(attrib, "array", False): + min_size = self._extract_optional_number_attrib(attrib, + "minsize") + max_size = self._extract_optional_number_attrib(attrib, + "maxsize") + param_type = Model.Array(element_type=param_type, + min_size=min_size, + max_size=max_size) + + base_type = \ + param_type.element_type if isinstance(param_type, Model.Array) \ + else param_type + + other_subelements = [] + for subelement in subelements: + if subelement.tag == "element": + if type(base_type) is not Model.Enum and \ + type(base_type) is not Model.EnumSubset: + raise ParseError("Elements specified for parameter '" + + params["name"] + "' of type " + + type(base_type).__name__) + if type(base_type) is Model.Enum: + base_type = Model.EnumSubset( + name=params["name"], + enum=base_type, + description=params["description"], + design_description=params["design_description"], + issues=params["issues"], + todos=params["todos"], + allowed_elements={}) + if "name" not in subelement.attrib: + raise ParseError( + "Element name is not specified for parameter '" + + params["name"] + "'") + element_name = subelement.attrib["name"] + if len(subelement.attrib) != 1: + raise ParseError("Unexpected attributes for element '" + + element_name + "' of parameter '" + + params["name"]) + if len(subelement.getchildren()) != 0: + raise ParseError("Unexpected subelements for element '" + + element_name + "' of parameter '" + + params["name"]) + if element_name in base_type.allowed_elements: + raise ParseError("Element '" + element_name + + "' is specified more than once for" + + " parameter '" + params["name"] + "'") + if element_name not in base_type.enum.elements: + raise ParseError("Element '" + element_name + + "' is not a member of enum '" + + base_type.enum.name + "'") + base_type.allowed_elements[element_name] = \ + base_type.enum.elements[element_name] + else: + other_subelements.append(subelement) + + if isinstance(param_type, Model.Array): + param_type.element_type = base_type + else: + param_type = base_type + + params["param_type"] = param_type + if default_value is not None: + params["default_value"] = default_value + + return params, other_subelements, attrib + + def _extract_optional_bool_attrib(self, attrib, name, default): + """Extract boolean attribute with given name. + + Returns value of the attribute. + + """ + value = self._extract_attrib(attrib, name) + + if value is None: + value = default + else: + value = self._get_bool_from_string(value) + + return value + + def _extract_optional_number_attrib(self, attrib, name, _type=int): + """Extract number attribute with given name. + + Returns value of the attribute. + + """ + value = self._extract_attrib(attrib, name) + + if value is not None: + try: + value = _type(value) + except: + raise ParseError("Invlaid value for " + _type.__name__ + + ": '" + value + "'") + + return value + + @staticmethod + def _extract_attrib(attrib, name): + """Extract attribute with given name. + + Returns value of the attribute. + + """ + value = None + + if name in attrib: + value = attrib[name] + del attrib[name] + + return value + + @staticmethod + def _get_bool_from_string(bool_string): + """Convert string representation of boolean to real bool value. + + Returns converted value. + + """ + value = None + + if bool_string in ['0', 'false']: + value = False + elif bool_string in ['1', 'true']: + value = True + else: + raise ParseError("Invalid value for bool: '" + + bool_string + "'") + + return value + + def _ignore_attribute(self, attrib, name): + """To be called when attribute is meaningless in terms + of code generation but it's presence is not issue. + + Removes this attribute from attribute list. + + """ + if name in attrib: + del attrib[name] + print ("Ignoring attribute '" + + name + "'") + return True diff --git a/tools/InterfaceGenerator/generator/parsers/SDLRPCV1.py b/tools/InterfaceGenerator/generator/parsers/SDLRPCV1.py new file mode 100755 index 000000000..52158ee93 --- /dev/null +++ b/tools/InterfaceGenerator/generator/parsers/SDLRPCV1.py @@ -0,0 +1,14 @@ +"""SDLRPCV1 parser. + +Contains parser for SDLRPCV1 XML format. + +""" + +from generator.parsers import RPCBase + + +class Parser(RPCBase.Parser): + + """SDLRPCV1 parser.""" + + pass diff --git a/tools/InterfaceGenerator/generator/parsers/SDLRPCV2.py b/tools/InterfaceGenerator/generator/parsers/SDLRPCV2.py new file mode 100755 index 000000000..3d67c6e4c --- /dev/null +++ b/tools/InterfaceGenerator/generator/parsers/SDLRPCV2.py @@ -0,0 +1,88 @@ +"""SDLRPCV2 parser. + +Contains parser for SDLRPCV2 XML format. + +""" + +import collections + +from generator import Model +from generator.parsers import RPCBase + + +class Parser(RPCBase.Parser): + + """SDLRPCV2 parser.""" + + def _initialize_enums(self): + """Initialize enums. + + This implementation returns empty OrderedDict because in SDLRPCV2 + all enums must be declared explicitly in the XML file. + + """ + return collections.OrderedDict() + + def _check_enum_name(self, enum): + """Check enum name. + + This method is called to check whether the newly parsed enum's name + conflicts with some predefined enum. + As SDLRPCV2 has no predefined enums this implementation does nothing. + + """ + pass + + def _parse_function_id_type(self, function_name, attrib): + """Parse function id and message type according to XML format. + + This implementation extracts attribute "FunctionID" as function id + and messagetype as message type and searches them in enums + "FunctionID" and "messageType". If at least one of them (or the entire + enum) is missing it raises an error. + + Returns function id and message type as an instances of EnumElement. + + """ + if "functionID" not in attrib: + raise RPCBase.ParseError( + "No functionID specified for function '" + + function_name + "'") + + if "messagetype" not in attrib: + raise RPCBase.ParseError( + "No messagetype specified for function '" + + function_name + "'") + + function_id = self._get_enum_element_for_function( + "FunctionID", + self._extract_attrib(attrib, "functionID")) + message_type = self._get_enum_element_for_function( + "messageType", + self._extract_attrib(attrib, "messagetype")) + + return function_id, message_type + + def _get_enum_element_for_function(self, enum_name, element_name): + """Get enum element with given name from given enumeration. + + Returns an instance of generator.Model.EnumElement. + + """ + if enum_name not in self._types: + raise RPCBase.ParseError( + "Enumeration '" + enum_name + + "' must be declared before any function") + + enum = self._types[enum_name] + + if type(enum) is not Model.Enum: + raise RPCBase.ParseError("'" + enum_name + + "' is not an enumeration") + + if element_name not in enum.elements: + raise RPCBase.ParseError( + "'" + element_name + + "' is not a member of enum '" + enum_name + "'") + + return enum.elements[element_name] diff --git a/tools/InterfaceGenerator/generator/parsers/__init__.py b/tools/InterfaceGenerator/generator/parsers/__init__.py new file mode 100755 index 000000000..7005503b0 --- /dev/null +++ b/tools/InterfaceGenerator/generator/parsers/__init__.py @@ -0,0 +1,3 @@ +"""Package that contains parsers from different formats to internal model +representation. +""" diff --git a/tools/InterfaceGenerator/pylint.cfg b/tools/InterfaceGenerator/pylint.cfg new file mode 100644 index 000000000..44e23eb1b --- /dev/null +++ b/tools/InterfaceGenerator/pylint.cfg @@ -0,0 +1,264 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Profiled execution. +profile=no + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + + +[MESSAGES CONTROL] + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +#disable= + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=colorized + +# Include message's id in output +include-ids=yes + +# Include symbolic ids of messages in output +symbols=no + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Add a comment according to your evaluation note. This is used by the global +# evaluation report (RP0004). +comment=no + + +[BASIC] + +# Required attributes for module, separated by a comma +required-attributes= + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,apply,input + +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression which should only match correct module level names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct instance attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct list comprehension / +# generator expression variable names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Regular expression which should only match functions or classes name which do +# not require a docstring +no-docstring-rgx=__.*__ + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=no + +# Ignore docstrings when computing similarities. +ignore-docstrings=no + +# Ignore imports when computing similarities. +ignore-imports=no + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject + +# When zope mode is activated, add a predefined set of Zope acquired attributes +# to generated-members. +zope=no + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST,acl_users,aq_parent + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the beginning of the name of dummy variables +# (i.e. not used). +dummy-variables-rgx=_|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,string,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[CLASSES] + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=10 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branchs=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=1 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/tools/InterfaceGenerator/requirements.txt b/tools/InterfaceGenerator/requirements.txt new file mode 100644 index 000000000..af21f6cb9 --- /dev/null +++ b/tools/InterfaceGenerator/requirements.txt @@ -0,0 +1,6 @@ +flake8 +pep8-naming +pep257 +mccabe +pylint +mock
\ No newline at end of file diff --git a/tools/InterfaceGenerator/runAllTests.sh b/tools/InterfaceGenerator/runAllTests.sh new file mode 100755 index 000000000..ab5b7c82c --- /dev/null +++ b/tools/InterfaceGenerator/runAllTests.sh @@ -0,0 +1 @@ +python -m unittest discover -b
\ No newline at end of file diff --git a/tools/InterfaceGenerator/test/__init__.py b/tools/InterfaceGenerator/test/__init__.py new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/tools/InterfaceGenerator/test/__init__.py diff --git a/tools/InterfaceGenerator/test/generator/__init__.py b/tools/InterfaceGenerator/test/generator/__init__.py new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/__init__.py diff --git a/tools/InterfaceGenerator/test/generator/generators/__init__.py b/tools/InterfaceGenerator/test/generator/generators/__init__.py new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/generators/__init__.py diff --git a/tools/InterfaceGenerator/test/generator/generators/test_SmartFactoryBase.py b/tools/InterfaceGenerator/test/generator/generators/test_SmartFactoryBase.py new file mode 100755 index 000000000..aea91f4a4 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/generators/test_SmartFactoryBase.py @@ -0,0 +1,283 @@ +"""Test for SmartFactory generator base. + +Verifies common helper functions and produced source code. + +""" +import collections +import unittest + +from generator.generators import SmartFactoryBase +from generator import Model + + +EXPECTED_RESULT_FULL_COMMENT = u"""/** + * @brief Enumeration Test Name. + * + * Description Line1 + * Description Line2 + * + * Design Line1 + * + * @note Issue1 + * @note Issue2 + * @note Issue3 + * + * @todo Do1 + * @todo Do2 + */""" + +EXPECTED_RESULT_ENUM_ELEMENT1 = u"""/** + * @brief InternalName. + */ +InternalName = 10""" + +EXPECTED_RESULT_ENUM_ELEMENT2 = u"""/** + * @brief NO_VALUE_ELEMENT. + * + * Description Line1 + * Description Line2 + * + * Design Line1 + */ +NO_VALUE_ELEMENT""" + +EXPECTED_RESULT_ENUM_ELEMENTS1 = u"""/** + * @brief name1. + * + * Design Line1 + * + * @todo Do1 + * @todo Do2 + */ +name1 = 1, + +/** + * @brief internal_name2. + * + * Description Line1 + * Description Line2 + * + * @note Issue1 + * @note Issue2 + * @note Issue3 + */ +internal_name2""" + +EXPECTED_RESULT_ENUM1 = u"""namespace Enum1 { +/** + * @brief Enumeration Enum1. + * + * @todo Do1 + * @todo Do2 + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief name1. + * + * Design Line1 + * + * @todo Do1 + * @todo Do2 + */ + name1 = 1, + + /** + * @brief internal_name2. + * + * Description Line1 + * Description Line2 + * + * @note Issue1 + * @note Issue2 + * @note Issue3 + */ + internal_name2 +}; +} // Enum1 +""" + +EXPECTED_RESULT_ENUM2 = u"""namespace E2 { +/** + * @brief Enumeration E2. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief val_1. + */ + val_1, + + /** + * @brief val_2. + */ + val_2 = 100, + + /** + * @brief val_3. + */ + val_3 +}; +} // E2 +""" + +DESCRIPTION = [u"Description Line1", u"Description Line2"] + +DESIGN_DESCRIPTION = [u"Design Line1"] + +ISSUES = [Model.Issue(value=u"Issue1"), + Model.Issue(value=u"Issue2"), + Model.Issue(value=u"Issue3")] + +TODOS = [u"Do1", u"Do2"] + + +class Test(unittest.TestCase): + + """Test for SmartFactory base generator. + + This class holds set of test cases for the SmartFactory base generator. + + """ + + def test_gen_comment(self): + """Test generation of the source code comments. + + Verifies correct generation of the code comments. + + """ + generator = SmartFactoryBase.CodeGenerator() + + enum = Model.Enum(name=u"Test Name", + description=DESCRIPTION, + design_description=DESIGN_DESCRIPTION, + issues=ISSUES, + todos=TODOS) + self.assertEqual(generator._gen_comment(enum), + EXPECTED_RESULT_FULL_COMMENT, + "Full comment for enum is invalid") + + def test_gen_enum_element(self): + """Test generation of the single enum element. + + Verifies correct generation of the single enum element. + + """ + generator = SmartFactoryBase.CodeGenerator() + + enum_element1 = Model.EnumElement(name=u"Element1", + internal_name=u"InternalName", + value=u"10") + + self.assertEqual( + generator._gen_enum_element(enum_element1), + EXPECTED_RESULT_ENUM_ELEMENT1, + "Short commented enum element with internal name is invalid") + + enum_element2 = Model.EnumElement( + name=u"NO_VALUE_ELEMENT", + description=DESCRIPTION, + design_description=DESIGN_DESCRIPTION) + self.assertEqual(generator._gen_enum_element(enum_element2), + EXPECTED_RESULT_ENUM_ELEMENT2, + "Enum element with no value is invalid") + + def test_gen_enum_elements(self): + """Test generation of the enum elements. + + Verifies correct generation of the enum elements. + + """ + generator = SmartFactoryBase.CodeGenerator() + + elements = [Model.EnumElement(name=u"name1", + design_description=DESIGN_DESCRIPTION, + todos=TODOS, + value=u"1"), + Model.EnumElement(name=u"name2", + description=DESCRIPTION, + issues=ISSUES, + internal_name=u"internal_name2")] + self.assertEqual(generator._gen_enum_elements(elements), + EXPECTED_RESULT_ENUM_ELEMENTS1, + "Simple enum elements are invalid") + + def test_gen_enum(self): + """Test generation of the enum. + + Verifies correct generation of the enum. + + """ + generator = SmartFactoryBase.CodeGenerator() + + elements1 = collections.OrderedDict() + elements1[u"name1"] = Model.EnumElement( + name=u"name1", + design_description=DESIGN_DESCRIPTION, + todos=TODOS, + value=u"1") + elements1[u"name2"] = Model.EnumElement( + name=u"name2", + description=DESCRIPTION, + issues=ISSUES, + internal_name=u"internal_name2") + + enum1 = Model.Enum(name=u"Enum1", + todos=TODOS, + elements=elements1) + + self.assertEqual(generator._gen_enum(enum1), + EXPECTED_RESULT_ENUM1, + "Simple enum is invalid") + + elements2 = collections.OrderedDict() + elements2[u"xxx"] = Model.EnumElement(name=u"xxx", + internal_name=u"val_1") + elements2[u"yyy"] = Model.EnumElement(name=u"yyy", + internal_name=u"val_2", + value=u"100") + elements2[u"zzz"] = Model.EnumElement(name=u"val_3") + + enum2 = Model.Enum(name=u"E2", + elements=elements2) + self.assertEqual(generator._gen_enum(enum2), + EXPECTED_RESULT_ENUM2, + "Long enum is invalid") + + self.assertEqual(generator._gen_enums([enum1, enum2], + collections.OrderedDict()), + u"{0}\n{1}".format(EXPECTED_RESULT_ENUM1, + EXPECTED_RESULT_ENUM2), + "Generated enums are invalid") + + def test_normalize_multiline_comments(self): + """Test normalization of the multiline comments. + + Verifies correct normalization of the multiline comments. + + """ + generator = SmartFactoryBase.CodeGenerator() + + self.assertEqual(generator._normalize_multiline_comments([]), []) + + self.assertEqual(generator._normalize_multiline_comments(["aaa", + "bbb", + "ccc ccc", + "ddd\tddd"]), + ["aaa", "bbb", "ccc ccc", "ddd\tddd"]) + self.assertEqual(generator._normalize_multiline_comments(["aaa\n1", + "bbb\r\n2", + "ccc\r3", + "aaa aaa"]), + ["aaa", "1", "bbb", "2", "ccc", "3", "aaa aaa"]) + +if __name__ == '__main__': + unittest.main() diff --git a/tools/InterfaceGenerator/test/generator/generators/test_SmartFactoryJSONRPC.py b/tools/InterfaceGenerator/test/generator/generators/test_SmartFactoryJSONRPC.py new file mode 100755 index 000000000..b21e32003 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/generators/test_SmartFactoryJSONRPC.py @@ -0,0 +1,482 @@ +"""Test for JSONRPC SmartFactory generator. + +Verifies format specific functions and produced source code. + +""" +import collections +import codecs +import os +import unittest +import uuid + +from mock import MagicMock +from mock import call + +from generator.generators import SmartFactoryJSONRPC +from generator import Model + + +EXPECTED_RESULT_REQUEST = ( + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<FunctionID::eType>::create(""" + u"""function_id_items), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<messageType::eType>::create(""" + u"""message_type_items), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" +) + +EXPECTED_RESULT_RESPONSE = ( + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<FunctionID::eType>::create(""" + u"""function_id_items), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<messageType::eType>::create(""" + u"""message_type_items), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::kCode] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" +) + +EXPECTED_RESULT_NOTIFICATION = ( + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<FunctionID::eType>::create(""" + u"""function_id_items), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<messageType::eType>::create(""" + u"""message_type_items), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" +) + +EXPECTED_PRE_FUNCTION_CODE = ( + u""" std::map<std::string, CObjectSchemaItem::SMember> """ + u"""params_members;\n""" + u""" params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<FunctionID::eType>::create(""" + u"""function_id_items), true);\n""" + u""" params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<messageType::eType>::create(""" + u"""message_type_items), true);\n""" + u""" params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u""" params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u""" params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u""" params_members[NsSmartDeviceLink::NsJSONHandler""" + u"""::strings::kCode] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u""" params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::kMessage] = CObjectSchemaItem::SMember(""" + u"""CStringSchemaItem::create(), true);\n""" + u"""\n""" + u""" std::map<std::string, CObjectSchemaItem::SMember> """ + u"""root_members_map;\n""" + u""" root_members_map[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PARAMS] = CObjectSchemaItem::SMember(""" + u"""CObjectSchemaItem::create(params_members), true);\n""" + u"""\n""" + u""" CSmartSchema error_response_schema(CObjectSchemaItem::create(""" + u"""root_members_map));\n""" + u"""\n""" + u""" functions_schemes_.insert(std::make_pair(""" + u"""NsSmartDeviceLink::NsJSONHandler::SmartSchemaKey<""" + u"""FunctionID::eType, messageType::eType>(""" + u"""FunctionID::request, messageType::error_response)""" + u""", error_response_schema));\n""" + u"""\n""" +) + +DESCRIPTION = [u"Description Line1", u"Description Line2"] + +DESIGN_DESCRIPTION = [u"Design Line1"] + +ISSUES = [Model.Issue(value=u"Issue1"), + Model.Issue(value=u"Issue2"), + Model.Issue(value=u"Issue3")] + +TODOS = [u"Do1", u"Do2"] + + +class Test(unittest.TestCase): + + """Test for JSONRPC SmartFactory generator. + + This class holds set of test cases for the JSONRPC SmartFactory generator. + + """ + + def test_gen_schema_params_fill(self): + """Test feature that allows to create format specific PARAMS. + + Verifies JSONRPC implementation of the _gen_schema_params_fill + method. + + """ + generator = SmartFactoryJSONRPC.CodeGenerator() + + self.assertEqual(generator._gen_schema_params_fill("request"), + EXPECTED_RESULT_REQUEST, + "Invalid code generation for request") + + self.assertEqual(generator._gen_schema_params_fill(u"request"), + EXPECTED_RESULT_REQUEST, + "Invalid code generation for request") + + self.assertEqual(generator._gen_schema_params_fill("response"), + EXPECTED_RESULT_RESPONSE, + "Invalid code generation for response") + + self.assertEqual(generator._gen_schema_params_fill(u"response"), + EXPECTED_RESULT_RESPONSE, + "Invalid code generation for response") + + self.assertEqual(generator._gen_schema_params_fill("notification"), + EXPECTED_RESULT_NOTIFICATION, + "Invalid code generation for notification") + + self.assertEqual(generator._gen_schema_params_fill(u"notification"), + EXPECTED_RESULT_NOTIFICATION, + "Invalid code generation for notification") + + def test_preprocess_message_type(self): + """Test preprocessing of the message_type enum. + + Verifies JSONPRC implementation of the _preprocess_message_type + function. + + """ + + generator = SmartFactoryJSONRPC.CodeGenerator() + + message_type_elements = collections.OrderedDict() + message_type_elements[u"request"] = Model.EnumElement(name=u"request") + message_type_elements[u"response"] = Model.EnumElement( + name=u"response") + message_type_elements[u"notification"] = Model.EnumElement( + name=u"notification") + + message_type = Model.Enum(name=u"messageType", + elements=message_type_elements) + + result_enum = generator._preprocess_message_type(message_type) + + self.assertIn("error_response", result_enum.elements) + self.assertEqual("error_response", + result_enum.elements["error_response"].primary_name) + + message_type_elements = collections.OrderedDict() + message_type_elements[u"request"] = Model.EnumElement(name=u"request") + message_type_elements[u"notification"] = Model.EnumElement( + name=u"notification") + + message_type = Model.Enum(name=u"messageType", + elements=message_type_elements) + + result_enum = generator._preprocess_message_type(message_type) + + self.assertNotIn("error_response", result_enum.elements) + + def test_gen_pre_function_schemas(self): + """Test code that goes before schema initialization. + + Verifies JSONPRC implementation of the _gen_pre_function_schemas + function. + + """ + + generator = SmartFactoryJSONRPC.CodeGenerator() + + self.assertEqual(u"", + generator._gen_pre_function_schemas([]), + "Invalid code for empty functions list") + + message_type_elements = collections.OrderedDict() + message_type_elements[u"request"] = Model.EnumElement(name=u"request") + message_type_elements[u"response"] = Model.EnumElement( + name=u"response") + message_type_elements[u"notification"] = Model.EnumElement( + name=u"notification") + + message_type = Model.Enum(name=u"messageType", + elements=message_type_elements) + + function1 = Model.Function( + "func1", function_id=message_type.elements[u"request"], + message_type=message_type.elements[u"request"]) + + self.assertEqual(u"", + generator._gen_pre_function_schemas([function1]), + "Invalid code for empty functions list") + + function2 = Model.Function( + "func2", function_id=message_type.elements[u"request"], + message_type=message_type.elements[u"response"]) + + self.assertEqual(EXPECTED_PRE_FUNCTION_CODE, + generator._gen_pre_function_schemas([function2]), + "Invalid code for single response function") + + self.assertEqual(EXPECTED_PRE_FUNCTION_CODE, + generator._gen_pre_function_schemas([function1, + function2]), + "Invalid code for mixed function list") + + def test_full_generation(self): + """Test full generation using JSONRPC SmartSchema generator. + + Creates output files which is captured by the mock and compare them + with sample files with correct code. This test requires valid + test_expected_jsonrpc.h and test_expected_jsonrpc.cc in the same + directory as this module. + + """ + + expected_h_file_content = open("test_expected_jsonrpc.h", "r").read() + expected_cc_file_content = open("test_expected_jsonrpc.cc", "r").read() + + generator = SmartFactoryJSONRPC.CodeGenerator() + + message_type_elements = collections.OrderedDict() + message_type_elements[u"request"] = Model.EnumElement(name=u"request") + message_type_elements[u"response"] = Model.EnumElement( + name=u"response") + message_type_elements[u"notification"] = Model.EnumElement( + name=u"notification") + + message_type = Model.Enum(name=u"messageType", + elements=message_type_elements) + + elements1 = collections.OrderedDict() + elements1[u"name1"] = Model.EnumElement( + name=u"name1", + design_description=DESIGN_DESCRIPTION, + todos=TODOS, + value=u"1") + elements1[u"name2"] = Model.EnumElement( + name="name2", + description=DESCRIPTION, + issues=ISSUES, + internal_name=u"internal_name2") + + enum1 = Model.Enum(name=u"Enum1", + todos=TODOS, + elements=elements1) + + elements2 = collections.OrderedDict() + elements2[u"xxx"] = Model.EnumElement(name=u"xxx", + internal_name=u"val_1") + elements2[u"yyy"] = Model.EnumElement(name=u"yyy", + internal_name=u"val_2", + value=u"100") + elements2[u"zzz"] = Model.EnumElement(name=u"val_3") + + enum2 = Model.Enum(name=u"E2", + elements=elements2) + + elements3 = collections.OrderedDict() + elements3["1"] = Model.EnumElement(name="xxx", + internal_name="_1") + elements3["2"] = Model.EnumElement(name="xxx", + internal_name="_2") + elements3["3"] = Model.EnumElement(name="xxx", + internal_name="_3") + enum3 = Model.Enum(name="Enum_new2", + elements=elements3) + + elements4 = collections.OrderedDict() + elements4["name1"] = Model.EnumElement(name="xxx", + internal_name="_11") + elements4["name2"] = Model.EnumElement(name="xxx", + internal_name="_22") + enum4 = Model.Enum(name="Enum_new4", + elements=elements4) + + enums = collections.OrderedDict() + enums["Enum1"] = enum1 + enums["Enum2"] = enum2 + enums["Enum3"] = enum3 + enums["Enum4"] = enum4 + enums["messageType"] = message_type + + params1 = collections.OrderedDict() + params1["1"] = Model.FunctionParam( + name="param1", + design_description=DESIGN_DESCRIPTION, + description=DESCRIPTION, + issues=ISSUES, + todos=TODOS, + param_type=enum4, + default_value=elements4["name1"]) + params1["2"] = Model.FunctionParam( + name="param2", + param_type=Model.EnumSubset( + name="sub1", + enum=enum1, + allowed_elements={"e1": elements1["name1"]}), + default_value=elements1["name1"]) + + functions = collections.OrderedDict() + functions["Function1"] = Model.Function( + name="Function1", + function_id=elements1["name1"], + message_type=message_type_elements["request"], + params=params1) + functions["Function2"] = Model.Function( + name="Function2", + function_id=elements2["xxx"], + message_type=message_type_elements["response"]) + functions["Function3"] = Model.Function( + name="Function2", + function_id=elements2["yyy"], + message_type=message_type_elements["notification"]) + + members1 = collections.OrderedDict() + members1["m1"] = Model.Param(name="intParam", + param_type=Model.Integer(max_value=2)) + members1["m11"] = Model.Param(name="doubleParam", + param_type=Model.Double(min_value=0.333), + is_mandatory=False) + members1["m222"] = Model.Param(name="boolParam", + param_type=Model.Boolean()) + members1["m2"] = Model.Param(name="structParam", + param_type=Model.Struct(name="Struct2")) + members1["aaa"] = Model.Param(name="enumParam", + param_type=enum1) + members1["bbb"] = Model.Param(name="enumParam1", + param_type=enum1) + members1["xxx"] = Model.Param( + name="enumSubset1", + param_type=Model.EnumSubset( + name="sub", + enum=enum1, + allowed_elements={"e1": elements1["name1"]}), + is_mandatory=False) + members1["1"] = Model.Param( + name="arrayOfInt", + param_type=Model.Array(min_size=0, + max_size=20, + element_type=Model.Boolean()), + is_mandatory=False) + members1["2"] = Model.Param( + name="arrayOfEnum1", + param_type=Model.Array(min_size=0, + max_size=20, + element_type=enum1), + is_mandatory=False) + members1["3"] = Model.Param( + name="arrayOfEnum3", + param_type=Model.Array(min_size=10, + max_size=40, + element_type=enum3), + is_mandatory=True) + members1["4"] = Model.Param( + name="arrayOfEnum4", + param_type=Model.Array( + min_size=10, + max_size=41, + element_type=Model.EnumSubset( + name="sub1", + enum=enum1, + allowed_elements={"e1": elements1["name1"]}))) + members1["5"] = Model.Param( + name="arrayOfEnum5", + param_type=Model.Array( + min_size=10, + max_size=42, + element_type=Model.EnumSubset( + name="sub2", + enum=enum1, + allowed_elements={"e1": elements1["name2"]}))) + members1["6"] = Model.Param( + name="arrayOfEnum6", + param_type=Model.Array( + min_size=10, + max_size=43, + element_type=Model.EnumSubset( + name="sub3", + enum=enum4, + allowed_elements={"e1": elements4["name2"]}))) + + structs = collections.OrderedDict() + structs["Struct1"] = Model.Struct( + name="Struct1", + design_description=DESIGN_DESCRIPTION, + issues=ISSUES, + members=members1) + structs["Struct2"] = Model.Struct(name="Struct2", + issues=ISSUES) + + interface = Model.Interface(enums=enums, + structs=structs, + functions=functions, + params={"param1": "value1", + "param2": "value2"}) + + os.path.exists = MagicMock(return_value=True) + uuid.uuid1 = MagicMock( + return_value=uuid.UUID("12345678123456781234567812345678")) + codecs.open = MagicMock() + + generator.generate(interface=interface, + filename="Test.xml", + namespace="XXX::YYY::ZZZ", + destination_dir="/some/test/dir") + + os.path.exists.assert_has_calls([call('/some/test/dir')]) + + open_result = codecs.open + mock_calls = open_result.mock_calls + + self.assertEqual(mock_calls[0], + call('/some/test/dir/Test.h', + mode='w', + encoding='utf-8'), + "Invalid header file creation") + + self.assertEqual(mock_calls[4], + call('/some/test/dir/Test.cc', + mode='w', + encoding='utf-8'), + "Invalid source file creation") + + self.assertEqual(str(mock_calls[2])[27:-2].replace("\\n", "\n"), + expected_h_file_content, + "Invalid header file content") + + self.assertEqual(str(mock_calls[6])[27:-2].replace("\\n", "\n"), + expected_cc_file_content, + "Invalid source file content") diff --git a/tools/InterfaceGenerator/test/generator/generators/test_SmartFactorySDLRPC.py b/tools/InterfaceGenerator/test/generator/generators/test_SmartFactorySDLRPC.py new file mode 100755 index 000000000..111ffb3cb --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/generators/test_SmartFactorySDLRPC.py @@ -0,0 +1,325 @@ +"""Test for SDLRPC SmartFactory generator. + +Verifies format specific functions and produced source code. + +""" +import collections +import codecs +import os +import unittest +import uuid + +from mock import MagicMock +from mock import call + +from generator.generators import SmartFactorySDLRPC +from generator import Model + + +EXPECTED_NOTIFICATION_RESULT = ( + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<FunctionID::eType>::create(""" + u"""function_id_items), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(""" + u"""TEnumSchemaItem<messageType::eType>::create(""" + u"""message_type_items), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""" + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""") + +EXPECTED_REQ_RESP_RESULT = "".join([EXPECTED_NOTIFICATION_RESULT, ( + u"""params_members[NsSmartDeviceLink::NsJSONHandler::""" + u"""strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(""" + u"""TNumberSchemaItem<int>::create(), true);\n""")]) + +DESCRIPTION = [u"Description Line1", u"Description Line2"] + +DESIGN_DESCRIPTION = [u"Design Line1"] + +ISSUES = [Model.Issue(value=u"Issue1"), + Model.Issue(value=u"Issue2"), + Model.Issue(value=u"Issue3")] + +TODOS = [u"Do1", u"Do2"] + + +class Test(unittest.TestCase): + + """Test for SLDRPC SmartFactory generator. + + This class holds set of test cases for the SDLRPC SmartFactory generator. + + """ + + def test_gen_schema_params_fill(self): + """Test feature that allows to create format specific PARAMS. + + Verifies SDLRPC implementation of the _gen_schema_params_fill + method. + + """ + + generator = SmartFactorySDLRPC.CodeGenerator() + + self.assertEqual(generator._gen_schema_params_fill("request"), + EXPECTED_REQ_RESP_RESULT, + "Invalid code generation for request") + + self.assertEqual(generator._gen_schema_params_fill(u"request"), + EXPECTED_REQ_RESP_RESULT, + "Invalid code generation for request") + + self.assertEqual(generator._gen_schema_params_fill("response"), + EXPECTED_REQ_RESP_RESULT, + "Invalid code generation for response") + + self.assertEqual(generator._gen_schema_params_fill(u"response"), + EXPECTED_REQ_RESP_RESULT, + "Invalid code generation for response") + + self.assertEqual(generator._gen_schema_params_fill("notification"), + EXPECTED_NOTIFICATION_RESULT, + "Invalid code generation for notification") + + self.assertEqual(generator._gen_schema_params_fill(u"notification"), + EXPECTED_NOTIFICATION_RESULT, + "Invalid code generation for notification") + + self.assertEqual(generator._gen_schema_params_fill("some text"), + EXPECTED_REQ_RESP_RESULT, + "Invalid code generation") + + self.assertEqual(generator._gen_schema_params_fill(u"some text"), + EXPECTED_REQ_RESP_RESULT, + "Invalid code generation") + + def test_full_generation(self): + """Test full generation using SDLPRC SmartSchema generator. + + Creates output files which is captured by the mock and compare them + with sample files with correct code. This test requires valid + test_expected_sdlrpc.h and test_expected_sdlrpc.cc in the same as + this module. + + """ + + expected_h_file_content = open("test_expected_sdlrpc.h", "r").read() + expected_cc_file_content = open("test_expected_sdlrpc.cc", "r").read() + + generator = SmartFactorySDLRPC.CodeGenerator() + + message_type_elements = collections.OrderedDict() + message_type_elements[u"request"] = Model.EnumElement(name=u"request") + message_type_elements[u"response"] = Model.EnumElement( + name=u"response") + message_type_elements[u"notification"] = Model.EnumElement( + name=u"notification") + + message_type = Model.Enum(name=u"messageType", + elements=message_type_elements) + + elements1 = collections.OrderedDict() + elements1[u"name1"] = Model.EnumElement( + name=u"name1", + design_description=DESIGN_DESCRIPTION, + todos=TODOS, + value=u"1") + elements1[u"name2"] = Model.EnumElement( + name="name2", + description=DESCRIPTION, + issues=ISSUES, + internal_name=u"internal_name2") + + enum1 = Model.Enum(name=u"Enum1", + todos=TODOS, + elements=elements1) + + elements2 = collections.OrderedDict() + elements2[u"xxx"] = Model.EnumElement(name=u"xxx", + internal_name=u"val_1") + elements2[u"yyy"] = Model.EnumElement(name=u"yyy", + internal_name=u"val_2", + value=u"100") + elements2[u"zzz"] = Model.EnumElement(name=u"val_3") + + enum2 = Model.Enum(name=u"E2", + elements=elements2) + + elements3 = collections.OrderedDict() + elements3["1"] = Model.EnumElement(name="xxx", + internal_name="_1") + elements3["2"] = Model.EnumElement(name="xxx", + internal_name="_2") + elements3["3"] = Model.EnumElement(name="xxx", + internal_name="_3") + enum3 = Model.Enum(name="Enum_new2", + elements=elements3) + + elements4 = collections.OrderedDict() + elements4["name1"] = Model.EnumElement(name="xxx", + internal_name="_11") + elements4["name2"] = Model.EnumElement(name="xxx", + internal_name="_22") + enum4 = Model.Enum(name="Enum_new4", + elements=elements4) + + enums = collections.OrderedDict() + enums["Enum1"] = enum1 + enums["Enum2"] = enum2 + enums["Enum3"] = enum3 + enums["Enum4"] = enum4 + enums["messageType"] = message_type + + params1 = collections.OrderedDict() + params1["1"] = Model.FunctionParam( + name="param1", + design_description=DESIGN_DESCRIPTION, + description=DESCRIPTION, + issues=ISSUES, + todos=TODOS, + param_type=enum4, + default_value=elements4["name1"]) + params1["2"] = Model.FunctionParam( + name="param2", + param_type=Model.EnumSubset( + name="sub1", + enum=enum1, + allowed_elements={"e1": elements1["name1"]}), + default_value=elements1["name1"]) + + functions = collections.OrderedDict() + functions["Function1"] = Model.Function( + name="Function1", + function_id=elements1["name1"], + message_type=message_type_elements["request"], + params=params1) + functions["Function2"] = Model.Function( + name="Function2", + function_id=elements2["xxx"], + message_type=message_type_elements["response"]) + functions["Function3"] = Model.Function( + name="Function2", + function_id=elements2["yyy"], + message_type=message_type_elements["notification"]) + + members1 = collections.OrderedDict() + members1["m1"] = Model.Param(name="intParam", + param_type=Model.Integer(max_value=2)) + members1["m11"] = Model.Param(name="doubleParam", + param_type=Model.Double(min_value=0.333), + is_mandatory=False) + members1["m222"] = Model.Param(name="boolParam", + param_type=Model.Boolean()) + members1["m2"] = Model.Param(name="structParam", + param_type=Model.Struct(name="Struct2")) + members1["aaa"] = Model.Param(name="enumParam", + param_type=enum1) + members1["bbb"] = Model.Param(name="enumParam1", + param_type=enum1) + members1["xxx"] = Model.Param( + name="enumSubset1", + param_type=Model.EnumSubset( + name="sub", + enum=enum1, + allowed_elements={"e1": elements1["name1"]}), + is_mandatory=False) + members1["1"] = Model.Param( + name="arrayOfInt", + param_type=Model.Array(min_size=0, + max_size=20, + element_type=Model.Boolean()), + is_mandatory=False) + members1["2"] = Model.Param( + name="arrayOfEnum1", + param_type=Model.Array(min_size=0, + max_size=20, + element_type=enum1), + is_mandatory=False) + members1["3"] = Model.Param( + name="arrayOfEnum3", + param_type=Model.Array(min_size=10, + max_size=40, + element_type=enum3), + is_mandatory=True) + members1["4"] = Model.Param( + name="arrayOfEnum4", + param_type=Model.Array( + min_size=10, + max_size=41, + element_type=Model.EnumSubset( + name="sub1", + enum=enum1, + allowed_elements={"e1": elements1["name1"]}))) + members1["5"] = Model.Param( + name="arrayOfEnum5", + param_type=Model.Array( + min_size=10, + max_size=42, + element_type=Model.EnumSubset( + name="sub2", + enum=enum1, + allowed_elements={"e1": elements1["name2"]}))) + members1["6"] = Model.Param( + name="arrayOfEnum6", + param_type=Model.Array( + min_size=10, + max_size=43, + element_type=Model.EnumSubset( + name="sub3", + enum=enum4, + allowed_elements={"e1": elements4["name2"]}))) + + structs = collections.OrderedDict() + structs["Struct1"] = Model.Struct( + name="Struct1", + design_description=DESIGN_DESCRIPTION, + issues=ISSUES, + members=members1) + structs["Struct2"] = Model.Struct(name="Struct2", + issues=ISSUES) + + interface = Model.Interface(enums=enums, + structs=structs, + functions=functions, + params={"param1": "value1", + "param2": "value2"}) + + os.path.exists = MagicMock(return_value=True) + uuid.uuid1 = MagicMock( + return_value=uuid.UUID("12345678123456781234567812345678")) + codecs.open = MagicMock() + + generator.generate(interface=interface, + filename="Test.xml", + namespace="XXX::YYY::ZZZ", + destination_dir="/some/test/dir") + + os.path.exists.assert_has_calls([call('/some/test/dir')]) + + open_result = codecs.open + mock_calls = open_result.mock_calls + + self.assertEqual(mock_calls[0], + call('/some/test/dir/Test.h', + mode='w', + encoding='utf-8'), + "Invalid header file creation") + + self.assertEqual(mock_calls[4], + call('/some/test/dir/Test.cc', + mode='w', + encoding='utf-8'), + "Invalid source file creation") + + self.assertEqual(str(mock_calls[2])[27:-2].replace("\\n", "\n"), + expected_h_file_content, + "Invalid header file content") + + self.assertEqual(str(mock_calls[6])[27:-2].replace("\\n", "\n"), + expected_cc_file_content, + "Invalid source file content") diff --git a/tools/InterfaceGenerator/test/generator/generators/test_expected_jsonrpc.cc b/tools/InterfaceGenerator/test/generator/generators/test_expected_jsonrpc.cc new file mode 100644 index 000000000..458c27543 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/generators/test_expected_jsonrpc.cc @@ -0,0 +1,385 @@ +/** + * @file Test.cc + * @brief Generated class Test source file. + * + * This class is a part of SmartObjects solution. It provides + * factory functionallity which allows client to use SmartSchemas + * in accordance with definitions from Test.xml file + */ +// Copyright (c) 2013, 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 <map> +#include <set> + +#include "Test.h" +#include "SmartObjects/CAlwaysTrueSchemaItem.hpp" +#include "SmartObjects/CAlwaysFalseSchemaItem.hpp" +#include "SmartObjects/CArraySchemaItem.hpp" +#include "SmartObjects/CBoolSchemaItem.hpp" +#include "SmartObjects/CObjectSchemaItem.hpp" +#include "SmartObjects/CStringSchemaItem.hpp" +#include "SmartObjects/TEnumSchemaItem.hpp" +#include "SmartObjects/TNumberSchemaItem.hpp" +#include "SmartObjects/TSchemaItemParameter.hpp" + +using namespace NsSmartDeviceLink::NsSmartObjects; + +XXX::YYY::ZZZ::Test::Test() + : CSmartFactory<FunctionID::eType, messageType::eType, StructIdentifiers::eType>() { + TStructsSchemaItems struct_schema_items; + InitStructSchemes(struct_schema_items); + + std::set<FunctionID::eType> function_id_items; + + + std::set<messageType::eType> message_type_items; + message_type_items.insert(messageType::request); + message_type_items.insert(messageType::response); + message_type_items.insert(messageType::notification); + message_type_items.insert(messageType::error_response); + + InitFunctionSchemes(struct_schema_items, function_id_items, message_type_items); +} + +TSharedPtr<ISchemaItem> XXX::YYY::ZZZ::Test::ProvideObjectSchemaItemForStruct( + const TStructsSchemaItems &struct_schema_items, + const StructIdentifiers::eType struct_id) { + const TStructsSchemaItems::const_iterator it = struct_schema_items.find(struct_id); + if (it != struct_schema_items.end()) { + return it->second; + } + + return NsSmartDeviceLink::NsSmartObjects::CAlwaysFalseSchemaItem::create(); +} + +void XXX::YYY::ZZZ::Test::InitStructSchemes( + TStructsSchemaItems &struct_schema_items) { + TSharedPtr<ISchemaItem> struct_schema_item_Struct2 = InitStructSchemaItem_Struct2(struct_schema_items); + struct_schema_items.insert(std::make_pair(StructIdentifiers::Struct2, struct_schema_item_Struct2)); + structs_schemes_.insert(std::make_pair(StructIdentifiers::Struct2, CSmartSchema(struct_schema_item_Struct2))); + + TSharedPtr<ISchemaItem> struct_schema_item_Struct1 = InitStructSchemaItem_Struct1(struct_schema_items); + struct_schema_items.insert(std::make_pair(StructIdentifiers::Struct1, struct_schema_item_Struct1)); + structs_schemes_.insert(std::make_pair(StructIdentifiers::Struct1, CSmartSchema(struct_schema_item_Struct1))); +} + +void XXX::YYY::ZZZ::Test::InitFunctionSchemes( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items) { + std::map<std::string, CObjectSchemaItem::SMember> params_members; + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(TEnumSchemaItem<FunctionID::eType>::create(function_id_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(TEnumSchemaItem<messageType::eType>::create(message_type_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::kCode] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::kMessage] = CObjectSchemaItem::SMember(CStringSchemaItem::create(), true); + + std::map<std::string, CObjectSchemaItem::SMember> root_members_map; + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(params_members), true); + + CSmartSchema error_response_schema(CObjectSchemaItem::create(root_members_map)); + + functions_schemes_.insert(std::make_pair(NsSmartDeviceLink::NsJSONHandler::SmartSchemaKey<FunctionID::eType, messageType::eType>(FunctionID::val_1, messageType::error_response), error_response_schema)); + + functions_schemes_.insert(std::make_pair(NsSmartDeviceLink::NsJSONHandler::SmartSchemaKey<FunctionID::eType, messageType::eType>(FunctionID::name1, messageType::request), InitFunction_name1_request(struct_schema_items, function_id_items, message_type_items))); + functions_schemes_.insert(std::make_pair(NsSmartDeviceLink::NsJSONHandler::SmartSchemaKey<FunctionID::eType, messageType::eType>(FunctionID::val_1, messageType::response), InitFunction_val_1_response(struct_schema_items, function_id_items, message_type_items))); + functions_schemes_.insert(std::make_pair(NsSmartDeviceLink::NsJSONHandler::SmartSchemaKey<FunctionID::eType, messageType::eType>(FunctionID::val_2, messageType::notification), InitFunction_val_2_notification(struct_schema_items, function_id_items, message_type_items))); +} + +//------------- Functions schemes initialization ------------- + +CSmartSchema XXX::YYY::ZZZ::Test::InitFunction_name1_request( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items) { + std::set<Enum_new4::eType> Enum_new4_all_enum_values; + Enum_new4_all_enum_values.insert(Enum_new4::_11); + Enum_new4_all_enum_values.insert(Enum_new4::_22); + + std::set<Enum1::eType> param2_allowed_enum_subset_values; + param2_allowed_enum_subset_values.insert(Enum1::name1); + + // Function parameter param1. + // + // Description Line1 + // Description Line2 + // + // Design Line1 + // + // Note: Issue1 + // Note: Issue2 + // Note: Issue3 + // + // ToDo: Do1 + // ToDo: Do2 + TSharedPtr<ISchemaItem> param1_SchemaItem = TEnumSchemaItem<Enum_new4::eType>::create(Enum_new4_all_enum_values, TSchemaItemParameter<Enum_new4::eType>(Enum_new4::_11)); + + // Function parameter param2. + TSharedPtr<ISchemaItem> param2_SchemaItem = TEnumSchemaItem<Enum1::eType>::create(param2_allowed_enum_subset_values, TSchemaItemParameter<Enum1::eType>(name1)); + + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + schema_members["param1"] = CObjectSchemaItem::SMember(param1_SchemaItem, true); + schema_members["param2"] = CObjectSchemaItem::SMember(param2_SchemaItem, true); + + std::map<std::string, CObjectSchemaItem::SMember> params_members; + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(TEnumSchemaItem<FunctionID::eType>::create(function_id_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(TEnumSchemaItem<messageType::eType>::create(message_type_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + + std::map<std::string, CObjectSchemaItem::SMember> root_members_map; + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_MSG_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(schema_members), true); + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(params_members), true); + + return CSmartSchema(CObjectSchemaItem::create(root_members_map)); +} + +CSmartSchema XXX::YYY::ZZZ::Test::InitFunction_val_1_response( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items) { + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + std::map<std::string, CObjectSchemaItem::SMember> params_members; + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(TEnumSchemaItem<FunctionID::eType>::create(function_id_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(TEnumSchemaItem<messageType::eType>::create(message_type_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::kCode] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + + std::map<std::string, CObjectSchemaItem::SMember> root_members_map; + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_MSG_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(schema_members), true); + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(params_members), true); + + return CSmartSchema(CObjectSchemaItem::create(root_members_map)); +} + +CSmartSchema XXX::YYY::ZZZ::Test::InitFunction_val_2_notification( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items) { + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + std::map<std::string, CObjectSchemaItem::SMember> params_members; + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(TEnumSchemaItem<FunctionID::eType>::create(function_id_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(TEnumSchemaItem<messageType::eType>::create(message_type_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + + std::map<std::string, CObjectSchemaItem::SMember> root_members_map; + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_MSG_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(schema_members), true); + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(params_members), true); + + return CSmartSchema(CObjectSchemaItem::create(root_members_map)); +} + +//----------- Structs schema items initialization ------------ + +TSharedPtr<ISchemaItem> XXX::YYY::ZZZ::Test::InitStructSchemaItem_Struct1( + const TStructsSchemaItems &struct_schema_items) { + std::set<Enum1::eType> Enum1_all_enum_values; + Enum1_all_enum_values.insert(Enum1::name1); + Enum1_all_enum_values.insert(Enum1::internal_name2); + + std::set<Enum1::eType> enumSubset1_allowed_enum_subset_values; + enumSubset1_allowed_enum_subset_values.insert(Enum1::name1); + + std::set<Enum_new2::eType> Enum_new2_all_enum_values; + Enum_new2_all_enum_values.insert(Enum_new2::_1); + Enum_new2_all_enum_values.insert(Enum_new2::_2); + Enum_new2_all_enum_values.insert(Enum_new2::_3); + + std::set<Enum1::eType> sub1_allowed_enum_subset_values; + sub1_allowed_enum_subset_values.insert(Enum1::name1); + + std::set<Enum1::eType> sub2_allowed_enum_subset_values; + sub2_allowed_enum_subset_values.insert(Enum1::internal_name2); + + std::set<Enum_new4::eType> sub3_allowed_enum_subset_values; + sub3_allowed_enum_subset_values.insert(Enum_new4::_22); + + // Struct member intParam. + TSharedPtr<ISchemaItem> intParam_SchemaItem = TNumberSchemaItem<int>::create(TSchemaItemParameter<int>(), TSchemaItemParameter<int>(2), TSchemaItemParameter<int>()); + + // Struct member doubleParam. + TSharedPtr<ISchemaItem> doubleParam_SchemaItem = TNumberSchemaItem<double>::create(TSchemaItemParameter<double>(0.333), TSchemaItemParameter<double>(), TSchemaItemParameter<double>()); + + // Struct member boolParam. + TSharedPtr<ISchemaItem> boolParam_SchemaItem = CBoolSchemaItem::create(TSchemaItemParameter<bool>()); + + // Struct member structParam. + TSharedPtr<ISchemaItem> structParam_SchemaItem = ProvideObjectSchemaItemForStruct(struct_schema_items, StructIdentifiers::Struct2); + + // Struct member enumParam. + TSharedPtr<ISchemaItem> enumParam_SchemaItem = TEnumSchemaItem<Enum1::eType>::create(Enum1_all_enum_values, TSchemaItemParameter<Enum1::eType>()); + + // Struct member enumParam1. + TSharedPtr<ISchemaItem> enumParam1_SchemaItem = TEnumSchemaItem<Enum1::eType>::create(Enum1_all_enum_values, TSchemaItemParameter<Enum1::eType>()); + + // Struct member enumSubset1. + TSharedPtr<ISchemaItem> enumSubset1_SchemaItem = TEnumSchemaItem<Enum1::eType>::create(enumSubset1_allowed_enum_subset_values, TSchemaItemParameter<Enum1::eType>()); + + // Struct member arrayOfInt. + TSharedPtr<ISchemaItem> arrayOfInt_SchemaItem = CArraySchemaItem::create(CBoolSchemaItem::create(TSchemaItemParameter<bool>()), TSchemaItemParameter<size_t>(0), TSchemaItemParameter<size_t>(20)); + + // Struct member arrayOfEnum1. + TSharedPtr<ISchemaItem> arrayOfEnum1_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum1::eType>::create(Enum1_all_enum_values, TSchemaItemParameter<Enum1::eType>()), TSchemaItemParameter<size_t>(0), TSchemaItemParameter<size_t>(20)); + + // Struct member arrayOfEnum3. + TSharedPtr<ISchemaItem> arrayOfEnum3_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum_new2::eType>::create(Enum_new2_all_enum_values, TSchemaItemParameter<Enum_new2::eType>()), TSchemaItemParameter<size_t>(10), TSchemaItemParameter<size_t>(40)); + + // Struct member arrayOfEnum4. + TSharedPtr<ISchemaItem> arrayOfEnum4_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum1::eType>::create(sub1_allowed_enum_subset_values, TSchemaItemParameter<Enum1::eType>()), TSchemaItemParameter<size_t>(10), TSchemaItemParameter<size_t>(41)); + + // Struct member arrayOfEnum5. + TSharedPtr<ISchemaItem> arrayOfEnum5_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum1::eType>::create(sub2_allowed_enum_subset_values, TSchemaItemParameter<Enum1::eType>()), TSchemaItemParameter<size_t>(10), TSchemaItemParameter<size_t>(42)); + + // Struct member arrayOfEnum6. + TSharedPtr<ISchemaItem> arrayOfEnum6_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum_new4::eType>::create(sub3_allowed_enum_subset_values, TSchemaItemParameter<Enum_new4::eType>()), TSchemaItemParameter<size_t>(10), TSchemaItemParameter<size_t>(43)); + + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + schema_members["intParam"] = CObjectSchemaItem::SMember(intParam_SchemaItem, true); + schema_members["doubleParam"] = CObjectSchemaItem::SMember(doubleParam_SchemaItem, false); + schema_members["boolParam"] = CObjectSchemaItem::SMember(boolParam_SchemaItem, true); + schema_members["structParam"] = CObjectSchemaItem::SMember(structParam_SchemaItem, true); + schema_members["enumParam"] = CObjectSchemaItem::SMember(enumParam_SchemaItem, true); + schema_members["enumParam1"] = CObjectSchemaItem::SMember(enumParam1_SchemaItem, true); + schema_members["enumSubset1"] = CObjectSchemaItem::SMember(enumSubset1_SchemaItem, false); + schema_members["arrayOfInt"] = CObjectSchemaItem::SMember(arrayOfInt_SchemaItem, false); + schema_members["arrayOfEnum1"] = CObjectSchemaItem::SMember(arrayOfEnum1_SchemaItem, false); + schema_members["arrayOfEnum3"] = CObjectSchemaItem::SMember(arrayOfEnum3_SchemaItem, true); + schema_members["arrayOfEnum4"] = CObjectSchemaItem::SMember(arrayOfEnum4_SchemaItem, true); + schema_members["arrayOfEnum5"] = CObjectSchemaItem::SMember(arrayOfEnum5_SchemaItem, true); + schema_members["arrayOfEnum6"] = CObjectSchemaItem::SMember(arrayOfEnum6_SchemaItem, true); + + return CObjectSchemaItem::create(schema_members); +} + +TSharedPtr<ISchemaItem> XXX::YYY::ZZZ::Test::InitStructSchemaItem_Struct2( + const TStructsSchemaItems &struct_schema_items) { + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + return CObjectSchemaItem::create(schema_members); +} + +//-------------- String to value enum mapping ---------------- + +namespace NsSmartDeviceLink { +namespace NsSmartObjects { + +template <> +const std::map<XXX::YYY::ZZZ::Enum1::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::Enum1::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::Enum1::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum1::name1, "name1")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum1::internal_name2, "name2")); + + is_initialized = true; + } + + return enum_string_representation; +} + +template <> +const std::map<XXX::YYY::ZZZ::E2::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::E2::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::E2::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::E2::val_1, "xxx")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::E2::val_2, "yyy")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::E2::val_3, "val_3")); + + is_initialized = true; + } + + return enum_string_representation; +} + +template <> +const std::map<XXX::YYY::ZZZ::Enum_new2::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::Enum_new2::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::Enum_new2::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new2::_1, "xxx")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new2::_2, "xxx")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new2::_3, "xxx")); + + is_initialized = true; + } + + return enum_string_representation; +} + +template <> +const std::map<XXX::YYY::ZZZ::Enum_new4::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::Enum_new4::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::Enum_new4::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new4::_11, "xxx")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new4::_22, "xxx")); + + is_initialized = true; + } + + return enum_string_representation; +} + +template <> +const std::map<XXX::YYY::ZZZ::messageType::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::messageType::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::messageType::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::messageType::request, "request")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::messageType::response, "response")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::messageType::notification, "notification")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::messageType::error_response, "error_response")); + + is_initialized = true; + } + + return enum_string_representation; +} + +} // NsSmartObjects +} // NsSmartDeviceLink + diff --git a/tools/InterfaceGenerator/test/generator/generators/test_expected_jsonrpc.h b/tools/InterfaceGenerator/test/generator/generators/test_expected_jsonrpc.h new file mode 100644 index 000000000..b26560348 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/generators/test_expected_jsonrpc.h @@ -0,0 +1,326 @@ +/** + * @file Test.h + * @brief Generated class Test header file. + * + * This class is a part of SmartObjects solution. It provides + * factory functionallity which allows client to use SmartSchemas + * in accordance with definitions from Test.xml file + */ +// Copyright (c) 2013, Ford Motor Company +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with the +// distribution. +// +// Neither the name of the Ford Motor Company nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef __CSMARTFACTORY_TEST_12345678123456781234567812345678_H__ +#define __CSMARTFACTORY_TEST_12345678123456781234567812345678_H__ + +#include "JSONHandler/CSmartFactory.hpp" +#include "SmartObjects/CSmartSchema.hpp" +#include "SmartObjects/ISchemaItem.hpp" +#include "SmartObjects/TSharedPtr.hpp" + +namespace XXX { +namespace YYY { +namespace ZZZ { + +namespace StructIdentifiers { +/** + * @brief Enumeration StructIdentifiers. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief Struct1. + */ + Struct1, + + /** + * @brief Struct2. + */ + Struct2 +}; +} // StructIdentifiers + +namespace Enum1 { +/** + * @brief Enumeration Enum1. + * + * @todo Do1 + * @todo Do2 + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief name1. + * + * Design Line1 + * + * @todo Do1 + * @todo Do2 + */ + name1 = 1, + + /** + * @brief internal_name2. + * + * Description Line1 + * Description Line2 + * + * @note Issue1 + * @note Issue2 + * @note Issue3 + */ + internal_name2 +}; +} // Enum1 + +namespace E2 { +/** + * @brief Enumeration E2. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief val_1. + */ + val_1, + + /** + * @brief val_2. + */ + val_2 = 100, + + /** + * @brief val_3. + */ + val_3 +}; +} // E2 + +namespace Enum_new2 { +/** + * @brief Enumeration Enum_new2. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief _1. + */ + _1, + + /** + * @brief _2. + */ + _2, + + /** + * @brief _3. + */ + _3 +}; +} // Enum_new2 + +namespace Enum_new4 { +/** + * @brief Enumeration Enum_new4. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief _11. + */ + _11, + + /** + * @brief _22. + */ + _22 +}; +} // Enum_new4 + +namespace messageType { +/** + * @brief Enumeration messageType. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief request. + */ + request, + + /** + * @brief response. + */ + response, + + /** + * @brief notification. + */ + notification, + + /** + * @brief error_response. + */ + error_response +}; +} // messageType + + +/** + * @brief Class Test. + * + * Params: + * param2 - value2 + * param1 - value1 + */ +class Test : public NsSmartDeviceLink::NsJSONHandler::CSmartFactory<FunctionID::eType, messageType::eType, StructIdentifiers::eType> { + public: + /** + * @brief Constructor. + */ + Test(); + + protected: + /** + * @brief Type that maps of struct IDs to schema items. + */ + typedef std::map<const StructIdentifiers::eType, NsSmartDeviceLink::NsSmartObjects::TSharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> > TStructsSchemaItems; + + /** + * @brief Helper that allows to make reference to struct + * + * @param struct_schema_items Struct schema items. + * @param struct_id ID of structure to provide. + * + * @return TSharedPtr of strucute + */ + static NsSmartDeviceLink::NsSmartObjects::TSharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> ProvideObjectSchemaItemForStruct( + const TStructsSchemaItems &struct_schema_items, + const StructIdentifiers::eType struct_id); + + /** + * @brief Initializes all struct schemes. + */ + void InitStructSchemes(TStructsSchemaItems &struct_schema_items); + + /** + * @brief Initializes all function schemes. + * + * @param struct_schema_items Struct schema items. + * @param function_id_items Set of all elements of FunctionID enum. + * @param message_type_items Set of all elements of messageType enum. + */ + void InitFunctionSchemes( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items); + + /** + * @brief Method that generates schema for function Function1. + * + * @return NsSmartDeviceLink::NsSmartObjects::CSmartSchema + */ + static NsSmartDeviceLink::NsSmartObjects::CSmartSchema InitFunction_name1_request( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items); + + /** + * @brief Method that generates schema for function Function2. + * + * @return NsSmartDeviceLink::NsSmartObjects::CSmartSchema + */ + static NsSmartDeviceLink::NsSmartObjects::CSmartSchema InitFunction_val_1_response( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items); + + /** + * @brief Method that generates schema for function Function2. + * + * @return NsSmartDeviceLink::NsSmartObjects::CSmartSchema + */ + static NsSmartDeviceLink::NsSmartObjects::CSmartSchema InitFunction_val_2_notification( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items); + + /** + * @brief Method that generates schema item for structure Struct1. + * + * Design Line1 + * + * @note Issue1 + * @note Issue2 + * @note Issue3 + */ + static NsSmartDeviceLink::NsSmartObjects::TSharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> InitStructSchemaItem_Struct1( + const TStructsSchemaItems &struct_schema_items); + + /** + * @brief Method that generates schema item for structure Struct2. + * + * @note Issue1 + * @note Issue2 + * @note Issue3 + */ + static NsSmartDeviceLink::NsSmartObjects::TSharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> InitStructSchemaItem_Struct2( + const TStructsSchemaItems &struct_schema_items); +}; + +} // XXX +} // YYY +} // ZZZ + +#endif //__CSMARTFACTORY_TEST_12345678123456781234567812345678_H__ + diff --git a/tools/InterfaceGenerator/test/generator/generators/test_expected_sdlrpc.cc b/tools/InterfaceGenerator/test/generator/generators/test_expected_sdlrpc.cc new file mode 100644 index 000000000..53e5b7f78 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/generators/test_expected_sdlrpc.cc @@ -0,0 +1,366 @@ +/** + * @file Test.cc + * @brief Generated class Test source file. + * + * This class is a part of SmartObjects solution. It provides + * factory functionallity which allows client to use SmartSchemas + * in accordance with definitions from Test.xml file + */ +// Copyright (c) 2013, 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 <map> +#include <set> + +#include "Test.h" +#include "SmartObjects/CAlwaysTrueSchemaItem.hpp" +#include "SmartObjects/CAlwaysFalseSchemaItem.hpp" +#include "SmartObjects/CArraySchemaItem.hpp" +#include "SmartObjects/CBoolSchemaItem.hpp" +#include "SmartObjects/CObjectSchemaItem.hpp" +#include "SmartObjects/CStringSchemaItem.hpp" +#include "SmartObjects/TEnumSchemaItem.hpp" +#include "SmartObjects/TNumberSchemaItem.hpp" +#include "SmartObjects/TSchemaItemParameter.hpp" + +using namespace NsSmartDeviceLink::NsSmartObjects; + +XXX::YYY::ZZZ::Test::Test() + : CSmartFactory<FunctionID::eType, messageType::eType, StructIdentifiers::eType>() { + TStructsSchemaItems struct_schema_items; + InitStructSchemes(struct_schema_items); + + std::set<FunctionID::eType> function_id_items; + + + std::set<messageType::eType> message_type_items; + message_type_items.insert(messageType::request); + message_type_items.insert(messageType::response); + message_type_items.insert(messageType::notification); + + InitFunctionSchemes(struct_schema_items, function_id_items, message_type_items); +} + +TSharedPtr<ISchemaItem> XXX::YYY::ZZZ::Test::ProvideObjectSchemaItemForStruct( + const TStructsSchemaItems &struct_schema_items, + const StructIdentifiers::eType struct_id) { + const TStructsSchemaItems::const_iterator it = struct_schema_items.find(struct_id); + if (it != struct_schema_items.end()) { + return it->second; + } + + return NsSmartDeviceLink::NsSmartObjects::CAlwaysFalseSchemaItem::create(); +} + +void XXX::YYY::ZZZ::Test::InitStructSchemes( + TStructsSchemaItems &struct_schema_items) { + TSharedPtr<ISchemaItem> struct_schema_item_Struct2 = InitStructSchemaItem_Struct2(struct_schema_items); + struct_schema_items.insert(std::make_pair(StructIdentifiers::Struct2, struct_schema_item_Struct2)); + structs_schemes_.insert(std::make_pair(StructIdentifiers::Struct2, CSmartSchema(struct_schema_item_Struct2))); + + TSharedPtr<ISchemaItem> struct_schema_item_Struct1 = InitStructSchemaItem_Struct1(struct_schema_items); + struct_schema_items.insert(std::make_pair(StructIdentifiers::Struct1, struct_schema_item_Struct1)); + structs_schemes_.insert(std::make_pair(StructIdentifiers::Struct1, CSmartSchema(struct_schema_item_Struct1))); +} + +void XXX::YYY::ZZZ::Test::InitFunctionSchemes( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items) { + functions_schemes_.insert(std::make_pair(NsSmartDeviceLink::NsJSONHandler::SmartSchemaKey<FunctionID::eType, messageType::eType>(FunctionID::name1, messageType::request), InitFunction_name1_request(struct_schema_items, function_id_items, message_type_items))); + functions_schemes_.insert(std::make_pair(NsSmartDeviceLink::NsJSONHandler::SmartSchemaKey<FunctionID::eType, messageType::eType>(FunctionID::val_1, messageType::response), InitFunction_val_1_response(struct_schema_items, function_id_items, message_type_items))); + functions_schemes_.insert(std::make_pair(NsSmartDeviceLink::NsJSONHandler::SmartSchemaKey<FunctionID::eType, messageType::eType>(FunctionID::val_2, messageType::notification), InitFunction_val_2_notification(struct_schema_items, function_id_items, message_type_items))); +} + +//------------- Functions schemes initialization ------------- + +CSmartSchema XXX::YYY::ZZZ::Test::InitFunction_name1_request( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items) { + std::set<Enum_new4::eType> Enum_new4_all_enum_values; + Enum_new4_all_enum_values.insert(Enum_new4::_11); + Enum_new4_all_enum_values.insert(Enum_new4::_22); + + std::set<Enum1::eType> param2_allowed_enum_subset_values; + param2_allowed_enum_subset_values.insert(Enum1::name1); + + // Function parameter param1. + // + // Description Line1 + // Description Line2 + // + // Design Line1 + // + // Note: Issue1 + // Note: Issue2 + // Note: Issue3 + // + // ToDo: Do1 + // ToDo: Do2 + TSharedPtr<ISchemaItem> param1_SchemaItem = TEnumSchemaItem<Enum_new4::eType>::create(Enum_new4_all_enum_values, TSchemaItemParameter<Enum_new4::eType>(Enum_new4::_11)); + + // Function parameter param2. + TSharedPtr<ISchemaItem> param2_SchemaItem = TEnumSchemaItem<Enum1::eType>::create(param2_allowed_enum_subset_values, TSchemaItemParameter<Enum1::eType>(name1)); + + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + schema_members["param1"] = CObjectSchemaItem::SMember(param1_SchemaItem, true); + schema_members["param2"] = CObjectSchemaItem::SMember(param2_SchemaItem, true); + + std::map<std::string, CObjectSchemaItem::SMember> params_members; + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(TEnumSchemaItem<FunctionID::eType>::create(function_id_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(TEnumSchemaItem<messageType::eType>::create(message_type_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + + std::map<std::string, CObjectSchemaItem::SMember> root_members_map; + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_MSG_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(schema_members), true); + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(params_members), true); + + return CSmartSchema(CObjectSchemaItem::create(root_members_map)); +} + +CSmartSchema XXX::YYY::ZZZ::Test::InitFunction_val_1_response( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items) { + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + std::map<std::string, CObjectSchemaItem::SMember> params_members; + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(TEnumSchemaItem<FunctionID::eType>::create(function_id_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(TEnumSchemaItem<messageType::eType>::create(message_type_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_CORRELATION_ID] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + + std::map<std::string, CObjectSchemaItem::SMember> root_members_map; + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_MSG_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(schema_members), true); + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(params_members), true); + + return CSmartSchema(CObjectSchemaItem::create(root_members_map)); +} + +CSmartSchema XXX::YYY::ZZZ::Test::InitFunction_val_2_notification( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items) { + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + std::map<std::string, CObjectSchemaItem::SMember> params_members; + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_FUNCTION_ID] = CObjectSchemaItem::SMember(TEnumSchemaItem<FunctionID::eType>::create(function_id_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_MESSAGE_TYPE] = CObjectSchemaItem::SMember(TEnumSchemaItem<messageType::eType>::create(message_type_items), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_VERSION] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + params_members[NsSmartDeviceLink::NsJSONHandler::strings::S_PROTOCOL_TYPE] = CObjectSchemaItem::SMember(TNumberSchemaItem<int>::create(), true); + + std::map<std::string, CObjectSchemaItem::SMember> root_members_map; + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_MSG_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(schema_members), true); + root_members_map[NsSmartDeviceLink::NsJSONHandler::strings::S_PARAMS] = CObjectSchemaItem::SMember(CObjectSchemaItem::create(params_members), true); + + return CSmartSchema(CObjectSchemaItem::create(root_members_map)); +} + +//----------- Structs schema items initialization ------------ + +TSharedPtr<ISchemaItem> XXX::YYY::ZZZ::Test::InitStructSchemaItem_Struct1( + const TStructsSchemaItems &struct_schema_items) { + std::set<Enum1::eType> Enum1_all_enum_values; + Enum1_all_enum_values.insert(Enum1::name1); + Enum1_all_enum_values.insert(Enum1::internal_name2); + + std::set<Enum1::eType> enumSubset1_allowed_enum_subset_values; + enumSubset1_allowed_enum_subset_values.insert(Enum1::name1); + + std::set<Enum_new2::eType> Enum_new2_all_enum_values; + Enum_new2_all_enum_values.insert(Enum_new2::_1); + Enum_new2_all_enum_values.insert(Enum_new2::_2); + Enum_new2_all_enum_values.insert(Enum_new2::_3); + + std::set<Enum1::eType> sub1_allowed_enum_subset_values; + sub1_allowed_enum_subset_values.insert(Enum1::name1); + + std::set<Enum1::eType> sub2_allowed_enum_subset_values; + sub2_allowed_enum_subset_values.insert(Enum1::internal_name2); + + std::set<Enum_new4::eType> sub3_allowed_enum_subset_values; + sub3_allowed_enum_subset_values.insert(Enum_new4::_22); + + // Struct member intParam. + TSharedPtr<ISchemaItem> intParam_SchemaItem = TNumberSchemaItem<int>::create(TSchemaItemParameter<int>(), TSchemaItemParameter<int>(2), TSchemaItemParameter<int>()); + + // Struct member doubleParam. + TSharedPtr<ISchemaItem> doubleParam_SchemaItem = TNumberSchemaItem<double>::create(TSchemaItemParameter<double>(0.333), TSchemaItemParameter<double>(), TSchemaItemParameter<double>()); + + // Struct member boolParam. + TSharedPtr<ISchemaItem> boolParam_SchemaItem = CBoolSchemaItem::create(TSchemaItemParameter<bool>()); + + // Struct member structParam. + TSharedPtr<ISchemaItem> structParam_SchemaItem = ProvideObjectSchemaItemForStruct(struct_schema_items, StructIdentifiers::Struct2); + + // Struct member enumParam. + TSharedPtr<ISchemaItem> enumParam_SchemaItem = TEnumSchemaItem<Enum1::eType>::create(Enum1_all_enum_values, TSchemaItemParameter<Enum1::eType>()); + + // Struct member enumParam1. + TSharedPtr<ISchemaItem> enumParam1_SchemaItem = TEnumSchemaItem<Enum1::eType>::create(Enum1_all_enum_values, TSchemaItemParameter<Enum1::eType>()); + + // Struct member enumSubset1. + TSharedPtr<ISchemaItem> enumSubset1_SchemaItem = TEnumSchemaItem<Enum1::eType>::create(enumSubset1_allowed_enum_subset_values, TSchemaItemParameter<Enum1::eType>()); + + // Struct member arrayOfInt. + TSharedPtr<ISchemaItem> arrayOfInt_SchemaItem = CArraySchemaItem::create(CBoolSchemaItem::create(TSchemaItemParameter<bool>()), TSchemaItemParameter<size_t>(0), TSchemaItemParameter<size_t>(20)); + + // Struct member arrayOfEnum1. + TSharedPtr<ISchemaItem> arrayOfEnum1_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum1::eType>::create(Enum1_all_enum_values, TSchemaItemParameter<Enum1::eType>()), TSchemaItemParameter<size_t>(0), TSchemaItemParameter<size_t>(20)); + + // Struct member arrayOfEnum3. + TSharedPtr<ISchemaItem> arrayOfEnum3_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum_new2::eType>::create(Enum_new2_all_enum_values, TSchemaItemParameter<Enum_new2::eType>()), TSchemaItemParameter<size_t>(10), TSchemaItemParameter<size_t>(40)); + + // Struct member arrayOfEnum4. + TSharedPtr<ISchemaItem> arrayOfEnum4_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum1::eType>::create(sub1_allowed_enum_subset_values, TSchemaItemParameter<Enum1::eType>()), TSchemaItemParameter<size_t>(10), TSchemaItemParameter<size_t>(41)); + + // Struct member arrayOfEnum5. + TSharedPtr<ISchemaItem> arrayOfEnum5_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum1::eType>::create(sub2_allowed_enum_subset_values, TSchemaItemParameter<Enum1::eType>()), TSchemaItemParameter<size_t>(10), TSchemaItemParameter<size_t>(42)); + + // Struct member arrayOfEnum6. + TSharedPtr<ISchemaItem> arrayOfEnum6_SchemaItem = CArraySchemaItem::create(TEnumSchemaItem<Enum_new4::eType>::create(sub3_allowed_enum_subset_values, TSchemaItemParameter<Enum_new4::eType>()), TSchemaItemParameter<size_t>(10), TSchemaItemParameter<size_t>(43)); + + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + schema_members["intParam"] = CObjectSchemaItem::SMember(intParam_SchemaItem, true); + schema_members["doubleParam"] = CObjectSchemaItem::SMember(doubleParam_SchemaItem, false); + schema_members["boolParam"] = CObjectSchemaItem::SMember(boolParam_SchemaItem, true); + schema_members["structParam"] = CObjectSchemaItem::SMember(structParam_SchemaItem, true); + schema_members["enumParam"] = CObjectSchemaItem::SMember(enumParam_SchemaItem, true); + schema_members["enumParam1"] = CObjectSchemaItem::SMember(enumParam1_SchemaItem, true); + schema_members["enumSubset1"] = CObjectSchemaItem::SMember(enumSubset1_SchemaItem, false); + schema_members["arrayOfInt"] = CObjectSchemaItem::SMember(arrayOfInt_SchemaItem, false); + schema_members["arrayOfEnum1"] = CObjectSchemaItem::SMember(arrayOfEnum1_SchemaItem, false); + schema_members["arrayOfEnum3"] = CObjectSchemaItem::SMember(arrayOfEnum3_SchemaItem, true); + schema_members["arrayOfEnum4"] = CObjectSchemaItem::SMember(arrayOfEnum4_SchemaItem, true); + schema_members["arrayOfEnum5"] = CObjectSchemaItem::SMember(arrayOfEnum5_SchemaItem, true); + schema_members["arrayOfEnum6"] = CObjectSchemaItem::SMember(arrayOfEnum6_SchemaItem, true); + + return CObjectSchemaItem::create(schema_members); +} + +TSharedPtr<ISchemaItem> XXX::YYY::ZZZ::Test::InitStructSchemaItem_Struct2( + const TStructsSchemaItems &struct_schema_items) { + std::map<std::string, CObjectSchemaItem::SMember> schema_members; + + return CObjectSchemaItem::create(schema_members); +} + +//-------------- String to value enum mapping ---------------- + +namespace NsSmartDeviceLink { +namespace NsSmartObjects { + +template <> +const std::map<XXX::YYY::ZZZ::Enum1::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::Enum1::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::Enum1::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum1::name1, "name1")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum1::internal_name2, "name2")); + + is_initialized = true; + } + + return enum_string_representation; +} + +template <> +const std::map<XXX::YYY::ZZZ::E2::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::E2::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::E2::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::E2::val_1, "xxx")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::E2::val_2, "yyy")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::E2::val_3, "val_3")); + + is_initialized = true; + } + + return enum_string_representation; +} + +template <> +const std::map<XXX::YYY::ZZZ::Enum_new2::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::Enum_new2::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::Enum_new2::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new2::_1, "xxx")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new2::_2, "xxx")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new2::_3, "xxx")); + + is_initialized = true; + } + + return enum_string_representation; +} + +template <> +const std::map<XXX::YYY::ZZZ::Enum_new4::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::Enum_new4::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::Enum_new4::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new4::_11, "xxx")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::Enum_new4::_22, "xxx")); + + is_initialized = true; + } + + return enum_string_representation; +} + +template <> +const std::map<XXX::YYY::ZZZ::messageType::eType, std::string> &TEnumSchemaItem<XXX::YYY::ZZZ::messageType::eType>::getEnumElementsStringRepresentation() { + static bool is_initialized = false; + static std::map<XXX::YYY::ZZZ::messageType::eType, std::string> enum_string_representation; + + if (false == is_initialized) { + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::messageType::request, "request")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::messageType::response, "response")); + enum_string_representation.insert(std::make_pair(XXX::YYY::ZZZ::messageType::notification, "notification")); + + is_initialized = true; + } + + return enum_string_representation; +} + +} // NsSmartObjects +} // NsSmartDeviceLink + diff --git a/tools/InterfaceGenerator/test/generator/generators/test_expected_sdlrpc.h b/tools/InterfaceGenerator/test/generator/generators/test_expected_sdlrpc.h new file mode 100644 index 000000000..826ea55ce --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/generators/test_expected_sdlrpc.h @@ -0,0 +1,321 @@ +/** + * @file Test.h + * @brief Generated class Test header file. + * + * This class is a part of SmartObjects solution. It provides + * factory functionallity which allows client to use SmartSchemas + * in accordance with definitions from Test.xml file + */ +// Copyright (c) 2013, Ford Motor Company +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with the +// distribution. +// +// Neither the name of the Ford Motor Company nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef __CSMARTFACTORY_TEST_12345678123456781234567812345678_H__ +#define __CSMARTFACTORY_TEST_12345678123456781234567812345678_H__ + +#include "JSONHandler/CSmartFactory.hpp" +#include "SmartObjects/CSmartSchema.hpp" +#include "SmartObjects/ISchemaItem.hpp" +#include "SmartObjects/TSharedPtr.hpp" + +namespace XXX { +namespace YYY { +namespace ZZZ { + +namespace StructIdentifiers { +/** + * @brief Enumeration StructIdentifiers. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief Struct1. + */ + Struct1, + + /** + * @brief Struct2. + */ + Struct2 +}; +} // StructIdentifiers + +namespace Enum1 { +/** + * @brief Enumeration Enum1. + * + * @todo Do1 + * @todo Do2 + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief name1. + * + * Design Line1 + * + * @todo Do1 + * @todo Do2 + */ + name1 = 1, + + /** + * @brief internal_name2. + * + * Description Line1 + * Description Line2 + * + * @note Issue1 + * @note Issue2 + * @note Issue3 + */ + internal_name2 +}; +} // Enum1 + +namespace E2 { +/** + * @brief Enumeration E2. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief val_1. + */ + val_1, + + /** + * @brief val_2. + */ + val_2 = 100, + + /** + * @brief val_3. + */ + val_3 +}; +} // E2 + +namespace Enum_new2 { +/** + * @brief Enumeration Enum_new2. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief _1. + */ + _1, + + /** + * @brief _2. + */ + _2, + + /** + * @brief _3. + */ + _3 +}; +} // Enum_new2 + +namespace Enum_new4 { +/** + * @brief Enumeration Enum_new4. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief _11. + */ + _11, + + /** + * @brief _22. + */ + _22 +}; +} // Enum_new4 + +namespace messageType { +/** + * @brief Enumeration messageType. + */ +enum eType { + /** + * @brief INVALID_ENUM. + */ + INVALID_ENUM = -1, + + /** + * @brief request. + */ + request, + + /** + * @brief response. + */ + response, + + /** + * @brief notification. + */ + notification +}; +} // messageType + + +/** + * @brief Class Test. + * + * Params: + * param2 - value2 + * param1 - value1 + */ +class Test : public NsSmartDeviceLink::NsJSONHandler::CSmartFactory<FunctionID::eType, messageType::eType, StructIdentifiers::eType> { + public: + /** + * @brief Constructor. + */ + Test(); + + protected: + /** + * @brief Type that maps of struct IDs to schema items. + */ + typedef std::map<const StructIdentifiers::eType, NsSmartDeviceLink::NsSmartObjects::TSharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> > TStructsSchemaItems; + + /** + * @brief Helper that allows to make reference to struct + * + * @param struct_schema_items Struct schema items. + * @param struct_id ID of structure to provide. + * + * @return TSharedPtr of strucute + */ + static NsSmartDeviceLink::NsSmartObjects::TSharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> ProvideObjectSchemaItemForStruct( + const TStructsSchemaItems &struct_schema_items, + const StructIdentifiers::eType struct_id); + + /** + * @brief Initializes all struct schemes. + */ + void InitStructSchemes(TStructsSchemaItems &struct_schema_items); + + /** + * @brief Initializes all function schemes. + * + * @param struct_schema_items Struct schema items. + * @param function_id_items Set of all elements of FunctionID enum. + * @param message_type_items Set of all elements of messageType enum. + */ + void InitFunctionSchemes( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items); + + /** + * @brief Method that generates schema for function Function1. + * + * @return NsSmartDeviceLink::NsSmartObjects::CSmartSchema + */ + static NsSmartDeviceLink::NsSmartObjects::CSmartSchema InitFunction_name1_request( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items); + + /** + * @brief Method that generates schema for function Function2. + * + * @return NsSmartDeviceLink::NsSmartObjects::CSmartSchema + */ + static NsSmartDeviceLink::NsSmartObjects::CSmartSchema InitFunction_val_1_response( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items); + + /** + * @brief Method that generates schema for function Function2. + * + * @return NsSmartDeviceLink::NsSmartObjects::CSmartSchema + */ + static NsSmartDeviceLink::NsSmartObjects::CSmartSchema InitFunction_val_2_notification( + const TStructsSchemaItems &struct_schema_items, + const std::set<FunctionID::eType> &function_id_items, + const std::set<messageType::eType> &message_type_items); + + /** + * @brief Method that generates schema item for structure Struct1. + * + * Design Line1 + * + * @note Issue1 + * @note Issue2 + * @note Issue3 + */ + static NsSmartDeviceLink::NsSmartObjects::TSharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> InitStructSchemaItem_Struct1( + const TStructsSchemaItems &struct_schema_items); + + /** + * @brief Method that generates schema item for structure Struct2. + * + * @note Issue1 + * @note Issue2 + * @note Issue3 + */ + static NsSmartDeviceLink::NsSmartObjects::TSharedPtr<NsSmartDeviceLink::NsSmartObjects::ISchemaItem> InitStructSchemaItem_Struct2( + const TStructsSchemaItems &struct_schema_items); +}; + +} // XXX +} // YYY +} // ZZZ + +#endif //__CSMARTFACTORY_TEST_12345678123456781234567812345678_H__ + diff --git a/tools/InterfaceGenerator/test/generator/parsers/__init__.py b/tools/InterfaceGenerator/test/generator/parsers/__init__.py new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/parsers/__init__.py diff --git a/tools/InterfaceGenerator/test/generator/parsers/test_JSONRPC.py b/tools/InterfaceGenerator/test/generator/parsers/test_JSONRPC.py new file mode 100755 index 000000000..f2fecdb90 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/parsers/test_JSONRPC.py @@ -0,0 +1,595 @@ +"""JSONRPC XML parser unit test.""" +import os +import unittest + +import generator.Model +import generator.parsers.JSONRPC + + +class TestJSONRPCVParser(unittest.TestCase): + + """Test for JSONRPC xml parser.""" + + class _Issue: + def __init__(self, creator, value): + self.creator = creator + self.value = value + + def __eq__(self, other): + return self.creator == other.creator and self.value == other.value + + def setUp(self): + """Test initialization.""" + self.valid_xml_name = os.path.dirname(os.path.realpath(__file__)) + \ + "/valid_JSONRPC.xml" + self.parser = generator.parsers.JSONRPC.Parser() + + def test_valid_xml(self): + """Test parsing of valid xml.""" + interface = self.parser.parse(self.valid_xml_name) + + self.assertEqual(9, len(interface.params)) + self.assertDictEqual({"attr1": "v1", + "attr2": "v2", + "interface1_attribute1": "value1", + "interface1_attribute2": "value2", + "interface1_issues": "Issue1\nIssue2", + "interface1_design_description": "dd", + "interface2_attribute": "value", + "interface2_description": + "Description of interface2", + "interface2_todos": "i2 todo"}, + interface.params) + + # Enumerations + + self.assertEqual(5, len(interface.enums)) + + # Enumeration "FunctionID" + + self.assertIn("FunctionID", interface.enums) + enum = interface.enums["FunctionID"] + self.verify_base_item(item=enum, + name="FunctionID") + self.assertIsNone(enum.internal_scope) + + self.assertEqual(3, len(enum.elements)) + + self.assertIn("interface1.Function1", enum.elements) + element = enum.elements["interface1.Function1"] + self.verify_base_item( + item=element, + name="interface1.Function1") + self.assertEqual("interface1_Function1", element.internal_name) + self.assertIsNone(element.value) + + self.assertIn("interface1.Function2", enum.elements) + element = enum.elements["interface1.Function2"] + self.verify_base_item( + item=element, + name="interface1.Function2") + self.assertEqual("interface1_Function2", element.internal_name) + self.assertIsNone(element.value) + + self.assertIn("interface2.Function1", enum.elements) + element = enum.elements["interface2.Function1"] + self.verify_base_item( + item=element, + name="interface2.Function1") + self.assertEqual("interface2_Function1", element.internal_name) + self.assertIsNone(element.value) + + # Enumeration "messageType" + + self.assertIn("messageType", interface.enums) + enum = interface.enums["messageType"] + self.verify_base_item( + item=enum, + name="messageType") + self.assertIsNone(enum.internal_scope) + + self.assertEqual(3, len(enum.elements)) + + self.assertIn("request", enum.elements) + element = enum.elements["request"] + self.verify_base_item(item=element, + name="request") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + self.assertIn("response", enum.elements) + element = enum.elements["response"] + self.verify_base_item(item=element, name="response") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + self.assertIn("notification", enum.elements) + element = enum.elements["notification"] + self.verify_base_item(item=element, name="notification") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + # Enumeration "interface1_enum1" + + self.assertIn("interface1_enum1", interface.enums) + enum = interface.enums["interface1_enum1"] + self.verify_base_item(item=enum, name="interface1_enum1", + platform="enum1 platform") + self.assertEqual("scope", enum.internal_scope) + + self.assertEqual(3, len(enum.elements)) + + self.assertIn("element1", enum.elements) + element = enum.elements["element1"] + self.verify_base_item(item=element, name="element1") + self.assertIsNone(element.internal_name) + self.assertEqual(10, element.value) + + self.assertIn("element2", enum.elements) + element = enum.elements["element2"] + self.verify_base_item(item=element, name="element2") + self.assertEqual("element2_internal", element.internal_name) + self.assertEqual(11, element.value) + + self.assertIn("element3", enum.elements) + element = enum.elements["element3"] + self.verify_base_item( + item=element, + name="element3", + design_description=["Element design description"], + platform="element3 platform") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + # Enumeration "interface2_enum1" + + self.assertIn("interface2_enum1", interface.enums) + enum = interface.enums["interface2_enum1"] + self.verify_base_item(item=enum, name="interface2_enum1", + description=["Interface2 enum1 description"]) + self.assertIsNone(enum.internal_scope) + + self.assertEqual(2, len(enum.elements)) + + self.assertIn("e1", enum.elements) + element = enum.elements["e1"] + self.verify_base_item(item=element, name="e1") + self.assertEqual("int_e1", element.internal_name) + self.assertEqual(0, element.value) + + self.assertIn("e2", enum.elements) + element = enum.elements["e2"] + self.verify_base_item(item=element, name="e2") + self.assertEqual("int_e2", element.internal_name) + self.assertEqual(10, element.value) + + # Enumeration "interface2_enum2" + + self.assertIn("interface2_enum2", interface.enums) + enum = interface.enums["interface2_enum2"] + self.verify_base_item(item=enum, name="interface2_enum2", + platform="e2 platform") + self.assertEqual("e2 scope", enum.internal_scope) + + self.assertEqual(3, len(enum.elements)) + + self.assertIn("element1", enum.elements) + element = enum.elements["element1"] + self.verify_base_item(item=element, name="element1") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + self.assertIn("element2", enum.elements) + element = enum.elements["element2"] + self.verify_base_item(item=element, name="element2") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + self.assertIn("element3", enum.elements) + element = enum.elements["element3"] + self.verify_base_item(item=element, name="element3") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + # Structures + + self.assertEqual(3, len(interface.structs)) + + # Structure "interface1_struct1" + + self.assertIn("interface1_struct1", interface.structs) + struct = interface.structs["interface1_struct1"] + self.verify_base_item( + item=struct, + name="interface1_struct1", + description=["Struct description"], + issues=[TestJSONRPCVParser._Issue(creator="creator1", + value="Issue1"), + TestJSONRPCVParser._Issue(creator="creator2", + value="Issue2")]) + + self.assertEqual(4, len(struct.members)) + + self.assertIn("member1", struct.members) + member = struct.members["member1"] + self.verify_base_item( + item=member, + name="member1", + description=["Param1 description"]) + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Integer) + self.assertIsNone(member.param_type.min_value) + self.assertIsNone(member.param_type.max_value) + + self.assertIn("member2", struct.members) + member = struct.members["member2"] + self.verify_base_item(item=member, name="member2", + platform="member2 platform") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Boolean) + + self.assertIn("member3", struct.members) + member = struct.members["member3"] + self.verify_base_item(item=member, name="member3") + self.assertEqual(False, member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Double) + self.assertIsNone(member.param_type.min_value) + self.assertAlmostEqual(20.5, member.param_type.max_value) + + self.assertIn("member4", struct.members) + member = struct.members["member4"] + self.verify_base_item(item=member, name="member4") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertIsNone(member.param_type.min_size) + self.assertIsNone(member.param_type.max_size) + self.assertIsInstance(member.param_type.element_type, + generator.Model.Integer) + self.assertEqual(11, member.param_type.element_type.min_value) + self.assertEqual(100, member.param_type.element_type.max_value) + + # Structure "interface1_struct2" + + self.assertIn("interface1_struct2", interface.structs) + struct = interface.structs["interface1_struct2"] + self.verify_base_item(item=struct, + name="interface1_struct2", + description=["Description of struct2"], + platform="struct2 platform") + + self.assertEqual(4, len(struct.members)) + + self.assertIn("m1", struct.members) + member = struct.members["m1"] + self.verify_base_item(item=member, name="m1") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.String) + self.assertIsNone(member.param_type.max_length) + + self.assertIn("m2", struct.members) + member = struct.members["m2"] + self.verify_base_item(item=member, name="m2") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertEqual(1, member.param_type.min_size) + self.assertEqual(50, member.param_type.max_size) + self.assertIsInstance(member.param_type.element_type, + generator.Model.String) + self.assertEqual(100, member.param_type.element_type.max_length) + + self.assertIn("m3", struct.members) + member = struct.members["m3"] + self.verify_base_item(item=member, name="m3") + self.assertTrue(member.is_mandatory) + self.assertIs(member.param_type, interface.enums["interface1_enum1"]) + + self.assertIn("m4", struct.members) + member = struct.members["m4"] + self.verify_base_item(item=member, name="m4") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertIsNone(member.param_type.min_size) + self.assertEqual(10, member.param_type.max_size) + self.assertIs(member.param_type.element_type, + interface.structs["interface1_struct1"]) + + # Structure "interface2_struct1" + + self.assertIn("interface2_struct1", interface.structs) + struct = interface.structs["interface2_struct1"] + self.verify_base_item(item=struct, name="interface2_struct1") + + self.assertEqual(3, len(struct.members)) + + self.assertIn("m_1", struct.members) + member = struct.members["m_1"] + self.verify_base_item(item=member, name="m_1") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertEqual(1, member.param_type.min_size) + self.assertEqual(10, member.param_type.max_size) + self.assertIs(member.param_type.element_type, + interface.enums["interface2_enum1"]) + + self.assertIn("m_2", struct.members) + member = struct.members["m_2"] + self.verify_base_item(item=member, name="m_2") + self.assertTrue(member.is_mandatory) + self.assertIs(member.param_type, interface.enums["interface2_enum2"]) + + self.assertIn("m_3", struct.members) + member = struct.members["m_3"] + self.verify_base_item(item=member, name="m_3") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.String) + self.assertEqual(20, member.param_type.max_length) + + # Functions + + self.assertEqual(5, len(interface.functions)) + + # Function request "interface1_Function1" + + self.assertIn( + (interface.enums["FunctionID"].elements["interface1.Function1"], + interface.enums["messageType"].elements["request"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["interface1.Function1"], + interface.enums["messageType"].elements["request"])] + self.verify_base_item( + item=function, + name="interface1_Function1", + description=["Description of request Function1"], + todos=["Function1 request todo"]) + self.assertIs( + function.function_id, + interface.enums["FunctionID"].elements["interface1.Function1"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["request"]) + + self.assertEqual(3, len(function.params)) + + self.assertIn("param1", function.params) + param = function.params["param1"] + self.verify_base_item( + item=param, + name="param1", + issues=[TestJSONRPCVParser._Issue(creator="", value="")]) + self.assertEqual(False, param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.String) + self.assertIsNone(param.param_type.max_length) + self.assertEqual("String default value", param.default_value) + + self.assertIn("param2", function.params) + param = function.params["param2"] + self.verify_base_item( + item=param, + name="param2", + description=["Param2 description", ""], + todos=["Param2 todo"], + platform="param2 platform") + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Integer) + self.assertIsNone(param.param_type.min_value) + self.assertIsNone(param.param_type.max_value) + self.assertIsNone(param.default_value) + + self.assertIn("param3", function.params) + param = function.params["param3"] + self.verify_base_item(item=param, name="param3") + self.assertEqual(False, param.is_mandatory) + self.assertIs(param.param_type, + interface.structs["interface1_struct1"]) + self.assertIsNone(param.default_value) + + # Function response "interface1_Function1" + + self.assertIn( + (interface.enums["FunctionID"].elements["interface1.Function1"], + interface.enums["messageType"].elements["response"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["interface1.Function1"], + interface.enums["messageType"].elements["response"])] + self.verify_base_item( + item=function, + name="interface1_Function1", + issues=[TestJSONRPCVParser._Issue(creator="c1", value=""), + TestJSONRPCVParser._Issue(creator="c2", value="")], + platform="") + self.assertIs( + function.function_id, + interface.enums["FunctionID"].elements["interface1.Function1"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["response"]) + + self.assertEqual(3, len(function.params)) + + self.assertIn("p1", function.params) + param = function.params["p1"] + self.verify_base_item(item=param, name="p1") + self.assertTrue(param.is_mandatory) + self.assertIs(param.param_type, interface.enums["interface1_enum1"]) + self.assertIsNone(param.default_value) + + self.assertIn("p2", function.params) + param = function.params["p2"] + self.verify_base_item(item=param, name="p2") + self.assertTrue(param.is_mandatory) + self.assertIs(param.param_type, interface.enums["interface1_enum1"]) + self.assertIs( + param.default_value, + interface.enums["interface1_enum1"].elements["element2"]) + + self.assertIn("p3", function.params) + param = function.params["p3"] + self.verify_base_item(item=param, name="p3", design_description=[""]) + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Boolean) + self.assertEqual(False, param.default_value) + + # Function notification "interface1_Function2" + + self.assertIn( + (interface.enums["FunctionID"].elements["interface1.Function2"], + interface.enums["messageType"].elements["notification"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["interface1.Function2"], + interface.enums["messageType"].elements["notification"])] + self.verify_base_item(item=function, + name="interface1_Function2", + description=["Function2 description"], + platform="function2 platform") + self.assertIs( + function.function_id, + interface.enums["FunctionID"].elements["interface1.Function2"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["notification"]) + + self.assertEqual(3, len(function.params)) + + self.assertIn("n1", function.params) + param = function.params["n1"] + self.verify_base_item(item=param, name="n1", todos=["n1 todo"]) + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.EnumSubset) + self.assertIs(param.param_type.enum, + interface.enums["interface1_enum1"]) + self.assertDictEqual( + {"element2": + interface.enums["interface1_enum1"].elements["element2"], + "element3": + interface.enums["interface1_enum1"].elements["element3"]}, + param.param_type.allowed_elements) + self.assertIsNone(param.default_value) + + self.assertIn("n2", function.params) + param = function.params["n2"] + self.verify_base_item(item=param, name="n2", todos=["n2 todo"]) + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Array) + self.assertEqual(1, param.param_type.min_size) + self.assertEqual(100, param.param_type.max_size) + self.assertIsInstance(param.param_type.element_type, + generator.Model.EnumSubset) + self.assertIs(param.param_type.element_type.enum, + interface.enums["interface1_enum1"]) + self.assertDictEqual( + {"element1": + interface.enums["interface1_enum1"].elements["element1"], + "element3": + interface.enums["interface1_enum1"].elements["element3"]}, + param.param_type.element_type.allowed_elements) + self.assertIsNone(param.default_value) + + self.assertIn("n3", function.params) + param = function.params["n3"] + self.verify_base_item(item=param, name="n3") + self.assertEqual(False, param.is_mandatory) + self.assertIs(param.param_type, + interface.structs["interface1_struct2"]) + self.assertIsNone(param.default_value) + + # Function request "interface2_Function1" + + self.assertIn( + (interface.enums["FunctionID"].elements["interface2.Function1"], + interface.enums["messageType"].elements["request"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["interface2.Function1"], + interface.enums["messageType"].elements["request"])] + self.verify_base_item(item=function, name="interface2_Function1") + self.assertIs( + function.function_id, + interface.enums["FunctionID"].elements["interface2.Function1"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["request"]) + + self.assertEqual(2, len(function.params)) + + self.assertIn("param1", function.params) + param = function.params["param1"] + self.verify_base_item(item=param, name="param1") + self.assertEqual(False, param.is_mandatory) + self.assertIs(param.param_type, interface.enums["interface2_enum1"]) + self.assertIsNone(param.default_value) + + self.assertIn("param2", function.params) + param = function.params["param2"] + self.verify_base_item(item=param, name="param2") + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Array) + self.assertEqual(5, param.param_type.min_size) + self.assertEqual(25, param.param_type.max_size) + self.assertIs(param.param_type.element_type, + interface.structs["interface2_struct1"]) + self.assertIsNone(param.default_value) + + # Function notification "interface2_Function1" + + self.assertIn( + (interface.enums["FunctionID"].elements["interface2.Function1"], + interface.enums["messageType"].elements["notification"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["interface2.Function1"], + interface.enums["messageType"].elements["notification"])] + self.verify_base_item( + item=function, + name="interface2_Function1", + issues=[ + TestJSONRPCVParser._Issue(creator="c", value="Issue text")], + platform="platform") + self.assertIs( + function.function_id, + interface.enums["FunctionID"].elements["interface2.Function1"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["notification"]) + + self.assertEqual(2, len(function.params)) + + self.assertIn("param", function.params) + param = function.params["param"] + self.verify_base_item(item=param, name="param") + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.EnumSubset) + self.assertIs(param.param_type.enum, + interface.enums["interface2_enum2"]) + self.assertDictEqual( + {"element2": + interface.enums["interface2_enum2"].elements["element2"], + "element3": + interface.enums["interface2_enum2"].elements["element3"]}, + param.param_type.allowed_elements) + self.assertIsNone(param.default_value) + + self.assertIn("i1", function.params) + param = function.params["i1"] + self.verify_base_item(item=param, name="i1") + self.assertTrue(param.is_mandatory) + self.assertIs(param.param_type, + interface.structs["interface1_struct2"]) + self.assertIsNone(param.default_value) + + def verify_base_item(self, item, name, description=None, + design_description=None, issues=None, todos=None, + platform=None): + """Verify base interface item variables.""" + self.assertEqual(name, item.name) + self.assertSequenceEqual(self.get_list(description), item.description) + self.assertSequenceEqual(self.get_list(design_description), + item.design_description) + self.assertSequenceEqual(self.get_list(issues), item.issues) + self.assertSequenceEqual(self.get_list(todos), item.todos) + self.assertEqual(platform, item.platform) + + @staticmethod + def get_list(list=None): + """Return provided list or empty list if None is provided.""" + return list if list is not None else [] + +if __name__ == "__main__": + unittest.main() diff --git a/tools/InterfaceGenerator/test/generator/parsers/test_SDLRPCV1.py b/tools/InterfaceGenerator/test/generator/parsers/test_SDLRPCV1.py new file mode 100755 index 000000000..1464658ff --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/parsers/test_SDLRPCV1.py @@ -0,0 +1,404 @@ +"""SDLRPCV1 XML parser unit test.""" +import os +import unittest + +import generator.Model +import generator.parsers.SDLRPCV1 + + +class TestSDLRPCV1Parser(unittest.TestCase): + + """Test for SDLRPCV1 xml parser.""" + + class _Issue: + def __init__(self, creator, value): + self.creator = creator + self.value = value + + def __eq__(self, other): + return self.creator == other.creator and self.value == other.value + + def setUp(self): + """Test initialization.""" + self.valid_xml_name = os.path.dirname(os.path.realpath(__file__)) + \ + "/valid_SDLRPCV1.xml" + self.parser = generator.parsers.SDLRPCV1.Parser() + + def test_valid_xml(self): + """Test parsing of valid xml.""" + interface = self.parser.parse(self.valid_xml_name) + + self.assertEqual(2, len(interface.params)) + self.assertDictEqual({"attribute1": "value1", "attribute2": "value2"}, + interface.params) + + # Enumerations + + self.assertEqual(3, len(interface.enums)) + + # Enumeration "FunctionID" + + self.assertIn("FunctionID", interface.enums) + enum = interface.enums["FunctionID"] + self.verify_base_item(item=enum, + name="FunctionID") + self.assertIsNone(enum.internal_scope) + + self.assertEqual(2, len(enum.elements)) + + self.assertIn("Function1", enum.elements) + element = enum.elements["Function1"] + self.verify_base_item( + item=element, + name="Function1") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + self.assertIn("Function2", enum.elements) + element = enum.elements["Function2"] + self.verify_base_item( + item=element, + name="Function2") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + # Enumeration "messageType" + + self.assertIn("messageType", interface.enums) + enum = interface.enums["messageType"] + self.verify_base_item( + item=enum, + name="messageType") + self.assertIsNone(enum.internal_scope) + + self.assertEqual(3, len(enum.elements)) + + self.assertIn("request", enum.elements) + element = enum.elements["request"] + self.verify_base_item(item=element, + name="request") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + self.assertIn("response", enum.elements) + element = enum.elements["response"] + self.verify_base_item(item=element, name="response") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + self.assertIn("notification", enum.elements) + element = enum.elements["notification"] + self.verify_base_item(item=element, name="notification") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + # Enumeration "enum1" + + self.assertIn("enum1", interface.enums) + enum = interface.enums["enum1"] + self.verify_base_item(item=enum, name="enum1", + platform="enum1 platform") + self.assertEqual("scope", enum.internal_scope) + + self.assertEqual(3, len(enum.elements)) + + self.assertIn("element1", enum.elements) + element = enum.elements["element1"] + self.verify_base_item(item=element, name="element1") + self.assertIsNone(element.internal_name) + self.assertEqual(10, element.value) + + self.assertIn("element2", enum.elements) + element = enum.elements["element2"] + self.verify_base_item(item=element, name="element2") + self.assertEqual("element2_internal", element.internal_name) + self.assertEqual(11, element.value) + + self.assertIn("element3", enum.elements) + element = enum.elements["element3"] + self.verify_base_item( + item=element, + name="element3", + design_description=["Element design description"], + platform="element3 platform") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + # Structures + + self.assertEqual(2, len(interface.structs)) + + # Structure "struct1" + + self.assertIn("struct1", interface.structs) + struct = interface.structs["struct1"] + self.verify_base_item( + item=struct, + name="struct1", + description=["Struct description"], + issues=[TestSDLRPCV1Parser._Issue(creator="creator1", + value="Issue1"), + TestSDLRPCV1Parser._Issue(creator="creator2", + value="Issue2")]) + + self.assertEqual(4, len(struct.members)) + + self.assertIn("member1", struct.members) + member = struct.members["member1"] + self.verify_base_item( + item=member, + name="member1", + description=["Param1 description"]) + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Integer) + self.assertIsNone(member.param_type.min_value) + self.assertIsNone(member.param_type.max_value) + + self.assertIn("member2", struct.members) + member = struct.members["member2"] + self.verify_base_item(item=member, name="member2", + platform="member2 platform") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Boolean) + + self.assertIn("member3", struct.members) + member = struct.members["member3"] + self.verify_base_item(item=member, name="member3") + self.assertEqual(False, member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Double) + self.assertIsNone(member.param_type.min_value) + self.assertAlmostEqual(20.5, member.param_type.max_value) + + self.assertIn("member4", struct.members) + member = struct.members["member4"] + self.verify_base_item(item=member, name="member4") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertIsNone(member.param_type.min_size) + self.assertIsNone(member.param_type.max_size) + self.assertIsInstance(member.param_type.element_type, + generator.Model.Integer) + self.assertEqual(11, member.param_type.element_type.min_value) + self.assertEqual(100, member.param_type.element_type.max_value) + + # Structure "struct2" + + self.assertIn("struct2", interface.structs) + struct = interface.structs["struct2"] + self.verify_base_item(item=struct, + name="struct2", + description=["Description of struct2"], + platform="struct2 platform") + + self.assertEqual(4, len(struct.members)) + + self.assertIn("m1", struct.members) + member = struct.members["m1"] + self.verify_base_item(item=member, name="m1") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.String) + self.assertIsNone(member.param_type.max_length) + + self.assertIn("m2", struct.members) + member = struct.members["m2"] + self.verify_base_item(item=member, name="m2") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertEqual(1, member.param_type.min_size) + self.assertEqual(50, member.param_type.max_size) + self.assertIsInstance(member.param_type.element_type, + generator.Model.String) + self.assertEqual(100, member.param_type.element_type.max_length) + + self.assertIn("m3", struct.members) + member = struct.members["m3"] + self.verify_base_item(item=member, name="m3") + self.assertTrue(member.is_mandatory) + self.assertIs(member.param_type, interface.enums["enum1"]) + + self.assertIn("m4", struct.members) + member = struct.members["m4"] + self.verify_base_item(item=member, name="m4") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertIsNone(member.param_type.min_size) + self.assertEqual(10, member.param_type.max_size) + self.assertIs(member.param_type.element_type, + interface.structs["struct1"]) + + # Functions + + self.assertEqual(3, len(interface.functions)) + + # Function request "Function1" + + self.assertIn( + (interface.enums["FunctionID"].elements["Function1"], + interface.enums["messageType"].elements["request"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["Function1"], + interface.enums["messageType"].elements["request"])] + self.verify_base_item( + item=function, + name="Function1", + description=["Description of request Function1"], + todos=["Function1 request todo"]) + self.assertIs(function.function_id, + interface.enums["FunctionID"].elements["Function1"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["request"]) + + self.assertEqual(3, len(function.params)) + + self.assertIn("param1", function.params) + param = function.params["param1"] + self.verify_base_item( + item=param, + name="param1", + issues=[TestSDLRPCV1Parser._Issue(creator="", value="")]) + self.assertEqual(False, param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.String) + self.assertIsNone(param.param_type.max_length) + self.assertEqual("String default value", param.default_value) + + self.assertIn("param2", function.params) + param = function.params["param2"] + self.verify_base_item( + item=param, + name="param2", + description=["Param2 description", ""], + todos=["Param2 todo"], + platform="param2 platform") + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Integer) + self.assertIsNone(param.param_type.min_value) + self.assertIsNone(param.param_type.max_value) + self.assertIsNone(param.default_value) + + self.assertIn("param3", function.params) + param = function.params["param3"] + self.verify_base_item(item=param, name="param3") + self.assertEqual(False, param.is_mandatory) + self.assertIs(param.param_type, interface.structs["struct1"]) + self.assertIsNone(param.default_value) + + # Function response "Function1" + + self.assertIn( + (interface.enums["FunctionID"].elements["Function1"], + interface.enums["messageType"].elements["response"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["Function1"], + interface.enums["messageType"].elements["response"])] + self.verify_base_item( + item=function, + name="Function1", + issues=[TestSDLRPCV1Parser._Issue(creator="c1", value=""), + TestSDLRPCV1Parser._Issue(creator="c2", value="")], + platform="") + self.assertIs(function.function_id, + interface.enums["FunctionID"].elements["Function1"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["response"]) + + self.assertEqual(3, len(function.params)) + + self.assertIn("p1", function.params) + param = function.params["p1"] + self.verify_base_item(item=param, name="p1") + self.assertTrue(param.is_mandatory) + self.assertIs(param.param_type, interface.enums["enum1"]) + self.assertIsNone(param.default_value) + + self.assertIn("p2", function.params) + param = function.params["p2"] + self.verify_base_item(item=param, name="p2") + self.assertTrue(param.is_mandatory) + self.assertIs(param.param_type, interface.enums["enum1"]) + self.assertIs(param.default_value, + interface.enums["enum1"].elements["element2"]) + + self.assertIn("p3", function.params) + param = function.params["p3"] + self.verify_base_item(item=param, name="p3", design_description=[""]) + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Boolean) + self.assertEqual(False, param.default_value) + + # Function notification "Function2" + + self.assertIn( + (interface.enums["FunctionID"].elements["Function2"], + interface.enums["messageType"].elements["notification"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["Function2"], + interface.enums["messageType"].elements["notification"])] + self.verify_base_item(item=function, + name="Function2", + description=["Function2 description"], + platform="function2 platform") + self.assertIs(function.function_id, + interface.enums["FunctionID"].elements["Function2"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["notification"]) + + self.assertEqual(3, len(function.params)) + + self.assertIn("n1", function.params) + param = function.params["n1"] + self.verify_base_item(item=param, name="n1", todos=["n1 todo"]) + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.EnumSubset) + self.assertIs(param.param_type.enum, interface.enums["enum1"]) + self.assertDictEqual( + {"element2": interface.enums["enum1"].elements["element2"], + "element3": interface.enums["enum1"].elements["element3"]}, + param.param_type.allowed_elements) + self.assertIsNone(param.default_value) + + self.assertIn("n2", function.params) + param = function.params["n2"] + self.verify_base_item(item=param, name="n2", todos=["n2 todo"]) + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Array) + self.assertEqual(1, param.param_type.min_size) + self.assertEqual(100, param.param_type.max_size) + self.assertIsInstance(param.param_type.element_type, + generator.Model.EnumSubset) + self.assertIs(param.param_type.element_type.enum, + interface.enums["enum1"]) + self.assertDictEqual( + {"element1": interface.enums["enum1"].elements["element1"], + "element3": interface.enums["enum1"].elements["element3"]}, + param.param_type.element_type.allowed_elements) + self.assertIsNone(param.default_value) + + self.assertIn("n3", function.params) + param = function.params["n3"] + self.verify_base_item(item=param, name="n3") + self.assertEqual(False, param.is_mandatory) + self.assertIs(param.param_type, interface.structs["struct2"]) + self.assertIsNone(param.default_value) + + def verify_base_item(self, item, name, description=None, + design_description=None, issues=None, todos=None, + platform=None): + """Verify base interface item variables.""" + self.assertEqual(name, item.name) + self.assertSequenceEqual(self.get_list(description), item.description) + self.assertSequenceEqual(self.get_list(design_description), + item.design_description) + self.assertSequenceEqual(self.get_list(issues), item.issues) + self.assertSequenceEqual(self.get_list(todos), item.todos) + self.assertEqual(platform, item.platform) + + @staticmethod + def get_list(list=None): + """Return provided list or empty list if None is provided.""" + return list if list is not None else [] + +if __name__ == "__main__": + unittest.main() diff --git a/tools/InterfaceGenerator/test/generator/parsers/test_SDLRPCV2.py b/tools/InterfaceGenerator/test/generator/parsers/test_SDLRPCV2.py new file mode 100755 index 000000000..c37962cfe --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/parsers/test_SDLRPCV2.py @@ -0,0 +1,417 @@ +"""SDLRPCV2 XML parser unit test.""" +import os +import unittest + +import generator.Model +import generator.parsers.SDLRPCV2 + + +class TestSDLRPCV2Parser(unittest.TestCase): + + """Test for SDLRPCV2 xml parser.""" + + class _Issue: + def __init__(self, creator, value): + self.creator = creator + self.value = value + + def __eq__(self, other): + return self.creator == other.creator and self.value == other.value + + def setUp(self): + """Test initialization.""" + self.valid_xml_name = os.path.dirname(os.path.realpath(__file__)) + \ + "/valid_SDLRPCV2.xml" + self.parser = generator.parsers.SDLRPCV2.Parser() + + def test_valid_xml(self): + """Test parsing of valid xml.""" + interface = self.parser.parse(self.valid_xml_name) + + self.assertEqual(2, len(interface.params)) + self.assertDictEqual({"attribute1": "value1", "attribute2": "value2"}, + interface.params) + + # Enumerations + + self.assertEqual(3, len(interface.enums)) + + # Enumeration "FunctionID" + + self.assertIn("FunctionID", interface.enums) + enum = interface.enums["FunctionID"] + self.verify_base_item(item=enum, + name="FunctionID", + description=["Description string 1", + "Description string 2"], + todos=['Function id todo']) + self.assertIsNone(enum.internal_scope) + + self.assertEqual(2, len(enum.elements)) + + self.assertIn("Function1_id", enum.elements) + element = enum.elements["Function1_id"] + self.verify_base_item( + item=element, + name="Function1_id", + design_description=["Function1 element design description"]) + self.assertIsNone(element.internal_name) + self.assertEqual(10, element.value) + + self.assertIn("Function2_id", enum.elements) + element = enum.elements["Function2_id"] + self.verify_base_item( + item=element, + name="Function2_id") + self.assertEqual("Function2_internal", element.internal_name) + self.assertIsNone(element.value) + + # Enumeration "messageType" + + self.assertIn("messageType", interface.enums) + enum = interface.enums["messageType"] + self.verify_base_item( + item=enum, + name="messageType", + design_description=["messageType design description", + "messageType design description 2"], + issues=[TestSDLRPCV2Parser._Issue( + creator="messageType issue creator", + value="Issue text")]) + self.assertIsNone(enum.internal_scope) + + self.assertEqual(3, len(enum.elements)) + + self.assertIn("request", enum.elements) + element = enum.elements["request"] + self.verify_base_item(item=element, + name="request", + todos=["request todo 1", "request todo 2"], + issues=[TestSDLRPCV2Parser._Issue( + creator="issue creator", + value="request issue")]) + self.assertIsNone(element.internal_name) + self.assertEqual(0, element.value) + + self.assertIn("response", enum.elements) + element = enum.elements["response"] + self.verify_base_item(item=element, name="response") + self.assertIsNone(element.internal_name) + self.assertEqual(1, element.value) + + self.assertIn("notification", enum.elements) + element = enum.elements["notification"] + self.verify_base_item(item=element, name="notification") + self.assertIsNone(element.internal_name) + self.assertEqual(2, element.value) + + # Enumeration "enum1" + + self.assertIn("enum1", interface.enums) + enum = interface.enums["enum1"] + self.verify_base_item(item=enum, name="enum1", + platform="enum1 platform") + self.assertEqual("scope", enum.internal_scope) + + self.assertEqual(3, len(enum.elements)) + + self.assertIn("element1", enum.elements) + element = enum.elements["element1"] + self.verify_base_item(item=element, name="element1") + self.assertIsNone(element.internal_name) + self.assertEqual(10, element.value) + + self.assertIn("element2", enum.elements) + element = enum.elements["element2"] + self.verify_base_item(item=element, name="element2") + self.assertEqual("element2_internal", element.internal_name) + self.assertEqual(11, element.value) + + self.assertIn("element3", enum.elements) + element = enum.elements["element3"] + self.verify_base_item( + item=element, + name="element3", + design_description=["Element design description"], + platform="element3 platform") + self.assertIsNone(element.internal_name) + self.assertIsNone(element.value) + + # Structures + + self.assertEqual(2, len(interface.structs)) + + # Structure "struct1" + + self.assertIn("struct1", interface.structs) + struct = interface.structs["struct1"] + self.verify_base_item( + item=struct, + name="struct1", + description=["Struct description"], + issues=[TestSDLRPCV2Parser._Issue(creator="creator1", + value="Issue1"), + TestSDLRPCV2Parser._Issue(creator="creator2", + value="Issue2")]) + + self.assertEqual(4, len(struct.members)) + + self.assertIn("member1", struct.members) + member = struct.members["member1"] + self.verify_base_item( + item=member, + name="member1", + description=["Param1 description"]) + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Integer) + self.assertIsNone(member.param_type.min_value) + self.assertIsNone(member.param_type.max_value) + + self.assertIn("member2", struct.members) + member = struct.members["member2"] + self.verify_base_item(item=member, name="member2", + platform="member2 platform") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Boolean) + + self.assertIn("member3", struct.members) + member = struct.members["member3"] + self.verify_base_item(item=member, name="member3") + self.assertEqual(False, member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Double) + self.assertIsNone(member.param_type.min_value) + self.assertAlmostEqual(20.5, member.param_type.max_value) + + self.assertIn("member4", struct.members) + member = struct.members["member4"] + self.verify_base_item(item=member, name="member4") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertIsNone(member.param_type.min_size) + self.assertIsNone(member.param_type.max_size) + self.assertIsInstance(member.param_type.element_type, + generator.Model.Integer) + self.assertEqual(11, member.param_type.element_type.min_value) + self.assertEqual(100, member.param_type.element_type.max_value) + + # Structure "struct2" + + self.assertIn("struct2", interface.structs) + struct = interface.structs["struct2"] + self.verify_base_item(item=struct, + name="struct2", + description=["Description of struct2"], + platform="struct2 platform") + + self.assertEqual(4, len(struct.members)) + + self.assertIn("m1", struct.members) + member = struct.members["m1"] + self.verify_base_item(item=member, name="m1") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.String) + self.assertIsNone(member.param_type.max_length) + + self.assertIn("m2", struct.members) + member = struct.members["m2"] + self.verify_base_item(item=member, name="m2") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertEqual(1, member.param_type.min_size) + self.assertEqual(50, member.param_type.max_size) + self.assertIsInstance(member.param_type.element_type, + generator.Model.String) + self.assertEqual(100, member.param_type.element_type.max_length) + + self.assertIn("m3", struct.members) + member = struct.members["m3"] + self.verify_base_item(item=member, name="m3") + self.assertTrue(member.is_mandatory) + self.assertIs(member.param_type, interface.enums["enum1"]) + + self.assertIn("m4", struct.members) + member = struct.members["m4"] + self.verify_base_item(item=member, name="m4") + self.assertTrue(member.is_mandatory) + self.assertIsInstance(member.param_type, generator.Model.Array) + self.assertIsNone(member.param_type.min_size) + self.assertEqual(10, member.param_type.max_size) + self.assertIs(member.param_type.element_type, + interface.structs["struct1"]) + + # Functions + + self.assertEqual(3, len(interface.functions)) + + # Function request "Function1" + + self.assertIn( + (interface.enums["FunctionID"].elements["Function1_id"], + interface.enums["messageType"].elements["request"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["Function1_id"], + interface.enums["messageType"].elements["request"])] + self.verify_base_item( + item=function, + name="Function1", + description=["Description of request Function1"], + todos=["Function1 request todo"]) + self.assertIs(function.function_id, + interface.enums["FunctionID"].elements["Function1_id"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["request"]) + + self.assertEqual(3, len(function.params)) + + self.assertIn("param1", function.params) + param = function.params["param1"] + self.verify_base_item( + item=param, + name="param1", + issues=[TestSDLRPCV2Parser._Issue(creator="", value="")]) + self.assertEqual(False, param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.String) + self.assertIsNone(param.param_type.max_length) + self.assertEqual("String default value", param.default_value) + + self.assertIn("param2", function.params) + param = function.params["param2"] + self.verify_base_item( + item=param, + name="param2", + description=["Param2 description", ""], + todos=["Param2 todo"], + platform="param2 platform") + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Integer) + self.assertIsNone(param.param_type.min_value) + self.assertIsNone(param.param_type.max_value) + self.assertIsNone(param.default_value) + + self.assertIn("param3", function.params) + param = function.params["param3"] + self.verify_base_item(item=param, name="param3") + self.assertEqual(False, param.is_mandatory) + self.assertIs(param.param_type, interface.structs["struct1"]) + self.assertIsNone(param.default_value) + + # Function response "Function1" + + self.assertIn( + (interface.enums["FunctionID"].elements["Function1_id"], + interface.enums["messageType"].elements["response"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["Function1_id"], + interface.enums["messageType"].elements["response"])] + self.verify_base_item( + item=function, + name="Function1", + issues=[TestSDLRPCV2Parser._Issue(creator="c1", value=""), + TestSDLRPCV2Parser._Issue(creator="c2", value="")], + platform="") + self.assertIs(function.function_id, + interface.enums["FunctionID"].elements["Function1_id"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["response"]) + + self.assertEqual(3, len(function.params)) + + self.assertIn("p1", function.params) + param = function.params["p1"] + self.verify_base_item(item=param, name="p1") + self.assertTrue(param.is_mandatory) + self.assertIs(param.param_type, interface.enums["enum1"]) + self.assertIsNone(param.default_value) + + self.assertIn("p2", function.params) + param = function.params["p2"] + self.verify_base_item(item=param, name="p2") + self.assertTrue(param.is_mandatory) + self.assertIs(param.param_type, interface.enums["enum1"]) + self.assertIs(param.default_value, + interface.enums["enum1"].elements["element2"]) + + self.assertIn("p3", function.params) + param = function.params["p3"] + self.verify_base_item(item=param, name="p3", design_description=[""]) + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Boolean) + self.assertEqual(False, param.default_value) + + # Function notification "Function2" + + self.assertIn( + (interface.enums["FunctionID"].elements["Function2_id"], + interface.enums["messageType"].elements["notification"]), + interface.functions) + function = interface.functions[ + (interface.enums["FunctionID"].elements["Function2_id"], + interface.enums["messageType"].elements["notification"])] + self.verify_base_item(item=function, + name="Function2", + description=["Function2 description"], + platform="function2 platform") + self.assertIs(function.function_id, + interface.enums["FunctionID"].elements["Function2_id"]) + self.assertIs(function.message_type, + interface.enums["messageType"].elements["notification"]) + + self.assertEqual(3, len(function.params)) + + self.assertIn("n1", function.params) + param = function.params["n1"] + self.verify_base_item(item=param, name="n1", todos=["n1 todo"]) + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.EnumSubset) + self.assertIs(param.param_type.enum, interface.enums["enum1"]) + self.assertDictEqual( + {"element2": interface.enums["enum1"].elements["element2"], + "element3": interface.enums["enum1"].elements["element3"]}, + param.param_type.allowed_elements) + self.assertIsNone(param.default_value) + + self.assertIn("n2", function.params) + param = function.params["n2"] + self.verify_base_item(item=param, name="n2", todos=["n2 todo"]) + self.assertTrue(param.is_mandatory) + self.assertIsInstance(param.param_type, generator.Model.Array) + self.assertEqual(1, param.param_type.min_size) + self.assertEqual(100, param.param_type.max_size) + self.assertIsInstance(param.param_type.element_type, + generator.Model.EnumSubset) + self.assertIs(param.param_type.element_type.enum, + interface.enums["enum1"]) + self.assertDictEqual( + {"element1": interface.enums["enum1"].elements["element1"], + "element3": interface.enums["enum1"].elements["element3"]}, + param.param_type.element_type.allowed_elements) + self.assertIsNone(param.default_value) + + self.assertIn("n3", function.params) + param = function.params["n3"] + self.verify_base_item(item=param, name="n3") + self.assertEqual(False, param.is_mandatory) + self.assertIs(param.param_type, interface.structs["struct2"]) + self.assertIsNone(param.default_value) + + def verify_base_item(self, item, name, description=None, + design_description=None, issues=None, todos=None, + platform=None): + """Verify base interface item variables.""" + self.assertEqual(name, item.name) + self.assertSequenceEqual(self.get_list(description), item.description) + self.assertSequenceEqual(self.get_list(design_description), + item.design_description) + self.assertSequenceEqual(self.get_list(issues), item.issues) + self.assertSequenceEqual(self.get_list(todos), item.todos) + self.assertEqual(platform, item.platform) + + @staticmethod + def get_list(list=None): + """Return provided list or empty list if None is provided.""" + return list if list is not None else [] + +if __name__ == "__main__": + unittest.main() diff --git a/tools/InterfaceGenerator/test/generator/parsers/valid_JSONRPC.xml b/tools/InterfaceGenerator/test/generator/parsers/valid_JSONRPC.xml new file mode 100644 index 000000000..a754e5714 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/parsers/valid_JSONRPC.xml @@ -0,0 +1,100 @@ +<?xml version="1.0"?> +<interfaces attr1="v1" attr2="v2"> + <interface name="interface1" attribute1="value1" attribute2="value2"> + <struct name="struct1"> + <param name="member1" type="Integer"> + <description>Param1 description</description> + </param> + <issue creator="creator1">Issue1</issue> + <param name="member2" type="Boolean" mandatory="true" platform="member2 platform"/> + <param name="member3" type="Float" maxvalue="20.5" mandatory="false"/> + <description>Struct description</description> + <issue creator="creator2">Issue2</issue> + <param name="member4" type="Integer" minvalue="11" maxvalue="100" array="true"/> + </struct> + <issue creator="c">Issue1</issue> + <function name="Function1" messagetype="request"> + <description>Description of request Function1</description> + <param name="param1" type="String" mandatory="false" defvalue="String default value"> + <issue creator=""/> + </param> + <param name="param2" type="Integer" platform="param2 platform"> + <description>Param2 description</description> + <todo>Param2 todo</todo> + <description/> + </param> + <todo>Function1 request todo</todo> + <param name="param3" type="struct1" mandatory="false"/> + </function> + <enum name="enum1" internal_scope="scope" platform="enum1 platform"> + <element name="element1" value="10"/> + <element name="element2" internal_name="element2_internal" value="11"/> + <element name="element3" platform="element3 platform"> + <designdescription>Element design description</designdescription> + </element> + </enum> + <designdescription>dd</designdescription> + <issue creator="c">Issue2</issue> + <function name="Function1" messagetype="response" platform=""> + <param name="p1" type="enum1"/> + <issue creator="c1"/> + <issue creator="c2"></issue> + <param name="p2" type="enum1" defvalue="element2"/> + <param name="p3" type="Boolean" defvalue="false"> + <designdescription/> + </param> + </function> + <struct name="struct2" platform="struct2 platform"> + <description>Description of struct2</description> + <param name="m1" type="String"/> + <param name="m2" type="String" maxlength="100" array="true" minsize="1" maxsize="50"/> + <param name="m3" type="enum1"/> + <param name="m4" type="struct1" array="true" maxsize="10"/> + </struct> + <function name="Function2" messagetype="notification" platform="function2 platform"> + <description>Function2 description</description> + <param name="n1" type="enum1"> + <element name="element2"/> + <element name="element3"/> + <todo>n1 todo</todo> + </param> + <param name="n2" type="enum1" array="true" minsize="1" maxsize="100"> + <element name="element3"/> + <todo>n2 todo</todo> + <element name="element1"/> + </param> + <param name="n3" type="struct2" mandatory="false"/> + </function> + </interface> + <interface name="interface2" attribute="value"> + <description>Description of interface2</description> + <enum name="enum1"> + <description>Interface2 enum1 description</description> + <element name="e1" internal_name="int_e1" value="0"/> + <element name="e2" internal_name="int_e2" value="10"/> + </enum> + <enum name="enum2" internal_scope="e2 scope" platform="e2 platform"> + <element name="element1"/> + <element name="element2"/> + <element name="element3"/> + </enum> + <struct name="struct1"> + <param name="m_1" type="enum1" minsize="1" maxsize="10" array="true"/> + <param name="m_2" type="enum2"/> + <param name="m_3" type="String" maxlength="20"/> + </struct> + <function name="Function1" messagetype="request"> + <param name="param1" type="enum1" mandatory="false"/> + <param name="param2" type="struct1" array="true" minsize="5" maxsize="25"/> + </function> + <todo>i2 todo</todo> + <function name="Function1" messagetype="notification" platform="platform"> + <issue creator="c">Issue text</issue> + <param name="param" type="enum2"> + <element name="element2"/> + <element name="element3"/> + </param> + <param name="i1" type="interface1.struct2"/> + </function> + </interface> +</interfaces>
\ No newline at end of file diff --git a/tools/InterfaceGenerator/test/generator/parsers/valid_SDLRPCV1.xml b/tools/InterfaceGenerator/test/generator/parsers/valid_SDLRPCV1.xml new file mode 100644 index 000000000..37ebf39d3 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/parsers/valid_SDLRPCV1.xml @@ -0,0 +1,64 @@ +<?xml version="1.0"?> +<interface name="test_interface" attribute1="value1" attribute2="value2"> + <struct name="struct1"> + <param name="member1" type="Integer"> + <description>Param1 description</description> + </param> + <issue creator="creator1">Issue1</issue> + <param name="member2" type="Boolean" mandatory="true" platform="member2 platform"/> + <param name="member3" type="Float" maxvalue="20.5" mandatory="false"/> + <description>Struct description</description> + <issue creator="creator2">Issue2</issue> + <param name="member4" type="Integer" minvalue="11" maxvalue="100" array="true"/> + </struct> + <function name="Function1" messagetype="request"> + <description>Description of request Function1</description> + <param name="param1" type="String" mandatory="false" defvalue="String default value"> + <issue creator=""/> + </param> + <param name="param2" type="Integer" platform="param2 platform"> + <description>Param2 description</description> + <todo>Param2 todo</todo> + <description/> + </param> + <todo>Function1 request todo</todo> + <param name="param3" type="struct1" mandatory="false"/> + </function> + <enum name="enum1" internal_scope="scope" platform="enum1 platform"> + <element name="element1" value="10"/> + <element name="element2" internal_name="element2_internal" value="11"/> + <element name="element3" platform="element3 platform"> + <designdescription>Element design description</designdescription> + </element> + </enum> + <function name="Function1" messagetype="response" platform=""> + <param name="p1" type="enum1"/> + <issue creator="c1"/> + <issue creator="c2"></issue> + <param name="p2" type="enum1" defvalue="element2"/> + <param name="p3" type="Boolean" defvalue="false"> + <designdescription/> + </param> + </function> + <struct name="struct2" platform="struct2 platform"> + <description>Description of struct2</description> + <param name="m1" type="String"/> + <param name="m2" type="String" maxlength="100" array="true" minsize="1" maxsize="50"/> + <param name="m3" type="enum1"/> + <param name="m4" type="struct1" array="true" maxsize="10"/> + </struct> + <function name="Function2" messagetype="notification" platform="function2 platform"> + <description>Function2 description</description> + <param name="n1" type="enum1"> + <element name="element2"/> + <element name="element3"/> + <todo>n1 todo</todo> + </param> + <param name="n2" type="enum1" array="true" minsize="1" maxsize="100"> + <element name="element3"/> + <todo>n2 todo</todo> + <element name="element1"/> + </param> + <param name="n3" type="struct2" mandatory="false"/> + </function> +</interface> diff --git a/tools/InterfaceGenerator/test/generator/parsers/valid_SDLRPCV2.xml b/tools/InterfaceGenerator/test/generator/parsers/valid_SDLRPCV2.xml new file mode 100644 index 000000000..cdc5f1ae8 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/parsers/valid_SDLRPCV2.xml @@ -0,0 +1,85 @@ +<?xml version="1.0"?> +<interface name="test_interface" attribute1="value1" attribute2="value2"> + <enum name="FunctionID"> + <description>Description string 1</description> + <element name="Function1_id" value="10"> + <designdescription>Function1 element design description</designdescription> + </element> + <description>Description string 2</description> + <todo>Function id todo</todo> + <element name="Function2_id" internal_name="Function2_internal"/> + </enum> + <enum name="messageType"> + <element name="request" value="0"> + <todo>request todo 1</todo> + <issue creator="issue creator">request issue</issue> + <todo>request todo 2</todo> + </element> + <designdescription>messageType design description</designdescription> + <issue creator="messageType issue creator">Issue text</issue> + <element name="response" value="1"/> + <element name="notification" value="2"/> + <designdescription>messageType design description 2</designdescription> + </enum> + <struct name="struct1"> + <param name="member1" type="Integer"> + <description>Param1 description</description> + </param> + <issue creator="creator1">Issue1</issue> + <param name="member2" type="Boolean" mandatory="true" platform="member2 platform"/> + <param name="member3" type="Float" maxvalue="20.5" mandatory="false"/> + <description>Struct description</description> + <issue creator="creator2">Issue2</issue> + <param name="member4" type="Integer" minvalue="11" maxvalue="100" array="true"/> + </struct> + <function name="Function1" functionID="Function1_id" messagetype="request"> + <description>Description of request Function1</description> + <param name="param1" type="String" mandatory="false" defvalue="String default value"> + <issue creator=""/> + </param> + <param name="param2" type="Integer" platform="param2 platform"> + <description>Param2 description</description> + <todo>Param2 todo</todo> + <description/> + </param> + <todo>Function1 request todo</todo> + <param name="param3" type="struct1" mandatory="false"/> + </function> + <enum name="enum1" internal_scope="scope" platform="enum1 platform"> + <element name="element1" value="10"/> + <element name="element2" internal_name="element2_internal" value="11"/> + <element name="element3" platform="element3 platform"> + <designdescription>Element design description</designdescription> + </element> + </enum> + <function name="Function1" functionID="Function1_id" messagetype="response" platform=""> + <param name="p1" type="enum1"/> + <issue creator="c1"/> + <issue creator="c2"></issue> + <param name="p2" type="enum1" defvalue="element2"/> + <param name="p3" type="Boolean" defvalue="false"> + <designdescription/> + </param> + </function> + <struct name="struct2" platform="struct2 platform"> + <description>Description of struct2</description> + <param name="m1" type="String"/> + <param name="m2" type="String" maxlength="100" array="true" minsize="1" maxsize="50"/> + <param name="m3" type="enum1"/> + <param name="m4" type="struct1" array="true" maxsize="10"/> + </struct> + <function name="Function2" functionID="Function2_id" messagetype="notification" platform="function2 platform"> + <description>Function2 description</description> + <param name="n1" type="enum1"> + <element name="element2"/> + <element name="element3"/> + <todo>n1 todo</todo> + </param> + <param name="n2" type="enum1" array="true" minsize="1" maxsize="100"> + <element name="element3"/> + <todo>n2 todo</todo> + <element name="element1"/> + </param> + <param name="n3" type="struct2" mandatory="false"/> + </function> +</interface> diff --git a/tools/InterfaceGenerator/test/generator/test_Model.py b/tools/InterfaceGenerator/test/generator/test_Model.py new file mode 100755 index 000000000..55f6a5470 --- /dev/null +++ b/tools/InterfaceGenerator/test/generator/test_Model.py @@ -0,0 +1,27 @@ +"""Interface model unit test""" +import unittest + +import generator.Model + + +class TestInterfaceModel(unittest.TestCase): + + """Test for interface model.""" + + def test_enum_element_primary_name(self): + """Test property primary_name of EnumElement.""" + element = generator.Model.EnumElement(name="name1") + self.assertEqual("name1", element.primary_name) + + element = generator.Model.EnumElement(name="name2", + internal_name="internal_name1") + self.assertEqual("internal_name1", element.primary_name) + + element.internal_name = None + self.assertEqual("name2", element.primary_name) + + element.internal_name = "internal_name2" + self.assertEqual("internal_name2", element.primary_name) + +if __name__ == "__main__": + unittest.main() diff --git a/tools/InterfaceGenerator/test/test_CodeFormatAndQuality.py b/tools/InterfaceGenerator/test/test_CodeFormatAndQuality.py new file mode 100755 index 000000000..3ce56e0fa --- /dev/null +++ b/tools/InterfaceGenerator/test/test_CodeFormatAndQuality.py @@ -0,0 +1,59 @@ +import subprocess +import unittest +import flake8.main +import pep257 +import os.path +import fnmatch +import os +import pylint.lint +import sys + +class TestCodeFormatAndQuality(unittest.TestCase): + + def setUp(self): + self.projectRootDir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + projectTestsDir = os.path.join(self.projectRootDir, "test") + self.filesToAnalyze = [] + for root, dirnames, filenames in os.walk(self.projectRootDir): + if root.startswith(projectTestsDir): + continue # Currently we skipping test files + for filename in fnmatch.filter(filenames, '*.py'): + fullFileName = os.path.join(root, filename) + relativeFileName = os.path.relpath(fullFileName, self.projectRootDir) + self.filesToAnalyze.append(relativeFileName) + + def test_pep8_conformance(self): + maxCyclomaticComplexity = 10 + errors = 0 + for file in self.filesToAnalyze: + errors = errors + flake8.main.check_file(file, None, maxCyclomaticComplexity) + + self.assertEqual(errors, 0, "Found code style errors or warnings.") + + def test_pep257_conformance(self): + errors = [] + + for filePath in self.filesToAnalyze: + print("Processing file: {0}".format(filePath)) + result = pep257.check_files([filePath]) + if result: + errors.extend(result) + for error in result: + print(error) + print + self.assertEqual(len(errors), 0, "Found Docstring Conventions violations.") + + def test_pylint_conformance(self): + print + self.assertEqual(0, + subprocess.call( + ["pylint", + '--rcfile=pylint.cfg', + 'generator', + 'Generator.py'] + ), "Found Pylint violations") + return + +if __name__ == '__main__': + unittest.main() + |