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 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_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_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 _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 since = None until = None deprecated = None removed = None result = 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] + "'") elif attribute == "since": result = self._parse_version(attributes[attribute]) since = result elif attribute == "until": result = self._parse_version(attributes[attribute]) until = result elif attribute == "deprecated": deprecated = attributes[attribute] elif attribute == "removed": removed = attributes[attribute] params["internal_name"] = internal_name params["value"] = value params["since"] = since params["until"] = until params["deprecated"] = deprecated params["removed"] = removed # Magic usage is correct # pylint: disable=W0142 return Model.EnumElement(**params)
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_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 _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 _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 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")
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. """ if interface is None: raise GenerateError("Given interface is None.") params_set = set() for func in interface.functions.values(): for param in func.params: params_set.add(param) parameter_enum = Model.Enum('Parameter') for item in params_set: parameter_enum.elements[item.upper()] = Model.EnumElement(item) required_enums_for_policy = [ "HMILevel", "FunctionID", "HybridAppPreference", "AppHMIType", "RequestType", "ModuleType", "Common_AppPriority", "Parameter" ] self.required_empty_value = ["RequestType", "ModuleType", "Parameter"] self.enum_items_naming_conversion_ = { "HMILevel": lambda item_name: "HL_" + item_name.replace("HMI_", ""), "AppHMIType": lambda item_name: "AHT_" + item_name, "FunctionID": lambda item_name: item_name, "HybridAppPreference": lambda item_name: item_name, "RequestType": lambda item_name: "RT_" + item_name, "ModuleType": lambda item_name: "MT_" + item_name, "Common_AppPriority": lambda item_name: "P_" + item_name if not item_name == "VOICE_COMMUNICATION" else "P_VOICECOM", "Parameter": lambda item_name: "P_" + to_snake_case(item_name).upper() } self.enum_items_string_naming_conversion_ = { "HMILevel": lambda item_name: item_name, "AppHMIType": lambda item_name: item_name, "FunctionID": lambda item_name: item_name[:item_name.rfind("ID")], "HybridAppPreference": lambda item_name: item_name, "RequestType": lambda item_name: item_name, "ModuleType": lambda item_name: item_name, "Common_AppPriority": lambda item_name: item_name if not item_name == "VOICE_COMMUNICATION" else "VOICECOM", "Parameter": lambda item_name: item_name } self.enum_naming_conversion_ = { "HMILevel": "HmiLevel", "AppHMIType": "AppHMIType", "FunctionID": "FunctionID", "HybridAppPreference": "HybridAppPreference", "RequestType": "RequestType", "ModuleType": "ModuleType", "Common_AppPriority": "Priority", "Parameter": "Parameter" } get_first_enum_value_name = lambda enum: enum.elements.values()[0].name enum_required_for_policy = lambda enum: enum.name in required_enums_for_policy and "." not in get_first_enum_value_name( enum) # In case if "." is in FunctionID name this is HMI_API function ID and should not be included in Policy enums required_enum_values = [ val for val in interface.enums.values() if enum_required_for_policy(val) ] if filename == "MOBILE_API": self._write_cc_with_enum_schema_factory(filename, namespace, destination_dir, interface.enums.values()) # Params should be generated as enum for MOBILE_API to validate RPCSpec parameters required_enum_values.append(parameter_enum) self._write_header_with_enums(filename, namespace, destination_dir, required_enum_values) self._write_cc_with_enums(filename, namespace, destination_dir, required_enum_values)