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 _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 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_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_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_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")
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)