From 70b476bcede602383d5f96b812cb60f19ff6fdfa Mon Sep 17 00:00:00 2001 From: Benedetta Arena Date: Tue, 17 Feb 2026 10:04:23 +0100 Subject: [PATCH 1/5] add: data for the tests --- ...ext-source-registration-exclusive-2.jsonld | 22 +++++++++ ...ext-source-registration-inclusive-2.jsonld | 22 +++++++++ .../offstreet-parking1-full.jsonld | 45 +++++++++++++++++++ .../offstreet-parking2-full.jsonld | 45 +++++++++++++++++++ ...g2-no-location-and-totalspotsnumber.jsonld | 31 +++++++++++++ 5 files changed, 165 insertions(+) create mode 100644 data/csourceRegistrations/interoperability/context-source-registration-exclusive-2.jsonld create mode 100644 data/csourceRegistrations/interoperability/context-source-registration-inclusive-2.jsonld create mode 100644 data/entities/interoperability/offstreet-parking1-full.jsonld create mode 100644 data/entities/interoperability/offstreet-parking2-full.jsonld create mode 100644 data/entities/interoperability/offstreet-parking2-no-location-and-totalspotsnumber.jsonld diff --git a/data/csourceRegistrations/interoperability/context-source-registration-exclusive-2.jsonld b/data/csourceRegistrations/interoperability/context-source-registration-exclusive-2.jsonld new file mode 100644 index 00000000..fdc4730a --- /dev/null +++ b/data/csourceRegistrations/interoperability/context-source-registration-exclusive-2.jsonld @@ -0,0 +1,22 @@ +{ + "id": "urn:ngsi-ld:ContextSourceRegistration:Exclusive:2", + "type": "ContextSourceRegistration", + "information": [ + { + "entities": [ + { + "id": "urn:ngsi-ld:OffStreetParking:2", + "type": "OffStreetParking" + } + ], + "propertyNames": [ + "location" + ] + } + ], + "mode": "exclusive", + "endpoint": "xxx", + "@context":[ + "https://forge.etsi.org/rep/cim/ngsi-ld-test-suite/-/raw/develop/resources/jsonld-contexts/ngsi-ld-test-suite-compound.jsonld" + ] +} \ No newline at end of file diff --git a/data/csourceRegistrations/interoperability/context-source-registration-inclusive-2.jsonld b/data/csourceRegistrations/interoperability/context-source-registration-inclusive-2.jsonld new file mode 100644 index 00000000..4f835c57 --- /dev/null +++ b/data/csourceRegistrations/interoperability/context-source-registration-inclusive-2.jsonld @@ -0,0 +1,22 @@ +{ + "id": "urn:ngsi-ld:ContextSourceRegistration:Inclusive:2", + "type": "ContextSourceRegistration", + "information": [ + { + "entities": [ + { + "type": "OffStreetParking" + } + ], + "propertyNames": [ + "availableSpotsNumber", + "totalSpotsNumber" + ] + } + ], + "mode": "inclusive", + "endpoint": "xxx", + "@context":[ + "https://forge.etsi.org/rep/cim/ngsi-ld-test-suite/-/raw/develop/resources/jsonld-contexts/ngsi-ld-test-suite-compound.jsonld" + ] +} \ No newline at end of file diff --git a/data/entities/interoperability/offstreet-parking1-full.jsonld b/data/entities/interoperability/offstreet-parking1-full.jsonld new file mode 100644 index 00000000..c35bf599 --- /dev/null +++ b/data/entities/interoperability/offstreet-parking1-full.jsonld @@ -0,0 +1,45 @@ +{ + "id": "urn:ngsi-ld:OffStreetParking:1", + "type": "OffStreetParking", + "name": { + "type": "Property", + "value": "Downtown One" + }, + "availableSpotsNumber": { + "type": "Property", + "value": 121, + "observedAt": "2017-07-29T12:05:02Z", + "reliability": { + "type": "Property", + "value": 0.7 + } + }, + "totalSpotsNumber": { + "type": "Property", + "value": 200 + }, + "location": { + "type": "GeoProperty", + "value": { + "type": "Point", + "coordinates": [ + -8.5, + 41.2 + ] + } + }, + "@context": [ + { + "OffStreetParking": "https://ngsi-ld-test-suite/context#OffStreetParking", + "Vehicle": "https://ngsi-ld-test-suite/context#Vehicle", + "availableSpotsNumber": "https://ngsi-ld-test-suite/context#availableSpotsNumber", + "brandName": "https://ngsi-ld-test-suite/context#brandName", + "isParked": "https://ngsi-ld-test-suite/context#isParked", + "name": "https://ngsi-ld-test-suite/context#name", + "source": "https://ngsi-ld-test-suite/context#source", + "speed": "https://ngsi-ld-test-suite/context#speed", + "totalSpotsNumber": "https://ngsi-ld-test-suite/context#totalSpotsNumber" + }, + "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld" + ] +} \ No newline at end of file diff --git a/data/entities/interoperability/offstreet-parking2-full.jsonld b/data/entities/interoperability/offstreet-parking2-full.jsonld new file mode 100644 index 00000000..0708f5e7 --- /dev/null +++ b/data/entities/interoperability/offstreet-parking2-full.jsonld @@ -0,0 +1,45 @@ +{ + "id": "urn:ngsi-ld:OffStreetParking:2", + "type": "OffStreetParking", + "name": { + "type": "Property", + "value": "Downtown Two" + }, + "availableSpotsNumber": { + "type": "Property", + "value": 112, + "observedAt": "2017-07-29T12:05:02Z", + "reliability": { + "type": "Property", + "value": 0.4 + } + }, + "totalSpotsNumber": { + "type": "Property", + "value": 150 + }, + "location": { + "type": "GeoProperty", + "value": { + "type": "Point", + "coordinates": [ + -8.45, + 41.2 + ] + } + }, + "@context": [ + { + "OffStreetParking": "https://ngsi-ld-test-suite/context#OffStreetParking", + "Vehicle": "https://ngsi-ld-test-suite/context#Vehicle", + "availableSpotsNumber": "https://ngsi-ld-test-suite/context#availableSpotsNumber", + "brandName": "https://ngsi-ld-test-suite/context#brandName", + "isParked": "https://ngsi-ld-test-suite/context#isParked", + "name": "https://ngsi-ld-test-suite/context#name", + "source": "https://ngsi-ld-test-suite/context#source", + "speed": "https://ngsi-ld-test-suite/context#speed", + "totalSpotsNumber": "https://ngsi-ld-test-suite/context#totalSpotsNumber" + }, + "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld" + ] +} \ No newline at end of file diff --git a/data/entities/interoperability/offstreet-parking2-no-location-and-totalspotsnumber.jsonld b/data/entities/interoperability/offstreet-parking2-no-location-and-totalspotsnumber.jsonld new file mode 100644 index 00000000..0e04c702 --- /dev/null +++ b/data/entities/interoperability/offstreet-parking2-no-location-and-totalspotsnumber.jsonld @@ -0,0 +1,31 @@ +{ + "id": "urn:ngsi-ld:OffStreetParking:2", + "type": "OffStreetParking", + "name": { + "type": "Property", + "value": "Downtown Two" + }, + "availableSpotsNumber": { + "type": "Property", + "value": 92, + "observedAt": "2017-07-30T12:10:02Z", + "reliability": { + "type": "Property", + "value": 0.56 + } + }, + "@context": [ + { + "OffStreetParking": "https://ngsi-ld-test-suite/context#OffStreetParking", + "Vehicle": "https://ngsi-ld-test-suite/context#Vehicle", + "availableSpotsNumber": "https://ngsi-ld-test-suite/context#availableSpotsNumber", + "brandName": "https://ngsi-ld-test-suite/context#brandName", + "isParked": "https://ngsi-ld-test-suite/context#isParked", + "name": "https://ngsi-ld-test-suite/context#name", + "source": "https://ngsi-ld-test-suite/context#source", + "speed": "https://ngsi-ld-test-suite/context#speed", + "totalSpotsNumber": "https://ngsi-ld-test-suite/context#totalSpotsNumber" + }, + "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld" + ] +} \ No newline at end of file -- GitLab From 3e191aee4100c90a165f7858cf737889afb7d767 Mon Sep 17 00:00:00 2001 From: Benedetta Arena Date: Tue, 17 Feb 2026 17:36:08 +0100 Subject: [PATCH 2/5] feat: add new test for query entities with three brokers --- .../Entity/QueryEntities/IOP_CNF_01_01.robot | 102 ++++++++++++++++++ .../ContextInformationConsumption.resource | 4 +- .../ContextInformationProvision.resource | 10 +- .../ContextSourceRegistration.resource | 19 ++-- 4 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot diff --git a/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot new file mode 100644 index 00000000..b0d16dfc --- /dev/null +++ b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot @@ -0,0 +1,102 @@ +*** Settings *** +Documentation Verify that the entities found in b2 and b3 can be queried from b1.Verify that the broker b2 mirrors the information stored in the b1 broker and broker b3 contains some exclusive data. + +Resource ${EXECDIR}/resources/ApiUtils/ContextInformationConsumption.resource +Resource ${EXECDIR}/resources/ApiUtils/ContextInformationProvision.resource +Resource ${EXECDIR}/resources/ApiUtils/ContextSourceDiscovery.resource +Resource ${EXECDIR}/resources/ApiUtils/ContextSourceRegistration.resource +Resource ${EXECDIR}/resources/AssertionUtils.resource +Resource ${EXECDIR}/resources/JsonUtils.resource + +Test Setup Setup Initial Context Source Registrations +Test Teardown Delete Entities and Delete Registrations + +*** Variables *** +${first_entity_payload_filename} interoperability/offstreet-parking1-full.jsonld +${second_entity_payload_filename} interoperability/offstreet-parking2-full.jsonld +${third_entity_payload_filename} interoperability/offstreet-parking2-no-location-and-totalspotsnumber.jsonld +${inclusive_registration_payload_file_path} csourceRegistrations/interoperability/context-source-registration-inclusive-2.jsonld +${exclusive_registration_payload_file_path} csourceRegistrations/interoperability/context-source-registration-exclusive-2.jsonld +${b1_url} +${b2_url} +${b3_url} + +*** Test Cases *** +IOP_CNF_01_01 Create Entity In B1 And Query Entity In All Brokers + [Documentation] Check that entities can be queried from all brokers. + [Tags] 6_3 I6_3_1_1 inclusive exclusive interoperability + + ${response}= Query Entities entity_types=OffstreetParking broker_url=${b1_url} + Check Response Status Code 200 ${response.status_code} + @{payload}= Set Variable ${response.json()} + Should Contain ${payload}\[OffstreetParking1] availableSpotsNumber + Should Contain ${payload}\[OffstreetParking1] totalSpotsNumber + + ${response}= Query Entities entity_types=OffstreetParking broker_url=${b2_url} + @{first_expected_payload}= Set Variable ${response.json()} + ${entity_ids}= Create List ${entity_id} ${second_entity_id} + Check Response Body Containing Entities URIS set to ${entity_ids} ${response.json()} + + ${response}= Query Entities entity_types=OffstreetParking broker_url=${b3_url} + @{second_expected_payload}= Set Variable ${response.json()} + ${entity_ids}= Create List ${entity_id} + Check Response Body Containing Entities URIS set to ${entity_ids} ${response.json()} + + Should Be Equal ${payload}\[OffstreetParking1] ${first_expected_payload}\[OffstreetParking1] + Should Contain ${payload}\[OffstreetParking2] ${first_expected_payload}\[OffstreetParking2][totalSpotsNumber] + Should Contain ${payload}\[OffstreetParking2] ${second_expected_payload}\[OffstreetParking2][location] + +*** Keywords *** +Setup Initial Context Source Registrations + + ${entity_id}= Generate Random Parking Entity Id + Set Suite Variable ${entity_id} + ${second_entity_id}= Generate Random Parking Entity Id + Set Suite Variable ${second_entity_id} + ${response}= Create Entity ${first_entity_payload_filename} ${entity_id} broker_url=${b2_url} + Check Response Status Code 201 ${response.status_code} + ${response}= Create Entity ${third_entity_payload_filename} ${second_entity_id} broker_url=${b2_url} + Check Response Status Code 201 ${response.status_code} + ${response}= Create Entity ${second_entity_payload_filename} ${entity_id} broker_url=${b3_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id1}= Generate Random CSR Id + Set Suite Variable ${registration_id1} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id1} + ... ${inclusive_registration_payload_file_path} + ... entity_id=${entity_id} + ... broker_url=${b2_url} + ... mode=inclusive + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id2}= Generate Random CSR Id + Set Suite Variable ${registration_id2} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id2} + ... ${inclusive_registration_payload_file_path} + ... entity_id=${second_entity_id} + ... broker_url=${b2_url} + ... mode=inclusive + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id3}= Generate Random CSR Id + Set Suite Variable ${registration_id3} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id3} + ... ${exclusive_registration_payload_file_path} + ... entity_id=${entity_id} + ... broker_url=${b3_url} + ... mode=exclusive + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + +Delete Entities And Delete Registrations + Delete Context Source Registration ${registration_id1} broker_url=${b1_url} + Delete Context Source Registration ${registration_id2} broker_url=${b1_url} + Delete Context Source Registration ${registration_id3} broker_url=${b1_url} + Delete Entity By Id ${entity_id} broker_url=${b2_url} + Delete Entity by Id ${second_entity_id} broker_url=${b2_url} + Delete Entity By Id ${entity_id} broker_url=${b3_url} \ No newline at end of file diff --git a/resources/ApiUtils/ContextInformationConsumption.resource b/resources/ApiUtils/ContextInformationConsumption.resource index c93c91f8..1dda133a 100755 --- a/resources/ApiUtils/ContextInformationConsumption.resource +++ b/resources/ApiUtils/ContextInformationConsumption.resource @@ -46,11 +46,13 @@ Query Entities ... ${datasetId}=${EMPTY} ... ${join}=${EMPTY} ... ${joinLevel}=${EMPTY} + ... ${broker_url}=${EMPTY} ${attrs_length}= Get Length ${attrs} ${accept_length}= Get Length ${accept} ${options_length}= Get Length ${options} ${entity_ids_length}= Get Length ${entity_ids} ${entity_types_length}= Get Length ${entity_types} + ${final_url}= Set Variable If '${broker_url}'!='' ${broker_url} ${url} &{headers}= Create Dictionary &{params}= Create Dictionary IF ${accept_length}>0 @@ -99,7 +101,7 @@ Query Entities END ${response}= GET - ... url=${url}/${ENTITIES_ENDPOINT_PATH} + ... url=${final_url}/${ENTITIES_ENDPOINT_PATH} ... headers=${headers} ... params=${params} ... expected_status=any diff --git a/resources/ApiUtils/ContextInformationProvision.resource b/resources/ApiUtils/ContextInformationProvision.resource index a38e9d8b..ae9ddbef 100755 --- a/resources/ApiUtils/ContextInformationProvision.resource +++ b/resources/ApiUtils/ContextInformationProvision.resource @@ -151,14 +151,15 @@ Batch Upsert Entities RETURN ${response} Create Entity - [Arguments] ${filename} ${entity_id} ${local}=${EMPTY} + [Arguments] ${filename} ${entity_id} ${local}=${EMPTY} ${broker_url}=${EMPTY} &{params}= Create Dictionary IF '${local}'!='' Set To Dictionary ${params} local=${local} ${entity_payload}= Load JSON From File ${EXECDIR}/data/entities/${filename} ${entity}= Update Value To JSON ${entity_payload} $.id ${entity_id} + ${final_url}= Set Variable If '${broker_url}'!='' ${broker_url} ${url} &{headers}= Create Dictionary Content-Type=application/ld+json ${response}= POST - ... url=${url}/${ENTITIES_ENDPOINT_PATH} + ... url=${final_url}/${ENTITIES_ENDPOINT_PATH} ... json=${entity} ... params=${params} ... headers=${headers} @@ -207,11 +208,12 @@ Create Entity Selecting Content Type RETURN ${response} Create Entity From File - [Arguments] ${filename} + [Arguments] ${filename} ${broker_url}=${EMPTY} ${file_content}= Get File ${EXECDIR}/data/entities/${filename} + ${final_url}= Set Variable If '${broker_url}'!='' ${broker_url} ${url} &{headers}= Create Dictionary Content-Type=application/ld+json ${response}= POST - ... url=${url}/${ENTITIES_ENDPOINT_PATH} + ... url=${final_url}/${ENTITIES_ENDPOINT_PATH} ... data=${file_content} ... headers=${headers} ... expected_status=any diff --git a/resources/ApiUtils/ContextSourceRegistration.resource b/resources/ApiUtils/ContextSourceRegistration.resource index e4d2d98e..348934b2 100755 --- a/resources/ApiUtils/ContextSourceRegistration.resource +++ b/resources/ApiUtils/ContextSourceRegistration.resource @@ -31,9 +31,11 @@ Prepare Context Source Registration From File ... ${entity_id_pattern}=${EMPTY} ... ${mode}=${EMPTY} ... ${endpoint}=${EMPTY} + ... ${broker_url}=${EMPTY} ... ${operations}=[] ${payload}= Load JSON From File ${EXECDIR}/data/${registration_file} + ${final_context_source_url}= Set Variable If '${broker_url}'!='' ${broker_url} ${context_source_url} ${registration_payload}= Update Value To JSON ... ${payload} ... $.id @@ -41,7 +43,7 @@ Prepare Context Source Registration From File ${registration_payload}= Update Value To JSON ... ${registration_payload} ... $..endpoint - ... ${context_source_url}${endpoint} + ... ${final_context_source_url}${endpoint} IF '${entity_id}' != '' ${dict}= Create Dictionary id=${entity_id} ${registration_payload}= Add Object To JSON @@ -85,8 +87,9 @@ Create Context Source Registration RETURN ${response} Create Context Source Registration With Return - [Arguments] ${payload} ${content_type}=${CONTENT_TYPE_LD_JSON} ${context}=${EMPTY} ${accept}=${EMPTY} + [Arguments] ${payload} ${content_type}=${CONTENT_TYPE_LD_JSON} ${context}=${EMPTY} ${accept}=${EMPTY} ${broker_url}=${EMPTY} &{headers}= Create Dictionary Content-Type=${content_type} + ${final_url}= Set Variable If '${broker_url}'!='' ${broker_url} ${url} IF '${accept}'!='' Set To Dictionary ${headers} Accept=${context} END @@ -97,7 +100,7 @@ Create Context Source Registration With Return ... Link=${context_link} END ${response}= POST - ... url=${url}/${CONTEXT_SOURCE_REGISTRATION_ENDPOINT_PATH} + ... url=${final_url}/${CONTEXT_SOURCE_REGISTRATION_ENDPOINT_PATH} ... json=${payload} ... headers=${headers} ... expected_status=any @@ -105,16 +108,18 @@ Create Context Source Registration With Return RETURN ${response} Delete Context Source Registration - [Arguments] ${context_source_registration_id} + [Arguments] ${context_source_registration_id} ${broker_url}=${EMPTY} - ${response}= DELETE url=${url}/${CONTEXT_SOURCE_REGISTRATION_ENDPOINT_PATH}/${context_source_registration_id} + ${final_url}= Set Variable If '${broker_url}' != '' ${broker_url} ${url} + ${response}= DELETE url=${final_url}/${CONTEXT_SOURCE_REGISTRATION_ENDPOINT_PATH}/${context_source_registration_id} Output ${response} Delete Context Source Registration RETURN ${response} Delete Context Source Registration With Return - [Arguments] ${registration_id} + [Arguments] ${registration_id} ${broker_url}=${EMPTY} + ${final_url}= Set Variable If '${broker_url}' != '' ${broker_url} ${url} ${response}= DELETE - ... url=${url}/${CONTEXT_SOURCE_REGISTRATION_ENDPOINT_PATH}/${registration_id} + ... url=${final_url}/${CONTEXT_SOURCE_REGISTRATION_ENDPOINT_PATH}/${registration_id} ... expected_status=any Output ${response} Delete Context Source Registration RETURN ${response} -- GitLab From 47ed69efa0e6f8f8c994331130a37a10afe69085 Mon Sep 17 00:00:00 2001 From: Benedetta Arena Date: Tue, 17 Feb 2026 17:47:12 +0100 Subject: [PATCH 3/5] feat: add new test for query entities via POST with three brokers --- .../Entity/QueryEntities/IOP_CNF_01_01.robot | 6 +- .../Entity/QueryEntities/IOP_CNF_01_02.robot | 101 ++++++++++++++++++ .../ContextInformationConsumption.resource | 4 +- 3 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_02.robot diff --git a/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot index b0d16dfc..c9dcf29d 100644 --- a/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot +++ b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot @@ -1,6 +1,5 @@ *** Settings *** -Documentation Verify that the entities found in b2 and b3 can be queried from b1.Verify that the broker b2 mirrors the information stored in the b1 broker and broker b3 contains some exclusive data. - +Documentation Verify that the entities found in b2 and b3 can be queried from b1 via HTTP GET. Resource ${EXECDIR}/resources/ApiUtils/ContextInformationConsumption.resource Resource ${EXECDIR}/resources/ApiUtils/ContextInformationProvision.resource Resource ${EXECDIR}/resources/ApiUtils/ContextSourceDiscovery.resource @@ -39,8 +38,7 @@ IOP_CNF_01_01 Create Entity In B1 And Query Entity In All Brokers ${response}= Query Entities entity_types=OffstreetParking broker_url=${b3_url} @{second_expected_payload}= Set Variable ${response.json()} - ${entity_ids}= Create List ${entity_id} - Check Response Body Containing Entities URIS set to ${entity_ids} ${response.json()} + Check Response Body Containing Entities URIS set to ${entity_id} ${response.json()} Should Be Equal ${payload}\[OffstreetParking1] ${first_expected_payload}\[OffstreetParking1] Should Contain ${payload}\[OffstreetParking2] ${first_expected_payload}\[OffstreetParking2][totalSpotsNumber] diff --git a/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_02.robot b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_02.robot new file mode 100644 index 00000000..3b1d0e63 --- /dev/null +++ b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_02.robot @@ -0,0 +1,101 @@ +*** Settings *** +Documentation Verify that the entities found in b2 and b3 can be queried from b1 via HTTP POST. + +Resource ${EXECDIR}/resources/ApiUtils/ContextInformationConsumption.resource +Resource ${EXECDIR}/resources/ApiUtils/ContextInformationProvision.resource +Resource ${EXECDIR}/resources/ApiUtils/ContextSourceDiscovery.resource +Resource ${EXECDIR}/resources/ApiUtils/ContextSourceRegistration.resource +Resource ${EXECDIR}/resources/AssertionUtils.resource +Resource ${EXECDIR}/resources/JsonUtils.resource + +Test Setup Setup Initial Context Source Registrations +Test Teardown Delete Entities and Delete Registrations + +*** Variables *** +${first_entity_payload_filename} interoperability/offstreet-parking1-full.jsonld +${second_entity_payload_filename} interoperability/offstreet-parking2-full.jsonld +${third_entity_payload_filename} interoperability/offstreet-parking2-no-location-and-totalspotsnumber.jsonld +${inclusive_registration_payload_file_path} csourceRegistrations/interoperability/context-source-registration-inclusive-2.jsonld +${exclusive_registration_payload_file_path} csourceRegistrations/interoperability/context-source-registration-exclusive-2.jsonld +${b1_url} +${b2_url} +${b3_url} + +*** Test Cases *** +IOP_CNF_01_01 Create Entity In B1 And Query Entity In All Brokers + [Documentation] Check that entities can be queried from all brokers. + [Tags] 6_3 I6_3_1_2 inclusive exclusive interoperability + + @{entities}= Create List ${entity_id} ${second_entity_id} + ${response}= Query Entities Via POST entities=${entities} broker_url=${b1_url} + Check Response Status Code 200 ${response.status_code} + @{payload}= Set Variable ${response.json()} + Should Contain ${payload}\[OffstreetParking1] availableSpotsNumber + Should Contain ${payload}\[OffstreetParking1] totalSpotsNumber + + ${response}= Query Entities Via POST entities=${entities} broker_url=${b2_url} + @{first_expected_payload}= Set Variable ${response.json()} + Check Response Body Containing Entities URIS set to ${entities} ${response.json()} + + ${response}= Query Entities Via POST entities=${entity_id} broker_url=${b3_url} + @{second_expected_payload}= Set Variable ${response.json()} + Check Response Body Containing Entities URIS set to ${entity_id} ${response.json()} + + Should Be Equal ${payload}\[OffstreetParking1] ${first_expected_payload}\[OffstreetParking1] + Should Contain ${payload}\[OffstreetParking2] ${first_expected_payload}\[OffstreetParking2][totalSpotsNumber] + Should Contain ${payload}\[OffstreetParking2] ${second_expected_payload}\[OffstreetParking2][location] + +*** Keywords *** +Setup Initial Context Source Registrations + + ${entity_id}= Generate Random Parking Entity Id + Set Suite Variable ${entity_id} + ${second_entity_id}= Generate Random Parking Entity Id + Set Suite Variable ${second_entity_id} + ${response}= Create Entity ${first_entity_payload_filename} ${entity_id} broker_url=${b2_url} + Check Response Status Code 201 ${response.status_code} + ${response}= Create Entity ${third_entity_payload_filename} ${second_entity_id} broker_url=${b2_url} + Check Response Status Code 201 ${response.status_code} + ${response}= Create Entity ${second_entity_payload_filename} ${entity_id} broker_url=${b3_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id1}= Generate Random CSR Id + Set Suite Variable ${registration_id1} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id1} + ... ${inclusive_registration_payload_file_path} + ... entity_id=${entity_id} + ... broker_url=${b2_url} + ... mode=inclusive + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id2}= Generate Random CSR Id + Set Suite Variable ${registration_id2} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id2} + ... ${inclusive_registration_payload_file_path} + ... entity_id=${second_entity_id} + ... broker_url=${b2_url} + ... mode=inclusive + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id3}= Generate Random CSR Id + Set Suite Variable ${registration_id3} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id3} + ... ${exclusive_registration_payload_file_path} + ... entity_id=${entity_id} + ... broker_url=${b3_url} + ... mode=exclusive + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + +Delete Entities And Delete Registrations + Delete Context Source Registration ${registration_id1} broker_url=${b1_url} + Delete Context Source Registration ${registration_id2} broker_url=${b1_url} + Delete Context Source Registration ${registration_id3} broker_url=${b1_url} + Delete Entity By Id ${entity_id} broker_url=${b2_url} + Delete Entity by Id ${second_entity_id} broker_url=${b2_url} + Delete Entity By Id ${entity_id} broker_url=${b3_url} \ No newline at end of file diff --git a/resources/ApiUtils/ContextInformationConsumption.resource b/resources/ApiUtils/ContextInformationConsumption.resource index 1dda133a..376bbf2f 100755 --- a/resources/ApiUtils/ContextInformationConsumption.resource +++ b/resources/ApiUtils/ContextInformationConsumption.resource @@ -116,6 +116,8 @@ Query Entities Via POST ... ${context}=${EMPTY} ... ${attrs}=${EMPTY} ... ${geometry_property}=${EMPTY} + ... ${broker_url}=${EMPTY} + ${final_url}= Set Variable If '${broker_url}'!='' ${broker_url} ${url} &{headers}= Create Dictionary Set To Dictionary ${headers} Content-Type ${content_type} Set To Dictionary ${headers} Accept ${accept} @@ -137,7 +139,7 @@ Query Entities Via POST Set To Dictionary ${body} geometryProperty=${geometry_property} END ${response}= POST - ... url=${url}/${ENTITY_OPERATIONS_QUERY_ENDPOINT_PATH} + ... url=${final_url}/${ENTITY_OPERATIONS_QUERY_ENDPOINT_PATH} ... json=${body} ... headers=${headers} ... expected_status=any -- GitLab From e7b8b04162d00f667a271d1b38c431978873677e Mon Sep 17 00:00:00 2001 From: Benedetta Arena Date: Tue, 17 Feb 2026 17:49:49 +0100 Subject: [PATCH 4/5] fix: improve test logic --- .../Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot | 2 ++ .../Consumption/Entity/QueryEntities/IOP_CNF_01_02.robot | 2 ++ 2 files changed, 4 insertions(+) diff --git a/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot index c9dcf29d..5ede4ebc 100644 --- a/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot +++ b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_01.robot @@ -30,6 +30,8 @@ IOP_CNF_01_01 Create Entity In B1 And Query Entity In All Brokers @{payload}= Set Variable ${response.json()} Should Contain ${payload}\[OffstreetParking1] availableSpotsNumber Should Contain ${payload}\[OffstreetParking1] totalSpotsNumber + Should Contain ${payload}\[OffstreetParking2] availableSpotsNumber + Should Contain ${payload}\[OffstreetParking2] location ${response}= Query Entities entity_types=OffstreetParking broker_url=${b2_url} @{first_expected_payload}= Set Variable ${response.json()} diff --git a/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_02.robot b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_02.robot index 3b1d0e63..43adec5d 100644 --- a/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_02.robot +++ b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_01_02.robot @@ -32,6 +32,8 @@ IOP_CNF_01_01 Create Entity In B1 And Query Entity In All Brokers @{payload}= Set Variable ${response.json()} Should Contain ${payload}\[OffstreetParking1] availableSpotsNumber Should Contain ${payload}\[OffstreetParking1] totalSpotsNumber + Should Contain ${payload}\[OffstreetParking2] availableSpotsNumber + Should Contain ${payload}\[OffstreetParking2] location ${response}= Query Entities Via POST entities=${entities} broker_url=${b2_url} @{first_expected_payload}= Set Variable ${response.json()} -- GitLab From 9e424267c8fcaf5e7d27e6280830a0112b176bdb Mon Sep 17 00:00:00 2001 From: Benedetta Arena Date: Wed, 18 Feb 2026 12:08:00 +0100 Subject: [PATCH 5/5] feat: add new interoperability test with four brokers --- .../Entity/QueryEntities/IOP_CNF_02_01.robot | 144 ++++++++++++++++++ ...text-source-registration-redirect-2.jsonld | 22 +++ ...text-source-registration-redirect-3.jsonld | 23 +++ .../offstreet-parking1-no-location.jsonld | 35 +++++ ...ffstreet-parking2-location-and-name.jsonld | 33 ++++ .../offstreet-parking2-no-location.jsonld | 35 +++++ 6 files changed, 292 insertions(+) create mode 100644 TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_02_01.robot create mode 100644 data/csourceRegistrations/interoperability/context-source-registration-redirect-2.jsonld create mode 100644 data/csourceRegistrations/interoperability/context-source-registration-redirect-3.jsonld create mode 100644 data/entities/interoperability/offstreet-parking1-no-location.jsonld create mode 100644 data/entities/interoperability/offstreet-parking2-location-and-name.jsonld create mode 100644 data/entities/interoperability/offstreet-parking2-no-location.jsonld diff --git a/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_02_01.robot b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_02_01.robot new file mode 100644 index 00000000..a9ac1ec6 --- /dev/null +++ b/TP/NGSI-LD/Interoperability/Consumption/Entity/QueryEntities/IOP_CNF_02_01.robot @@ -0,0 +1,144 @@ +*** Settings *** +Documentation Verify that the entities found in b2, b3 and b4 can be queried from b1 via Query. +Resource ${EXECDIR}/resources/ApiUtils/ContextInformationConsumption.resource +Resource ${EXECDIR}/resources/ApiUtils/ContextInformationProvision.resource +Resource ${EXECDIR}/resources/ApiUtils/ContextSourceDiscovery.resource +Resource ${EXECDIR}/resources/ApiUtils/ContextSourceRegistration.resource +Resource ${EXECDIR}/resources/AssertionUtils.resource +Resource ${EXECDIR}/resources/JsonUtils.resource + +Test Setup Setup Initial Context Source Registrations +Test Teardown Delete Entities and Delete Registrations + +*** Variables *** +${location_name_payload_filename} interoperability/offstreet-parking2-location-and-name.jsonld +${first_entity_no_location_payload_filename} interoperability/offstreet-parking1-no-location.jsonld +${second_entity_no_location_payload_filename} interoperability/offstreet-parking2-no-location.jsonld +${first_full_entity_payload_filename} interoperability/offstreet-parking1-full.jsonld +${second_full_entity_payload_filename} interoperability/offstreet-parking2-full.jsonld +${inclusive_registration_payload_file_path} csourceRegistrations/interoperability/context-source-registration-inclusive-2.jsonld +${first_redirect_registration_payload_file_path} csourceRegistrations/interoperability/context-source-registration-redirect-2.jsonld +${second_redirect_registration_payload_file_path} csourceRegistrations/interoperability/context-source-registration-redirect-3.jsonld +${b1_url} +${b2_url} +${b3_url} +${b4_url} + +*** Test Cases *** +IOP_CNF_02_01 Create Entity In B1 And Query Entity In All Brokers + [Documentation] Check that entities can be queried from all brokers. + [Tags] 6_3 I6_3_2_1 inclusive redirect interoperability + + ${response}= Query Entities entity_types=OffstreetParking broker_url=${b1_url} + Check Response Status Code 200 ${response.status_code} + @{entities_b1}= Set Variable ${response.json()} + ${first_payload}= Get From List ${entities_b1} 0 + ${second_payload}= Get From List ${entities_b1} 1 + Should Not Contain ${first_payload} name + Should Not Contain ${second_payload} name + + ${response}= Query Entities entity_types=OffstreetParking broker_url=${b2_url} + @{entities_b2}= Set Variable ${response.json()} + ${first_b2_payload}= Get From List ${entities_b2} 0 + ${second_b2_payload}= Get From List ${entities_b2} 1 + + ${response}= Query Entities entity_types=OffstreetParking broker_url=${b3_url} + @{entities_b3}= Set Variable ${response.json()} + ${b3_payload}= Get From List ${entities_b3} 0 + + ${response}= Query Entities entity_types=OffstreetParking broker_url=${b4_url} + @{entities_b4}= Set Variable ${response.json()} + ${b4_payload}= Get From List ${entities_b4} 0 + + Should Be Equal ${first_payload}[availableSpotsNumber] ${first_b2_payload}[availableSpotsNumber] + Should Be Equal ${first_payload}[totalSpotsNumber] ${first_b2_payload}[totalSpotsNumber] + Should Be Equal ${first_payload}[location] ${b3_payload}[location] + + Should Be Equal ${second_payload}[availableSpotsNumber] ${second_b2_payload}[availableSpotsNumber] + Should Be Equal ${second_payload}[totalSpotsNumber] ${second_b2_payload}[totalSpotsNumber] + Should Be Equal ${second_payload}[location] ${b4_payload}[location] + +*** Keywords *** +Setup Initial Context Source Registrations + + ${entity_id}= Generate Random Parking Entity Id + Set Suite Variable ${entity_id} + ${second_entity_id}= Generate Random Parking Entity Id + Set Suite Variable ${second_entity_id} + ${response}= Create Entity ${first_entity_no_location_payload_filename} ${entity_id} broker_url=${b2_url} + Check Response Status Code 201 ${response.status_code} + ${response}= Create Entity ${second_entity_no_location_payload_filename} ${second_entity_id} broker_url=${b2_url} + Check Response Status Code 201 ${response.status_code} + ${response}= Create Entity ${first_full_entity_payload_filename} ${entity_id} broker_url=${b3_url} + Check Response Status Code 201 ${response.status_code} + ${response}= Create Entity ${second_full_entity_payload_filename} ${second_entity_id} broker_url=${b3_url} + Check Response Status Code 201 ${response.status_code} + ${response}= Create Entity ${location_name_payload_filename} ${entity_id} broker_url=${b4_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id1}= Generate Random CSR Id + Set Suite Variable ${registration_id1} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id1} + ... ${inclusive_registration_payload_file_path} + ... entity_id=${entity_id} + ... broker_url=${b2_url} + ... mode=inclusive + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id2}= Generate Random CSR Id + Set Suite Variable ${registration_id2} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id2} + ... ${inclusive_registration_payload_file_path} + ... entity_id=${second_entity_id} + ... broker_url=${b2_url} + ... mode=inclusive + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id3}= Generate Random CSR Id + Set Suite Variable ${registration_id3} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id3} + ... ${first_redirect_registration_payload_file_path} + ... entity_id=${entity_id} + ... broker_url=${b3_url} + ... mode=redirect + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id4}= Generate Random CSR Id + Set Suite Variable ${registration_id4} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id4} + ... ${first_redirect_registration_payload_file_path} + ... entity_id=${second_entity_id} + ... broker_url=${b3_url} + ... mode=redirect + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + + ${registration_id5}= Generate Random CSR Id + Set Suite Variable ${registration_id5} + ${registration_payload}= Prepare Context Source Registration From File + ... ${registration_id5} + ... ${second_redirect_registration_payload_file_path} + ... entity_id=${entity_id} + ... broker_url=${b4_url} + ... mode=redirect + ${response}= Create Context Source Registration With Return ${registration_payload} broker_url=${b1_url} + Check Response Status Code 201 ${response.status_code} + +Delete Entities And Delete Registrations + Delete Context Source Registration ${registration_id1} broker_url=${b1_url} + Delete Context Source Registration ${registration_id2} broker_url=${b1_url} + Delete Context Source Registration ${registration_id3} broker_url=${b1_url} + Delete Context Source Registration ${registration_id4} broker_url=${b1_url} + Delete Context Source Registration ${registration_id5} broker_url=${b1_url} + Delete Entity By Id ${entity_id} broker_url=${b2_url} + Delete Entity by Id ${second_entity_id} broker_url=${b2_url} + Delete Entity By Id ${entity_id} broker_url=${b3_url} + Delete Entity By Id ${second_entity_id} broker_url=${b3_url} + Delete Entity By Id ${entity_id} broker_url=${b4_url} \ No newline at end of file diff --git a/data/csourceRegistrations/interoperability/context-source-registration-redirect-2.jsonld b/data/csourceRegistrations/interoperability/context-source-registration-redirect-2.jsonld new file mode 100644 index 00000000..2fd0aa25 --- /dev/null +++ b/data/csourceRegistrations/interoperability/context-source-registration-redirect-2.jsonld @@ -0,0 +1,22 @@ +{ + "id": "urn:ngsi-ld:ContextSourceRegistration:Redirect:2", + "type": "ContextSourceRegistration", + "information": [ + { + "entities": [ + { + "type": "OffStreetParking" + } + ], + "propertyNames": [ + "location" + ] + } + ], + "mode": "redirect", + "operations": ["redirectionOps"], + "endpoint": "xxx", + "@context":[ + "https://forge.etsi.org/rep/cim/ngsi-ld-test-suite/-/raw/develop/resources/jsonld-contexts/ngsi-ld-test-suite-compound.jsonld" + ] +} \ No newline at end of file diff --git a/data/csourceRegistrations/interoperability/context-source-registration-redirect-3.jsonld b/data/csourceRegistrations/interoperability/context-source-registration-redirect-3.jsonld new file mode 100644 index 00000000..44e537ca --- /dev/null +++ b/data/csourceRegistrations/interoperability/context-source-registration-redirect-3.jsonld @@ -0,0 +1,23 @@ +{ + "id": "urn:ngsi-ld:ContextSourceRegistration:Redirect:3", + "type": "ContextSourceRegistration", + "information": [ + { + "entities": [ + { + "type": "OffStreetParking", + "id": "urn:ngsi-ld:OffStreetParking:2" + } + ], + "propertyNames": [ + "location" + ] + } + ], + "mode": "redirect", + "operations": ["redirectionOps"], + "endpoint": "xxx", + "@context":[ + "https://forge.etsi.org/rep/cim/ngsi-ld-test-suite/-/raw/develop/resources/jsonld-contexts/ngsi-ld-test-suite-compound.jsonld" + ] +} \ No newline at end of file diff --git a/data/entities/interoperability/offstreet-parking1-no-location.jsonld b/data/entities/interoperability/offstreet-parking1-no-location.jsonld new file mode 100644 index 00000000..a9e6f2c5 --- /dev/null +++ b/data/entities/interoperability/offstreet-parking1-no-location.jsonld @@ -0,0 +1,35 @@ +{ + "id": "urn:ngsi-ld:OffStreetParking:1", + "type": "OffStreetParking", + "name": { + "type": "Property", + "value": "Downtown One" + }, + "availableSpotsNumber": { + "type": "Property", + "value": 169, + "observedAt": "2017-07-29T12:10:02Z", + "reliability": { + "type": "Property", + "value": 0.3 + } + }, + "totalSpotsNumber": { + "type": "Property", + "value": 200 + }, + "@context": [ + { + "OffStreetParking": "https://ngsi-ld-test-suite/context#OffStreetParking", + "Vehicle": "https://ngsi-ld-test-suite/context#Vehicle", + "availableSpotsNumber": "https://ngsi-ld-test-suite/context#availableSpotsNumber", + "brandName": "https://ngsi-ld-test-suite/context#brandName", + "isParked": "https://ngsi-ld-test-suite/context#isParked", + "name": "https://ngsi-ld-test-suite/context#name", + "source": "https://ngsi-ld-test-suite/context#source", + "speed": "https://ngsi-ld-test-suite/context#speed", + "totalSpotsNumber": "https://ngsi-ld-test-suite/context#totalSpotsNumber" + }, + "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld" + ] +} \ No newline at end of file diff --git a/data/entities/interoperability/offstreet-parking2-location-and-name.jsonld b/data/entities/interoperability/offstreet-parking2-location-and-name.jsonld new file mode 100644 index 00000000..b707bf73 --- /dev/null +++ b/data/entities/interoperability/offstreet-parking2-location-and-name.jsonld @@ -0,0 +1,33 @@ +{ + "id": "urn:ngsi-ld:OffStreetParking:2", + "type": "OffStreetParking", + "name": { + "type": "Property", + "value": "Downtown Two" + }, + "location": { + "type": "GeoProperty", + "value": { + "type": "Point", + "coordinates": [ + -8.46, + 41.25 + ] , + "observedAt": "2021-04-04T11:46:00Z" + } + }, + "@context": [ + { + "OffStreetParking": "https://ngsi-ld-test-suite/context#OffStreetParking", + "Vehicle": "https://ngsi-ld-test-suite/context#Vehicle", + "availableSpotsNumber": "https://ngsi-ld-test-suite/context#availableSpotsNumber", + "brandName": "https://ngsi-ld-test-suite/context#brandName", + "isParked": "https://ngsi-ld-test-suite/context#isParked", + "name": "https://ngsi-ld-test-suite/context#name", + "source": "https://ngsi-ld-test-suite/context#source", + "speed": "https://ngsi-ld-test-suite/context#speed", + "totalSpotsNumber": "https://ngsi-ld-test-suite/context#totalSpotsNumber" + }, + "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld" + ] +} \ No newline at end of file diff --git a/data/entities/interoperability/offstreet-parking2-no-location.jsonld b/data/entities/interoperability/offstreet-parking2-no-location.jsonld new file mode 100644 index 00000000..266d15c1 --- /dev/null +++ b/data/entities/interoperability/offstreet-parking2-no-location.jsonld @@ -0,0 +1,35 @@ +{ + "id": "urn:ngsi-ld:OffStreetParking:2", + "type": "OffStreetParking", + "name": { + "type": "Property", + "value": "Downtown Two" + }, + "availableSpotsNumber": { + "type": "Property", + "value": 87, + "observedAt": "2017-07-29T12:10:02Z", + "reliability": { + "type": "Property", + "value": 0.55 + } + }, + "totalSpotsNumber": { + "type": "Property", + "value": 150 + }, + "@context": [ + { + "OffStreetParking": "https://ngsi-ld-test-suite/context#OffStreetParking", + "Vehicle": "https://ngsi-ld-test-suite/context#Vehicle", + "availableSpotsNumber": "https://ngsi-ld-test-suite/context#availableSpotsNumber", + "brandName": "https://ngsi-ld-test-suite/context#brandName", + "isParked": "https://ngsi-ld-test-suite/context#isParked", + "name": "https://ngsi-ld-test-suite/context#name", + "source": "https://ngsi-ld-test-suite/context#source", + "speed": "https://ngsi-ld-test-suite/context#speed", + "totalSpotsNumber": "https://ngsi-ld-test-suite/context#totalSpotsNumber" + }, + "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld" + ] +} \ No newline at end of file -- GitLab