diff --git a/CHANGELOG.md b/CHANGELOG.md index dc40a50..38d23fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,13 +11,17 @@ Non-collectable elements are various sub-elements to collectable elements. #### XML Port interface elements +* ClientServerInterface | CLIENT-SERVER-INTERFACE | `collectable` * NvDataInterface | NV-DATA-INTERFACE | `collectable` * ParameterInterface | PARAMETER-INTERFACE | `collectable` * SenderReceiverInterface | SENDER-RECEIVER-INTERFACE | `collectable` +* ApplicationError | APPLICATION-ERROR +* ClientServerOperation | CLIENT-SERVER-OPERATION * InvalidationPolicy | INVALIDATION-POLICY #### XML - Data type elements +* ArgumentDataPrototype | ARGUMENT-DATA-PROTOTYPE * ParameterDataPrototype | PARAMETER-DATA-PROTOTYPE * VariableDataPrototype | VARIABLE-DATA-PROTOTYPE diff --git a/examples/xml/port_interface/client_server_interface.py b/examples/xml/port_interface/client_server_interface.py new file mode 100644 index 0000000..b7127de --- /dev/null +++ b/examples/xml/port_interface/client_server_interface.py @@ -0,0 +1,73 @@ +""" +Sender-receiver port interface examples +""" +import os +import autosar +import autosar.xml.element as ar_element +import autosar.xml.enumeration as ar_enum + + +def create_platform_types(packages: dict[str, ar_element.Package]): + """ + Creates necessary platform types + """ + uint8_base_type = ar_element.SwBaseType('uint8', size=8) + packages["PlatformBaseTypes"].append(uint8_base_type) + uint32_base_type = ar_element.SwBaseType('uint32', size=32) + packages["PlatformBaseTypes"].append(uint32_base_type) + sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint8_base_type.ref()) + uint8_impl_type = ar_element.ImplementationDataType("uint8", + category="VALUE", + sw_data_def_props=sw_data_def_props) + packages["PlatformImplementationDataTypes"].append(uint8_impl_type) + sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint32_base_type.ref()) + uint32_impl_type = ar_element.ImplementationDataType("uint32", + category="VALUE", + sw_data_def_props=sw_data_def_props) + packages["PlatformImplementationDataTypes"].append(uint32_impl_type) + + +def create_port_interfaces(packages: dict[str, ar_element.Package]): + """ + Creates interface with one element + """ + uint32_impl_type = packages["PlatformImplementationDataTypes"].find("uint32") + interface = ar_element.ClientServerInterface("FreeRunningTimer_I", is_service=True) + operation = interface.make_operation("GetTimeStamp") + operation.make_out_argument("value", + ar_enum.ServerArgImplPolicy.USE_ARGUMENT_TYPE, + type_ref=uint32_impl_type.ref()) + packages["PortInterfaces"].append(interface) + + +def save_xml_files(workspace: autosar.xml.Workspace): + """ + Saves workspace as XML documents + """ + interface_document_path = os.path.abspath(os.path.join(os.path.dirname( + __file__), 'data', 'client_server_interface.arxml')) + platform_document_path = os.path.abspath(os.path.join(os.path.dirname( + __file__), 'data', 'platform.arxml')) + workspace.create_document(interface_document_path, packages="/PortInterfaces") + workspace.create_document(platform_document_path, packages="/AUTOSAR_Platform") + workspace.write_documents() + + +def main(): + """ + Main + """ + workspace = autosar.xml.Workspace() + packages = dict(zip(["PlatformBaseTypes", + "PlatformImplementationDataTypes", + "PortInterfaces"], + workspace.make_packages("AUTOSAR_Platform/BaseTypes", + "AUTOSAR_Platform/ImplementationDataTypes", + "PortInterfaces"))) + create_platform_types(packages) + create_port_interfaces(packages) + save_xml_files(workspace) + + +if __name__ == "__main__": + main() diff --git a/examples/xml/port_interface/data/client_server_interface.arxml b/examples/xml/port_interface/data/client_server_interface.arxml new file mode 100644 index 0000000..50cba23 --- /dev/null +++ b/examples/xml/port_interface/data/client_server_interface.arxml @@ -0,0 +1,27 @@ + + + + + PortInterfaces + + + FreeRunningTimer_I + true + + + GetTimeStamp + + + value + /AUTOSAR_Platform/ImplementationDataTypes/uint32 + OUT + USE-ARGUMENT-TYPE + + + + + + + + + \ No newline at end of file diff --git a/examples/xml/port_interface/data/platform.arxml b/examples/xml/port_interface/data/platform.arxml index 98f0ffd..536a4a8 100644 --- a/examples/xml/port_interface/data/platform.arxml +++ b/examples/xml/port_interface/data/platform.arxml @@ -11,6 +11,10 @@ uint8 8 + + uint32 + 32 + @@ -27,6 +31,17 @@ + + uint32 + VALUE + + + + /AUTOSAR_Platform/BaseTypes/uint32 + + + + diff --git a/examples/xml/port_interface/nv_data_interface.py b/examples/xml/port_interface/nv_data_interface.py index 6519499..64221f1 100644 --- a/examples/xml/port_interface/nv_data_interface.py +++ b/examples/xml/port_interface/nv_data_interface.py @@ -12,11 +12,18 @@ def create_platform_types(packages: dict[str, ar_element.Package]): """ uint8_base_type = ar_element.SwBaseType('uint8', size=8) packages["PlatformBaseTypes"].append(uint8_base_type) + uint32_base_type = ar_element.SwBaseType('uint32', size=32) + packages["PlatformBaseTypes"].append(uint32_base_type) sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint8_base_type.ref()) uint8_impl_type = ar_element.ImplementationDataType("uint8", category="VALUE", sw_data_def_props=sw_data_def_props) packages["PlatformImplementationDataTypes"].append(uint8_impl_type) + sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint32_base_type.ref()) + uint32_impl_type = ar_element.ImplementationDataType("uint32", + category="VALUE", + sw_data_def_props=sw_data_def_props) + packages["PlatformImplementationDataTypes"].append(uint32_impl_type) def create_nv_data_interface_with_one_element(packages: dict[str, ar_element.Package]): diff --git a/examples/xml/port_interface/parameter_interface.py b/examples/xml/port_interface/parameter_interface.py index 01176de..c2a9532 100644 --- a/examples/xml/port_interface/parameter_interface.py +++ b/examples/xml/port_interface/parameter_interface.py @@ -12,11 +12,18 @@ def create_platform_types(packages: dict[str, ar_element.Package]): """ uint8_base_type = ar_element.SwBaseType('uint8', size=8) packages["PlatformBaseTypes"].append(uint8_base_type) + uint32_base_type = ar_element.SwBaseType('uint32', size=32) + packages["PlatformBaseTypes"].append(uint32_base_type) sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint8_base_type.ref()) uint8_impl_type = ar_element.ImplementationDataType("uint8", category="VALUE", sw_data_def_props=sw_data_def_props) packages["PlatformImplementationDataTypes"].append(uint8_impl_type) + sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint32_base_type.ref()) + uint32_impl_type = ar_element.ImplementationDataType("uint32", + category="VALUE", + sw_data_def_props=sw_data_def_props) + packages["PlatformImplementationDataTypes"].append(uint32_impl_type) def create_parameter_interface_with_one_parameter(packages: dict[str, ar_element.Package]): diff --git a/examples/xml/port_interface/sender_receiver_interface.py b/examples/xml/port_interface/sender_receiver_interface.py index 2c6140d..360089b 100644 --- a/examples/xml/port_interface/sender_receiver_interface.py +++ b/examples/xml/port_interface/sender_receiver_interface.py @@ -12,11 +12,18 @@ def create_platform_types(packages: dict[str, ar_element.Package]): """ uint8_base_type = ar_element.SwBaseType('uint8', size=8) packages["PlatformBaseTypes"].append(uint8_base_type) + uint32_base_type = ar_element.SwBaseType('uint32', size=32) + packages["PlatformBaseTypes"].append(uint32_base_type) sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint8_base_type.ref()) uint8_impl_type = ar_element.ImplementationDataType("uint8", category="VALUE", sw_data_def_props=sw_data_def_props) packages["PlatformImplementationDataTypes"].append(uint8_impl_type) + sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint32_base_type.ref()) + uint32_impl_type = ar_element.ImplementationDataType("uint32", + category="VALUE", + sw_data_def_props=sw_data_def_props) + packages["PlatformImplementationDataTypes"].append(uint32_impl_type) def create_implementation_data_types(packages: dict[str, ar_element.Package]): diff --git a/run_examples.cmd b/run_examples.cmd index 15b8374..7a89eac 100644 --- a/run_examples.cmd +++ b/run_examples.cmd @@ -11,6 +11,7 @@ python examples\xml\unit\unit.py python examples\xml\port_interface\nv_data_interface.py python examples\xml\port_interface\parameter_interface.py python examples\xml\port_interface\sender_receiver_interface.py +python examples\xml\port_interface\client_server_interface.py python examples\generator\data_types\gen_type_defs_scalar.py python examples\generator\data_types\gen_type_defs_array.py python examples\generator\data_types\gen_type_defs_record.py diff --git a/src/autosar/xml/element.py b/src/autosar/xml/element.py index b73909b..6089c7f 100644 --- a/src/autosar/xml/element.py +++ b/src/autosar/xml/element.py @@ -562,6 +562,20 @@ def _accepted_subtypes(self) -> set[ar_enum.IdentifiableSubTypes]: """Acceptable values for dest""" return {ar_enum.IdentifiableSubTypes.VARIABLE_DATA_PROTOTYPE} + +class ApplicationErrorRef(BaseRef): + """ + Reference to ApplicationError + tag variants: 'POSSIBLE-ERROR-REF' + """ + + def __init__(self, value: str) -> None: + super().__init__(value, ar_enum.IdentifiableSubTypes.APPLICATION_ERROR) + + def _accepted_subtypes(self) -> set[ar_enum.IdentifiableSubTypes]: + """Acceptable values for dest""" + return {ar_enum.IdentifiableSubTypes.APPLICATION_ERROR} + # Documentation Elements @@ -2153,10 +2167,31 @@ class ParameterDataPrototype(VariableDataPrototype): Type: Concrete Tag variants: 'PARAMETER-DATA-PROTOTYPE' | 'ROM-BLOCK' - This is identical in functionality to VariableDataPrototype, hence the inheritance. + This is identical in behavior to VariableDataPrototype, hence the inheritance. """ +class ArgumentDataPrototype(AutosarDataPrototype): + """ + Complex type AR:ARGUMENT-DATA-PROTOTYPE + Type: Concrete + Tag variants: 'ARGUMENT-DATA-PROTOTYPE' + """ + + def __init__(self, + name: str, + direction: ar_enum.ArgumentDirection | None = None, + server_arg_impl_policy: ar_enum.ServerArgImplPolicy | None = None, + **kwargs) -> None: + super().__init__(name, **kwargs) + self.direction: ar_enum.ArgumentDirection | None = None # .DIRECTION + self.server_arg_impl_policy: ar_enum.ServerArgImplPolicy | None = None # .SERVER-ARGUMENT-IMPL-POLICY + # .TYPE-BLUEPRINTS not supported + # .VARIATION-POINT not supported + self._assign_optional("direction", direction, ar_enum.ArgumentDirection) + self._assign_optional("server_arg_impl_policy", server_arg_impl_policy, ar_enum.ServerArgImplPolicy) + + class ApplicationDataType(AutosarDataType): """ Group AR:APPLICATION-DATA-TYPE @@ -3119,6 +3154,220 @@ def make_parameter(self, return data_element +class ApplicationError(Identifiable): + """ + Complex type AR:APPLICATION-ERROR + Tag variants: 'APPLICATION-ERROR' + """ + + def __init__(self, + name: str, + error_code: int | None = None, + **kwargs) -> None: + super().__init__(name, **kwargs) + self.error_code: int | None = None + self._assign_optional_strict("error_code", error_code, int) + + +class ClientServerOperation(Identifiable): + """ + Complex type AR:CLIENT-SERVER-OPERATION + Tag variants: 'CLIENT-SERVER-OPERATION' + """ + + def __init__(self, + name: str, + arguments: ArgumentDataPrototype | list[ArgumentDataPrototype] | None = None, + diag_arg_integrity: bool | None = None, + fire_and_forget: bool | None = None, + possible_error_refs: ApplicationErrorRef | list[ApplicationErrorRef] | None = None, + **kwargs) -> None: + super().__init__(name, **kwargs) + self.arguments: list[ArgumentDataPrototype] = [] # .ARGUMENTS + self.diag_arg_integrity: bool | None = None # .DIAG-ARG-INTEGRITY + self.fire_and_forget: bool | None = None # .FIRE-AND-FORGET + # .POSSIBLE-AP-ERROR-REFS not supported + # .POSSIBLE-AP-ERROR-SET-REFS not supported + self.possible_error_refs: list[ApplicationErrorRef] = [] # .POSSIBLE-ERROR-REFS + # .VARIATION-POINT not supported + + self._assign_optional_strict("diag_arg_integrity", diag_arg_integrity, bool) + self._assign_optional_strict("fire_and_forget", fire_and_forget, bool) + if arguments is not None: + if isinstance(arguments, ArgumentDataPrototype): + self.append_argument(arguments) + elif isinstance(arguments, list): + for argument in arguments: + self.append_argument(argument) + else: + msg = f"parameters: Invalid type '{str(type(arguments))}'" + raise TypeError(msg + ". Expected 'ArgumentDataPrototype' or list[ArgumentDataPrototype]") + + if possible_error_refs is not None: + if isinstance(possible_error_refs, ApplicationErrorRef): + self.append_argument(arguments) + elif isinstance(possible_error_refs, list): + for possible_error_ref in possible_error_refs: + self.append_possible_error_ref(possible_error_ref) + else: + msg = f"possible_error_refs: Invalid type '{str(type(possible_error_refs))}'" + raise TypeError(msg + ". Expected 'ApplicationErrorRef' or list[ApplicationErrorRef]") + + def append_argument(self, argument: ArgumentDataPrototype) -> None: + """ + Appends argument to internal list of arguments + """ + if isinstance(argument, ArgumentDataPrototype): + self.arguments.append(argument) + else: + msg = f"argument: Invalid type '{str(type(argument))}'" + raise TypeError(msg + ". Expected 'ArgumentDataPrototype'") + + def make_argument(self, + name: str, + direction: ar_enum.ArgumentDirection | None = None, + server_arg_impl_policy: ar_enum.ServerArgImplPolicy | None = None, + **kwargs) -> ArgumentDataPrototype: + """ + Convenience method for adding a new argument to this operation + """ + argument = ArgumentDataPrototype(name, direction, server_arg_impl_policy, **kwargs) + self.append_argument(argument) + return argument + + def make_in_argument(self, + name: str, + server_arg_impl_policy: ar_enum.ServerArgImplPolicy | None = None, + **kwargs) -> ArgumentDataPrototype: + """ + Convenience method for adding a new in-argument to this operation + """ + argument = ArgumentDataPrototype(name, ar_enum.ArgumentDirection.IN, server_arg_impl_policy, **kwargs) + self.append_argument(argument) + return argument + + def make_inout_argument(self, + name: str, + server_arg_impl_policy: ar_enum.ServerArgImplPolicy | None = None, + **kwargs) -> ArgumentDataPrototype: + """ + Convenience method for adding a new inout-argument to this operation + """ + argument = ArgumentDataPrototype(name, ar_enum.ArgumentDirection.INOUT, server_arg_impl_policy, **kwargs) + self.append_argument(argument) + return argument + + def make_out_argument(self, + name: str, + server_arg_impl_policy: ar_enum.ServerArgImplPolicy | None = None, + **kwargs) -> ArgumentDataPrototype: + """ + Convenience method for adding a new out-argument to this operation + """ + argument = ArgumentDataPrototype(name, ar_enum.ArgumentDirection.OUT, server_arg_impl_policy, **kwargs) + self.append_argument(argument) + return argument + + def append_possible_error_ref(self, possible_error_ref: ApplicationErrorRef) -> None: + """ + Appends error reference to internal list of possible errors for this operation + """ + if isinstance(possible_error_ref, ApplicationErrorRef): + self.possible_error_refs.append(possible_error_ref) + else: + msg = f"argument: Invalid type '{str(type(possible_error_ref))}'" + raise TypeError(msg + ". Expected 'ApplicationErrorRef'") + + def make_possible_error_ref(self, value: str) -> ApplicationErrorRef: + """ + Convenience method for creating and adding a new possible error reference to this operation + """ + possible_error_ref = ApplicationErrorRef(value) + self.append_possible_error_ref(possible_error_ref) + return possible_error_ref + + +class ClientServerInterface(PortInterface): + """ + Complex type AR:CLIENT-SERVER-INTERFACE + Tag variants: 'CLIENT-SERVER-INTERFACE' + """ + + def __init__(self, + name: str, + operations: ClientServerOperation | list[ClientServerOperation] | None = None, + possible_errors: ApplicationError | list[ApplicationError] | None = None, + **kwargs) -> None: + super().__init__(name, **kwargs) + self.operations: list[ClientServerOperation] = [] + self.possible_errors: list[ApplicationError] = [] + + if operations is not None: + if isinstance(operations, ClientServerOperation): + self.append_operation(operations) + elif isinstance(operations, list): + for operation in operations: + self.append_operation(operation) + else: + msg = f"operations: Invalid type '{str(type(operations))}'" + raise TypeError(msg + ". Expected 'ClientServerOperation' or list[ClientServerOperation]") + + if possible_errors is not None: + if isinstance(possible_errors, ApplicationError): + self.append_operation(possible_errors) + elif isinstance(possible_errors, list): + for possible_error in possible_errors: + self.append_possible_errors(possible_error) + else: + msg = f"possible_errors: Invalid type '{str(type(possible_errors))}'" + raise TypeError(msg + ". Expected 'ApplicationError' or list[ApplicationError]") + + def append_operation(self, operation: ClientServerOperation) -> None: + """ + Appends operation to internal list of operations + """ + if isinstance(operation, ClientServerOperation): + self.operations.append(operation) + else: + msg = f"operation: Invalid type '{str(type(operation))}'" + raise TypeError(msg + ". Expected 'ClientServerOperation'") + + def append_possible_errors(self, possible_error: ApplicationError) -> None: + """ + Appends possible error to internal list of possible errors + """ + if isinstance(possible_error, ApplicationError): + self.possible_errors.append(possible_error) + else: + msg = f"operation: Invalid type '{str(type(possible_error))}'" + raise TypeError(msg + ". Expected 'ApplicationError'") + + def make_operation(self, + name: str, + arguments: ArgumentDataPrototype | list[ArgumentDataPrototype] | None = None, + diag_arg_integrity: bool | None = None, + fire_and_forget: bool | None = None, + possible_error_refs: ApplicationErrorRef | list[ApplicationErrorRef] | None = None, + **kwargs) -> ClientServerOperation: + """ + Convenience method for creating a new operation in this port interface + """ + operation = ClientServerOperation(name, arguments, diag_arg_integrity, fire_and_forget, possible_error_refs, + **kwargs) + self.append_operation(operation) + return operation + + def make_possible_error(self, + name: str, + error_code: int | None = None, + **kwargs) -> ApplicationError: + """ + Convenience-method for creating a new possible error in this port interface + """ + possible_error = ApplicationError(name, error_code, **kwargs) + self.append_possible_errors(possible_error) + return possible_error + # !!UNFINISHED!! Component Types diff --git a/src/autosar/xml/enumeration.py b/src/autosar/xml/enumeration.py index b843d16..1b46ab1 100644 --- a/src/autosar/xml/enumeration.py +++ b/src/autosar/xml/enumeration.py @@ -10,6 +10,16 @@ import autosar.xml.exception as ar_exception +class ArgumentDirection(Enum): + """ + AR:ARGUMENT-DIRECTION-ENUM--SIMPLE + """ + + IN = 0 + INOUT = 1 + OUT = 2 + + class ArrayImplPolicy(Enum): """ AR:ARRAY-IMPL-POLICY-ENUM--SIMPLE @@ -151,20 +161,21 @@ class IdentifiableSubTypes(Enum): APPLICATION_ASSOC_MAP_DATA_TYPE = 2 APPLICATION_COMPOSITE_DATA_TYPE = 3 APPLICATION_DATA_TYPE = 4 - APPLICATION_DEFERRED_DATA_TYPE = 5 - APPLICATION_PRIMITIVE_DATA_TYPE = 6 - APPLICATION_RECORD_DATA_TYPE = 7 - AUTOSAR_DATA_TYPE = 8 - BSW_MODULE_ENTRY = 9 - COMPU_METHOD = 10 - CONSTANT_SPECIFICATION = 11 - DATA_CONSTR = 12 - IMPLEMENTATION_DATA_TYPE = 13 - PHYSICAL_DIMENSION = 14 - SW_ADDR_METHOD = 15 - SW_BASE_TYPE = 16 - UNIT = 17 - VARIABLE_DATA_PROTOTYPE = 18 + APPLICATION_ERROR = 5 + APPLICATION_DEFERRED_DATA_TYPE = 6 + APPLICATION_PRIMITIVE_DATA_TYPE = 7 + APPLICATION_RECORD_DATA_TYPE = 8 + AUTOSAR_DATA_TYPE = 9 + BSW_MODULE_ENTRY = 10 + COMPU_METHOD = 11 + CONSTANT_SPECIFICATION = 12 + DATA_CONSTR = 13 + IMPLEMENTATION_DATA_TYPE = 14 + PHYSICAL_DIMENSION = 15 + SW_ADDR_METHOD = 16 + SW_BASE_TYPE = 17 + UNIT = 18 + VARIABLE_DATA_PROTOTYPE = 19 class IntervalType(Enum): @@ -391,6 +402,16 @@ class ScaleConstraintValidity(Enum): VALID = 3 +class ServerArgImplPolicy(Enum): + """ + AR:SERVER-ARGUMENT-IMPL-POLICY-ENUM--SIMPLE + """ + + USE_ARGUMENT_TYPE = 0 + USE_ARRAY_BASED_TYPE = 1 + USE_VOID = 2 + + class ServiceKind(Enum): """ SERVICE-PROVIDER-ENUM--SIMPLE @@ -497,6 +518,11 @@ class VersionedTextValue: ### xml_to_enum_map = { + "ArgumentDirection": { + "IN": ArgumentDirection.IN, + "INOUT": ArgumentDirection.INOUT, + "OUT": ArgumentDirection.OUT, + }, "ArrayImplPolicy": { "PAYLOAD-AS-ARRAY": VersionedEnumValue(ArrayImplPolicy.PAYLOAD_AS_ARRAY, {49, 50, 51}), "PAYLOAD-AS-POINTER-TO-ARRAY": VersionedEnumValue(ArrayImplPolicy.PAYLOAD_AS_POINTER_TO_ARRAY, {49, 50, 51}), @@ -557,6 +583,7 @@ class VersionedTextValue: "APPLICATION-ASSOC-MAP-DATA-TYPE": IdentifiableSubTypes.APPLICATION_ASSOC_MAP_DATA_TYPE, "APPLICATION-COMPOSITE-DATA-TYPE": IdentifiableSubTypes.APPLICATION_COMPOSITE_DATA_TYPE, "APPLICATION-DATA-TYPE": IdentifiableSubTypes.APPLICATION_DATA_TYPE, + "APPLICATION-ERROR": IdentifiableSubTypes.APPLICATION_ERROR, "APPLICATION-DEFERRED-DATA-TYPE": IdentifiableSubTypes.APPLICATION_DEFERRED_DATA_TYPE, "APPLICATION-PRIMITIVE-DATA-TYPE": IdentifiableSubTypes.APPLICATION_PRIMITIVE_DATA_TYPE, "APPLICATION-RECORD-DATA-TYPE": IdentifiableSubTypes.APPLICATION_RECORD_DATA_TYPE, @@ -742,6 +769,11 @@ class VersionedTextValue: "NOT-VALID": ScaleConstraintValidity.NOT_VALID, "VALID": ScaleConstraintValidity.VALID }, + "ServerArgImplPolicy": { + "USE-ARGUMENT-TYPE": ServerArgImplPolicy.USE_ARGUMENT_TYPE, + "USE-ARRAY-BASE-TYPE": ServerArgImplPolicy.USE_ARRAY_BASED_TYPE, + "USE-VOID": ServerArgImplPolicy.USE_VOID + }, "SwCalibrationAccess": { "NOT-ACCESSIBLE": SwCalibrationAccess.NOT_ACCESSIBLE, "READ-ONLY": SwCalibrationAccess.READ_ONLY, @@ -777,6 +809,11 @@ def xml_to_enum(enum_type_name: str, xml_text: str, schema_version: int = ar_bas enum_to_xml_map = { + "ArgumentDirection": [ + "IN", # 0 + "INOUT", # 1 + "OUT", # 2 + ], "ArrayImplPolicy": [ VersionedTextValue("PAYLOAD-AS-ARRAY", {49, 50, 51}), # 0 VersionedTextValue("PAYLOAD-AS-POINTER-TO-ARRAY", {49, 50, 51}), # 1 @@ -832,20 +869,21 @@ def xml_to_enum(enum_type_name: str, xml_text: str, schema_version: int = ar_bas "APPLICATION-ASSOC-MAP-DATA-TYPE", # 2 "APPLICATION-COMPOSITE-DATA-TYPE", # 3 "APPLICATION-DATA-TYPE", # 4 - "APPLICATION-DEFERRED-DATA-TYPE", # 5 - "APPLICATION-PRIMITIVE-DATA-TYPE", # 6 - "APPLICATION-RECORD-DATA-TYPE", # 7 - "AUTOSAR-DATA-TYPE", # 8 - "BSW-MODULE-ENTRY", # 9 - "COMPU-METHOD", # 10 - "CONSTANT-SPECIFICATION", # 11 - "DATA-CONSTR", # 12 - "IMPLEMENTATION-DATA-TYPE", # 13 - "PHYSICAL-DIMENSION", # 14 - "SW-ADDR-METHOD", # 15 - "SW-BASE-TYPE", # 16 - "UNIT", # 17 - "VARIABLE-DATA-PROTOTYPE" # 18 + "APPLICATION-ERROR", # 5 + "APPLICATION-DEFERRED-DATA-TYPE", # 6 + "APPLICATION-PRIMITIVE-DATA-TYPE", # 7 + "APPLICATION-RECORD-DATA-TYPE", # 8 + "AUTOSAR-DATA-TYPE", # 9 + "BSW-MODULE-ENTRY", # 10 + "COMPU-METHOD", # 11 + "CONSTANT-SPECIFICATION", # 12 + "DATA-CONSTR", # 13 + "IMPLEMENTATION-DATA-TYPE", # 14 + "PHYSICAL-DIMENSION", # 15 + "SW-ADDR-METHOD", # 16 + "SW-BASE-TYPE", # 17 + "UNIT", # 18 + "VARIABLE-DATA-PROTOTYPE" # 19 ], "IntervalType": [ "CLOSED", # 0 @@ -1017,6 +1055,11 @@ def xml_to_enum(enum_type_name: str, xml_text: str, schema_version: int = ar_bas "NOT-VALID", # 2 "VALID" # 3 ], + "ServerArgImplPolicy": [ + "USE-ARGUMENT-TYPE", # 0 + "USE-ARRAY-BASE-TYPE", # 1 + "USE-VOID", # 2 + ], "SwCalibrationAccess": [ "NOT-ACCESSIBLE", # 0 "READ-ONLY", # 1 diff --git a/src/autosar/xml/reader.py b/src/autosar/xml/reader.py index 4545a60..9fd27dc 100644 --- a/src/autosar/xml/reader.py +++ b/src/autosar/xml/reader.py @@ -127,6 +127,7 @@ def __init__(self, 'NV-DATA-INTERFACE': self._read_nv_data_interface, 'PARAMETER-INTERFACE': self._read_parameter_interface, 'SENDER-RECEIVER-INTERFACE': self._read_sender_receiver_interface, + 'CLIENT-SERVER-INTERFACE': self._read_client_server_interface, # Unit elements 'UNIT': self._read_unit, @@ -181,6 +182,7 @@ def __init__(self, 'SYMBOL-PROPS': self._read_symbol_props, 'IMPLEMENTATION-DATA-TYPE-ELEMENT': self._read_implementation_data_type_element, 'APPLICATION-RECORD-ELEMENT': self._read_application_record_element, + 'ARGUMENT-DATA-PROTOTYPE': self._read_argument_data_prototype, 'DATA-TYPE-MAP': self._read_data_type_map, 'SW-ARRAYSIZE': self._read_value_list, # CalibrationData elements @@ -193,6 +195,8 @@ def __init__(self, 'CONSTANT-REF': self._read_constant_ref, # Port interface element 'INVALIDATION-POLICY': self._read_invalidation_policy, + 'APPLICATION-ERROR': self._read_application_error, + 'CLIENT-SERVER-OPERATION': self._read_client_server_operation, } self.switcher_all = {} self.switcher_all.update(self.switcher_collectable) @@ -1957,6 +1961,35 @@ def _read_variable_data_prototype_group(self, child_elements: ChildElementMap, d pass child_elements.skip('VARIATION-POINT') # Not supported + def _read_argument_data_prototype(self, elem: ElementTree.Element) -> ar_element.ArgumentDataPrototype: + """ + Reads complex-type AR:ARGUMENT-DATA-PROTOTYPE + Type: Concrete + """ + data = {} + child_elements = ChildElementMap(elem) + self._read_referrable(child_elements, data) + self._read_multi_language_referrable(child_elements, data) + self._read_identifiable(child_elements, elem.attrib, data) + self._read_data_prototype(child_elements, data) + self._read_autosar_data_prototype(child_elements, data) + self._read_argument_data_prototype_group(child_elements, data) + self._report_unprocessed_elements(child_elements) + return ar_element.ArgumentDataPrototype(**data) + + def _read_argument_data_prototype_group(self, child_elements: ChildElementMap, data: dict) -> None: + """ + Reads group AR:ARGUMENT-DATA-PROTOTYPE + """ + xml_child = child_elements.get('DIRECTION') + if xml_child is not None: + data["direction"] = ar_enum.xml_to_enum("ArgumentDirection", xml_child.text) + xml_child = child_elements.get('SERVER-ARGUMENT-IMPL-POLICY') + if xml_child is not None: + data["server_arg_impl_policy"] = ar_enum.xml_to_enum("ServerArgImplPolicy", xml_child.text) + child_elements.skip("TYPE-BLUEPRINTS") # Not supported + child_elements.skip("VARIATION-POINT") # Not supported + # --- Reference elements def _read_compu_method_ref(self, xml_elem: ElementTree.Element) -> ar_element.CompuMethodRef: @@ -2135,6 +2168,20 @@ def _read_variable_data_prototype_ref( raise ar_exception.ParseError(msg) return ar_element.VariableDataPrototypeRef(xml_elem.text) + def _read_application_error_ref( + self, + xml_elem: ElementTree.Element) -> ar_element.ApplicationErrorRef: + """ + Reads reference to ApplicationError + Type: Concrete + """ + data = {} + self._read_base_ref_attributes(xml_elem.attrib, data) + if data['dest'] != 'APPLICATION-ERROR': + msg = f"Invalid value for DEST. Expected 'APPLICATION-ERROR', got '{data['dest']}'" + raise ar_exception.ParseError(msg) + return ar_element.ApplicationErrorRef(xml_elem.text) + def _read_base_ref_attributes(self, attr: dict, data: dict) -> None: """ Reads DEST attribute @@ -2624,3 +2671,105 @@ def _read_invalidation_policy(self, xml_element: ElementTree.Element) -> ar_elem if xml_child is not None: data["handle_invalid"] = ar_enum.xml_to_enum("HandleInvalid", xml_child.text) return ar_element.InvalidationPolicy(**data) + + def _read_application_error(self, xml_element: ElementTree.Element) -> ar_element.ApplicationError: + """ + Reads complex type AR:APPLICATION-ERROR + Tag variants: 'APPLICATION-ERROR' + """ + data = {} + child_elements = ChildElementMap(xml_element) + self._read_referrable(child_elements, data) + self._read_multi_language_referrable(child_elements, data) + self._read_identifiable(child_elements, xml_element.attrib, data) + self._read_application_error_group(child_elements, data) + self._report_unprocessed_elements(child_elements) + return ar_element.ApplicationError(**data) + + def _read_application_error_group(self, child_elements: ChildElementMap, data: dict) -> None: + """ + Reads group AR:APPLICATION-ERROR + """ + xml_child = child_elements.get("ERROR-CODE") + if xml_child is not None: + data["error_code"] = self._read_integer(xml_child.text) + + def _read_client_server_operation(self, xml_element: ElementTree.Element) -> ar_element.ClientServerOperation: + """ + Reads complex type AR:CLIENT-SERVER-OPERATION + Tag variants: 'CLIENT-SERVER-OPERATION' + """ + data = {} + child_elements = ChildElementMap(xml_element) + self._read_referrable(child_elements, data) + self._read_multi_language_referrable(child_elements, data) + self._read_identifiable(child_elements, xml_element.attrib, data) + self._read_client_server_operation_group(child_elements, data) + self._report_unprocessed_elements(child_elements) + return ar_element.ClientServerOperation(**data) + + def _read_client_server_operation_group(self, child_elements: ChildElementMap, data: dict) -> None: + """ + Reads group AR:CLIENT-SERVER-OPERATION + """ + xml_child = child_elements.get("ARGUMENTS") + if xml_child is not None: + arguments = [] + data["arguments"] = arguments + for xml_grand_child in xml_child.findall("./*"): + if xml_grand_child.tag == "ARGUMENT-DATA-PROTOTYPE": + element = self._read_argument_data_prototype(xml_grand_child) + arguments.append(element) + xml_child = child_elements.get("DIAG-ARG-INTEGRITY") + if xml_child is not None: + data["diag_arg_integrity"] = self._read_boolean(xml_child.text) + xml_child = child_elements.get("FIRE-AND-FORGET") + if xml_child is not None: + data["fire_and_forget"] = self._read_boolean(xml_child.text) + child_elements.skip("POSSIBLE-AP-ERROR-REFS") # not supported + child_elements.skip("POSSIBLE-AP-ERROR-SET-REFS") # not supported + xml_child = child_elements.get("POSSIBLE-ERROR-REFS") + if xml_child is not None: + possible_error_refs = [] + data["possible_error_refs"] = possible_error_refs + for xml_grand_child in xml_child.findall("./*"): + if xml_grand_child.tag == "POSSIBLE-ERROR-REF": + element = self._read_application_error_ref(xml_grand_child) + possible_error_refs.append(element) + child_elements.skip("VARIATION-POINT") # not supported + + def _read_client_server_interface(self, xml_element: ElementTree.Element) -> ar_element.ClientServerInterface: + """ + Reads complex type AR:CLIENT-SERVER-INTERFACE + Tag variants: 'CLIENT-SERVER-INTERFACE' + """ + data = {} + child_elements = ChildElementMap(xml_element) + self._read_referrable(child_elements, data) + self._read_multi_language_referrable(child_elements, data) + self._read_identifiable(child_elements, xml_element.attrib, data) + self._read_port_interface(child_elements, data) + self._read_client_server_interface_group(child_elements, data) + self._report_unprocessed_elements(child_elements) + return ar_element.ClientServerInterface(**data) + + def _read_client_server_interface_group(self, child_elements: ChildElementMap, data: dict) -> None: + """ + Reads group AR:CLIENT-SERVER-INTERFACE + """ + xml_child = child_elements.get('OPERATIONS') + if xml_child is not None: + operations = [] + data["operations"] = operations + for xml_grand_child in xml_child.findall('./*'): + if xml_grand_child.tag == 'CLIENT-SERVER-OPERATION': + element = self._read_client_server_operation(xml_grand_child) + operations.append(element) + xml_child = child_elements.get('POSSIBLE-ERRORS') + if xml_child is not None: + possible_errors = [] + data["possible_errors"] = possible_errors + for xml_grand_child in xml_child.findall('./*'): + if xml_grand_child.tag == 'APPLICATION-ERROR': + element = self._read_application_error(xml_grand_child) + possible_errors.append(element) diff --git a/src/autosar/xml/writer.py b/src/autosar/xml/writer.py index c268d1a..5a067ae 100644 --- a/src/autosar/xml/writer.py +++ b/src/autosar/xml/writer.py @@ -205,6 +205,7 @@ def __init__(self) -> None: 'NvDataInterface': self._write_nv_data_interface, 'ParameterInterface': self._write_parameter_interface, 'SenderReceiverInterface': self._write_sender_receiver_interface, + 'ClientServerInterface': self._write_client_server_interface, } # Value specification elements self.switcher_value_specification = { @@ -259,6 +260,7 @@ def __init__(self) -> None: 'ValueList': self._write_value_list, 'VariableDataPrototype': self._write_variable_data_prototype, 'ParameterDataPrototype': self._write_parameter_data_prototype, + 'ArgumentDataPrototype': self._write_argument_data_prototype, # CalibrationData elements 'SwValues': self._write_sw_values, 'SwAxisCont': self._write_sw_axis_cont, @@ -269,6 +271,8 @@ def __init__(self) -> None: 'ConstantRef': self._write_constant_ref, # Port interface element 'InvalidationPolicy': self._write_invalidation_policy, + 'ApplicationError': self._write_application_error, + 'ClientServerOperation': self._write_client_server_operation, } self.switcher_all = {} # All concrete elements (used for unit testing) self.switcher_all.update(self.switcher_collectable) @@ -1684,6 +1688,34 @@ def _write_parameter_data_prototype_group(self, elem: ar_element.ParameterDataPr self._write_value_specification_element(elem.init_value) self._leave_child() + def _write_argument_data_prototype(self, elem: ar_element.ArgumentDataPrototype) -> None: + """ + Reads complex-type AR:ARGUMENT-DATA-PROTOTYPE + Type: Concrete + Tag variants: 'ARGUMENT-DATA-PROTOTYPE' + """ + assert isinstance(elem, ar_element.ArgumentDataPrototype) + attr: TupleList = [] + self._collect_identifiable_attributes(elem, attr) + self._add_child("ARGUMENT-DATA-PROTOTYPE", attr) + self._write_referrable(elem) + self._write_multilanguage_referrable(elem) + self._write_identifiable(elem) + self._write_data_prototype(elem) + self._write_autosar_data_prototype(elem) + self._write_argument_data_prototype_group(elem) + self._leave_child() + + def _write_argument_data_prototype_group(self, elem: ar_element.ArgumentDataPrototype) -> None: + """ + Reads group AR:ARGUMENT-DATA-PROTOTYPE + Type: Abstract + """ + if elem.direction is not None: + self._add_content("DIRECTION", ar_enum.enum_to_xml(elem.direction)) + if elem.server_arg_impl_policy is not None: + self._add_content("SERVER-ARGUMENT-IMPL-POLICY", ar_enum.enum_to_xml(elem.server_arg_impl_policy)) + # --- Reference Elements def _collect_base_ref_attr(self, @@ -1855,7 +1887,18 @@ def _write_variable_data_prototype_ref(self, elem: ar_element.VariableDataProtot self._collect_base_ref_attr(elem, attr) self._add_content(tag, elem.value, attr) -# Constant and value specifications + def _write_application_error_ref(self, elem: ar_element.ApplicationErrorRef, tag: str) -> None: + """ + Writes reference to ApplicationError + Type: Concrete + Tag variants: 'POSSIBLE-ERROR-REF' | 'FIRST-APPLICATION-ERROR-REF' | 'SECOND-APPLICATION-ERROR-REF' + """ + assert isinstance(elem, ar_element.ApplicationErrorRef) + attr: TupleList = [] + self._collect_base_ref_attr(elem, attr) + self._add_content(tag, elem.value, attr) + +# -- Constant and value specifications def _write_text_value_specification(self, elem: ar_element.TextValueSpecification) -> None: """ @@ -2047,7 +2090,7 @@ def _write_constant_reference(self, elem: ar_element.ConstantReference) -> None: self._write_constant_ref(elem.constant_ref, "CONSTANT-REF") self._leave_child() -# CalibrationData elements +# --- CalibrationData elements def _write_sw_values(self, elem: ar_element.SwValues) -> None: """ @@ -2154,7 +2197,7 @@ def _write_sw_value_cont_group(self, elem: ar_element.SwValueCont) -> None: if elem.sw_values_phys is not None: self._write_sw_values(elem.sw_values_phys) -# Port interface elements +# --- Port interface elements def _write_port_interface(self, elem: ar_element.PortInterface) -> None: """ @@ -2269,3 +2312,84 @@ def _write_invalidation_policy_group(self, elem: ar_element.InvalidationPolicy) self._write_variable_data_prototype_ref(elem.data_element_ref, "DATA-ELEMENT-REF") if elem.handle_invalid is not None: self._add_content("HANDLE-INVALID", ar_enum.enum_to_xml(elem.handle_invalid)) + + def _write_application_error(self, elem: ar_element.ApplicationError) -> None: + """ + Writes complex type AR:APPLICATION-ERROR + Tag variants: 'APPLICATION-ERROR' + """ + assert isinstance(elem, ar_element.ApplicationError) + self._add_child("APPLICATION-ERROR") + self._write_referrable(elem) + self._write_multilanguage_referrable(elem) + self._write_identifiable(elem) + self._write_application_error_group(elem) + self._leave_child() + + def _write_application_error_group(self, elem: ar_element.ApplicationError) -> None: + """ + Writes group AR:APPLICATION-ERROR + """ + if elem.error_code is not None: + self._add_content("ERROR-CODE", str(elem.error_code)) + + def _write_client_server_operation(self, elem: ar_element.ClientServerOperation) -> None: + """ + Writes complex type AR:CLIENT-SERVER-OPERATION + Tag variants: 'CLIENT-SERVER-OPERATION' + """ + assert isinstance(elem, ar_element.ClientServerOperation) + self._add_child("CLIENT-SERVER-OPERATION") + self._write_referrable(elem) + self._write_multilanguage_referrable(elem) + self._write_identifiable(elem) + self._write_client_server_operation_group(elem) + self._leave_child() + + def _write_client_server_operation_group(self, elem: ar_element.ClientServerOperation) -> None: + """ + Writes group AR:CLIENT-SERVER-OPERATION + """ + if elem.arguments: + self._add_child("ARGUMENTS") + for argument in elem.arguments: + self._write_argument_data_prototype(argument) + self._leave_child() + if elem.diag_arg_integrity is not None: + self._add_content("DIAG-ARG-INTEGRITY", self._format_boolean(elem.diag_arg_integrity)) + if elem.fire_and_forget is not None: + self._add_content("FIRE-AND-FORGET", self._format_boolean(elem.fire_and_forget)) + if elem.possible_error_refs: + self._add_child("POSSIBLE-ERROR-REFS") + for possible_error_ref in elem.possible_error_refs: + self._write_application_error_ref(possible_error_ref, "POSSIBLE-ERROR-REF") + self._leave_child() + + def _write_client_server_interface(self, elem: ar_element.ClientServerInterface) -> None: + """ + Writes complex type AR:CLIENT-SERVER-INTERFACE + Tag variants: 'CLIENT-SERVER-INTERFACE' + """ + assert isinstance(elem, ar_element.ClientServerInterface) + self._add_child("CLIENT-SERVER-INTERFACE") + self._write_referrable(elem) + self._write_multilanguage_referrable(elem) + self._write_identifiable(elem) + self._write_port_interface(elem) + self._write_client_server_interface_group(elem) + self._leave_child() + + def _write_client_server_interface_group(self, elem: ar_element.ClientServerInterface) -> None: + """ + Writes group AR:CLIENT-SERVER-INTERFACE + """ + if elem.operations: + self._add_child("OPERATIONS") + for operation in elem.operations: + self._write_client_server_operation(operation) + self._leave_child() + if elem.possible_errors: + self._add_child("POSSIBLE-ERRORS") + for possible_error in elem.possible_errors: + self._write_application_error(possible_error) + self._leave_child() diff --git a/tests/xml/test_data_type.py b/tests/xml/test_data_type.py index 8234ac8..2aaeb1e 100644 --- a/tests/xml/test_data_type.py +++ b/tests/xml/test_data_type.py @@ -2073,5 +2073,73 @@ def test_read_write_init_value(self): self.assertEqual(elem.init_value.value, 4) +class TestArgumentDataPrototype(unittest.TestCase): + + def test_read_write_empty(self): + element = ar_element.ArgumentDataPrototype("ShortName") + writer = autosar.xml.Writer() + xml = ''' + ShortName +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ArgumentDataPrototype = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ArgumentDataPrototype) + self.assertEqual(elem.name, "ShortName") + + def test_read_write_sw_data_props(self): + sw_data_props = ar_element.SwDataDefPropsConditional( + calibration_access=ar_enum.SwCalibrationAccess.NOT_ACCESSIBLE) + element = ar_element.ArgumentDataPrototype("ShortName", sw_data_def_props=sw_data_props) + writer = autosar.xml.Writer() + xml = ''' + ShortName + + + + NOT-ACCESSIBLE + + + +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ArgumentDataPrototype = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ArgumentDataPrototype) + self.assertEqual(elem.name, "ShortName") + props: ar_element.SwDataDefPropsConditional = elem.sw_data_def_props[0] + self.assertEqual(props.calibration_access, ar_enum.SwCalibrationAccess.NOT_ACCESSIBLE) + + def test_read_write_direction(self): + element = ar_element.ArgumentDataPrototype("ShortName", + direction=ar_enum.ArgumentDirection.OUT) + writer = autosar.xml.Writer() + xml = ''' + ShortName + OUT +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ArgumentDataPrototype = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ArgumentDataPrototype) + self.assertEqual(elem.name, "ShortName") + self.assertEqual(elem.direction, ar_enum.ArgumentDirection.OUT) + + def test_read_write_server_arg_impl_policu(self): + element = ar_element.ArgumentDataPrototype("ShortName", + server_arg_impl_policy=ar_enum.ServerArgImplPolicy.USE_ARGUMENT_TYPE) + writer = autosar.xml.Writer() + xml = ''' + ShortName + USE-ARGUMENT-TYPE +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ArgumentDataPrototype = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ArgumentDataPrototype) + self.assertEqual(elem.name, "ShortName") + self.assertEqual(elem.server_arg_impl_policy, ar_enum.ServerArgImplPolicy.USE_ARGUMENT_TYPE) + + if __name__ == '__main__': unittest.main() diff --git a/tests/xml/test_port_interface.py b/tests/xml/test_port_interface.py index c1d44f3..c859ef7 100644 --- a/tests/xml/test_port_interface.py +++ b/tests/xml/test_port_interface.py @@ -9,6 +9,8 @@ import autosar.xml.element as ar_element # noqa E402 import autosar # noqa E402 +IMPLEMENTATION_DATA_TYPE = ar_enum.IdentifiableSubTypes.IMPLEMENTATION_DATA_TYPE + class TestInvalidationPolicy(unittest.TestCase): @@ -577,5 +579,279 @@ def test_create_interface_with_two_parameters_using_make_method(self): self.assertEqual(str(parameter.type_ref), "AUTOSAR_Platform/ImplementationDataTypes/uint16") +class TestApplicationError(unittest.TestCase): + + def test_name_only(self): + element = ar_element.ApplicationError("ErrorName") + writer = autosar.xml.Writer() + xml = ''' + ErrorName +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ApplicationError = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ApplicationError) + self.assertEqual(elem.name, "ErrorName") + + def test_error_code(self): + element = ar_element.ApplicationError("ErrorName", error_code=10) + writer = autosar.xml.Writer() + xml = ''' + ErrorName + 10 +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ApplicationError = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ApplicationError) + self.assertEqual(elem.name, "ErrorName") + self.assertEqual(elem.error_code, 10) + + +class TestClientServerOperation(unittest.TestCase): + + def test_name_only(self): + element = ar_element.ClientServerOperation("OperationName") + writer = autosar.xml.Writer() + xml = ''' + OperationName +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerOperation = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerOperation) + self.assertEqual(elem.name, "OperationName") + + def test_one_argument(self): + element = ar_element.ClientServerOperation("OperationName") + element.make_in_argument("Arg1", + type_ref=ar_element.AutosarDataTypeRef("/DataTypes/uint8", IMPLEMENTATION_DATA_TYPE)) + writer = autosar.xml.Writer() + xml = ''' + OperationName + + + Arg1 + /DataTypes/uint8 + IN + + +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerOperation = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerOperation) + self.assertEqual(elem.name, "OperationName") + self.assertEqual(len(elem.arguments), 1) + argument: ar_element.ArgumentDataPrototype = elem.arguments[0] + self.assertIsInstance(argument, ar_element.ArgumentDataPrototype) + self.assertEqual(argument.name, "Arg1") + self.assertEqual(str(argument.type_ref), "/DataTypes/uint8") + self.assertEqual(argument.direction, ar_enum.ArgumentDirection.IN) + + def test_two_arguments(self): + element = ar_element.ClientServerOperation("OperationName") + element.make_in_argument("Arg1", + type_ref=ar_element.AutosarDataTypeRef("/DataTypes/uint8", IMPLEMENTATION_DATA_TYPE)) + element.make_out_argument("Arg2", + type_ref=ar_element.AutosarDataTypeRef("/DataTypes/bool", IMPLEMENTATION_DATA_TYPE)) + writer = autosar.xml.Writer() + xml = ''' + OperationName + + + Arg1 + /DataTypes/uint8 + IN + + + Arg2 + /DataTypes/bool + OUT + + +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerOperation = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerOperation) + self.assertEqual(len(elem.arguments), 2) + argument: ar_element.ArgumentDataPrototype = elem.arguments[0] + self.assertIsInstance(argument, ar_element.ArgumentDataPrototype) + self.assertEqual(argument.name, "Arg1") + self.assertEqual(str(argument.type_ref), "/DataTypes/uint8") + self.assertEqual(argument.direction, ar_enum.ArgumentDirection.IN) + argument: ar_element.ArgumentDataPrototype = elem.arguments[1] + self.assertIsInstance(argument, ar_element.ArgumentDataPrototype) + self.assertEqual(argument.name, "Arg2") + self.assertEqual(str(argument.type_ref), "/DataTypes/bool") + self.assertEqual(argument.direction, ar_enum.ArgumentDirection.OUT) + + def test_diag_arg_integrity(self): + element = ar_element.ClientServerOperation("OperationName", + diag_arg_integrity=False) + writer = autosar.xml.Writer() + xml = ''' + OperationName + false +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerOperation = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerOperation) + self.assertFalse(elem.diag_arg_integrity) + + def test_fire_and_forget(self): + element = ar_element.ClientServerOperation("OperationName", + fire_and_forget=True) + writer = autosar.xml.Writer() + xml = ''' + OperationName + true +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerOperation = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerOperation) + self.assertTrue(elem.fire_and_forget) + + def test_single_possible_error(self): + element = ar_element.ClientServerOperation("OperationName") + element.make_possible_error_ref("/PortInterfaces/OperationName/ErrorName1") + writer = autosar.xml.Writer() + xml = ''' + OperationName + + /PortInterfaces/OperationName/ErrorName1 + +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerOperation = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerOperation) + self.assertEqual(elem.name, "OperationName") + self.assertEqual(len(elem.possible_error_refs), 1) + possible_error_ref: ar_element.ApplicationErrorRef = elem.possible_error_refs[0] + self.assertIsInstance(possible_error_ref, ar_element.ApplicationErrorRef) + self.assertEqual(str(possible_error_ref), "/PortInterfaces/OperationName/ErrorName1") + + def test_dual_possible_errors(self): + element = ar_element.ClientServerOperation("OperationName") + element.make_possible_error_ref("/PortInterfaces/OperationName/ErrorName1") + element.make_possible_error_ref("/PortInterfaces/OperationName/ErrorName2") + writer = autosar.xml.Writer() + xml = ''' + OperationName + + /PortInterfaces/OperationName/ErrorName1 + /PortInterfaces/OperationName/ErrorName2 + +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerOperation = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerOperation) + self.assertEqual(elem.name, "OperationName") + self.assertEqual(len(elem.possible_error_refs), 2) + possible_error_ref: ar_element.ApplicationErrorRef = elem.possible_error_refs[0] + self.assertIsInstance(possible_error_ref, ar_element.ApplicationErrorRef) + self.assertEqual(str(possible_error_ref), "/PortInterfaces/OperationName/ErrorName1") + possible_error_ref: ar_element.ApplicationErrorRef = elem.possible_error_refs[1] + self.assertIsInstance(possible_error_ref, ar_element.ApplicationErrorRef) + self.assertEqual(str(possible_error_ref), "/PortInterfaces/OperationName/ErrorName2") + + +class TestClientServerInterface(unittest.TestCase): + + def test_name_only(self): + element = ar_element.ClientServerInterface("InterfaceName") + writer = autosar.xml.Writer() + xml = ''' + InterfaceName +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerInterface = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerInterface) + self.assertEqual(elem.name, "InterfaceName") + + def test_operation(self): + element = ar_element.ClientServerInterface("InterfaceName") + operation = element.make_operation("Operation1") + operation.make_in_argument("Arg1", + type_ref=ar_element.AutosarDataTypeRef("/DataTypes/uint8", IMPLEMENTATION_DATA_TYPE)) + writer = autosar.xml.Writer() + xml = ''' + InterfaceName + + + Operation1 + + + Arg1 + /DataTypes/uint8 + IN + + + + +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerInterface = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerInterface) + self.assertEqual(elem.name, "InterfaceName") + self.assertEqual(len(elem.operations), 1) + operation = elem.operations[0] + self.assertIsInstance(operation, ar_element.ClientServerOperation) + self.assertEqual(operation.name, "Operation1") + + def test_operation_with_possible_error(self): + element = ar_element.ClientServerInterface("InterfaceName") + element.make_possible_error("E_NOT_OK") + operation = element.make_operation("Operation1") + operation.make_in_argument("Arg1", + type_ref=ar_element.AutosarDataTypeRef("/DataTypes/uint8", IMPLEMENTATION_DATA_TYPE)) + operation.make_possible_error_ref("/Portinterfaces/InterfaceName/E_NOT_OK") + writer = autosar.xml.Writer() + xml = ''' + InterfaceName + + + Operation1 + + + Arg1 + /DataTypes/uint8 + IN + + + + /Portinterfaces/InterfaceName/E_NOT_OK + + + + + + E_NOT_OK + + +''' + self.assertEqual(writer.write_str_elem(element), xml) + reader = autosar.xml.Reader() + elem: ar_element.ClientServerInterface = reader.read_str_elem(xml) + self.assertIsInstance(elem, ar_element.ClientServerInterface) + self.assertEqual(elem.name, "InterfaceName") + self.assertEqual(len(elem.operations), 1) + operation = elem.operations[0] + self.assertIsInstance(operation, ar_element.ClientServerOperation) + self.assertEqual(len(operation.possible_error_refs), 1) + possible_error_ref = operation.possible_error_refs[0] + self.assertEqual(str(possible_error_ref), "/Portinterfaces/InterfaceName/E_NOT_OK") + self.assertEqual(len(elem.possible_errors), 1) + possible_errors = elem.possible_errors[0] + self.assertEqual(possible_errors.name, "E_NOT_OK") + + if __name__ == '__main__': unittest.main()