Loading doc/analysis/generaterobotdata.py +107 −15 Original line number Diff line number Diff line Loading @@ -682,7 +682,12 @@ class GenerateRobotData: return setup def _resolve_iop_value(self, value: str, field: str) -> str: def _resolve_iop_value( self, value: str, field: str, setup_variables: dict | None = None, ) -> str: original = str(value) result = original visited = set() Loading @@ -692,6 +697,10 @@ class GenerateRobotData: raise ValueError(f"{field} variable '{original}' contains a circular reference") visited.add(result) if setup_variables is not None and result in setup_variables: result = str(setup_variables[result]) continue if result in self.robot.variables: result = str(self.robot.variables[result]) continue Loading Loading @@ -749,12 +758,65 @@ class GenerateRobotData: return values @staticmethod def _compose_iop_configuration_context(args) -> str: for argument in (str(item) for item in args): key, separator, value = argument.partition('=') if separator and key == 'ld_context': return value if len(args) > 1: return str(args[1]) return '${ngsild_test_suite_context}' def _iop_context_kind( self, value: str, field: str, setup_variables: dict, ) -> tuple[str, bool]: resolved = self._resolve_iop_value( value=value, field=field, setup_variables=setup_variables, ) core_context = self._resolve_iop_value( value='${core_context}', field='Core context', ) test_suite_context = self._resolve_iop_value( value='${ngsild_test_suite_context}', field='Test suite context', ) return ( 'Default context' if resolved == core_context else 'User context', resolved == test_suite_context, ) def generate_iop_preconditions(self, test_name: str) -> list: setup = self._get_iop_setup(test_name=test_name) contexts = [] data = [] context_operations = [] setup_variables = {} for keyword in setup.body: if keyword.name == 'Set Test Variable' and len(keyword.args) >= 2: setup_variables[str(keyword.args[0])] = str(keyword.args[1]) continue if keyword.name == 'Compose IOP Configuration': context_kind, is_test_suite_context = self._iop_context_kind( value=self._compose_iop_configuration_context(keyword.args), field='Compose IOP Configuration context', setup_variables=setup_variables, ) context_operations.append(( 'registrations', context_kind, is_test_suite_context, )) continue if keyword.name != 'Create Entity': continue Loading @@ -771,23 +833,53 @@ class GenerateRobotData: ) data.append(f"{broker} contains {payload_filename}.") if 'context' in arguments: context_filename = self._iop_filename( value=arguments['context'], field='Create Entity context' context_kind, is_test_suite_context = self._iop_context_kind( value=arguments.get('context', '${ngsild_test_suite_context}'), field='Create Entity context', setup_variables=setup_variables, ) entity_id = self._resolve_iop_value( value=arguments['entity_id'], field='Create Entity entity ID', setup_variables=setup_variables, ) context_operations.append(( 'entity', context_kind, is_test_suite_context, entity_id, broker, )) if not context_operations or all( operation[1] == 'Default context' for operation in context_operations ): context_top_level = 'No user context used.' contexts = [] elif all(operation[2] for operation in context_operations): context_top_level = 'User context used in every operation.' contexts = [] else: context_top_level = 'The following user contexts are used:' contexts = [] for operation in context_operations: if operation[0] == 'entity': _, context_kind, _, entity_id, broker = operation contexts.append( f"The {context_filename} user context is used when creating on {broker}." f"{context_kind} when creating the entity with id {entity_id} " f"in broker {broker}." ) else: _, context_kind, _ = operation contexts.append( f"{context_kind} when creating the registrations in all brokers." ) return [ { 'type': 'context', 'top-level': ( 'Context used for creation in following brokers:' if contexts else 'No user context used.' ), 'top-level': context_top_level, 'nested-object': contexts }, { Loading doc/tests/test_iop_preconditions.py +52 −7 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ Prepare Preconditions ['since_v1.6.1', 'iop', '4_3_3'] ) def test_generates_context_and_data_objects(self): def test_generates_mixed_context_and_data_objects(self): result = self.generate( variables='''${first_payload} fixtures/first-entity.jsonld ${context_path} https://example.test/contexts/example-context.jsonld?version=1 Loading Loading @@ -95,12 +95,15 @@ ${b3_url} ${EMPTY}''', [ { 'type': 'context', 'top-level': 'Context used for creation in following brokers:', 'top-level': 'The following user contexts are used:', 'nested-object': [ 'The example-context.jsonld user context is used when creating on b2.', ( 'The ngsi-ld-test-suite-compound.jsonld user context ' 'is used when creating on b3.' 'User context when creating the entity with id ' 'urn:ngsi-ld:Example:1 in broker b2.' ), ( 'User context when creating the entity with id ' 'urn:ngsi-ld:Example:2 in broker b3.' ) ] }, Loading @@ -115,7 +118,7 @@ ${b3_url} ${EMPTY}''', ] ) def test_uses_empty_context_object_when_context_is_omitted(self): def test_uses_test_suite_context_when_context_is_omitted(self): result = self.generate( variables='${b2_url} ${EMPTY}', setup=( Loading @@ -131,7 +134,7 @@ ${b3_url} ${EMPTY}''', [ { 'type': 'context', 'top-level': 'No user context used.', 'top-level': 'User context used in every operation.', 'nested-object': [] }, { Loading @@ -145,6 +148,48 @@ ${b3_url} ${EMPTY}''', ] ) def test_uses_no_user_context_when_all_operations_use_core_context(self): result = self.generate( variables='${b1_url} ${EMPTY}', setup=''' Set Test Variable ${entity_id} urn:ngsi-ld:Example:1 Create Entity entity.jsonld ${entity_id} broker_url=${b1_url} context=${core_context} @{configuration}= Create List Compose IOP Configuration ${configuration} ld_context=${core_context}''' ) self.assertEqual( result['pre_conditions'][0], { 'type': 'context', 'top-level': 'No user context used.', 'nested-object': [] } ) def test_generates_mixed_entity_and_registration_contexts(self): result = self.generate( variables='${b1_url} ${EMPTY}', setup=''' Set Test Variable ${entity_id} urn:ngsi-ld:Example:1 Create Entity entity.jsonld ${entity_id} broker_url=${b1_url} context=${core_context} @{configuration}= Create List Compose IOP Configuration ${configuration} ld_context=${ngsild_test_suite_context}''' ) self.assertEqual( result['pre_conditions'][0], { 'type': 'context', 'top-level': 'The following user contexts are used:', 'nested-object': [ ( 'Default context when creating the entity with id ' 'urn:ngsi-ld:Example:1 in broker b1.' ), 'User context when creating the registrations in all brokers.' ] } ) def test_uses_empty_objects_without_create_entity(self): result = self.generate( variables='${b1_url} ${EMPTY}', Loading Loading
doc/analysis/generaterobotdata.py +107 −15 Original line number Diff line number Diff line Loading @@ -682,7 +682,12 @@ class GenerateRobotData: return setup def _resolve_iop_value(self, value: str, field: str) -> str: def _resolve_iop_value( self, value: str, field: str, setup_variables: dict | None = None, ) -> str: original = str(value) result = original visited = set() Loading @@ -692,6 +697,10 @@ class GenerateRobotData: raise ValueError(f"{field} variable '{original}' contains a circular reference") visited.add(result) if setup_variables is not None and result in setup_variables: result = str(setup_variables[result]) continue if result in self.robot.variables: result = str(self.robot.variables[result]) continue Loading Loading @@ -749,12 +758,65 @@ class GenerateRobotData: return values @staticmethod def _compose_iop_configuration_context(args) -> str: for argument in (str(item) for item in args): key, separator, value = argument.partition('=') if separator and key == 'ld_context': return value if len(args) > 1: return str(args[1]) return '${ngsild_test_suite_context}' def _iop_context_kind( self, value: str, field: str, setup_variables: dict, ) -> tuple[str, bool]: resolved = self._resolve_iop_value( value=value, field=field, setup_variables=setup_variables, ) core_context = self._resolve_iop_value( value='${core_context}', field='Core context', ) test_suite_context = self._resolve_iop_value( value='${ngsild_test_suite_context}', field='Test suite context', ) return ( 'Default context' if resolved == core_context else 'User context', resolved == test_suite_context, ) def generate_iop_preconditions(self, test_name: str) -> list: setup = self._get_iop_setup(test_name=test_name) contexts = [] data = [] context_operations = [] setup_variables = {} for keyword in setup.body: if keyword.name == 'Set Test Variable' and len(keyword.args) >= 2: setup_variables[str(keyword.args[0])] = str(keyword.args[1]) continue if keyword.name == 'Compose IOP Configuration': context_kind, is_test_suite_context = self._iop_context_kind( value=self._compose_iop_configuration_context(keyword.args), field='Compose IOP Configuration context', setup_variables=setup_variables, ) context_operations.append(( 'registrations', context_kind, is_test_suite_context, )) continue if keyword.name != 'Create Entity': continue Loading @@ -771,23 +833,53 @@ class GenerateRobotData: ) data.append(f"{broker} contains {payload_filename}.") if 'context' in arguments: context_filename = self._iop_filename( value=arguments['context'], field='Create Entity context' context_kind, is_test_suite_context = self._iop_context_kind( value=arguments.get('context', '${ngsild_test_suite_context}'), field='Create Entity context', setup_variables=setup_variables, ) entity_id = self._resolve_iop_value( value=arguments['entity_id'], field='Create Entity entity ID', setup_variables=setup_variables, ) context_operations.append(( 'entity', context_kind, is_test_suite_context, entity_id, broker, )) if not context_operations or all( operation[1] == 'Default context' for operation in context_operations ): context_top_level = 'No user context used.' contexts = [] elif all(operation[2] for operation in context_operations): context_top_level = 'User context used in every operation.' contexts = [] else: context_top_level = 'The following user contexts are used:' contexts = [] for operation in context_operations: if operation[0] == 'entity': _, context_kind, _, entity_id, broker = operation contexts.append( f"The {context_filename} user context is used when creating on {broker}." f"{context_kind} when creating the entity with id {entity_id} " f"in broker {broker}." ) else: _, context_kind, _ = operation contexts.append( f"{context_kind} when creating the registrations in all brokers." ) return [ { 'type': 'context', 'top-level': ( 'Context used for creation in following brokers:' if contexts else 'No user context used.' ), 'top-level': context_top_level, 'nested-object': contexts }, { Loading
doc/tests/test_iop_preconditions.py +52 −7 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ Prepare Preconditions ['since_v1.6.1', 'iop', '4_3_3'] ) def test_generates_context_and_data_objects(self): def test_generates_mixed_context_and_data_objects(self): result = self.generate( variables='''${first_payload} fixtures/first-entity.jsonld ${context_path} https://example.test/contexts/example-context.jsonld?version=1 Loading Loading @@ -95,12 +95,15 @@ ${b3_url} ${EMPTY}''', [ { 'type': 'context', 'top-level': 'Context used for creation in following brokers:', 'top-level': 'The following user contexts are used:', 'nested-object': [ 'The example-context.jsonld user context is used when creating on b2.', ( 'The ngsi-ld-test-suite-compound.jsonld user context ' 'is used when creating on b3.' 'User context when creating the entity with id ' 'urn:ngsi-ld:Example:1 in broker b2.' ), ( 'User context when creating the entity with id ' 'urn:ngsi-ld:Example:2 in broker b3.' ) ] }, Loading @@ -115,7 +118,7 @@ ${b3_url} ${EMPTY}''', ] ) def test_uses_empty_context_object_when_context_is_omitted(self): def test_uses_test_suite_context_when_context_is_omitted(self): result = self.generate( variables='${b2_url} ${EMPTY}', setup=( Loading @@ -131,7 +134,7 @@ ${b3_url} ${EMPTY}''', [ { 'type': 'context', 'top-level': 'No user context used.', 'top-level': 'User context used in every operation.', 'nested-object': [] }, { Loading @@ -145,6 +148,48 @@ ${b3_url} ${EMPTY}''', ] ) def test_uses_no_user_context_when_all_operations_use_core_context(self): result = self.generate( variables='${b1_url} ${EMPTY}', setup=''' Set Test Variable ${entity_id} urn:ngsi-ld:Example:1 Create Entity entity.jsonld ${entity_id} broker_url=${b1_url} context=${core_context} @{configuration}= Create List Compose IOP Configuration ${configuration} ld_context=${core_context}''' ) self.assertEqual( result['pre_conditions'][0], { 'type': 'context', 'top-level': 'No user context used.', 'nested-object': [] } ) def test_generates_mixed_entity_and_registration_contexts(self): result = self.generate( variables='${b1_url} ${EMPTY}', setup=''' Set Test Variable ${entity_id} urn:ngsi-ld:Example:1 Create Entity entity.jsonld ${entity_id} broker_url=${b1_url} context=${core_context} @{configuration}= Create List Compose IOP Configuration ${configuration} ld_context=${ngsild_test_suite_context}''' ) self.assertEqual( result['pre_conditions'][0], { 'type': 'context', 'top-level': 'The following user contexts are used:', 'nested-object': [ ( 'Default context when creating the entity with id ' 'urn:ngsi-ld:Example:1 in broker b1.' ), 'User context when creating the registrations in all brokers.' ] } ) def test_uses_empty_objects_without_create_entity(self): result = self.generate( variables='${b1_url} ${EMPTY}', Loading