From fe1f7c5552c98b25004c31a6fe027ae6339ad5c2 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Thu, 18 Jan 2024 14:43:24 +0100 Subject: [PATCH 01/22] feat(irs-registry-client): Add wiremock tests for decentral registry and discovery service --- irs-registry-client/pom.xml | 6 + ...igitalTwinRegistryServiceWiremockTest.java | 201 +++++++++++++++ .../decentral/DtrWiremockConfig.java | 239 ++++++++++++++++++ irs-testing/pom.xml | 17 ++ pom.xml | 4 +- 5 files changed, 465 insertions(+), 2 deletions(-) create mode 100644 irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java create mode 100644 irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DtrWiremockConfig.java diff --git a/irs-registry-client/pom.xml b/irs-registry-client/pom.xml index 9621ea237e..7c9a483a26 100644 --- a/irs-registry-client/pom.xml +++ b/irs-registry-client/pom.xml @@ -53,6 +53,12 @@ org.springframework.boot spring-boot-starter-web provided + + + snakeyaml + org.yaml + + org.yaml diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java new file mode 100644 index 0000000000..279aa091a5 --- /dev/null +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java @@ -0,0 +1,201 @@ +/******************************************************************************** + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.registryclient.decentral; + +import static com.github.tomakehurst.wiremock.client.WireMock.exactly; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.DATAPLANE_URL; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.DISCOVERY_FINDER_PATH; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.DISCOVERY_FINDER_URL; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.EDC_DISCOVERY_PATH; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.LOOKUP_SHELLS_PATH; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.LOOKUP_SHELLS_TEMPLATE; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.SHELL_DESCRIPTORS_PATH; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.SHELL_DESCRIPTORS_TEMPLATE; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.TEST_BPN; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getLookupShells200; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getLookupShells200Empty; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getLookupShells404; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getShellDescriptor200; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getShellDescriptor404; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postDiscoveryFinder200; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postDiscoveryFinder404; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postEdcDiscovery200; +import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postEdcDiscovery404; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.irs.component.assetadministrationshell.AssetAdministrationShellDescriptor; +import org.eclipse.tractusx.irs.registryclient.DigitalTwinRegistryKey; +import org.eclipse.tractusx.irs.registryclient.discovery.ConnectorEndpointsService; +import org.eclipse.tractusx.irs.registryclient.discovery.DiscoveryFinderClientImpl; +import org.eclipse.tractusx.irs.registryclient.exceptions.RegistryServiceException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +@WireMockTest +class DecentralDigitalTwinRegistryServiceWiremockTest { + private static final String PROXY_SERVER_HOST = "127.0.0.1"; + private final EdcEndpointReferenceRetriever edcSubmodelFacadeMock = mock(EdcEndpointReferenceRetriever.class); + private DecentralDigitalTwinRegistryService decentralDigitalTwinRegistryService; + + @BeforeEach + void setUp(WireMockRuntimeInfo wireMockRuntimeInfo) throws EdcRetrieverException { + // Configure RestTemplate to proxy all requests to localhost + final int httpPort = wireMockRuntimeInfo.getHttpPort(); + final Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_SERVER_HOST, httpPort)); + final SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setProxy(proxy); + final var restTemplate = new RestTemplate(requestFactory); + + final var discoveryFinderClient = new DiscoveryFinderClientImpl(DISCOVERY_FINDER_URL, restTemplate); + final var connectorEndpointsService = new ConnectorEndpointsService(discoveryFinderClient); + final var endpointDataForConnectorsService = new EndpointDataForConnectorsService(edcSubmodelFacadeMock); + final var decentralDigitalTwinRegistryClient = new DecentralDigitalTwinRegistryClient(restTemplate, + SHELL_DESCRIPTORS_TEMPLATE, LOOKUP_SHELLS_TEMPLATE); + decentralDigitalTwinRegistryService = new DecentralDigitalTwinRegistryService(connectorEndpointsService, + endpointDataForConnectorsService, decentralDigitalTwinRegistryClient); + final var endpointDataReference = EndpointDataReference.Builder.newInstance() + .endpoint(DATAPLANE_URL) + .authCode("TEST") + .authKey("X-API-KEY") + .properties(Map.of()) + .build(); + when(edcSubmodelFacadeMock.getEndpointReferenceForAsset(any(), any(), any())).thenReturn(endpointDataReference); + } + + @Test + void shouldDiscoverEDCAndRequestRegistry() throws RegistryServiceException { + // Arrange + givenThat(postDiscoveryFinder200()); + givenThat(postEdcDiscovery200()); + givenThat(getLookupShells200()); + givenThat(getShellDescriptor200()); + + // Act + final Collection assetAdministrationShellDescriptors = decentralDigitalTwinRegistryService.fetchShells( + List.of(new DigitalTwinRegistryKey("testId", TEST_BPN))); + + // Assert + assertThat(assetAdministrationShellDescriptors).hasSize(1); + assertThat(assetAdministrationShellDescriptors.stream().findFirst().get().getSubmodelDescriptors()).hasSize(3); + verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + verify(exactly(1), postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + verify(exactly(1), getRequestedFor(urlPathEqualTo(LOOKUP_SHELLS_PATH))); + verify(exactly(1), getRequestedFor(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*"))); + } + + @Test + void shouldThrowHttpClientExceptionInCaseOfDiscoveryError() { + // Arrange + givenThat(postDiscoveryFinder404()); + final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); + + // Act & Assert + assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( + HttpClientErrorException.class); + verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + } + + @Test + void shouldThrowHttpClientExceptionInCaseOfEdcDiscoveryError() { + // Arrange + givenThat(postDiscoveryFinder200()); + givenThat(postEdcDiscovery404()); + final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); + + // Act & Assert + assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( + HttpClientErrorException.class); + verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + verify(exactly(1), postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + } + + @Test + void shouldThrowHttpClientExceptionInCaseOfLookupShellsError() { + // Arrange + givenThat(postDiscoveryFinder200()); + givenThat(postEdcDiscovery200()); + givenThat(getLookupShells404()); + final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); + + // Act & Assert + assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( + HttpClientErrorException.class); + verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + verify(exactly(1), postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + verify(exactly(1), getRequestedFor(urlPathEqualTo(LOOKUP_SHELLS_PATH))); + } + + @Test + void shouldThrowHttpClientExceptionInCaseOfShellDescriptorsError() { + // Arrange + givenThat(postDiscoveryFinder200()); + givenThat(postEdcDiscovery200()); + givenThat(getLookupShells200()); + givenThat(getShellDescriptor404()); + final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); + + // Act & Assert + assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( + HttpClientErrorException.class); + verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + verify(exactly(1), postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + verify(exactly(1), getRequestedFor(urlPathEqualTo(LOOKUP_SHELLS_PATH))); + verify(exactly(1), getRequestedFor(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*"))); + } + + @Test + void shouldThrowExceptionOnEmptyShells() { + // Arrange + givenThat(postDiscoveryFinder200()); + givenThat(postEdcDiscovery200()); + givenThat(getLookupShells200Empty()); + givenThat(getShellDescriptor404()); + final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); + + // Act & Assert + assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( + HttpClientErrorException.class); + verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + verify(exactly(1), postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + verify(exactly(1), getRequestedFor(urlPathEqualTo(LOOKUP_SHELLS_PATH))); + verify(exactly(1), getRequestedFor(urlPathEqualTo(LOOKUP_SHELLS_PATH))); + } +} diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DtrWiremockConfig.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DtrWiremockConfig.java new file mode 100644 index 0000000000..00f1719e82 --- /dev/null +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DtrWiremockConfig.java @@ -0,0 +1,239 @@ +/******************************************************************************** + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.registryclient.decentral; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; + +import java.util.List; + +import com.github.tomakehurst.wiremock.client.MappingBuilder; +import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; + +public class DtrWiremockConfig { + public static final String SHELL_DESCRIPTORS_PATH = "/shell-descriptors/"; + public static final String SHELL_DESCRIPTORS_TEMPLATE = SHELL_DESCRIPTORS_PATH + "{aasIdentifier}"; + public static final String LOOKUP_SHELLS_PATH = "/lookup/shells"; + public static final String LOOKUP_SHELLS_TEMPLATE = LOOKUP_SHELLS_PATH + "?assetIds={assetIds}"; + public static final String DISCOVERY_FINDER_PATH = "/discoveryFinder"; + public static final String EDC_DISCOVERY_PATH = "/edcDiscovery"; + public static final String TEST_BPN = "BPNL00000000TEST"; + public static final String DISCOVERY_HOST = "http://discovery.finder"; + public static final String DATAPLANE_URL = "http://dataplane.test"; + public static final String DISCOVERY_FINDER_URL = DISCOVERY_HOST + DISCOVERY_FINDER_PATH; + + static ResponseDefinitionBuilder responseWithStatus(final int statusCode) { + return aResponse().withStatus(statusCode).withHeader("Content-Type", "application/json;charset=UTF-8"); + } + + static MappingBuilder getShellDescriptor200() { + final String materialForRecycling = submodel("https://dataplane.test/api/public/data/", + "urn:uuid:19b0338f-6d03-4198-b3b8-5c43f8958d60", "https://controlplane.test", "MaterialForRecycling", + "urn:uuid:cf06d5d5-e3f8-4bd4-bfcf-81815310701f", + "urn:bamm:io.catenax.material_for_recycling:1.1.0#MaterialForRecycling"); + + final String batch = submodel("https://dataplane.test/api/public/data/", + "urn:uuid:234edd2f-0223-47c7-9fe4-3984ab14c4f9", "https://controlplane.test", "Batch", + "urn:uuid:f53db6ef-7a58-4326-9169-0ae198b85dbf", "urn:samm:io.catenax.batch:2.0.0#Batch"); + + final String singleLevelUsageAsBuilt = submodel("https://dataplane.test/api/public/data/", + "urn:uuid:f8196d6a-1664-4531-bdee-f15dbb1daf26", "https://controlplane.test", "SingleLevelUsageAsBuilt", + "urn:uuid:e2899f43-eca8-4aec-b877-4a69691f0487", + "urn:bamm:io.catenax.single_level_usage_as_built:2.0.0#SingleLevelUsageAsBuilt"); + + final List submodelDescriptors = List.of(materialForRecycling, batch, singleLevelUsageAsBuilt); + final List specificAssetIds = List.of(specificAssetId("manufacturerId", "BPNL00000003B0Q0"), + specificAssetId("batchId", "BID12345678")); + return get(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*")).willReturn(responseWithStatus(200).withBody( + assetAdministrationShell(submodelDescriptors, "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5", + "EngineeringPlastics", "urn:uuid:9ce43b21-75e3-4cea-b13e-9a34f4f6822a", specificAssetIds))); + } + + public static String assetAdministrationShell(final List submodelDescriptors, final String globalAssetId, + final String idShort, final String shellId, final List specificAssetIds) { + return """ + { + "description": [], + "displayName": [], + "globalAssetId": "%s", + "idShort": "%s", + "id": "%s", + "specificAssetIds": [ + %s + ], + "submodelDescriptors": [ + %s + ] + } + """.formatted(globalAssetId, idShort, shellId, String.join(",\n", specificAssetIds), + String.join(",\n", submodelDescriptors)); + } + + public static String specificAssetId(final String key, final String value) { + return """ + { + "supplementalSemanticIds": [], + "name": "%s", + "value": "%s", + "externalSubjectId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "BPNL00000001CRHK" + } + ] + } + } + """.formatted(key, value); + } + + public static String submodel(final String dataplaneUrl, final String assetId, final String dspEndpoint, + final String idShort, final String submodelDescriptorId, final String semanticId) { + final String href = dataplaneUrl + submodelDescriptorId; + return """ + { + "endpoints": [ + { + "interface": "SUBMODEL-3.0", + "protocolInformation": { + "href": "%s", + "endpointProtocol": "HTTP", + "endpointProtocolVersion": [ + "1.1" + ], + "subprotocol": "DSP", + "subprotocolBody": "id=%s;dspEndpoint=%s", + "subprotocolBodyEncoding": "plain", + "securityAttributes": [ + { + "type": "NONE", + "key": "NONE", + "value": "NONE" + } + ] + } + } + ], + "idShort": "%s", + "id": "%s", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "%s" + } + ] + }, + "supplementalSemanticId": [], + "description": [], + "displayName": [] + } + """.formatted(href, assetId, dspEndpoint, idShort, submodelDescriptorId, semanticId); + } + + static MappingBuilder postEdcDiscovery200() { + return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn( + responseWithStatus(200).withBody(edcDiscovery("BPNL00000000TEST", List.of("http://edc.test/edc")))); + } + + public static String edcDiscovery(final String bpn, final List connectorEndpoints) { + return """ + [ + { + "bpn": "%s", + "connectorEndpoint": [ + %s + ] + } + ] + """.formatted(bpn, String.join(",\n", connectorEndpoints.stream().map(s -> "\"" + s + "\"").toList())); + } + + static MappingBuilder postDiscoveryFinder200() { + return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn( + responseWithStatus(200).withBody(discoveryFinder("http://discovery.finder/edcDiscovery"))); + } + + public static String discoveryFinder(final String discoveryFinderUrl) { + return """ + { + "endpoints": [ + { + "type": "bpn", + "description": "Service to discover EDC to a particular BPN", + "endpointAddress": "%s", + "documentation": "http://.../swagger/index.html", + "resourceId": "316417cd-0fb5-4daf-8dfa-8f68125923f1" + } + ] + } + """.formatted(discoveryFinderUrl); + } + + private static String discoveryFinderEmtpy() { + return """ + { + "endpoints": [ + ] + } + """; + } + + static MappingBuilder postDiscoveryFinder404() { + return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn(responseWithStatus(404)); + } + + static MappingBuilder postEdcDiscovery404() { + return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn(responseWithStatus(404)); + } + + static MappingBuilder getLookupShells200() { + return get(urlPathEqualTo(LOOKUP_SHELLS_PATH)).willReturn(responseWithStatus(200).withBody( + lookupShells(List.of("urn:uuid:21f7ebea-fa8a-410c-a656-bd9082e67dcf")))); + } + + static MappingBuilder getLookupShells200Empty() { + return get(urlPathMatching(LOOKUP_SHELLS_PATH + ".*")).willReturn( + responseWithStatus(200).withBody(lookupShells(List.of()))); + } + + public static String lookupShells(final List shellIds) { + return """ + { + "paging_metadata": {}, + "result": [ + %s + ] + } + """.formatted(String.join(",\n", shellIds.stream().map(s -> "\"" + s + "\"").toList())); + } + + static MappingBuilder getLookupShells404() { + return get(urlPathEqualTo(LOOKUP_SHELLS_PATH)).willReturn(responseWithStatus(404)); + } + + static MappingBuilder getShellDescriptor404() { + return get(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*")).willReturn(responseWithStatus(404)); + } +} \ No newline at end of file diff --git a/irs-testing/pom.xml b/irs-testing/pom.xml index 4bff31d728..f4b7d8dd81 100644 --- a/irs-testing/pom.xml +++ b/irs-testing/pom.xml @@ -69,11 +69,23 @@ net.datafaker datafaker ${datafaker.version} + + + snakeyaml + org.yaml + + org.eclipse.tractusx.irs irs-models ${irs-registry-client.version} + + + snakeyaml + org.yaml + + com.fasterxml.jackson.datatype @@ -91,5 +103,10 @@ org.testcontainers junit-jupiter + + org.wiremock + wiremock-standalone + ${wiremock-standalone.version} + diff --git a/pom.xml b/pom.xml index 0201230116..1fa66ecbcd 100644 --- a/pom.xml +++ b/pom.xml @@ -73,7 +73,7 @@ - 1.5.1-SNAPSHOT + 1.5.2-SNAPSHOT 3.1.6 @@ -94,7 +94,7 @@ 0.2.1 3.5.0 1.76 - 3.2.0 + 3.3.1 23.1.0 1.16.1 0.12.0 From 62cc323f78637a18f559cef34e391530c5f9adcd Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 23 Jan 2024 17:41:00 +0100 Subject: [PATCH 02/22] feat(irs-api):[#344] Add wiremock test for BpdmFacade --- .../tractusx/irs/bpdm/BpdmWiremockTest.java | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java new file mode 100644 index 0000000000..325c97cfd4 --- /dev/null +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java @@ -0,0 +1,126 @@ +/******************************************************************************** + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.bpdm; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; + +import java.util.Optional; + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.web.client.RestTemplate; + +@WireMockTest +class BpdmWiremockTest { + private static final String PROXY_SERVER_HOST = "127.0.0.1"; + private BpdmFacade bpdmFacade; + + @BeforeEach + void setUp(WireMockRuntimeInfo wireMockRuntimeInfo) { + final RestTemplate restTemplate = restTemplateProxy(PROXY_SERVER_HOST, wireMockRuntimeInfo.getHttpPort()); + + bpdmFacade = new BpdmFacade( + new BpdmClientImpl(restTemplate, "http://bpdm.test/legal-entities/{partnerId}?idType={idType}")); + } + + @Test + void shouldResolveManufacturerName() { + // Arrange + givenThat(get(urlPathEqualTo("/legal-entities/BPNL00000000TEST")).willReturn( + aResponse().withStatus(200).withHeader("Content-Type", "application/json;charset=UTF-8").withBody(""" + { + "bpn": "BPNL00000000TEST", + "identifiers": [ + { + "value": "BPNL00000000TEST", + "type": { + "technicalKey": "BPN", + "name": "Business Partner Number", + "url": "" + }, + "issuingBody": { + "technicalKey": "CATENAX", + "name": "Catena-X", + "url": "" + }, + "status": { + "technicalKey": "UNKNOWN", + "name": "Unknown" + } + } + ], + "names": [ + { + "value": "TEST_BPN_DFT_1", + "shortName": null, + "type": { + "technicalKey": "OTHER", + "name": "Any other alternative name used for a company, such as a specific language variant.", + "url": "" + }, + "language": { + "technicalKey": "undefined", + "name": "Undefined" + } + } + ], + "legalForm": null, + "status": null, + "profileClassifications": [], + "types": [ + { + "technicalKey": "UNKNOWN", + "name": "Unknown", + "url": "" + } + ], + "bankAccounts": [], + "roles": [], + "relations": [], + "currentness": "2022-07-26T08:17:38.737578Z" + } + """))); + + // Act + final Optional manufacturerName = bpdmFacade.findManufacturerName("BPNL00000000TEST"); + + // Assert + assertThat(manufacturerName).isPresent().contains("TEST_BPN_DFT_1"); + } + + @Test + void shouldReturnEmptyOnNotFound() { + // Arrange + givenThat(get(urlPathEqualTo("/legal-entities/BPNL00000000TEST")).willReturn( + aResponse().withStatus(404).withHeader("Content-Type", "application/json;charset=UTF-8"))); + + // Act + final Optional manufacturerName = bpdmFacade.findManufacturerName("BPNL00000000TEST"); + + // Assert + assertThat(manufacturerName).isEmpty(); + } +} From 57e09cda7cbf027b70a1ff2ea162b285b98c330a Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 23 Jan 2024 17:42:33 +0100 Subject: [PATCH 03/22] feat(irs-api):[#344] Extract WireMockConfig to irs-testing --- irs-testing/pom.xml | 5 ++ .../irs/testing/wiremock/WireMockConfig.java | 47 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java diff --git a/irs-testing/pom.xml b/irs-testing/pom.xml index f4b7d8dd81..7370be9eca 100644 --- a/irs-testing/pom.xml +++ b/irs-testing/pom.xml @@ -34,6 +34,7 @@ + org.springframework.boot @@ -53,6 +54,10 @@ + + org.springframework.boot + spring-boot-starter-web + net.minidev diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java new file mode 100644 index 0000000000..9ff8b9562c --- /dev/null +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java @@ -0,0 +1,47 @@ +/******************************************************************************** + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.testing.wiremock; + +import java.net.InetSocketAddress; +import java.net.Proxy; + +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +/** + * Common configurations for Wiremock tests. + */ +public final class WireMockConfig { + private WireMockConfig() { + } + + /** + * Configured RestTemplate which proxies all requests to the provided host / port. + * + * @param proxyServerHost the host where all requests will be proxied to + * @param httpPort the port of the host where all requests will be proxied to + * @return the configured {@link RestTemplate} + */ + public static RestTemplate restTemplateProxy(final String proxyServerHost, final int httpPort) { + final Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyServerHost, httpPort)); + final SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setProxy(proxy); + return new RestTemplate(requestFactory); + } +} From 302ddd2be944e09979206af6467c3fc748766f2f Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 23 Jan 2024 17:43:49 +0100 Subject: [PATCH 04/22] feat(irs-api):[#344] Extract WireMockConfig to irs-testing --- ...centralDigitalTwinRegistryServiceWiremockTest.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java index 279aa091a5..e00704f8c8 100644 --- a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java @@ -45,12 +45,11 @@ import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postDiscoveryFinder404; import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postEdcDiscovery200; import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postEdcDiscovery404; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.net.InetSocketAddress; -import java.net.Proxy; import java.util.Collection; import java.util.List; import java.util.Map; @@ -65,7 +64,6 @@ import org.eclipse.tractusx.irs.registryclient.exceptions.RegistryServiceException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; @@ -77,12 +75,7 @@ class DecentralDigitalTwinRegistryServiceWiremockTest { @BeforeEach void setUp(WireMockRuntimeInfo wireMockRuntimeInfo) throws EdcRetrieverException { - // Configure RestTemplate to proxy all requests to localhost - final int httpPort = wireMockRuntimeInfo.getHttpPort(); - final Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_SERVER_HOST, httpPort)); - final SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); - requestFactory.setProxy(proxy); - final var restTemplate = new RestTemplate(requestFactory); + final RestTemplate restTemplate = restTemplateProxy(PROXY_SERVER_HOST, wireMockRuntimeInfo.getHttpPort()); final var discoveryFinderClient = new DiscoveryFinderClientImpl(DISCOVERY_FINDER_URL, restTemplate); final var connectorEndpointsService = new ConnectorEndpointsService(discoveryFinderClient); From d819516cdf71e9a7eeeff08c83ffbfa97b6e66e8 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 23 Jan 2024 17:45:09 +0100 Subject: [PATCH 05/22] feat(edc-client):[#344] Extend SubmodelFacadeWiremockTest --- .../client/SubmodelFacadeWiremockTest.java | 40 +++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java index 80aba6ad4d..7471135414 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java @@ -34,6 +34,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration.NAMESPACE_EDC_CID; import static org.eclipse.tractusx.irs.edc.client.testutil.TestMother.createEdcTransformer; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -49,6 +50,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; import io.github.resilience4j.retry.RetryRegistry; import org.assertj.core.api.ThrowableAssert; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; @@ -74,23 +77,23 @@ import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; +@WireMockTest class SubmodelFacadeWiremockTest { + private static final String PROXY_SERVER_HOST = "127.0.0.1"; private final static String connectorEndpoint = "https://connector.endpoint.com"; private final static String submodelDataplanePath = "/api/public/shells/12345/submodels/5678/submodel"; + private final static String submodelDataplaneUrl = "http://dataplane.test" + submodelDataplanePath; private final static String assetId = "12345"; private final EdcConfiguration config = new EdcConfiguration(); private final EndpointDataReferenceStorage storage = new EndpointDataReferenceStorage(Duration.ofMinutes(1)); - private WireMockServer wireMockServer; private EdcSubmodelClient edcSubmodelClient; private AcceptedPoliciesProvider acceptedPoliciesProvider; @BeforeEach - void configureSystemUnderTest() { - this.wireMockServer = new WireMockServer(options().dynamicPort()); - this.wireMockServer.start(); - configureFor(this.wireMockServer.port()); + void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { + final RestTemplate restTemplate = restTemplateProxy(PROXY_SERVER_HOST, wireMockRuntimeInfo.getHttpPort()); - config.getControlplane().getEndpoint().setData(buildApiMethodUrl()); + config.getControlplane().getEndpoint().setData("http://controlplane.test"); config.getControlplane().getEndpoint().setCatalog("/catalog/request"); config.getControlplane().getEndpoint().setContractNegotiation("/contractnegotiations"); config.getControlplane().getEndpoint().setTransferProcess("/transferprocesses"); @@ -99,7 +102,6 @@ void configureSystemUnderTest() { config.getControlplane().setProviderSuffix("/api/v1/dsp"); config.getSubmodel().setUrnPrefix("/urn"); - final RestTemplate restTemplate = new RestTemplateBuilder().build(); final List> messageConverters = restTemplate.getMessageConverters(); for (final HttpMessageConverter converter : messageConverters) { if (converter instanceof final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter) { @@ -135,11 +137,6 @@ void configureSystemUnderTest() { pollingService, retryRegistry, catalogFacade, endpointDataReferenceCacheService); } - @AfterEach - void tearDown() { - this.wireMockServer.stop(); - } - @Test void shouldReturnAssemblyPartRelationshipAsString() throws EdcClientException, ExecutionException, InterruptedException { @@ -152,7 +149,7 @@ void shouldReturnAssemblyPartRelationshipAsString() "singleLevelBomAsBuilt.json"))); // Act - final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, buildWiremockDataplaneUrl(), + final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, assetId).get(); // Assert @@ -224,7 +221,7 @@ void shouldReturnMaterialForRecyclingAsString() "materialForRecycling.json"))); // Act - final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, buildWiremockDataplaneUrl(), + final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, assetId).get(); // Assert @@ -242,7 +239,7 @@ void shouldReturnObjectAsStringWhenResponseNotJSON() .withBody("test"))); // Act - final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, buildWiremockDataplaneUrl(), + final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, assetId).get(); // Assert @@ -271,7 +268,7 @@ void shouldThrowExceptionWhenPoliciesAreNotAccepted() { // Act & Assert final String errorMessage = "Consumption of asset '58505404-4da1-427a-82aa-b79482bcd1f0' is not permitted as the required catalog offer policies do not comply with defined IRS policies."; assertThatExceptionOfType(UsagePolicyException.class).isThrownBy( - () -> edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, buildWiremockDataplaneUrl(), assetId) + () -> edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, assetId) .get()).withMessageEndingWith(errorMessage); } @@ -286,7 +283,7 @@ void shouldThrowExceptionWhenResponse_400() { // Act final ThrowableAssert.ThrowingCallable throwingCallable = () -> edcSubmodelClient.getSubmodelRawPayload( - connectorEndpoint, buildWiremockDataplaneUrl(), assetId).get(5, TimeUnit.SECONDS); + connectorEndpoint, submodelDataplaneUrl, assetId).get(5, TimeUnit.SECONDS); // Assert assertThatExceptionOfType(ExecutionException.class).isThrownBy(throwingCallable) @@ -304,20 +301,13 @@ void shouldThrowExceptionWhenResponse_500() { // Act final ThrowableAssert.ThrowingCallable throwingCallable = () -> edcSubmodelClient.getSubmodelRawPayload( - connectorEndpoint, buildWiremockDataplaneUrl(), assetId).get(5, TimeUnit.SECONDS); + connectorEndpoint, submodelDataplaneUrl, assetId).get(5, TimeUnit.SECONDS); // Assert assertThatExceptionOfType(ExecutionException.class).isThrownBy(throwingCallable) .withCauseInstanceOf(RestClientException.class); } - private String buildWiremockDataplaneUrl() { - return buildApiMethodUrl() + submodelDataplanePath; - } - - private String buildApiMethodUrl() { - return String.format("http://localhost:%d", this.wireMockServer.port()); - } private org.eclipse.tractusx.irs.edc.client.policy.Policy policy(String policyId, List permissions) { return new org.eclipse.tractusx.irs.edc.client.policy.Policy(policyId, OffsetDateTime.now(), From 588b7bd403e0fe1ab87dd5cc81da40593492ff0c Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 23 Jan 2024 17:45:50 +0100 Subject: [PATCH 06/22] feat(edc-client):[#344] Extend SemanticHubWiremockTest --- .../semanticshub/SemanticHubWiremockTest.java | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java index 738a1d9373..1106c18891 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java @@ -29,44 +29,35 @@ import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; -import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; import org.eclipse.tractusx.irs.configuration.SemanticsHubConfiguration; import org.eclipse.tractusx.irs.services.validation.SchemaNotFoundException; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.web.client.RestTemplate; +@WireMockTest class SemanticHubWiremockTest { - private WireMockServer wireMockServer; - + private static final String PROXY_SERVER_HOST = "127.0.0.1"; private SemanticsHubFacade semanticsHubFacade; - private SemanticsHubConfiguration config; @BeforeEach - void configureSystemUnderTest() { - this.wireMockServer = new WireMockServer(options().dynamicPort()); - this.wireMockServer.start(); - configureFor(this.wireMockServer.port()); + void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { + final RestTemplate restTemplate = restTemplateProxy(PROXY_SERVER_HOST, wireMockRuntimeInfo.getHttpPort()); - config = new SemanticsHubConfiguration(); + final SemanticsHubConfiguration config = new SemanticsHubConfiguration(); config.setPageSize(10); - config.setUrl(String.format("http://localhost:%d/models", this.wireMockServer.port())); - config.setModelJsonSchemaEndpoint("sem.hub/models/{urn}/json-schema"); + config.setUrl("http://semantic.hub/models"); + config.setModelJsonSchemaEndpoint("http://semantic.hub/models/{urn}/json-schema"); - final RestTemplate restTemplate = new RestTemplate(); final SemanticsHubClient semanticsHubClient = new SemanticsHubClientImpl(restTemplate, config); semanticsHubFacade = new SemanticsHubFacade(semanticsHubClient); } - @AfterEach - void tearDown() { - this.wireMockServer.stop(); - } - @Test void shouldReturn1Page() throws SchemaNotFoundException { givenThat(get(urlPathEqualTo("/models")).willReturn(aResponse().withStatus(200) From 4125ea90b7b6d212a90a84cf4f2b219ca83a7524 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 23 Jan 2024 17:47:10 +0100 Subject: [PATCH 07/22] feat(edc-client):[#344] Add IrsWireMock integration test --- .../irs/configuration/RestTemplateConfig.java | 2 + .../eclipse/tractusx/irs/IrsWireMockIT.java | 150 +++++ .../tractusx/irs/WireMockTestConfig.java | 83 +++ .../resources/__files/all-models-page-IT.json | 554 ++++++++++++++++++ 4 files changed, 789 insertions(+) create mode 100644 irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java create mode 100644 irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java create mode 100644 irs-api/src/test/resources/__files/all-models-page-IT.json diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RestTemplateConfig.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RestTemplateConfig.java index faf99e94ea..991d81498e 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RestTemplateConfig.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/RestTemplateConfig.java @@ -41,6 +41,7 @@ import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; @@ -66,6 +67,7 @@ @Configuration @RequiredArgsConstructor @SuppressWarnings("PMD.ExcessiveImports") +@Profile("!integrationtest") public class RestTemplateConfig { public static final String DTR_REST_TEMPLATE = "dtrRestTemplate"; diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java new file mode 100644 index 0000000000..d7970bdee4 --- /dev/null +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java @@ -0,0 +1,150 @@ +/******************************************************************************** + * Copyright (c) 2021,2022,2023 + * 2022: ZF Friedrichshafen AG + * 2022: ISTOS GmbH + * 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2022,2023: BOSCH AG + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import org.eclipse.tractusx.irs.component.JobHandle; +import org.eclipse.tractusx.irs.component.PartChainIdentificationKey; +import org.eclipse.tractusx.irs.component.RegisterJob; +import org.eclipse.tractusx.irs.component.enums.Direction; +import org.eclipse.tractusx.irs.semanticshub.AspectModels; +import org.eclipse.tractusx.irs.services.IrsItemGraphQueryService; +import org.eclipse.tractusx.irs.services.SemanticHubService; +import org.eclipse.tractusx.irs.services.validation.SchemaNotFoundException; +import org.eclipse.tractusx.irs.testing.containers.MinioContainer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.context.support.TestPropertySourceUtils; +import org.testcontainers.junit.jupiter.Testcontainers; + +@WireMockTest(httpPort = 8085) +@Testcontainers +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WireMockTestConfig.class + /*, properties = "spring.main.allow-bean-definition-overriding=true"*/) +@ContextConfiguration(initializers = IrsWireMockIT.MinioConfigInitializer.class) +//@Import({ WireMockTestConfig.class }) +@ActiveProfiles("integrationtest") +class IrsWireMockIT { + public static final String BPDM_TEST = "http://bpdm.test/legal-entities/{partnerId}?idType={idType}"; + public static final String DISCOVERY_TEST = "http://discovery.test"; + public static final String SEMANTIC_HUB_URL = "http://semantic.hub/models"; + public static final String SEMANTIC_HUB_SCHEMA_URL = "http://semantic.hub/models/{urn}/json-schema"; + private static final String ACCESS_KEY = "accessKey"; + private static final String SECRET_KEY = "secretKey"; + private static final MinioContainer minioContainer = new MinioContainer( + new MinioContainer.CredentialsProvider(ACCESS_KEY, SECRET_KEY)).withReuse(true); + public static final String EDC_URL = "http://edc.test:8081/management"; + @Autowired + private IrsItemGraphQueryService irsService; + + @Autowired + private SemanticHubService semanticHubService; + + @BeforeAll + static void startContainer() { + minioContainer.start(); + givenThat(get(urlPathEqualTo("/models")).willReturn(aResponse().withStatus(200) + .withHeader("Content-Type", + "application/json;charset=UTF-8") + .withBodyFile("all-models-page-IT.json"))); + } + + @AfterAll + static void stopContainer() { + minioContainer.stop(); + } + + @DynamicPropertySource + static void configureProperties(DynamicPropertyRegistry registry) { + registry.add("bpdm.bpnEndpoint", () -> BPDM_TEST); + registry.add("digitalTwinRegistry.discoveryFinderUrl", () -> DISCOVERY_TEST); + registry.add("semanticshub.url", () -> SEMANTIC_HUB_URL); + registry.add("semanticshub.modelJsonSchemaEndpoint", () -> SEMANTIC_HUB_SCHEMA_URL); + registry.add("irs-edc-client.controlplane.endpoint.data", () -> EDC_URL); + } + + @Test + void shouldStartApplicationAndCollectSemanticModels() throws SchemaNotFoundException { + // Act + final AspectModels allAspectModels = semanticHubService.getAllAspectModels(); + + // Assert + assertThat(allAspectModels.models()).hasSize(78); + } + + @Test + void shouldStartJob() { + // Arrange + final RegisterJob request = RegisterJob.builder() + .key(PartChainIdentificationKey.builder() + .bpn("BPNTEST") + .globalAssetId("globalAssetId") + .build()) + .depth(2) + .aspects(List.of("SerialPart", "Batch", "SingleLevelBomAsBuilt")) + .collectAspects(true) + .lookupBPNs(true) + .direction(Direction.DOWNWARD) + .build(); + + // Act + final JobHandle jobHandle = irsService.registerItemJob(request); + + // Assert + assertThat(jobHandle.getId()).isNotNull(); + } + + public static class MinioConfigInitializer + implements ApplicationContextInitializer { + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + final String hostAddress = minioContainer.getHostAddress(); + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(applicationContext, + "blobstore.endpoint=http://" + hostAddress, "blobstore.accessKey=" + ACCESS_KEY, + "blobstore.secretKey=" + SECRET_KEY, "policystore.persistence.endpoint=http://" + hostAddress, + "policystore.persistence.accessKey=" + ACCESS_KEY, + "policystore.persistence.secretKey=" + SECRET_KEY, + "policystore.persistence.bucketName=policy-test"); + } + } + +} diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java new file mode 100644 index 0000000000..4e7d14c48a --- /dev/null +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java @@ -0,0 +1,83 @@ +/******************************************************************************** + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs; + +import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.BPDM_REST_TEMPLATE; +import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.DISCOVERY_REST_TEMPLATE; +import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.DTR_REST_TEMPLATE; +import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.EDC_REST_TEMPLATE; +import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.NO_ERROR_REST_TEMPLATE; +import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.SEMHUB_REST_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; +import org.springframework.web.client.RestTemplate; + +@TestConfiguration +public class WireMockTestConfig { + public static final int HTTP_PORT = 8085; + private static final String PROXY_SERVER_HOST = "127.0.0.1"; + + @Primary + @Profile("integrationtest") + @Bean(DTR_REST_TEMPLATE) + RestTemplate dtrRestTemplate() { + return restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); + } + + @Primary + @Profile("integrationtest") + @Bean(EDC_REST_TEMPLATE) + RestTemplate edcRestTemplate() { + return restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); + } + + @Primary + @Profile("integrationtest") + @Bean(NO_ERROR_REST_TEMPLATE) + RestTemplate noErrorRestTemplate() { + return restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); + } + + @Primary + @Profile("integrationtest") + @Bean(DISCOVERY_REST_TEMPLATE) + RestTemplate discoveryRestTemplate() { + return restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); + } + + @Primary + @Profile("integrationtest") + @Bean(BPDM_REST_TEMPLATE) + RestTemplate bpdmRestTemplate() { + return restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); + } + + @Primary + @Profile("integrationtest") + @Bean(SEMHUB_REST_TEMPLATE) + @Qualifier(SEMHUB_REST_TEMPLATE) + RestTemplate semanticHubRestTemplate() { + return restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); + } +} diff --git a/irs-api/src/test/resources/__files/all-models-page-IT.json b/irs-api/src/test/resources/__files/all-models-page-IT.json new file mode 100644 index 0000000000..36d2bd6a4a --- /dev/null +++ b/irs-api/src/test/resources/__files/all-models-page-IT.json @@ -0,0 +1,554 @@ +{ + "items": [ + { + "urn": "urn:bamm:io.catenax.asset_tracker_links:1.0.0#AssetTrackerLinks", + "version": "1.0.0", + "name": "AssetTrackerLinks", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.battery.battery_pass:3.0.1#BatteryPass", + "version": "3.0.1", + "name": "BatteryPass", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.battery.product_description:1.0.1#ProductDescription", + "version": "1.0.1", + "name": "ProductDescription", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.bom_as_specified:1.0.0#BomAsSpecified", + "version": "1.0.0", + "name": "BomAsSpecified", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.bom_as_specified:1.0.1#BomAsSpecified", + "version": "1.0.1", + "name": "BomAsSpecified", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.certificate_of_destruction:1.0.1#CertificateOfDestruction", + "version": "1.0.1", + "name": "CertificateOfDestruction", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.classified_load_spectrum:1.0.0#ClassifiedLoadSpectrum", + "version": "1.0.0", + "name": "ClassifiedLoadSpectrum", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.decomissioning_certificate:1.0.0#DecommissioningCertificate", + "version": "1.0.0", + "name": "DecommissioningCertificate", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.eol_story:1.0.0#EndOfLife", + "version": "1.0.0", + "name": "EndOfLife", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.fleet.claim_data:1.0.0#ClaimData", + "version": "1.0.0", + "name": "ClaimData", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.fleet.diagnostic_data:1.0.0#DiagnosticData", + "version": "1.0.0", + "name": "DiagnosticData", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.idconversion:1.0.0#IdConversion", + "version": "1.0.0", + "name": "IdConversion", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.individual_asset_definition:1.0.0#IndividualAssetDefinition", + "version": "1.0.0", + "name": "IndividualAssetDefinition", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.iot_sensor_data:1.0.0#IotSensorData", + "version": "1.0.0", + "name": "IotSensorData", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.iot_sensor_device_definition:1.0.0#IotSensorDeviceDefinition", + "version": "1.0.0", + "name": "IotSensorDeviceDefinition", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.manufactured_parts_quality_information:1.0.0#ManufacturedPartsQualityInformation", + "version": "1.0.0", + "name": "ManufacturedPartsQualityInformation", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.manufacturing_capability:1.0.0#ManufacturingCapability", + "version": "1.0.0", + "name": "ManufacturingCapability", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.market_place_offer:1.2.0#MarketplaceOffer", + "version": "1.2.0", + "name": "MarketplaceOffer", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.market_place_offer:1.4.0#MarketplaceOffer", + "version": "1.4.0", + "name": "MarketplaceOffer", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.material_flow_simulation_result:1.0.0#MaterialFlowSimulationResult", + "version": "1.0.0", + "name": "MaterialFlowSimulationResult", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.material_for_homologation:1.0.0#MaterialForHomologation", + "version": "1.0.0", + "name": "MaterialForHomologation", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.part_as_specified:1.0.0#PartAsSpecified", + "version": "1.0.0", + "name": "PartAsSpecified", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.part_as_specified:1.0.1#PartAsSpecified", + "version": "1.0.1", + "name": "PartAsSpecified", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.part_as_specified:2.0.0#PartAsSpecified", + "version": "2.0.0", + "name": "PartAsSpecified", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.pcf:2.0.0#Pcf", + "version": "2.0.0", + "name": "Pcf", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.pcf:3.0.0#Pcf", + "version": "3.0.0", + "name": "Pcf", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.pcf:4.0.0#Pcf", + "version": "4.0.0", + "name": "Pcf", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.pcf:4.0.1#Pcf", + "version": "4.0.1", + "name": "Pcf", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.product_stock:1.0.0#ProductStock", + "version": "1.0.0", + "name": "ProductStock", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.quality_task:1.0.0#QualityTask", + "version": "1.0.0", + "name": "QualityTask", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.refurbishing_certificate:1.0.0#RefurbishingCertificate", + "version": "1.0.0", + "name": "RefurbishingCertificate", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.remanufacturing_certificate:1.0.0#RemanufacturingCertificate", + "version": "1.0.0", + "name": "RemanufacturingCertificate", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.return_request:1.1.1#ReturnRequest", + "version": "1.1.1", + "name": "ReturnRequest", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.return_request:1.1.2#ReturnRequest", + "version": "1.1.2", + "name": "ReturnRequest", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.reuse_certificate:1.0.0#ReuseCertificate", + "version": "1.0.0", + "name": "ReuseCertificate", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.rul:1.0.0#RemainingUsefulLife", + "version": "1.0.0", + "name": "RemainingUsefulLife", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.sealant.sealant_pass:1.0.0#SealantPass", + "version": "1.0.0", + "name": "SealantPass", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.shared.address_characteristic:1.0.1#AddressAspect", + "version": "1.0.1", + "name": "AddressAspect", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.shared.address_characteristic:2.0.0#AddressAspect", + "version": "2.0.0", + "name": "AddressAspect", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.shared.contact_information:1.0.0#ContactInformation", + "version": "1.0.0", + "name": "ContactInformation", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.shared.contact_information:2.0.0#ContactInformation", + "version": "2.0.0", + "name": "ContactInformation", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.shared.physical_dimension:1.0.0#PhysicalDimensions", + "version": "1.0.0", + "name": "PhysicalDimensions", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.shared.physical_dimension:2.0.0#PhysicalDimensions", + "version": "2.0.0", + "name": "PhysicalDimensions", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.shared.recycling_strategy_certificate:1.0.0#RecyclingStrategyCertificate", + "version": "1.0.0", + "name": "RecyclingStrategyCertificate", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.single_level_bom_as_specified:1.0.0#SingleLevelBomAsSpecified", + "version": "1.0.0", + "name": "SingleLevelBomAsSpecified", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.single_level_usage_as_planned:1.1.0#SingleLevelUsageAsPlanned", + "version": "1.1.0", + "name": "SingleLevelUsageAsPlanned", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.time_series_reference:1.0.0#TimeSeriesReference", + "version": "1.0.0", + "name": "TimeSeriesReference", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.traction_battery_code:1.0.0#TractionBatteryCode", + "version": "1.0.0", + "name": "TractionBatteryCode", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.user_estimated_loading:1.0.0#UserEstimatedLoading", + "version": "1.0.0", + "name": "UserEstimatedLoading", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.vehicle.product_description:1.0.0#ProductDescription", + "version": "1.0.0", + "name": "ProductDescription", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.vehicle.product_description:2.0.0#ProductDescription", + "version": "2.0.0", + "name": "ProductDescription", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.waste:1.0.0#Waste", + "version": "1.0.0", + "name": "Waste", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.week_based_capacity_group:1.0.1#WeekBasedCapacityGroup", + "version": "1.0.1", + "name": "WeekBasedCapacityGroup", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.week_based_material_demand:1.0.1#WeekBasedMaterialDemand", + "version": "1.0.1", + "name": "WeekBasedMaterialDemand", + "type": "BAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.essincident:2.0.0#EssIncident", + "version": "2.0.0", + "name": "EssIncident", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.fleet.vehicles:1.0.0#Vehicles", + "version": "1.0.0", + "name": "Vehicles", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.id_based_comment:1.0.0#IdBasedComment", + "version": "1.0.0", + "name": "IdBasedComment", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.id_based_request_for_update:1.0.0#IdBasedRequestForUpdate", + "version": "1.0.0", + "name": "IdBasedRequestForUpdate", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.id_based_request_for_update:2.0.0#IdBasedRequestForUpdate", + "version": "2.0.0", + "name": "IdBasedRequestForUpdate", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.manufacturing_capability:2.0.0#ManufacturingCapability", + "version": "2.0.0", + "name": "ManufacturingCapability", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.material_flow_simulation_result:2.0.0#MaterialFlowSimulationResultAspect", + "version": "2.0.0", + "name": "MaterialFlowSimulationResultAspect", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.parts_analyses:2.0.0#PartsAnalyses", + "version": "2.0.0", + "name": "PartsAnalyses", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.planned_production_output:1.0.0#PlannedProductionOutput", + "version": "1.0.0", + "name": "PlannedProductionOutput", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.secondary_material_content:1.0.0#SecondaryMaterialContent", + "version": "1.0.0", + "name": "SecondaryMaterialContent", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.shared.address_characteristic:3.0.0#AddressAspect", + "version": "3.0.0", + "name": "AddressAspect", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.shared.business_partner_number:1.0.0#BusinessPartnerNumber", + "version": "1.0.0", + "name": "BusinessPartnerNumber", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.shared.contact_information:3.0.0#ContactInformation", + "version": "3.0.0", + "name": "ContactInformation", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.shared.part_site_information_as_built:1.0.0#PartSiteInformationAsBuilt", + "version": "1.0.0", + "name": "PartSiteInformationAsBuilt", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.shared.quantity:1.0.0#Quantity", + "version": "1.0.0", + "name": "Quantity", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.shared.recycling_strategy_certificate:2.0.0#RecyclingStrategyCertificate", + "version": "2.0.0", + "name": "RecyclingStrategyCertificate", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.shared.secondary_material_content:1.0.0#SecondaryMaterialContent", + "version": "1.0.0", + "name": "SecondaryMaterialContent", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.shared.shopfloor_information_types:1.0.0#ShopfloorInformationTypes", + "version": "1.0.0", + "name": "ShopfloorInformationTypes", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.shared.uuid:1.0.0#Uuid", + "version": "1.0.0", + "name": "Uuid", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.single_level_bom_as_specified:2.0.0#SingleLevelBomAsSpecified", + "version": "2.0.0", + "name": "SingleLevelBomAsSpecified", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:samm:io.catenax.vehicle.product_description:3.0.0#ProductDescription", + "version": "3.0.0", + "name": "ProductDescription", + "type": "SAMM", + "status": "RELEASED" + }, + { + "urn": "urn:bamm:io.catenax.single_level_bom_as_built:1.0.0#SingleLevelBomAsBuilt", + "version": "1.0.0", + "name": "SingleLevelBomAsBuilt", + "type": "BAMM", + "status": "DEPRECATED" + }, + { + "urn": "urn:samm:io.catenax.batch:2.0.0#Batch", + "version": "2.0.0", + "name": "Batch", + "type": "SAMM", + "status": "DEPRECATED" + }, + { + "urn": "urn:bamm:io.catenax.serial_part:1.0.1#SerialPart", + "version": "1.0.1", + "name": "SerialPart", + "type": "BAMM", + "status": "DEPRECATED" + } + ], + "totalItems": 78, + "currentPage": 0, + "totalPages": 1, + "itemCount": 78 +} \ No newline at end of file From 0d306135f5541176ee8abbc54e896f77d8530fd9 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Thu, 25 Jan 2024 11:18:37 +0100 Subject: [PATCH 08/22] feat(irs-test):[#344] Create reusable wiremock config --- .../tractusx/irs/WireMockTestConfig.java | 17 +- .../tractusx/irs/bpdm/BpdmWiremockTest.java | 15 +- .../semanticshub/SemanticHubWiremockTest.java | 87 ++++-- .../{ => semantichub}/all-models-page-IT.json | 0 .../semantichub/batch-2.0.0-schema.json | 143 ++++++++++ .../client/SubmodelFacadeWiremockConfig.java | 265 ++++++++++++++++++ .../client/SubmodelFacadeWiremockTest.java | 120 ++------ ...igitalTwinRegistryServiceWiremockTest.java | 43 +-- .../DiscoveryServiceWiremockConfig.java | 93 ++++++ .../testing/wiremock}/DtrWiremockConfig.java | 114 ++------ .../irs/testing/wiremock/WireMockConfig.java | 7 + 11 files changed, 674 insertions(+), 230 deletions(-) rename irs-api/src/test/resources/__files/{ => semantichub}/all-models-page-IT.json (100%) create mode 100644 irs-api/src/test/resources/__files/semantichub/batch-2.0.0-schema.json create mode 100644 irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockConfig.java create mode 100644 irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java rename {irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral => irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock}/DtrWiremockConfig.java (58%) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java index 4e7d14c48a..16e9e92c3c 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java @@ -26,11 +26,17 @@ import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.SEMHUB_REST_TEMPLATE; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; +import java.util.List; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.edc.policy.model.PolicyRegistrationTypes; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.client.RestTemplate; @TestConfiguration @@ -49,7 +55,16 @@ RestTemplate dtrRestTemplate() { @Profile("integrationtest") @Bean(EDC_REST_TEMPLATE) RestTemplate edcRestTemplate() { - return restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); + final RestTemplate edcRestTemplate = restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); + final List> messageConverters = edcRestTemplate.getMessageConverters(); + for (final HttpMessageConverter converter : messageConverters) { + if (converter instanceof final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter) { + final ObjectMapper mappingJackson2HttpMessageConverterObjectMapper = mappingJackson2HttpMessageConverter.getObjectMapper(); + PolicyRegistrationTypes.TYPES.forEach( + mappingJackson2HttpMessageConverterObjectMapper::registerSubtypes); + } + } + return edcRestTemplate; } @Primary diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java index 325c97cfd4..e9e107cd8d 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java @@ -23,6 +23,8 @@ import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import java.util.Optional; @@ -31,6 +33,7 @@ import com.github.tomakehurst.wiremock.junit5.WireMockTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; @WireMockTest @@ -114,13 +117,11 @@ void shouldResolveManufacturerName() { @Test void shouldReturnEmptyOnNotFound() { // Arrange - givenThat(get(urlPathEqualTo("/legal-entities/BPNL00000000TEST")).willReturn( - aResponse().withStatus(404).withHeader("Content-Type", "application/json;charset=UTF-8"))); + givenThat(get(urlPathEqualTo("/legal-entities/BPNL00000000TEST")).willReturn(responseWithStatus(404))); - // Act - final Optional manufacturerName = bpdmFacade.findManufacturerName("BPNL00000000TEST"); - - // Assert - assertThat(manufacturerName).isEmpty(); + // Act & Assert + // TODO fix implementation to not throw HttpClientErrorException$NotFound + assertThatExceptionOfType(HttpClientErrorException.class).isThrownBy( + () -> bpdmFacade.findManufacturerName("BPNL00000000TEST")); } } diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java index 1106c18891..321f4d6fef 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java @@ -23,15 +23,21 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.semanticshub; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.exactly; import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; +import com.github.tomakehurst.wiremock.client.MappingBuilder; import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; import com.github.tomakehurst.wiremock.junit5.WireMockTest; import org.eclipse.tractusx.irs.configuration.SemanticsHubConfiguration; @@ -45,6 +51,15 @@ class SemanticHubWiremockTest { private static final String PROXY_SERVER_HOST = "127.0.0.1"; private SemanticsHubFacade semanticsHubFacade; + private static MappingBuilder getAllModels200() { + return get(urlPathEqualTo("/models")).withHost(equalTo("semantic.hub")) + .willReturn(responseWithStatus(200).withBodyFile("all-models-page.json")); + } + + private static void verifyGetAllModels(final int times) { + verify(exactly(times), getRequestedFor(urlPathEqualTo("/models"))); + } + @BeforeEach void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { final RestTemplate restTemplate = restTemplateProxy(PROXY_SERVER_HOST, wireMockRuntimeInfo.getHttpPort()); @@ -60,35 +75,75 @@ void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { @Test void shouldReturn1Page() throws SchemaNotFoundException { - givenThat(get(urlPathEqualTo("/models")).willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBodyFile("all-models-page.json"))); + givenThat(getAllModels200()); final AspectModels allAspectModels = semanticsHubFacade.getAllAspectModels(); assertThat(allAspectModels.models()).isNotEmpty(); assertThat(allAspectModels.models().get(0).name()).isEqualTo("SerialPartTypization"); + verifyGetAllModels(1); } @Test void shouldReturn2Pages() throws SchemaNotFoundException { - givenThat(get(urlPathEqualTo("/models")).withQueryParam("page", equalTo("0")) + givenThat(get(urlPathEqualTo("/models")).withHost(equalTo("semantic.hub")) + .withQueryParam("page", equalTo("0")) .withQueryParam("pageSize", equalTo("10")) - .willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBodyFile("all-models-page1.json"))); - givenThat(get(urlPathEqualTo("/models")).withQueryParam("page", equalTo("1")) + .willReturn( + responseWithStatus(200).withBodyFile("all-models-page1.json"))); + givenThat(get(urlPathEqualTo("/models")).withHost(equalTo("semantic.hub")) + .withQueryParam("page", equalTo("1")) .withQueryParam("pageSize", equalTo("10")) - .willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBodyFile("all-models-page2.json"))); + .willReturn( + responseWithStatus(200).withBodyFile("all-models-page2.json"))); final AspectModels allAspectModels = semanticsHubFacade.getAllAspectModels(); assertThat(allAspectModels.models()).hasSize(20); assertThat(allAspectModels.models().get(0).name()).isEqualTo("SerialPartTypization"); + verifyGetAllModels(2); + } + + @Test + void shouldReturnJsonSchema() throws SchemaNotFoundException { + // Arrange + stubFor(get(urlPathMatching("/models/urn:samm:io.catenax.batch:2.0.0%23Batch/json-schema")).withHost( + equalTo("semantic.hub")) + .willReturn( + responseWithStatus( + 200).withBodyFile( + "semantichub/batch-2.0.0-schema.json"))); + + // Act + final String modelJsonSchema = semanticsHubFacade.getModelJsonSchema("urn:samm:io.catenax.batch:2.0.0#Batch"); + + // Assert + assertThat(modelJsonSchema).contains("urn_samm_io.catenax.batch_2.0.0_CatenaXIdTrait") + .contains("A batch is a quantity of (semi-) finished products or (raw) material"); + verify(exactly(1), + getRequestedFor(urlPathMatching("/models/urn:samm:io.catenax.batch:2.0.0%23Batch/json-schema"))); + } + + @Test + void shouldThrowSchemaExceptionWhenSchemaNotFound() { + // Arrange + final String url = "/models/%s/json-schema".formatted( + "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0%23SingleLevelBomAsBuilt"); + final String errorBody = """ + { + "timestamp": "2024-01-24T12:06:23.390+00:00", + "status": 500, + "error": "Internal Server Error", + "path": "/api/v1/models/urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt/json-schema" + } + """; + System.out.println(url); + stubFor(get(urlPathEqualTo(url)).withHost(equalTo("semantic.hub")) + .willReturn(responseWithStatus(500).withBody(errorBody))); + + // Act & Assert + assertThatExceptionOfType(SchemaNotFoundException.class).isThrownBy(() -> semanticsHubFacade.getModelJsonSchema( + "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt")); + verify(exactly(1), getRequestedFor(urlPathEqualTo(url))); } } diff --git a/irs-api/src/test/resources/__files/all-models-page-IT.json b/irs-api/src/test/resources/__files/semantichub/all-models-page-IT.json similarity index 100% rename from irs-api/src/test/resources/__files/all-models-page-IT.json rename to irs-api/src/test/resources/__files/semantichub/all-models-page-IT.json diff --git a/irs-api/src/test/resources/__files/semantichub/batch-2.0.0-schema.json b/irs-api/src/test/resources/__files/semantichub/batch-2.0.0-schema.json new file mode 100644 index 0000000000..4ff694cd76 --- /dev/null +++ b/irs-api/src/test/resources/__files/semantichub/batch-2.0.0-schema.json @@ -0,0 +1,143 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "description": "A batch is a quantity of (semi-) finished products or (raw) material product that have been produced under the same circumstances (e.g. same production location), as specified groups or amounts, within a certain time frame. Every batch can differ in the number or amount of products. Different batches can have varied specifications, e.g., different colors. A batch is identified via a Batch ID.", + "type": "object", + "components": { + "schemas": { + "urn_samm_io.catenax.batch_2.0.0_CatenaXIdTrait": { + "type": "string", + "description": "The provided regular expression ensures that the UUID is composed of five groups of characters separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters (32 hexadecimal characters and 4 hyphens), optionally prefixed by \"urn:uuid:\" to make it an IRI.", + "pattern": "(^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)|(^urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)" + }, + "urn_samm_io.catenax.batch_2.0.0_KeyTrait": { + "type": "string", + "description": "Constraint that ensures that the predefined keys are used.", + "pattern": "^(manufacturerId|batchId)$" + }, + "urn_samm_io.catenax.batch_2.0.0_ValueCharacteristic": { + "type": "string", + "description": "The value of an identifier." + }, + "urn_samm_io.catenax.batch_2.0.0_KeyValueList": { + "description": "A list of key value pairs for local identifiers, which are composed of a key and a corresponding value.", + "type": "object", + "properties": { + "key": { + "description": "The key of a local identifier.", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_KeyTrait" + }, + "value": { + "description": "The value of an identifier.", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_ValueCharacteristic" + } + }, + "required": [ + "key", + "value" + ] + }, + "urn_samm_io.catenax.batch_2.0.0_LocalIdentifierCharacteristic": { + "description": "A batch may have multiple attributes, which uniquely identify that batch in a specific dataspace (e.g. the manufacturer`s dataspace)", + "type": "array", + "items": { + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_KeyValueList" + }, + "uniqueItems": true + }, + "urn_samm_org.eclipse.esmf.samm_characteristic_2.1.0_Timestamp": { + "type": "string", + "pattern": "-?([1-9][0-9]{3,}|0[0-9]{3})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T(([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\\.[0-9]+)?|(24:00:00(\\.0+)?))(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?", + "description": "Describes a Property which contains the date and time with an optional timezone." + }, + "urn_samm_io.catenax.batch_2.0.0_ProductionCountryCodeTrait": { + "type": "string", + "description": "Regular Expression that ensures a three-letter code", + "pattern": "^[A-Z]{3}$" + }, + "urn_samm_io.catenax.batch_2.0.0_ManufacturingCharacteristic": { + "description": "Characteristic to describe manufacturing related data", + "type": "object", + "properties": { + "date": { + "description": "Timestamp of the manufacturing date as the final step in production process (e.g. final quality check, ready-for-shipment event)", + "$ref": "#/components/schemas/urn_samm_org.eclipse.esmf.samm_characteristic_2.1.0_Timestamp" + }, + "country": { + "description": "Country code where the part was manufactured", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_ProductionCountryCodeTrait" + } + }, + "required": [ + "date" + ] + }, + "urn_samm_io.catenax.batch_2.0.0_PartIdCharacteristic": { + "type": "string", + "description": "The part ID is a multi-character string, ususally assigned by an ERP system" + }, + "urn_samm_io.catenax.batch_2.0.0_PartNameCharacteristic": { + "type": "string", + "description": "Part Name in string format from the respective system in the value chain" + }, + "urn_samm_io.catenax.batch_2.0.0_ClassificationCharacteristic": { + "type": "string", + "description": "A part type must be placed into one of the following classes: 'component', 'product', 'software', 'assembly', 'tool', or 'raw material'.", + "enum": [ + "product", + "raw material", + "software", + "assembly", + "tool", + "component" + ] + }, + "urn_samm_io.catenax.batch_2.0.0_PartTypeInformationCharacteristic": { + "description": "The characteristics of the part type", + "type": "object", + "properties": { + "manufacturerPartId": { + "description": "Part ID as assigned by the manufacturer of the part. The Part ID identifies the part (as designed) in the manufacturer`s dataspace. The Part ID does not reference a specific instance of a part and thus should not be confused with the serial number or batch number.", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_PartIdCharacteristic" + }, + "nameAtManufacturer": { + "description": "Name of the part as assigned by the manufacturer", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_PartNameCharacteristic" + }, + "classification": { + "description": "The classification of the part type according to STEP standard definition", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_ClassificationCharacteristic" + } + }, + "required": [ + "manufacturerPartId", + "nameAtManufacturer", + "classification" + ] + } + } + }, + "properties": { + "catenaXId": { + "description": "The fully anonymous Catena-X ID of the batch, valid for the Catena-X dataspace.", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_CatenaXIdTrait" + }, + "localIdentifiers": { + "description": "A local identifier enables identification of a part in a specific dataspace, but is not unique in Catena-X dataspace. Multiple local identifiers may exist.", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_LocalIdentifierCharacteristic" + }, + "manufacturingInformation": { + "description": "Information from manufacturing process, such as manufacturing date and manufacturing country", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_ManufacturingCharacteristic" + }, + "partTypeInformation": { + "description": "The part type of which the batch has been instantiated of.", + "$ref": "#/components/schemas/urn_samm_io.catenax.batch_2.0.0_PartTypeInformationCharacteristic" + } + }, + "required": [ + "catenaXId", + "localIdentifiers", + "manufacturingInformation", + "partTypeInformation" + ] +} \ No newline at end of file diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockConfig.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockConfig.java new file mode 100644 index 0000000000..762ddeaef1 --- /dev/null +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockConfig.java @@ -0,0 +1,265 @@ +/******************************************************************************** + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.edc.client; + +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; +import java.util.Map; + +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.irs.data.StringMapper; +import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration; +import org.eclipse.tractusx.irs.edc.client.model.EDRAuthCode; +import org.jetbrains.annotations.NotNull; + +public class SubmodelFacadeWiremockConfig { + + public static final String PATH_CATALOG = "/catalog/request"; + public static final String PATH_NEGOTIATE = "/contractnegotiations"; + public static final String PATH_TRANSFER = "/transferprocesses"; + public static final String PATH_STATE = "/state"; + public static final String PATH_DATAPLANE_PUBLIC = "/api/public"; + public static final String DATAPLANE_HOST = "http://provider.dataplane"; + public static final String CONTEXT = """ + { + "dct": "https://purl.org/dc/terms/", + "tx": "https://w3id.org/tractusx/v0.0.1/ns/", + "edc": "https://w3id.org/edc/v0.0.1/ns/", + "dcat": "https://www.w3.org/ns/dcat/", + "odrl": "http://www.w3.org/ns/odrl/2/", + "dspace": "https://w3id.org/dspace/v0.8/" + }"""; + public static final String EDC_PROVIDER_DUMMY_URL = "https://edc.io/api/v1/dsp"; + public static final String IRS_INTERNAL_CALLBACK_URL = "https://irs.test/internal/endpoint-data-reference"; + + // TODO move to irs-testing + + public static void prepareNegotiation(final EndpointDataReferenceStorage storage) { + prepareNegotiation(storage, "1bbaec6e-c316-4e1e-8258-c07a648cc43c", "1b21e963-0bc5-422a-b30d-fd3511861d88", + "7681f966-36ea-4542-b5ea-0d0db81967de:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7:a6144a2e-c1b1-4ec6-96e1-a221da134e4f", + "5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7"); + } + + public static void prepareNegotiation(final EndpointDataReferenceStorage storage, final String negotiationId, + final String transferProcessId, final String contractAgreementId, final String edcAssetId) { + givenThat(post(urlPathEqualTo(PATH_CATALOG)).willReturn( + responseWithStatus(200).withBody(getCatalogResponse(edcAssetId, "USE", "BPNL00000003CRHK")))); + System.out.println(getCatalogResponse(edcAssetId, "USE", "BPNL00000003CRHK")); + givenThat(post(urlPathEqualTo(PATH_NEGOTIATE)).willReturn( + responseWithStatus(200).withBody(startNegotiationResponse(negotiationId)))); + + final String negotiationState = "FINALIZED"; + givenThat(get(urlPathEqualTo(PATH_NEGOTIATE + "/" + negotiationId)).willReturn(responseWithStatus(200).withBody( + getNegotiationConfirmedResponse(negotiationId, negotiationState, contractAgreementId)))); + + givenThat(get(urlPathEqualTo(PATH_NEGOTIATE + "/" + negotiationId + PATH_STATE)).willReturn( + responseWithStatus(200).withBody(getNegotiationStateResponse(negotiationState)))); + + givenThat(post(urlPathEqualTo(PATH_TRANSFER)).willReturn( + responseWithStatus(200).withBody(startTransferProcessResponse(transferProcessId)) + + )); + final String transferProcessState = "COMPLETED"; + givenThat(get(urlPathEqualTo(PATH_TRANSFER + "/" + transferProcessId + PATH_STATE)).willReturn( + responseWithStatus(200).withBody(getTransferProcessStateResponse(transferProcessState)) + + )); + givenThat(get(urlPathEqualTo(PATH_TRANSFER + "/" + transferProcessId)).willReturn( + responseWithStatus(200).withBody( + getTransferConfirmedResponse(transferProcessId, transferProcessState, edcAssetId, + contractAgreementId)))); + + final EndpointDataReference ref = createEndpointDataReference(contractAgreementId); + storage.put(contractAgreementId, ref); + } + + private static String startTransferProcessResponse(final String transferProcessId) { + return startNegotiationResponse(transferProcessId); + } + + private static String startNegotiationResponse(final String negotiationId) { + return """ + { + "@type": "edc:IdResponseDto", + "@id": "%s", + "edc:createdAt": 1686830151573, + "@context": %s + } + """.formatted(negotiationId, CONTEXT); + } + + private static String getNegotiationStateResponse(final String negotiationState) { + return stateResponseTemplate("edc:NegotiationState", negotiationState); + } + + private static String getTransferProcessStateResponse(final String transferProcessState) { + return stateResponseTemplate("edc:TransferState", transferProcessState); + } + + private static String stateResponseTemplate(final String responseType, final String negotiationState) { + return """ + { + "@type": "%s", + "edc:state": "%s", + "@context": %s + } + """.formatted(responseType, negotiationState, CONTEXT); + } + + private static String getNegotiationConfirmedResponse(final String negotiationId, final String negotiationState, + final String contractAgreementId) { + return """ + { + "@type": "edc:ContractNegotiationDto", + "@id": "%s", + "edc:type": "CONSUMER", + "edc:protocol": "dataspace-protocol-http", + "edc:state": "%s", + "edc:counterPartyAddress": "%s", + "edc:callbackAddresses": [], + "edc:contractAgreementId": "%s", + "@context": %s + } + """.formatted(negotiationId, negotiationState, EDC_PROVIDER_DUMMY_URL, contractAgreementId, CONTEXT); + } + + private static String getTransferConfirmedResponse(final String transferProcessId, final String transferState, + final String edcAssetId, final String contractAgreementId) { + return """ + { + "@id": "%s", + "@type": "edc:TransferProcessDto", + "edc:state": "%s", + "edc:stateTimestamp": 1688024335567, + "edc:type": "CONSUMER", + "edc:callbackAddresses": [], + "edc:dataDestination": { + "edc:type": "HttpProxy" + }, + "edc:dataRequest": { + "@type": "edc:DataRequestDto", + "@id": "%s", + "edc:assetId": "%s", + "edc:contractId": "%s", + "edc:connectorId": "BPNL00000003CRHK" + }, + "edc:receiverHttpEndpoint": "%s", + "@context": %s + } + """.formatted(transferProcessId, transferState, transferProcessId, edcAssetId, contractAgreementId, + IRS_INTERNAL_CALLBACK_URL, CONTEXT); + } + + private static String getCatalogResponse(final String edcAssetId, final String permissionType, + final String edcProviderBpn) { + return """ + { + "@id": "78ff625c-0c05-4014-965c-bd3d0a6a0de0", + "@type": "dcat:Catalog", + "dcat:dataset": { + "@id": "58505404-4da1-427a-82aa-b79482bcd1f0", + "@type": "dcat:Dataset", + "odrl:hasPolicy": { + "@id": "7681f966-36ea-4542-b5ea-0d0db81967de:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7:66131c58-32af-4df0-825d-77f7df6017c1", + "@type": "odrl:Set", + "odrl:permission": { + "odrl:target": "%s", + "odrl:action": { + "odrl:type": "%s" + }, + "odrl:constraint": %s + }, + "odrl:prohibition": [], + "odrl:obligation": [], + "odrl:target": "%s" + }, + "dcat:distribution": [ + { + "@type": "dcat:Distribution", + "dct:format": { + "@id": "HttpProxy" + }, + "dcat:accessService": "4ba1faa1-7f1a-4fb7-a41c-317f450e7443" + } + ], + "edc:description": "IRS EDC Test Asset", + "edc:id": "%s" + }, + "dcat:service": { + "@id": "4ba1faa1-7f1a-4fb7-a41c-317f450e7443", + "@type": "dcat:DataService", + "dct:terms": "connector", + "dct:endpointUrl": "%s" + }, + "edc:participantId": "%s", + "@context": %s + } + """.formatted(edcAssetId, permissionType, createConstraints(), edcAssetId, edcAssetId, + EDC_PROVIDER_DUMMY_URL, edcProviderBpn, CONTEXT); + } + + @NotNull + private static String createConstraints() { + final List atomitConstraints = List.of(createAtomicConstraint("Membership", "active"), + createAtomicConstraint("FrameworkAgreement.traceability", "active")); + return """ + { + "odrl:and": [ + %s + ] + }""".formatted(String.join(",\n", atomitConstraints)); + } + + private static String createAtomicConstraint(final String leftOperand, final String rightOperand) { + return """ + { + "odrl:leftOperand": "%s", + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "%s" + }""".formatted(leftOperand, rightOperand); + } + + public static EndpointDataReference createEndpointDataReference(final String contractAgreementId) { + final EDRAuthCode edrAuthCode = EDRAuthCode.builder() + .cid(contractAgreementId) + .dad("test") + .exp(9999999999L) + .build(); + final String b64EncodedAuthCode = Base64.getUrlEncoder() + .encodeToString(StringMapper.mapToString(edrAuthCode) + .getBytes(StandardCharsets.UTF_8)); + final String jwtToken = "eyJhbGciOiJSUzI1NiJ9." + b64EncodedAuthCode + ".test"; + return EndpointDataReference.Builder.newInstance() + .authKey("testkey") + .authCode(jwtToken) + .properties( + Map.of(JsonLdConfiguration.NAMESPACE_EDC_CID, contractAgreementId)) + .endpoint(DATAPLANE_HOST + PATH_DATAPLANE_PUBLIC) + .build(); + } +} \ No newline at end of file diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java index 7471135414..43ef624320 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java @@ -23,17 +23,13 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.edc.client; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; -import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration.NAMESPACE_EDC_CID; import static org.eclipse.tractusx.irs.edc.client.testutil.TestMother.createEdcTransformer; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -43,19 +39,16 @@ import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; import com.github.tomakehurst.wiremock.junit5.WireMockTest; import io.github.resilience4j.retry.RetryRegistry; import org.assertj.core.api.ThrowableAssert; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.tractusx.irs.edc.client.cache.endpointdatareference.EndpointDataReferenceCacheService; import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException; @@ -68,10 +61,8 @@ import org.eclipse.tractusx.irs.edc.client.policy.Permission; import org.eclipse.tractusx.irs.edc.client.policy.PolicyCheckerService; import org.eclipse.tractusx.irs.edc.client.policy.PolicyType; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.client.RestClientException; @@ -119,7 +110,8 @@ void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { final EdcDataPlaneClient dataPlaneClient = new EdcDataPlaneClient(restTemplate); final EDCCatalogFacade catalogFacade = new EDCCatalogFacade(controlPlaneClient, config); - final EndpointDataReferenceCacheService endpointDataReferenceCacheService = new EndpointDataReferenceCacheService(new EndpointDataReferenceStorage(Duration.ofMinutes(1))); + final EndpointDataReferenceCacheService endpointDataReferenceCacheService = new EndpointDataReferenceCacheService( + new EndpointDataReferenceStorage(Duration.ofMinutes(1))); acceptedPoliciesProvider = mock(AcceptedPoliciesProvider.class); when(acceptedPoliciesProvider.getAcceptedPolicies()).thenReturn(List.of(new AcceptedPolicy(policy("IRS Policy", @@ -141,12 +133,9 @@ void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { void shouldReturnAssemblyPartRelationshipAsString() throws EdcClientException, ExecutionException, InterruptedException { // Arrange - prepareNegotiation(); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBodyFile( - "singleLevelBomAsBuilt.json"))); + SubmodelFacadeWiremockConfig.prepareNegotiation(storage); + givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn( + responseWithStatus(200).withBodyFile("singleLevelBomAsBuilt.json"))); // Act final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, @@ -156,69 +145,13 @@ void shouldReturnAssemblyPartRelationshipAsString() assertThat(submodel).contains("\"catenaXId\": \"urn:uuid:fe99da3d-b0de-4e80-81da-882aebcca978\""); } - private void prepareNegotiation() { - final var contentType = "application/json;charset=UTF-8"; - final var pathCatalog = "/catalog/request"; - final var pathNegotiate = "/contractnegotiations"; - final var pathTransfer = "/transferprocesses"; - givenThat(post(urlPathEqualTo(pathCatalog)).willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", contentType) - .withBodyFile("edc/responseCatalog.json"))); - - givenThat(post(urlPathEqualTo(pathNegotiate)).willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", contentType) - .withBodyFile( - "edc/responseStartNegotiation.json"))); - - final var negotiationId = "1bbaec6e-c316-4e1e-8258-c07a648cc43c"; - givenThat(get(urlPathEqualTo(pathNegotiate + "/" + negotiationId)).willReturn(aResponse().withStatus(200) - .withHeader( - "Content-Type", - contentType) - .withBodyFile( - "edc/responseGetNegotiationConfirmed.json"))); - givenThat(get(urlPathEqualTo(pathNegotiate + "/" + negotiationId + "/state")).willReturn( - aResponse().withStatus(200) - .withHeader("Content-Type", contentType) - .withBodyFile("edc/responseGetNegotiationState.json"))); - - givenThat(post(urlPathEqualTo(pathTransfer)).willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", contentType) - .withBodyFile( - "edc/responseStartTransferprocess.json"))); - final var transferProcessId = "1b21e963-0bc5-422a-b30d-fd3511861d88"; - givenThat(get(urlPathEqualTo(pathTransfer + "/" + transferProcessId + "/state")).willReturn( - aResponse().withStatus(200) - .withHeader("Content-Type", contentType) - .withBodyFile("edc/responseGetTransferState.json"))); - givenThat(get(urlPathEqualTo(pathTransfer + "/" + transferProcessId)).willReturn(aResponse().withStatus(200) - .withHeader( - "Content-Type", - contentType) - .withBodyFile( - "edc/responseGetTransferConfirmed.json"))); - - final var contractAgreementId = "7681f966-36ea-4542-b5ea-0d0db81967de:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7:a6144a2e-c1b1-4ec6-96e1-a221da134e4f"; - final EndpointDataReference ref = EndpointDataReference.Builder.newInstance() - .authKey("testkey") - .authCode("testcode") - .properties(Map.of(NAMESPACE_EDC_CID, - contractAgreementId)) - .endpoint("http://provider.dataplane/api/public") - .build(); - storage.put(contractAgreementId, ref); - } - @Test void shouldReturnMaterialForRecyclingAsString() throws EdcClientException, ExecutionException, InterruptedException { // Arrange - prepareNegotiation(); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBodyFile( - "materialForRecycling.json"))); + SubmodelFacadeWiremockConfig.prepareNegotiation(storage); + givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn( + responseWithStatus(200).withBodyFile("materialForRecycling.json"))); // Act final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, @@ -232,11 +165,8 @@ void shouldReturnMaterialForRecyclingAsString() void shouldReturnObjectAsStringWhenResponseNotJSON() throws EdcClientException, ExecutionException, InterruptedException { // Arrange - prepareNegotiation(); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBody("test"))); + SubmodelFacadeWiremockConfig.prepareNegotiation(storage); + givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(responseWithStatus(200).withBody("test"))); // Act final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, @@ -259,27 +189,22 @@ void shouldThrowExceptionWhenPoliciesAreNotAccepted() { when(acceptedPoliciesProvider.getAcceptedPolicies()).thenReturn(List.of(acceptedPolicy)); - prepareNegotiation(); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBody("test"))); + SubmodelFacadeWiremockConfig.prepareNegotiation(storage); + givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(responseWithStatus(200).withBody("test"))); // Act & Assert final String errorMessage = "Consumption of asset '58505404-4da1-427a-82aa-b79482bcd1f0' is not permitted as the required catalog offer policies do not comply with defined IRS policies."; assertThatExceptionOfType(UsagePolicyException.class).isThrownBy( - () -> edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, assetId) - .get()).withMessageEndingWith(errorMessage); + () -> edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, assetId).get()) + .withMessageEndingWith(errorMessage); } @Test void shouldThrowExceptionWhenResponse_400() { // Arrange - prepareNegotiation(); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(aResponse().withStatus(400) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBody("{ error: '400'}"))); + SubmodelFacadeWiremockConfig.prepareNegotiation(storage); + givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn( + responseWithStatus(400).withBody("{ error: '400'}"))); // Act final ThrowableAssert.ThrowingCallable throwingCallable = () -> edcSubmodelClient.getSubmodelRawPayload( @@ -293,11 +218,9 @@ void shouldThrowExceptionWhenResponse_400() { @Test void shouldThrowExceptionWhenResponse_500() { // Arrange - prepareNegotiation(); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(aResponse().withStatus(500) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBody("{ error: '500'}"))); + SubmodelFacadeWiremockConfig.prepareNegotiation(storage); + givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn( + responseWithStatus(500).withBody("{ error: '500'}"))); // Act final ThrowableAssert.ThrowingCallable throwingCallable = () -> edcSubmodelClient.getSubmodelRawPayload( @@ -308,7 +231,6 @@ void shouldThrowExceptionWhenResponse_500() { .withCauseInstanceOf(RestClientException.class); } - private org.eclipse.tractusx.irs.edc.client.policy.Policy policy(String policyId, List permissions) { return new org.eclipse.tractusx.irs.edc.client.policy.Policy(policyId, OffsetDateTime.now(), OffsetDateTime.now().plusYears(1), permissions); diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java index e00704f8c8..1072ea7e6d 100644 --- a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java @@ -27,24 +27,24 @@ import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.DATAPLANE_URL; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.DISCOVERY_FINDER_PATH; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.DISCOVERY_FINDER_URL; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.EDC_DISCOVERY_PATH; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.LOOKUP_SHELLS_PATH; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.LOOKUP_SHELLS_TEMPLATE; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.SHELL_DESCRIPTORS_PATH; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.SHELL_DESCRIPTORS_TEMPLATE; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.TEST_BPN; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getLookupShells200; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getLookupShells200Empty; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getLookupShells404; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getShellDescriptor200; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.getShellDescriptor404; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postDiscoveryFinder200; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postDiscoveryFinder404; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postEdcDiscovery200; -import static org.eclipse.tractusx.irs.registryclient.decentral.DtrWiremockConfig.postEdcDiscovery404; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_URL; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.EDC_DISCOVERY_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.TEST_BPN; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder404; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscovery200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscovery404; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.DATAPLANE_URL; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.LOOKUP_SHELLS_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.LOOKUP_SHELLS_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.SHELL_DESCRIPTORS_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.SHELL_DESCRIPTORS_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getLookupShells200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getLookupShells200Empty; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getLookupShells404; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getShellDescriptor200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getShellDescriptor404; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -121,6 +121,7 @@ void shouldThrowHttpClientExceptionInCaseOfDiscoveryError() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert + // TODO fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); @@ -134,6 +135,7 @@ void shouldThrowHttpClientExceptionInCaseOfEdcDiscoveryError() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert + // TODO fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); @@ -149,6 +151,7 @@ void shouldThrowHttpClientExceptionInCaseOfLookupShellsError() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert + // TODO fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); @@ -166,6 +169,7 @@ void shouldThrowHttpClientExceptionInCaseOfShellDescriptorsError() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert + // TODO fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); @@ -184,11 +188,12 @@ void shouldThrowExceptionOnEmptyShells() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert + // TODO fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); verify(exactly(1), postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); verify(exactly(1), getRequestedFor(urlPathEqualTo(LOOKUP_SHELLS_PATH))); - verify(exactly(1), getRequestedFor(urlPathEqualTo(LOOKUP_SHELLS_PATH))); + verify(exactly(1), getRequestedFor(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*"))); } } diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java new file mode 100644 index 0000000000..6130c1501d --- /dev/null +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java @@ -0,0 +1,93 @@ +/******************************************************************************** + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.testing.wiremock; + +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.*; + +import java.util.List; + +import com.github.tomakehurst.wiremock.client.MappingBuilder; + +public class DiscoveryServiceWiremockConfig { + public static final String CONTROLPLANE_PUBLIC_URL = "https://controlplane.test"; + public static final String EDC_DISCOVERY_PATH = "/edcDiscovery"; + public static final String TEST_BPN = "BPNL00000000TEST"; + public static final String DISCOVERY_FINDER_PATH = "/discoveryFinder"; + public static final String DISCOVERY_HOST = "http://discovery.finder"; + public static final String EDC_DISCOVERY_URL = DISCOVERY_HOST + EDC_DISCOVERY_PATH; + public static final String DISCOVERY_FINDER_URL = DISCOVERY_HOST + DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_PATH; + + public static MappingBuilder postEdcDiscovery200() { + return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn( + responseWithStatus(200).withBody(edcDiscoveryResponse(TEST_BPN, List.of(CONTROLPLANE_PUBLIC_URL)))); + } + + public static String edcDiscoveryResponse(final String bpn, final List connectorEndpoints) { + return """ + [ + { + "bpn": "%s", + "connectorEndpoint": [ + %s + ] + } + ] + """.formatted(bpn, String.join(",\n", connectorEndpoints.stream().map(s -> "\"" + s + "\"").toList())); + } + + public static MappingBuilder postDiscoveryFinder200() { + return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn( + responseWithStatus(200).withBody(discoveryFinderResponse(EDC_DISCOVERY_URL))); + } + + public static String discoveryFinderResponse(final String discoveryFinderUrl) { + return """ + { + "endpoints": [ + { + "type": "bpn", + "description": "Service to discover EDC to a particular BPN", + "endpointAddress": "%s", + "documentation": "http://.../swagger/index.html", + "resourceId": "316417cd-0fb5-4daf-8dfa-8f68125923f1" + } + ] + } + """.formatted(discoveryFinderUrl); + } + + public static String discoveryFinderEmtpyResponse() { + return """ + { + "endpoints": [ + ] + } + """; + } + + public static MappingBuilder postDiscoveryFinder404() { + return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn(responseWithStatus(404)); + } + + public static MappingBuilder postEdcDiscovery404() { + return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn(responseWithStatus(404)); + } +} diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DtrWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java similarity index 58% rename from irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DtrWiremockConfig.java rename to irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java index 00f1719e82..4f29f1fbd1 100644 --- a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DtrWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java @@ -16,60 +16,54 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.registryclient.decentral; +package org.eclipse.tractusx.irs.testing.wiremock; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import java.util.List; import com.github.tomakehurst.wiremock.client.MappingBuilder; -import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; public class DtrWiremockConfig { + public static final String DATAPLANE_URL = "http://dataplane.test"; + public static final String DATAPLANE_PUBLIC_URL = DATAPLANE_URL + "/api/public/data/"; public static final String SHELL_DESCRIPTORS_PATH = "/shell-descriptors/"; public static final String SHELL_DESCRIPTORS_TEMPLATE = SHELL_DESCRIPTORS_PATH + "{aasIdentifier}"; public static final String LOOKUP_SHELLS_PATH = "/lookup/shells"; public static final String LOOKUP_SHELLS_TEMPLATE = LOOKUP_SHELLS_PATH + "?assetIds={assetIds}"; - public static final String DISCOVERY_FINDER_PATH = "/discoveryFinder"; - public static final String EDC_DISCOVERY_PATH = "/edcDiscovery"; - public static final String TEST_BPN = "BPNL00000000TEST"; - public static final String DISCOVERY_HOST = "http://discovery.finder"; - public static final String DATAPLANE_URL = "http://dataplane.test"; - public static final String DISCOVERY_FINDER_URL = DISCOVERY_HOST + DISCOVERY_FINDER_PATH; - static ResponseDefinitionBuilder responseWithStatus(final int statusCode) { - return aResponse().withStatus(statusCode).withHeader("Content-Type", "application/json;charset=UTF-8"); + private DtrWiremockConfig() { } - static MappingBuilder getShellDescriptor200() { - final String materialForRecycling = submodel("https://dataplane.test/api/public/data/", - "urn:uuid:19b0338f-6d03-4198-b3b8-5c43f8958d60", "https://controlplane.test", "MaterialForRecycling", - "urn:uuid:cf06d5d5-e3f8-4bd4-bfcf-81815310701f", + public static MappingBuilder getShellDescriptor200() { + final String materialForRecycling = submodelDescriptor(DATAPLANE_PUBLIC_URL, + "urn:uuid:19b0338f-6d03-4198-b3b8-5c43f8958d60", DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, + "MaterialForRecycling", "urn:uuid:cf06d5d5-e3f8-4bd4-bfcf-81815310701f", "urn:bamm:io.catenax.material_for_recycling:1.1.0#MaterialForRecycling"); - final String batch = submodel("https://dataplane.test/api/public/data/", - "urn:uuid:234edd2f-0223-47c7-9fe4-3984ab14c4f9", "https://controlplane.test", "Batch", + final String batch = submodelDescriptor(DATAPLANE_PUBLIC_URL, "urn:uuid:234edd2f-0223-47c7-9fe4-3984ab14c4f9", + DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, "Batch", "urn:uuid:f53db6ef-7a58-4326-9169-0ae198b85dbf", "urn:samm:io.catenax.batch:2.0.0#Batch"); - final String singleLevelUsageAsBuilt = submodel("https://dataplane.test/api/public/data/", - "urn:uuid:f8196d6a-1664-4531-bdee-f15dbb1daf26", "https://controlplane.test", "SingleLevelUsageAsBuilt", - "urn:uuid:e2899f43-eca8-4aec-b877-4a69691f0487", + final String singleLevelUsageAsBuilt = submodelDescriptor(DATAPLANE_PUBLIC_URL, + "urn:uuid:f8196d6a-1664-4531-bdee-f15dbb1daf26", DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, + "SingleLevelUsageAsBuilt", "urn:uuid:e2899f43-eca8-4aec-b877-4a69691f0487", "urn:bamm:io.catenax.single_level_usage_as_built:2.0.0#SingleLevelUsageAsBuilt"); final List submodelDescriptors = List.of(materialForRecycling, batch, singleLevelUsageAsBuilt); final List specificAssetIds = List.of(specificAssetId("manufacturerId", "BPNL00000003B0Q0"), specificAssetId("batchId", "BID12345678")); return get(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*")).willReturn(responseWithStatus(200).withBody( - assetAdministrationShell(submodelDescriptors, "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5", + assetAdministrationShellResponse(submodelDescriptors, "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5", "EngineeringPlastics", "urn:uuid:9ce43b21-75e3-4cea-b13e-9a34f4f6822a", specificAssetIds))); } - public static String assetAdministrationShell(final List submodelDescriptors, final String globalAssetId, - final String idShort, final String shellId, final List specificAssetIds) { + public static String assetAdministrationShellResponse(final List submodelDescriptors, + final String globalAssetId, final String idShort, final String shellId, + final List specificAssetIds) { return """ { "description": [], @@ -107,7 +101,7 @@ public static String specificAssetId(final String key, final String value) { """.formatted(key, value); } - public static String submodel(final String dataplaneUrl, final String assetId, final String dspEndpoint, + public static String submodelDescriptor(final String dataplaneUrl, final String assetId, final String dspEndpoint, final String idShort, final String submodelDescriptorId, final String semanticId) { final String href = dataplaneUrl + submodelDescriptorId; return """ @@ -152,73 +146,17 @@ public static String submodel(final String dataplaneUrl, final String assetId, f """.formatted(href, assetId, dspEndpoint, idShort, submodelDescriptorId, semanticId); } - static MappingBuilder postEdcDiscovery200() { - return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn( - responseWithStatus(200).withBody(edcDiscovery("BPNL00000000TEST", List.of("http://edc.test/edc")))); - } - - public static String edcDiscovery(final String bpn, final List connectorEndpoints) { - return """ - [ - { - "bpn": "%s", - "connectorEndpoint": [ - %s - ] - } - ] - """.formatted(bpn, String.join(",\n", connectorEndpoints.stream().map(s -> "\"" + s + "\"").toList())); - } - - static MappingBuilder postDiscoveryFinder200() { - return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn( - responseWithStatus(200).withBody(discoveryFinder("http://discovery.finder/edcDiscovery"))); - } - - public static String discoveryFinder(final String discoveryFinderUrl) { - return """ - { - "endpoints": [ - { - "type": "bpn", - "description": "Service to discover EDC to a particular BPN", - "endpointAddress": "%s", - "documentation": "http://.../swagger/index.html", - "resourceId": "316417cd-0fb5-4daf-8dfa-8f68125923f1" - } - ] - } - """.formatted(discoveryFinderUrl); - } - - private static String discoveryFinderEmtpy() { - return """ - { - "endpoints": [ - ] - } - """; - } - - static MappingBuilder postDiscoveryFinder404() { - return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn(responseWithStatus(404)); - } - - static MappingBuilder postEdcDiscovery404() { - return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn(responseWithStatus(404)); - } - - static MappingBuilder getLookupShells200() { + public static MappingBuilder getLookupShells200() { return get(urlPathEqualTo(LOOKUP_SHELLS_PATH)).willReturn(responseWithStatus(200).withBody( - lookupShells(List.of("urn:uuid:21f7ebea-fa8a-410c-a656-bd9082e67dcf")))); + lookupShellsResponse(List.of("urn:uuid:21f7ebea-fa8a-410c-a656-bd9082e67dcf")))); } - static MappingBuilder getLookupShells200Empty() { + public static MappingBuilder getLookupShells200Empty() { return get(urlPathMatching(LOOKUP_SHELLS_PATH + ".*")).willReturn( - responseWithStatus(200).withBody(lookupShells(List.of()))); + responseWithStatus(200).withBody(lookupShellsResponse(List.of()))); } - public static String lookupShells(final List shellIds) { + public static String lookupShellsResponse(final List shellIds) { return """ { "paging_metadata": {}, @@ -229,11 +167,11 @@ public static String lookupShells(final List shellIds) { """.formatted(String.join(",\n", shellIds.stream().map(s -> "\"" + s + "\"").toList())); } - static MappingBuilder getLookupShells404() { + public static MappingBuilder getLookupShells404() { return get(urlPathEqualTo(LOOKUP_SHELLS_PATH)).willReturn(responseWithStatus(404)); } - static MappingBuilder getShellDescriptor404() { + public static MappingBuilder getShellDescriptor404() { return get(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*")).willReturn(responseWithStatus(404)); } } \ No newline at end of file diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java index 9ff8b9562c..21598577df 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java @@ -18,9 +18,12 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.testing.wiremock; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; + import java.net.InetSocketAddress; import java.net.Proxy; +import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @@ -44,4 +47,8 @@ public static RestTemplate restTemplateProxy(final String proxyServerHost, final requestFactory.setProxy(proxy); return new RestTemplate(requestFactory); } + + public static ResponseDefinitionBuilder responseWithStatus(final int statusCode) { + return aResponse().withStatus(statusCode).withHeader("Content-Type", "application/json;charset=UTF-8"); + } } From d1fd503620a36f1d0272f0928730d2ed07a8bc73 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Fri, 26 Jan 2024 14:49:21 +0100 Subject: [PATCH 09/22] feat(irs-api):[#344] Add Irs WireMock Test simulating one level --- .../eclipse/tractusx/irs/IrsWireMockIT.java | 189 ++++++++++++++++-- .../tractusx/irs/WireMockTestConfig.java | 28 +++ .../tractusx/irs/bpdm/BpdmWireMockConfig.java | 86 ++++++++ .../tractusx/irs/bpdm/BpdmWiremockTest.java | 60 +----- .../SemanticHubWireMockConfig.java | 52 +++++ .../semanticshub/SemanticHubWiremockTest.java | 11 +- .../__files/integrationtesting/batch-1.json | 22 ++ .../singleLevelBomAsBuilt-1.json | 16 ++ .../singleLevelBomAsBuilt-2.0.0-schema.json | 102 ++++++++++ .../client/SubmodelFacadeWiremockTest.java | 87 +++++--- .../DiscoveryServiceWiremockConfig.java | 28 +-- .../testing/wiremock/DtrWiremockConfig.java | 34 +++- .../SubmodelFacadeWiremockConfig.java | 99 ++++----- 13 files changed, 620 insertions(+), 194 deletions(-) create mode 100644 irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java create mode 100644 irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java create mode 100644 irs-api/src/test/resources/__files/integrationtesting/batch-1.json create mode 100644 irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-1.json create mode 100644 irs-api/src/test/resources/__files/semantichub/singleLevelBomAsBuilt-2.0.0-schema.json rename {irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client => irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock}/SubmodelFacadeWiremockConfig.java (67%) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java index d7970bdee4..7de5396ebe 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java @@ -23,24 +23,62 @@ ********************************************************************************/ package org.eclipse.tractusx.irs; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.containing; import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.irs.WireMockTestConfig.createEndpointDataReference; +import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig.bpdmResponse; +import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.batchSchemaResponse200; +import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.singleLevelBomAsBuiltSchemaResponse200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_URL; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.EDC_DISCOVERY_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.TEST_BPN; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscovery200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.DATAPLANE_PUBLIC_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.LOOKUP_SHELLS_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.PUBLIC_LOOKUP_SHELLS_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.PUBLIC_SHELL_DESCRIPTORS_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.SHELL_DESCRIPTORS_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getLookupShells200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getShellDescriptor200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.lookupShellsResponse; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_CATALOG; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_NEGOTIATE; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_STATE; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_TRANSFER; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; +import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.util.List; import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import org.apache.commons.codec.binary.Base64; +import org.awaitility.Awaitility; +import org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig; import org.eclipse.tractusx.irs.component.JobHandle; +import org.eclipse.tractusx.irs.component.Jobs; import org.eclipse.tractusx.irs.component.PartChainIdentificationKey; import org.eclipse.tractusx.irs.component.RegisterJob; import org.eclipse.tractusx.irs.component.enums.Direction; +import org.eclipse.tractusx.irs.component.enums.JobState; +import org.eclipse.tractusx.irs.edc.client.EndpointDataReferenceStorage; import org.eclipse.tractusx.irs.semanticshub.AspectModels; +import org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig; import org.eclipse.tractusx.irs.services.IrsItemGraphQueryService; import org.eclipse.tractusx.irs.services.SemanticHubService; import org.eclipse.tractusx.irs.services.validation.SchemaNotFoundException; import org.eclipse.tractusx.irs.testing.containers.MinioContainer; +import org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -57,34 +95,29 @@ @WireMockTest(httpPort = 8085) @Testcontainers -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WireMockTestConfig.class - /*, properties = "spring.main.allow-bean-definition-overriding=true"*/) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WireMockTestConfig.class) @ContextConfiguration(initializers = IrsWireMockIT.MinioConfigInitializer.class) -//@Import({ WireMockTestConfig.class }) @ActiveProfiles("integrationtest") class IrsWireMockIT { - public static final String BPDM_TEST = "http://bpdm.test/legal-entities/{partnerId}?idType={idType}"; - public static final String DISCOVERY_TEST = "http://discovery.test"; public static final String SEMANTIC_HUB_URL = "http://semantic.hub/models"; - public static final String SEMANTIC_HUB_SCHEMA_URL = "http://semantic.hub/models/{urn}/json-schema"; + public static final String EDC_URL = "http://edc.test"; private static final String ACCESS_KEY = "accessKey"; private static final String SECRET_KEY = "secretKey"; private static final MinioContainer minioContainer = new MinioContainer( new MinioContainer.CredentialsProvider(ACCESS_KEY, SECRET_KEY)).withReuse(true); - public static final String EDC_URL = "http://edc.test:8081/management"; @Autowired private IrsItemGraphQueryService irsService; @Autowired private SemanticHubService semanticHubService; + @Autowired + private EndpointDataReferenceStorage endpointDataReferenceStorage; @BeforeAll static void startContainer() { minioContainer.start(); - givenThat(get(urlPathEqualTo("/models")).willReturn(aResponse().withStatus(200) - .withHeader("Content-Type", - "application/json;charset=UTF-8") - .withBodyFile("all-models-page-IT.json"))); + givenThat(get(urlPathEqualTo("/models")).willReturn( + responseWithStatus(200).withBodyFile("semantichub/all-models-page-IT.json"))); } @AfterAll @@ -94,11 +127,21 @@ static void stopContainer() { @DynamicPropertySource static void configureProperties(DynamicPropertyRegistry registry) { - registry.add("bpdm.bpnEndpoint", () -> BPDM_TEST); - registry.add("digitalTwinRegistry.discoveryFinderUrl", () -> DISCOVERY_TEST); + registry.add("bpdm.bpnEndpoint", () -> BpdmWireMockConfig.BPDM_TEST); + registry.add("digitalTwinRegistry.discoveryFinderUrl", () -> DISCOVERY_FINDER_URL); + registry.add("digitalTwinRegistry.shellDescriptorTemplate", () -> SHELL_DESCRIPTORS_TEMPLATE); + registry.add("digitalTwinRegistry.lookupShellsTemplate", () -> LOOKUP_SHELLS_TEMPLATE); + registry.add("digitalTwinRegistry.type", () -> "decentral"); registry.add("semanticshub.url", () -> SEMANTIC_HUB_URL); - registry.add("semanticshub.modelJsonSchemaEndpoint", () -> SEMANTIC_HUB_SCHEMA_URL); + registry.add("semanticshub.modelJsonSchemaEndpoint", () -> SemanticHubWireMockConfig.SEMANTIC_HUB_SCHEMA_URL); registry.add("irs-edc-client.controlplane.endpoint.data", () -> EDC_URL); + registry.add("irs-edc-client.controlplane.endpoint.catalog", () -> PATH_CATALOG); + registry.add("irs-edc-client.controlplane.endpoint.contract-negotiation", () -> PATH_NEGOTIATE); + registry.add("irs-edc-client.controlplane.endpoint.transfer-process", () -> PATH_TRANSFER); + registry.add("irs-edc-client.controlplane.endpoint.state-suffix", () -> PATH_STATE); + registry.add("irs-edc-client.controlplane.api-key.header", () -> "X-Api-Key"); + registry.add("irs-edc-client.controlplane.api-key.secret", () -> "test"); + registry.add("resilience4j.retry.configs.default.waitDuration", () -> "1s"); } @Test @@ -113,13 +156,25 @@ void shouldStartApplicationAndCollectSemanticModels() throws SchemaNotFoundExcep @Test void shouldStartJob() { // Arrange + final String startId = "globalAssetId"; + + successfulSemanticHubRequests(); + successfulDiscovery(); + successfulRegistryNegotiation(); + successfulDtrRequest(startId); + successfulAssetNegotiation(); + + successfulDataRequests(); + + successfulBpdmRequests(); + final RegisterJob request = RegisterJob.builder() .key(PartChainIdentificationKey.builder() - .bpn("BPNTEST") - .globalAssetId("globalAssetId") + .bpn(TEST_BPN) + .globalAssetId(startId) .build()) - .depth(2) - .aspects(List.of("SerialPart", "Batch", "SingleLevelBomAsBuilt")) + .depth(1) + .aspects(List.of("Batch", "SingleLevelBomAsBuilt")) .collectAspects(true) .lookupBPNs(true) .direction(Direction.DOWNWARD) @@ -127,9 +182,103 @@ void shouldStartJob() { // Act final JobHandle jobHandle = irsService.registerItemJob(request); + assertThat(jobHandle.getId()).isNotNull(); + Awaitility.await() + .timeout(Duration.ofSeconds(35)) + .pollInterval(Duration.ofSeconds(1)) + .until(() -> irsService.getJobForJobId(jobHandle.getId(), false) + .getJob() + .getState() + .equals(JobState.COMPLETED)); + + Jobs jobForJobId = irsService.getJobForJobId(jobHandle.getId(), true); // Assert - assertThat(jobHandle.getId()).isNotNull(); + verifyDiscoveryCalls(1); + verifyNegotiationCalls(3); + + assertThat(jobForJobId.getJob().getState()).isEqualTo(JobState.COMPLETED); + assertThat(jobForJobId.getShells()).hasSize(2); + assertThat(jobForJobId.getRelationships()).hasSize(1); + assertThat(jobForJobId.getTombstones()).isEmpty(); + } + + private void successfulRegistryNegotiation() { + final String negotiationId = "1bbaec6e-c316-4e1e-8258-c07a648cc43c"; + final String transferProcessId = "1b21e963-0bc5-422a-b30d-fd3511861d88"; + final String edcAssetId = "registry-asset"; + final String contractAgreementId = SubmodelFacadeWiremockConfig.prepareNegotiation(negotiationId, + transferProcessId, + "7681f966-36ea-4542-b5ea-0d0db81967de:registry-asset:a6144a2e-c1b1-4ec6-96e1-a221da134e4f", edcAssetId); + endpointDataReferenceStorage.put(contractAgreementId, createEndpointDataReference(contractAgreementId)); + } + + private void successfulAssetNegotiation() { + final String negotiationId = "1bbaec6e-c316-4e1e-8258-c07a648cc43c"; + final String transferProcessId = "1b21e963-0bc5-422a-b30d-fd3511861d88"; + final String edcAssetId = "urn:uuid:f8196d6a-1664-4531-bdee-f15dbb1daf26"; + final String contractAgreementId = SubmodelFacadeWiremockConfig.prepareNegotiation(negotiationId, + transferProcessId, + "7681f966-36ea-4542-b5ea-0d0db81967de:urn:uuid:f8196d6a-1664-4531-bdee-f15dbb1daf26:a6144a2e-c1b1-4ec6-96e1-a221da134e4f", + edcAssetId); + endpointDataReferenceStorage.put(contractAgreementId, createEndpointDataReference(contractAgreementId)); + } + + private static void successfulDiscovery() { + stubFor(postDiscoveryFinder200()); + stubFor(postEdcDiscovery200()); + } + + private static String encodedId(final String secondDTR) { + return Base64.encodeBase64String(secondDTR.getBytes(StandardCharsets.UTF_8)); + } + + private static void verifyDiscoveryCalls(final int times) { + verify(times, postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + verify(times, postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + } + + private static void verifyNegotiationCalls(final int times) { + verify(times, postRequestedFor(urlPathEqualTo(PATH_NEGOTIATE))); + verify(times, postRequestedFor(urlPathEqualTo(PATH_CATALOG))); + verify(times * 2, getRequestedFor(urlPathMatching(PATH_NEGOTIATE + "/.*"))); + verify(times, getRequestedFor(urlPathMatching(PATH_NEGOTIATE + "/.*" + PATH_STATE))); + verify(times, postRequestedFor(urlPathEqualTo(PATH_TRANSFER))); + verify(times * 2, getRequestedFor(urlPathMatching(PATH_TRANSFER + "/.*"))); + verify(times, getRequestedFor(urlPathMatching(PATH_TRANSFER + "/.*" + PATH_STATE))); + } + + private static void successfulBpdmRequests() { + stubFor(get(urlPathMatching("/legal-entities/.*")).willReturn( + responseWithStatus(200).withBody(bpdmResponse(TEST_BPN, "Company Name")))); + } + + private static void successfulDataRequests() { + givenThat(get(urlPathMatching( + DATAPLANE_PUBLIC_PATH + "/urn:uuid:f53db6ef-7a58-4326-9169-0ae198b85dbf")).willReturn( + responseWithStatus(200).withBodyFile("integrationtesting/batch-1.json"))); + givenThat(get(urlPathMatching( + DATAPLANE_PUBLIC_PATH + "/urn:uuid:0e413809-966b-4107-aae5-aeb28bcdaadf")).willReturn( + responseWithStatus(200).withBodyFile("integrationtesting/singleLevelBomAsBuilt-1.json"))); + } + + private static void successfulSemanticHubRequests() { + stubFor(batchSchemaResponse200()); + stubFor(singleLevelBomAsBuiltSchemaResponse200()); + } + + private static void successfulDtrRequest(final String startId) { + stubFor(getLookupShells200(PUBLIC_LOOKUP_SHELLS_PATH).withQueryParam("assetIds", containing(startId))); + stubFor(getShellDescriptor200( + PUBLIC_SHELL_DESCRIPTORS_PATH + encodedId("urn:uuid:21f7ebea-fa8a-410c-a656-bd9082e67dcf"))); + + final String secondDTR = "urn:uuid:6d505432-8b31-4966-9514-4b753372683f"; + stubFor(get(urlPathEqualTo(PUBLIC_LOOKUP_SHELLS_PATH)).withQueryParam("assetIds", + containing("urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5")) + .willReturn(responseWithStatus(200).withBody( + lookupShellsResponse(List.of(secondDTR))))); + + stubFor(getShellDescriptor200(PUBLIC_SHELL_DESCRIPTORS_PATH + encodedId(secondDTR))); } public static class MinioConfigInitializer diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java index 16e9e92c3c..5cc1adcf9d 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java @@ -24,12 +24,21 @@ import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.EDC_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.NO_ERROR_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.SEMHUB_REST_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.DATAPLANE_HOST; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_DATAPLANE_PUBLIC; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.List; +import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.irs.data.StringMapper; +import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration; +import org.eclipse.tractusx.irs.edc.client.model.EDRAuthCode; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; @@ -44,6 +53,25 @@ public class WireMockTestConfig { public static final int HTTP_PORT = 8085; private static final String PROXY_SERVER_HOST = "127.0.0.1"; + public static EndpointDataReference createEndpointDataReference(final String contractAgreementId) { + final EDRAuthCode edrAuthCode = EDRAuthCode.builder() + .cid(contractAgreementId) + .dad("test") + .exp(9999999999L) + .build(); + final String b64EncodedAuthCode = Base64.getUrlEncoder() + .encodeToString(StringMapper.mapToString(edrAuthCode) + .getBytes(StandardCharsets.UTF_8)); + final String jwtToken = "eyJhbGciOiJSUzI1NiJ9." + b64EncodedAuthCode + ".test"; + return EndpointDataReference.Builder.newInstance() + .authKey("testkey") + .authCode(jwtToken) + .properties( + Map.of(JsonLdConfiguration.NAMESPACE_EDC_CID, contractAgreementId)) + .endpoint(DATAPLANE_HOST + PATH_DATAPLANE_PUBLIC) + .build(); + } + @Primary @Profile("integrationtest") @Bean(DTR_REST_TEMPLATE) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java new file mode 100644 index 0000000000..8a1089c5ce --- /dev/null +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java @@ -0,0 +1,86 @@ +/******************************************************************************** + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.bpdm; + +/** + * WireMock configurations and requests used for testing BPDM flow. + */ +public final class BpdmWireMockConfig { + + public static final String BPDM_TEST = "http://bpdm.test/legal-entities/{partnerId}?idType={idType}"; + + private BpdmWireMockConfig() { + } + + public static String bpdmResponse(final String bpn, final String companyName) { + return """ + { + "bpn": "%s", + "identifiers": [ + { + "value": "%s", + "type": { + "technicalKey": "BPN", + "name": "Business Partner Number", + "url": "" + }, + "issuingBody": { + "technicalKey": "CATENAX", + "name": "Catena-X", + "url": "" + }, + "status": { + "technicalKey": "UNKNOWN", + "name": "Unknown" + } + } + ], + "names": [ + { + "value": "%s", + "shortName": null, + "type": { + "technicalKey": "OTHER", + "name": "Any other alternative name used for a company, such as a specific language variant.", + "url": "" + }, + "language": { + "technicalKey": "undefined", + "name": "Undefined" + } + } + ], + "legalForm": null, + "status": null, + "profileClassifications": [], + "types": [ + { + "technicalKey": "UNKNOWN", + "name": "Unknown", + "url": "" + } + ], + "bankAccounts": [], + "roles": [], + "relations": [], + "currentness": "2022-07-26T08:17:38.737578Z" + } + """.formatted(bpn, bpn, companyName); + } +} \ No newline at end of file diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java index e9e107cd8d..fc963f6163 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java @@ -18,12 +18,13 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.bpdm; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig.BPDM_TEST; +import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig.bpdmResponse; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; @@ -45,67 +46,14 @@ class BpdmWiremockTest { void setUp(WireMockRuntimeInfo wireMockRuntimeInfo) { final RestTemplate restTemplate = restTemplateProxy(PROXY_SERVER_HOST, wireMockRuntimeInfo.getHttpPort()); - bpdmFacade = new BpdmFacade( - new BpdmClientImpl(restTemplate, "http://bpdm.test/legal-entities/{partnerId}?idType={idType}")); + bpdmFacade = new BpdmFacade(new BpdmClientImpl(restTemplate, BPDM_TEST)); } @Test void shouldResolveManufacturerName() { // Arrange givenThat(get(urlPathEqualTo("/legal-entities/BPNL00000000TEST")).willReturn( - aResponse().withStatus(200).withHeader("Content-Type", "application/json;charset=UTF-8").withBody(""" - { - "bpn": "BPNL00000000TEST", - "identifiers": [ - { - "value": "BPNL00000000TEST", - "type": { - "technicalKey": "BPN", - "name": "Business Partner Number", - "url": "" - }, - "issuingBody": { - "technicalKey": "CATENAX", - "name": "Catena-X", - "url": "" - }, - "status": { - "technicalKey": "UNKNOWN", - "name": "Unknown" - } - } - ], - "names": [ - { - "value": "TEST_BPN_DFT_1", - "shortName": null, - "type": { - "technicalKey": "OTHER", - "name": "Any other alternative name used for a company, such as a specific language variant.", - "url": "" - }, - "language": { - "technicalKey": "undefined", - "name": "Undefined" - } - } - ], - "legalForm": null, - "status": null, - "profileClassifications": [], - "types": [ - { - "technicalKey": "UNKNOWN", - "name": "Unknown", - "url": "" - } - ], - "bankAccounts": [], - "roles": [], - "relations": [], - "currentness": "2022-07-26T08:17:38.737578Z" - } - """))); + responseWithStatus(200).withBody(bpdmResponse("BPNL00000000TEST", "TEST_BPN_DFT_1")))); // Act final Optional manufacturerName = bpdmFacade.findManufacturerName("BPNL00000000TEST"); diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java new file mode 100644 index 0000000000..16120c02cb --- /dev/null +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java @@ -0,0 +1,52 @@ +/******************************************************************************** + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.semanticshub; + +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; + +import com.github.tomakehurst.wiremock.client.MappingBuilder; + +/** + * WireMock configurations and requests used for testing Semantic Hub fLow. + */ +public final class SemanticHubWireMockConfig { + public static final String BATCH_URN = "urn:samm:io.catenax.batch:2.0.0%23Batch"; + public static final String SEMANTIC_HUB_SCHEMA_URL = "http://semantic.hub/models/{urn}/json-schema"; + private static final String SINGLE_LEVEL_BOM_AS_BUILT_URN = "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0%23SingleLevelBomAsBuilt"; + + private SemanticHubWireMockConfig() { + } + + public static MappingBuilder batchSchemaResponse200() { + return schemaResponse200("/models/" + BATCH_URN + "/json-schema", "semantichub/batch-2.0.0-schema.json"); + } + + public static MappingBuilder singleLevelBomAsBuiltSchemaResponse200() { + return schemaResponse200("/models/" + SINGLE_LEVEL_BOM_AS_BUILT_URN + "/json-schema", + "semantichub/singleLevelBomAsBuilt-2.0.0-schema.json"); + } + + private static MappingBuilder schemaResponse200(final String urlRegex, final String fileName) { + return get(urlPathMatching(urlRegex)).withHost(equalTo("semantic.hub")) + .willReturn(responseWithStatus(200).withBodyFile(fileName)); + } +} \ No newline at end of file diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java index 321f4d6fef..2a52ef68d7 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java @@ -34,6 +34,8 @@ import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.SEMANTIC_HUB_SCHEMA_URL; +import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.batchSchemaResponse200; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; @@ -67,7 +69,7 @@ void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { final SemanticsHubConfiguration config = new SemanticsHubConfiguration(); config.setPageSize(10); config.setUrl("http://semantic.hub/models"); - config.setModelJsonSchemaEndpoint("http://semantic.hub/models/{urn}/json-schema"); + config.setModelJsonSchemaEndpoint(SEMANTIC_HUB_SCHEMA_URL); final SemanticsHubClient semanticsHubClient = new SemanticsHubClientImpl(restTemplate, config); semanticsHubFacade = new SemanticsHubFacade(semanticsHubClient); @@ -107,12 +109,7 @@ void shouldReturn2Pages() throws SchemaNotFoundException { @Test void shouldReturnJsonSchema() throws SchemaNotFoundException { // Arrange - stubFor(get(urlPathMatching("/models/urn:samm:io.catenax.batch:2.0.0%23Batch/json-schema")).withHost( - equalTo("semantic.hub")) - .willReturn( - responseWithStatus( - 200).withBodyFile( - "semantichub/batch-2.0.0-schema.json"))); + stubFor(batchSchemaResponse200()); // Act final String modelJsonSchema = semanticsHubFacade.getModelJsonSchema("urn:samm:io.catenax.batch:2.0.0#Batch"); diff --git a/irs-api/src/test/resources/__files/integrationtesting/batch-1.json b/irs-api/src/test/resources/__files/integrationtesting/batch-1.json new file mode 100644 index 0000000000..76e6d99956 --- /dev/null +++ b/irs-api/src/test/resources/__files/integrationtesting/batch-1.json @@ -0,0 +1,22 @@ +{ + "localIdentifiers": [ + { + "value": "BPNL00000000TEST", + "key": "manufacturerId" + }, + { + "value": "BID12345678", + "key": "batchId" + } + ], + "manufacturingInformation": { + "date": "2022-02-04T14:48:54", + "country": "HUR" + }, + "catenaXId": "urn:uuid:334cce52-1f52-4bc9-9dd1-410bbe497bbc", + "partTypeInformation": { + "manufacturerPartId": "123-0.740-3434-A", + "classification": "product", + "nameAtManufacturer": "Glue" + } +} \ No newline at end of file diff --git a/irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-1.json b/irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-1.json new file mode 100644 index 0000000000..167a940ce7 --- /dev/null +++ b/irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-1.json @@ -0,0 +1,16 @@ +{ + "catenaXId": "urn:uuid:334cce52-1f52-4bc9-9dd1-410bbe497bbc", + "childItems": [ + { + "catenaXId": "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5", + "quantity": { + "quantityNumber": 0.2014, + "measurementUnit": "unit:kilogram" + }, + "hasAlternatives": true, + "businessPartner": "BPNL00000000TEST", + "createdOn": "2022-02-03T14:48:54.709Z", + "lastModifiedOn": "2022-02-03T14:48:54.709Z" + } + ] +} \ No newline at end of file diff --git a/irs-api/src/test/resources/__files/semantichub/singleLevelBomAsBuilt-2.0.0-schema.json b/irs-api/src/test/resources/__files/semantichub/singleLevelBomAsBuilt-2.0.0-schema.json new file mode 100644 index 0000000000..70fbf22bb0 --- /dev/null +++ b/irs-api/src/test/resources/__files/semantichub/singleLevelBomAsBuilt-2.0.0-schema.json @@ -0,0 +1,102 @@ +{ + "$schema" : "http://json-schema.org/draft-04/schema", + "description" : "The single-level bill of material represents one sub-level of an assembly and does not include any lower-level subassemblies. The as-built lifecycle references all child items as manufactured by the manufacturer referencing only child items in an as-built lifecycle themselves (e.g. serial parts or batches), unless parts can only be tracked by an part ID (on a type level).\n\nIf it is unclear which item has been built-in into the parent item, all potential parts must be listed. This is the case when, e.g. the same item is supplied by two suppliers and the item is only tracked by a customer part ID during assembly, these items can not be differentiated from each other.\n", + "type" : "object", + "components" : { + "schemas" : { + "urn_samm_io.catenax.single_level_bom_as_built_2.0.0_CatenaXIdTraitCharacteristic" : { + "type" : "string", + "description" : "The provided regular expression ensures that the UUID is composed of five groups of characters separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters (32 hexadecimal characters and 4 hyphens), optionally prefixed by \"urn:uuid:\" to make it an IRI.", + "pattern" : "(^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)|(^urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)" + }, + "urn_samm_org.eclipse.esmf.samm_characteristic_2.1.0_Timestamp" : { + "type" : "string", + "pattern" : "-?([1-9][0-9]{3,}|0[0-9]{3})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T(([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\\.[0-9]+)?|(24:00:00(\\.0+)?))(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?", + "description" : "Describes a Property which contains the date and time with an optional timezone." + }, + "urn_samm_io.catenax.single_level_bom_as_built_2.0.0_NumberOfObjects" : { + "type" : "number", + "description" : "Quantifiable number of objects in reference to the measurementUnit" + }, + "urn_samm_org.eclipse.esmf.samm_characteristic_2.1.0_UnitReference" : { + "type" : "string", + "pattern" : "[a-zA-Z]*:[a-zA-Z]+", + "description" : "Describes a Property containing a reference to one of the units in the Unit Catalog." + }, + "urn_samm_io.catenax.single_level_bom_as_built_2.0.0_QuantityCharacteristic" : { + "description" : "Describes the quantity in which the child item is assembled in the given parent item by providing a quantity value and the measurement unit in which the quantity is measured.", + "type" : "object", + "properties" : { + "quantityNumber" : { + "description" : "The number of objects related to the measurement unit", + "$ref" : "#/components/schemas/urn_samm_io.catenax.single_level_bom_as_built_2.0.0_NumberOfObjects" + }, + "measurementUnit" : { + "description" : "Unit of Measurement for the quantity of serialized objects", + "$ref" : "#/components/schemas/urn_samm_org.eclipse.esmf.samm_characteristic_2.1.0_UnitReference" + } + }, + "required" : [ "quantityNumber", "measurementUnit" ] + }, + "urn_samm_io.catenax.single_level_bom_as_built_2.0.0_BpnTrait" : { + "type" : "string", + "description" : "Business Partner Number Regular Expression allowing only BPNL which stands for a legal entity.", + "pattern" : "^(BPNL)([0-9]{8})([a-zA-Z0-9]{4})$" + }, + "urn_samm_io.catenax.single_level_bom_as_built_2.0.0_HasAlternativesCharacteristic" : { + "type" : "boolean", + "description" : "Describes the value whether the child data has alternatives." + }, + "urn_samm_io.catenax.single_level_bom_as_built_2.0.0_ChildData" : { + "description" : "Catena-X ID and meta data of the assembled child item.", + "type" : "object", + "properties" : { + "createdOn" : { + "description" : "Timestamp when the relation between the parent item and the child item was created, e.g. when the serialized child part was assembled into the given part.", + "$ref" : "#/components/schemas/urn_samm_org.eclipse.esmf.samm_characteristic_2.1.0_Timestamp" + }, + "quantity" : { + "description" : "Quantity of which the child item is assembled into the parent item. In general it is '1' for serialized parts.", + "$ref" : "#/components/schemas/urn_samm_io.catenax.single_level_bom_as_built_2.0.0_QuantityCharacteristic" + }, + "lastModifiedOn" : { + "description" : "Timestamp when the assembly relationship between parent item and child item was last modified.", + "$ref" : "#/components/schemas/urn_samm_org.eclipse.esmf.samm_characteristic_2.1.0_Timestamp" + }, + "catenaXId" : { + "description" : "The Catena-X ID of the given part (e.g. the assembly), valid for the Catena-X dataspace.", + "$ref" : "#/components/schemas/urn_samm_io.catenax.single_level_bom_as_built_2.0.0_CatenaXIdTraitCharacteristic" + }, + "businessPartner" : { + "description" : "The supplier of the given child item.", + "$ref" : "#/components/schemas/urn_samm_io.catenax.single_level_bom_as_built_2.0.0_BpnTrait" + }, + "hasAlternatives" : { + "description" : "Expresses wether the part is built-in or wether it is one of several options. If the value is false, it can be assumend this exact item is built-in. If the value is true, it is unknown wether this or an alternative item is built-in.\nThis is the case when, e.g. the same item is supplied by two suppliers, the item is only tracked by a customer part ID during assembly. Thus, these items can not be differentiated from each other.\n\n", + "$ref" : "#/components/schemas/urn_samm_io.catenax.single_level_bom_as_built_2.0.0_HasAlternativesCharacteristic" + } + }, + "required" : [ "createdOn", "quantity", "catenaXId", "businessPartner", "hasAlternatives" ] + }, + "urn_samm_io.catenax.single_level_bom_as_built_2.0.0_SetOfChildItemsCharacteristic" : { + "description" : "Set of child items the parent item is assembled by (one structural level down).", + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/urn_samm_io.catenax.single_level_bom_as_built_2.0.0_ChildData" + }, + "uniqueItems" : true + } + } + }, + "properties" : { + "catenaXId" : { + "description" : "The Catena-X ID of the given part (e.g. the assembly), valid for the Catena-X dataspace.", + "$ref" : "#/components/schemas/urn_samm_io.catenax.single_level_bom_as_built_2.0.0_CatenaXIdTraitCharacteristic" + }, + "childItems" : { + "description" : "Set of child items, of which the given parent item is assembled by (one structural level down).", + "$ref" : "#/components/schemas/urn_samm_io.catenax.single_level_bom_as_built_2.0.0_SetOfChildItemsCharacteristic" + } + }, + "required" : [ "catenaXId", "childItems" ] +} \ No newline at end of file diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java index 43ef624320..44effe1593 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java @@ -29,16 +29,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.eclipse.tractusx.irs.edc.client.testutil.TestMother.createEdcTransformer; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.DATAPLANE_HOST; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_DATAPLANE_PUBLIC; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.nio.charset.StandardCharsets; import java.time.Clock; import java.time.Duration; import java.time.OffsetDateTime; import java.util.ArrayList; +import java.util.Base64; import java.util.List; +import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -49,9 +54,13 @@ import io.github.resilience4j.retry.RetryRegistry; import org.assertj.core.api.ThrowableAssert; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.irs.data.StringMapper; import org.eclipse.tractusx.irs.edc.client.cache.endpointdatareference.EndpointDataReferenceCacheService; +import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration; import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException; import org.eclipse.tractusx.irs.edc.client.exceptions.UsagePolicyException; +import org.eclipse.tractusx.irs.edc.client.model.EDRAuthCode; import org.eclipse.tractusx.irs.edc.client.policy.AcceptedPoliciesProvider; import org.eclipse.tractusx.irs.edc.client.policy.AcceptedPolicy; import org.eclipse.tractusx.irs.edc.client.policy.Constraint; @@ -61,6 +70,7 @@ import org.eclipse.tractusx.irs.edc.client.policy.Permission; import org.eclipse.tractusx.irs.edc.client.policy.PolicyCheckerService; import org.eclipse.tractusx.irs.edc.client.policy.PolicyType; +import org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.converter.HttpMessageConverter; @@ -71,10 +81,10 @@ @WireMockTest class SubmodelFacadeWiremockTest { private static final String PROXY_SERVER_HOST = "127.0.0.1"; - private final static String connectorEndpoint = "https://connector.endpoint.com"; - private final static String submodelDataplanePath = "/api/public/shells/12345/submodels/5678/submodel"; - private final static String submodelDataplaneUrl = "http://dataplane.test" + submodelDataplanePath; - private final static String assetId = "12345"; + private final static String CONNECTOR_ENDPOINT_URL = "https://connector.endpoint.com"; + private final static String SUBMODEL_DATAPLANE_PATH = "/api/public/shells/12345/submodels/5678/submodel"; + private final static String SUBMODEL_DATAPLANE_URL = "http://dataplane.test" + SUBMODEL_DATAPLANE_PATH; + private final static String ASSET_ID = "12345"; private final EdcConfiguration config = new EdcConfiguration(); private final EndpointDataReferenceStorage storage = new EndpointDataReferenceStorage(Duration.ofMinutes(1)); private EdcSubmodelClient edcSubmodelClient; @@ -133,13 +143,13 @@ void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { void shouldReturnAssemblyPartRelationshipAsString() throws EdcClientException, ExecutionException, InterruptedException { // Arrange - SubmodelFacadeWiremockConfig.prepareNegotiation(storage); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn( + prepareNegotiation(); + givenThat(get(urlPathEqualTo(SUBMODEL_DATAPLANE_PATH)).willReturn( responseWithStatus(200).withBodyFile("singleLevelBomAsBuilt.json"))); // Act - final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, - assetId).get(); + final String submodel = edcSubmodelClient.getSubmodelRawPayload(CONNECTOR_ENDPOINT_URL, SUBMODEL_DATAPLANE_URL, + ASSET_ID).get(); // Assert assertThat(submodel).contains("\"catenaXId\": \"urn:uuid:fe99da3d-b0de-4e80-81da-882aebcca978\""); @@ -149,13 +159,13 @@ void shouldReturnAssemblyPartRelationshipAsString() void shouldReturnMaterialForRecyclingAsString() throws EdcClientException, ExecutionException, InterruptedException { // Arrange - SubmodelFacadeWiremockConfig.prepareNegotiation(storage); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn( + prepareNegotiation(); + givenThat(get(urlPathEqualTo(SUBMODEL_DATAPLANE_PATH)).willReturn( responseWithStatus(200).withBodyFile("materialForRecycling.json"))); // Act - final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, - assetId).get(); + final String submodel = edcSubmodelClient.getSubmodelRawPayload(CONNECTOR_ENDPOINT_URL, SUBMODEL_DATAPLANE_URL, + ASSET_ID).get(); // Assert assertThat(submodel).contains("\"materialName\": \"Cooper\","); @@ -165,12 +175,12 @@ void shouldReturnMaterialForRecyclingAsString() void shouldReturnObjectAsStringWhenResponseNotJSON() throws EdcClientException, ExecutionException, InterruptedException { // Arrange - SubmodelFacadeWiremockConfig.prepareNegotiation(storage); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(responseWithStatus(200).withBody("test"))); + prepareNegotiation(); + givenThat(get(urlPathEqualTo(SUBMODEL_DATAPLANE_PATH)).willReturn(responseWithStatus(200).withBody("test"))); // Act - final String submodel = edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, - assetId).get(); + final String submodel = edcSubmodelClient.getSubmodelRawPayload(CONNECTOR_ENDPOINT_URL, SUBMODEL_DATAPLANE_URL, + ASSET_ID).get(); // Assert assertThat(submodel).isEqualTo("test"); @@ -189,26 +199,26 @@ void shouldThrowExceptionWhenPoliciesAreNotAccepted() { when(acceptedPoliciesProvider.getAcceptedPolicies()).thenReturn(List.of(acceptedPolicy)); - SubmodelFacadeWiremockConfig.prepareNegotiation(storage); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn(responseWithStatus(200).withBody("test"))); + prepareNegotiation(); + givenThat(get(urlPathEqualTo(SUBMODEL_DATAPLANE_PATH)).willReturn(responseWithStatus(200).withBody("test"))); // Act & Assert final String errorMessage = "Consumption of asset '58505404-4da1-427a-82aa-b79482bcd1f0' is not permitted as the required catalog offer policies do not comply with defined IRS policies."; assertThatExceptionOfType(UsagePolicyException.class).isThrownBy( - () -> edcSubmodelClient.getSubmodelRawPayload(connectorEndpoint, submodelDataplaneUrl, assetId).get()) - .withMessageEndingWith(errorMessage); + () -> edcSubmodelClient.getSubmodelRawPayload(CONNECTOR_ENDPOINT_URL, SUBMODEL_DATAPLANE_URL, ASSET_ID) + .get()).withMessageEndingWith(errorMessage); } @Test void shouldThrowExceptionWhenResponse_400() { // Arrange - SubmodelFacadeWiremockConfig.prepareNegotiation(storage); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn( + prepareNegotiation(); + givenThat(get(urlPathEqualTo(SUBMODEL_DATAPLANE_PATH)).willReturn( responseWithStatus(400).withBody("{ error: '400'}"))); // Act final ThrowableAssert.ThrowingCallable throwingCallable = () -> edcSubmodelClient.getSubmodelRawPayload( - connectorEndpoint, submodelDataplaneUrl, assetId).get(5, TimeUnit.SECONDS); + CONNECTOR_ENDPOINT_URL, SUBMODEL_DATAPLANE_URL, ASSET_ID).get(5, TimeUnit.SECONDS); // Assert assertThatExceptionOfType(ExecutionException.class).isThrownBy(throwingCallable) @@ -218,19 +228,44 @@ void shouldThrowExceptionWhenResponse_400() { @Test void shouldThrowExceptionWhenResponse_500() { // Arrange - SubmodelFacadeWiremockConfig.prepareNegotiation(storage); - givenThat(get(urlPathEqualTo(submodelDataplanePath)).willReturn( + prepareNegotiation(); + givenThat(get(urlPathEqualTo(SUBMODEL_DATAPLANE_PATH)).willReturn( responseWithStatus(500).withBody("{ error: '500'}"))); // Act final ThrowableAssert.ThrowingCallable throwingCallable = () -> edcSubmodelClient.getSubmodelRawPayload( - connectorEndpoint, submodelDataplaneUrl, assetId).get(5, TimeUnit.SECONDS); + CONNECTOR_ENDPOINT_URL, SUBMODEL_DATAPLANE_URL, ASSET_ID).get(5, TimeUnit.SECONDS); // Assert assertThatExceptionOfType(ExecutionException.class).isThrownBy(throwingCallable) .withCauseInstanceOf(RestClientException.class); } + private void prepareNegotiation() { + final String contractAgreementId = SubmodelFacadeWiremockConfig.prepareNegotiation(); + final EndpointDataReference ref = createEndpointDataReference(contractAgreementId); + storage.put(contractAgreementId, ref); + } + + public static EndpointDataReference createEndpointDataReference(final String contractAgreementId) { + final EDRAuthCode edrAuthCode = EDRAuthCode.builder() + .cid(contractAgreementId) + .dad("test") + .exp(9999999999L) + .build(); + final String b64EncodedAuthCode = Base64.getUrlEncoder() + .encodeToString(StringMapper.mapToString(edrAuthCode) + .getBytes(StandardCharsets.UTF_8)); + final String jwtToken = "eyJhbGciOiJSUzI1NiJ9." + b64EncodedAuthCode + ".test"; + return EndpointDataReference.Builder.newInstance() + .authKey("testkey") + .authCode(jwtToken) + .properties( + Map.of(JsonLdConfiguration.NAMESPACE_EDC_CID, contractAgreementId)) + .endpoint(DATAPLANE_HOST + PATH_DATAPLANE_PUBLIC) + .build(); + } + private org.eclipse.tractusx.irs.edc.client.policy.Policy policy(String policyId, List permissions) { return new org.eclipse.tractusx.irs.edc.client.policy.Policy(policyId, OffsetDateTime.now(), OffsetDateTime.now().plusYears(1), permissions); diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java index 6130c1501d..db505bf240 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java @@ -20,24 +20,33 @@ import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.*; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import java.util.List; import com.github.tomakehurst.wiremock.client.MappingBuilder; -public class DiscoveryServiceWiremockConfig { - public static final String CONTROLPLANE_PUBLIC_URL = "https://controlplane.test"; +/** + * WireMock configurations and requests used for testing the Discovery Service flow. + */ +public final class DiscoveryServiceWiremockConfig { + public static final String CONTROLPLANE_PUBLIC_URL = "https://test.edc.io"; public static final String EDC_DISCOVERY_PATH = "/edcDiscovery"; public static final String TEST_BPN = "BPNL00000000TEST"; public static final String DISCOVERY_FINDER_PATH = "/discoveryFinder"; public static final String DISCOVERY_HOST = "http://discovery.finder"; public static final String EDC_DISCOVERY_URL = DISCOVERY_HOST + EDC_DISCOVERY_PATH; - public static final String DISCOVERY_FINDER_URL = DISCOVERY_HOST + DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_PATH; + public static final String DISCOVERY_FINDER_URL = DISCOVERY_HOST + DISCOVERY_FINDER_PATH; + private DiscoveryServiceWiremockConfig() { + } public static MappingBuilder postEdcDiscovery200() { + return postEdcDiscovery200(TEST_BPN, List.of(CONTROLPLANE_PUBLIC_URL)); + } + + public static MappingBuilder postEdcDiscovery200(final String bpn, final List edcUrls) { return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn( - responseWithStatus(200).withBody(edcDiscoveryResponse(TEST_BPN, List.of(CONTROLPLANE_PUBLIC_URL)))); + responseWithStatus(200).withBody(edcDiscoveryResponse(bpn, edcUrls))); } public static String edcDiscoveryResponse(final String bpn, final List connectorEndpoints) { @@ -74,15 +83,6 @@ public static String discoveryFinderResponse(final String discoveryFinderUrl) { """.formatted(discoveryFinderUrl); } - public static String discoveryFinderEmtpyResponse() { - return """ - { - "endpoints": [ - ] - } - """; - } - public static MappingBuilder postDiscoveryFinder404() { return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn(responseWithStatus(404)); } diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java index 4f29f1fbd1..a4f743d578 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java @@ -27,18 +27,28 @@ import com.github.tomakehurst.wiremock.client.MappingBuilder; -public class DtrWiremockConfig { +/** + * WireMock configurations and requests used for testing the decentralized DigitalTwinRegistry flow. + */ +public final class DtrWiremockConfig { public static final String DATAPLANE_URL = "http://dataplane.test"; - public static final String DATAPLANE_PUBLIC_URL = DATAPLANE_URL + "/api/public/data/"; + public static final String DATAPLANE_PUBLIC_PATH = "/api/public"; + public static final String DATAPLANE_PUBLIC_URL = DATAPLANE_URL + DATAPLANE_PUBLIC_PATH; public static final String SHELL_DESCRIPTORS_PATH = "/shell-descriptors/"; + public static final String PUBLIC_SHELL_DESCRIPTORS_PATH = DATAPLANE_PUBLIC_PATH + SHELL_DESCRIPTORS_PATH; public static final String SHELL_DESCRIPTORS_TEMPLATE = SHELL_DESCRIPTORS_PATH + "{aasIdentifier}"; public static final String LOOKUP_SHELLS_PATH = "/lookup/shells"; + public static final String PUBLIC_LOOKUP_SHELLS_PATH = DATAPLANE_PUBLIC_PATH + LOOKUP_SHELLS_PATH; public static final String LOOKUP_SHELLS_TEMPLATE = LOOKUP_SHELLS_PATH + "?assetIds={assetIds}"; private DtrWiremockConfig() { } public static MappingBuilder getShellDescriptor200() { + return getShellDescriptor200(SHELL_DESCRIPTORS_PATH + ".*"); + } + + public static MappingBuilder getShellDescriptor200(final String urlRegex) { final String materialForRecycling = submodelDescriptor(DATAPLANE_PUBLIC_URL, "urn:uuid:19b0338f-6d03-4198-b3b8-5c43f8958d60", DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, "MaterialForRecycling", "urn:uuid:cf06d5d5-e3f8-4bd4-bfcf-81815310701f", @@ -48,15 +58,15 @@ public static MappingBuilder getShellDescriptor200() { DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, "Batch", "urn:uuid:f53db6ef-7a58-4326-9169-0ae198b85dbf", "urn:samm:io.catenax.batch:2.0.0#Batch"); - final String singleLevelUsageAsBuilt = submodelDescriptor(DATAPLANE_PUBLIC_URL, - "urn:uuid:f8196d6a-1664-4531-bdee-f15dbb1daf26", DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, - "SingleLevelUsageAsBuilt", "urn:uuid:e2899f43-eca8-4aec-b877-4a69691f0487", - "urn:bamm:io.catenax.single_level_usage_as_built:2.0.0#SingleLevelUsageAsBuilt"); + final String singleLevelBomAsBuilt = submodelDescriptor(DATAPLANE_PUBLIC_URL, + "urn:uuid:234edd2f-0223-47c7-9fe4-3984ab14c4f9", DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, + "SingleLevelBomAsBuilt", "urn:uuid:0e413809-966b-4107-aae5-aeb28bcdaadf", + "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt"); - final List submodelDescriptors = List.of(materialForRecycling, batch, singleLevelUsageAsBuilt); + final List submodelDescriptors = List.of(batch, singleLevelBomAsBuilt, materialForRecycling); final List specificAssetIds = List.of(specificAssetId("manufacturerId", "BPNL00000003B0Q0"), specificAssetId("batchId", "BID12345678")); - return get(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*")).willReturn(responseWithStatus(200).withBody( + return get(urlPathMatching(urlRegex)).willReturn(responseWithStatus(200).withBody( assetAdministrationShellResponse(submodelDescriptors, "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5", "EngineeringPlastics", "urn:uuid:9ce43b21-75e3-4cea-b13e-9a34f4f6822a", specificAssetIds))); } @@ -103,7 +113,7 @@ public static String specificAssetId(final String key, final String value) { public static String submodelDescriptor(final String dataplaneUrl, final String assetId, final String dspEndpoint, final String idShort, final String submodelDescriptorId, final String semanticId) { - final String href = dataplaneUrl + submodelDescriptorId; + final String href = dataplaneUrl + "/" + submodelDescriptorId; return """ { "endpoints": [ @@ -147,7 +157,11 @@ public static String submodelDescriptor(final String dataplaneUrl, final String } public static MappingBuilder getLookupShells200() { - return get(urlPathEqualTo(LOOKUP_SHELLS_PATH)).willReturn(responseWithStatus(200).withBody( + return getLookupShells200(LOOKUP_SHELLS_PATH); + } + + public static MappingBuilder getLookupShells200(final String lookupShellsPath) { + return get(urlPathEqualTo(lookupShellsPath)).willReturn(responseWithStatus(200).withBody( lookupShellsResponse(List.of("urn:uuid:21f7ebea-fa8a-410c-a656-bd9082e67dcf")))); } diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java similarity index 67% rename from irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockConfig.java rename to irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java index 762ddeaef1..6c3453b6f5 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java @@ -16,27 +16,19 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.irs.edc.client; +package org.eclipse.tractusx.irs.testing.wiremock; import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; -import java.nio.charset.StandardCharsets; -import java.util.Base64; import java.util.List; -import java.util.Map; - -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.irs.data.StringMapper; -import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration; -import org.eclipse.tractusx.irs.edc.client.model.EDRAuthCode; -import org.jetbrains.annotations.NotNull; - -public class SubmodelFacadeWiremockConfig { +/** + * WireMock configurations and requests used for testing the EDC Flow. + */ +public final class SubmodelFacadeWiremockConfig { public static final String PATH_CATALOG = "/catalog/request"; public static final String PATH_NEGOTIATE = "/contractnegotiations"; public static final String PATH_TRANSFER = "/transferprocesses"; @@ -54,46 +46,50 @@ public class SubmodelFacadeWiremockConfig { }"""; public static final String EDC_PROVIDER_DUMMY_URL = "https://edc.io/api/v1/dsp"; public static final String IRS_INTERNAL_CALLBACK_URL = "https://irs.test/internal/endpoint-data-reference"; + public static final String EDC_PROVIDER_BPN = "BPNL00000003CRHK"; - // TODO move to irs-testing + private SubmodelFacadeWiremockConfig() { + } - public static void prepareNegotiation(final EndpointDataReferenceStorage storage) { - prepareNegotiation(storage, "1bbaec6e-c316-4e1e-8258-c07a648cc43c", "1b21e963-0bc5-422a-b30d-fd3511861d88", + public static String prepareNegotiation() { + return prepareNegotiation("1bbaec6e-c316-4e1e-8258-c07a648cc43c", "1b21e963-0bc5-422a-b30d-fd3511861d88", "7681f966-36ea-4542-b5ea-0d0db81967de:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7:a6144a2e-c1b1-4ec6-96e1-a221da134e4f", "5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7"); } - public static void prepareNegotiation(final EndpointDataReferenceStorage storage, final String negotiationId, - final String transferProcessId, final String contractAgreementId, final String edcAssetId) { - givenThat(post(urlPathEqualTo(PATH_CATALOG)).willReturn( - responseWithStatus(200).withBody(getCatalogResponse(edcAssetId, "USE", "BPNL00000003CRHK")))); - System.out.println(getCatalogResponse(edcAssetId, "USE", "BPNL00000003CRHK")); - givenThat(post(urlPathEqualTo(PATH_NEGOTIATE)).willReturn( - responseWithStatus(200).withBody(startNegotiationResponse(negotiationId)))); + public static String prepareNegotiation(final String negotiationId, final String transferProcessId, + final String contractAgreementId, final String edcAssetId) { + stubFor(post(urlPathEqualTo(PATH_CATALOG)).willReturn(WireMockConfig.responseWithStatus(200) + .withBody(getCatalogResponse(edcAssetId, + "USE", EDC_PROVIDER_BPN)))); + + stubFor(post(urlPathEqualTo(PATH_NEGOTIATE)).willReturn( + WireMockConfig.responseWithStatus(200).withBody(startNegotiationResponse(negotiationId)))); final String negotiationState = "FINALIZED"; - givenThat(get(urlPathEqualTo(PATH_NEGOTIATE + "/" + negotiationId)).willReturn(responseWithStatus(200).withBody( - getNegotiationConfirmedResponse(negotiationId, negotiationState, contractAgreementId)))); + stubFor(get(urlPathEqualTo(PATH_NEGOTIATE + "/" + negotiationId)).willReturn( + WireMockConfig.responseWithStatus(200) + .withBody(getNegotiationConfirmedResponse(negotiationId, negotiationState, + contractAgreementId)))); - givenThat(get(urlPathEqualTo(PATH_NEGOTIATE + "/" + negotiationId + PATH_STATE)).willReturn( - responseWithStatus(200).withBody(getNegotiationStateResponse(negotiationState)))); + stubFor(get(urlPathEqualTo(PATH_NEGOTIATE + "/" + negotiationId + PATH_STATE)).willReturn( + WireMockConfig.responseWithStatus(200).withBody(getNegotiationStateResponse(negotiationState)))); - givenThat(post(urlPathEqualTo(PATH_TRANSFER)).willReturn( - responseWithStatus(200).withBody(startTransferProcessResponse(transferProcessId)) + stubFor(post(urlPathEqualTo(PATH_TRANSFER)).willReturn( + WireMockConfig.responseWithStatus(200).withBody(startTransferProcessResponse(transferProcessId)) )); final String transferProcessState = "COMPLETED"; - givenThat(get(urlPathEqualTo(PATH_TRANSFER + "/" + transferProcessId + PATH_STATE)).willReturn( - responseWithStatus(200).withBody(getTransferProcessStateResponse(transferProcessState)) + stubFor(get(urlPathEqualTo(PATH_TRANSFER + "/" + transferProcessId + PATH_STATE)).willReturn( + WireMockConfig.responseWithStatus(200).withBody(getTransferProcessStateResponse(transferProcessState)) )); - givenThat(get(urlPathEqualTo(PATH_TRANSFER + "/" + transferProcessId)).willReturn( - responseWithStatus(200).withBody( - getTransferConfirmedResponse(transferProcessId, transferProcessState, edcAssetId, - contractAgreementId)))); - - final EndpointDataReference ref = createEndpointDataReference(contractAgreementId); - storage.put(contractAgreementId, ref); + stubFor(get(urlPathEqualTo(PATH_TRANSFER + "/" + transferProcessId)).willReturn( + WireMockConfig.responseWithStatus(200) + .withBody( + getTransferConfirmedResponse(transferProcessId, transferProcessState, edcAssetId, + contractAgreementId)))); + return contractAgreementId; } private static String startTransferProcessResponse(final String transferProcessId) { @@ -164,16 +160,16 @@ private static String getTransferConfirmedResponse(final String transferProcessI "@id": "%s", "edc:assetId": "%s", "edc:contractId": "%s", - "edc:connectorId": "BPNL00000003CRHK" + "edc:connectorId": "%s" }, "edc:receiverHttpEndpoint": "%s", "@context": %s } """.formatted(transferProcessId, transferState, transferProcessId, edcAssetId, contractAgreementId, - IRS_INTERNAL_CALLBACK_URL, CONTEXT); + EDC_PROVIDER_BPN, IRS_INTERNAL_CALLBACK_URL, CONTEXT); } - private static String getCatalogResponse(final String edcAssetId, final String permissionType, + public static String getCatalogResponse(final String edcAssetId, final String permissionType, final String edcProviderBpn) { return """ { @@ -221,7 +217,6 @@ private static String getCatalogResponse(final String edcAssetId, final String p EDC_PROVIDER_DUMMY_URL, edcProviderBpn, CONTEXT); } - @NotNull private static String createConstraints() { final List atomitConstraints = List.of(createAtomicConstraint("Membership", "active"), createAtomicConstraint("FrameworkAgreement.traceability", "active")); @@ -244,22 +239,4 @@ private static String createAtomicConstraint(final String leftOperand, final Str }""".formatted(leftOperand, rightOperand); } - public static EndpointDataReference createEndpointDataReference(final String contractAgreementId) { - final EDRAuthCode edrAuthCode = EDRAuthCode.builder() - .cid(contractAgreementId) - .dad("test") - .exp(9999999999L) - .build(); - final String b64EncodedAuthCode = Base64.getUrlEncoder() - .encodeToString(StringMapper.mapToString(edrAuthCode) - .getBytes(StandardCharsets.UTF_8)); - final String jwtToken = "eyJhbGciOiJSUzI1NiJ9." + b64EncodedAuthCode + ".test"; - return EndpointDataReference.Builder.newInstance() - .authKey("testkey") - .authCode(jwtToken) - .properties( - Map.of(JsonLdConfiguration.NAMESPACE_EDC_CID, contractAgreementId)) - .endpoint(DATAPLANE_HOST + PATH_DATAPLANE_PUBLIC) - .build(); - } } \ No newline at end of file From a262bab710042e99648829b8ab503ba96a0694a9 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Mon, 29 Jan 2024 09:57:18 +0100 Subject: [PATCH 10/22] feat(irs-testing):[#344] Fix code smells --- .../DiscoveryServiceWiremockConfig.java | 11 +++++--- .../testing/wiremock/DtrWiremockConfig.java | 16 +++++++----- .../SubmodelFacadeWiremockConfig.java | 26 ++++++++++--------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java index db505bf240..6377a0d3d2 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java @@ -37,6 +37,9 @@ public final class DiscoveryServiceWiremockConfig { public static final String DISCOVERY_HOST = "http://discovery.finder"; public static final String EDC_DISCOVERY_URL = DISCOVERY_HOST + EDC_DISCOVERY_PATH; public static final String DISCOVERY_FINDER_URL = DISCOVERY_HOST + DISCOVERY_FINDER_PATH; + public static final int STATUS_CODE_OK = 200; + public static final int STATUS_CODE_NOT_FOUND = 404; + private DiscoveryServiceWiremockConfig() { } @@ -46,7 +49,7 @@ public static MappingBuilder postEdcDiscovery200() { public static MappingBuilder postEdcDiscovery200(final String bpn, final List edcUrls) { return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn( - responseWithStatus(200).withBody(edcDiscoveryResponse(bpn, edcUrls))); + responseWithStatus(STATUS_CODE_OK).withBody(edcDiscoveryResponse(bpn, edcUrls))); } public static String edcDiscoveryResponse(final String bpn, final List connectorEndpoints) { @@ -64,7 +67,7 @@ public static String edcDiscoveryResponse(final String bpn, final List c public static MappingBuilder postDiscoveryFinder200() { return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn( - responseWithStatus(200).withBody(discoveryFinderResponse(EDC_DISCOVERY_URL))); + responseWithStatus(STATUS_CODE_OK).withBody(discoveryFinderResponse(EDC_DISCOVERY_URL))); } public static String discoveryFinderResponse(final String discoveryFinderUrl) { @@ -84,10 +87,10 @@ public static String discoveryFinderResponse(final String discoveryFinderUrl) { } public static MappingBuilder postDiscoveryFinder404() { - return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn(responseWithStatus(404)); + return post(urlPathEqualTo(DISCOVERY_FINDER_PATH)).willReturn(responseWithStatus(STATUS_CODE_NOT_FOUND)); } public static MappingBuilder postEdcDiscovery404() { - return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn(responseWithStatus(404)); + return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn(responseWithStatus(STATUS_CODE_NOT_FOUND)); } } diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java index a4f743d578..692c4dd798 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java @@ -40,6 +40,8 @@ public final class DtrWiremockConfig { public static final String LOOKUP_SHELLS_PATH = "/lookup/shells"; public static final String PUBLIC_LOOKUP_SHELLS_PATH = DATAPLANE_PUBLIC_PATH + LOOKUP_SHELLS_PATH; public static final String LOOKUP_SHELLS_TEMPLATE = LOOKUP_SHELLS_PATH + "?assetIds={assetIds}"; + public static final int STATUS_CODE_OK = 200; + public static final int STATUS_CODE_NOT_FOUND = 404; private DtrWiremockConfig() { } @@ -66,7 +68,7 @@ public static MappingBuilder getShellDescriptor200(final String urlRegex) { final List submodelDescriptors = List.of(batch, singleLevelBomAsBuilt, materialForRecycling); final List specificAssetIds = List.of(specificAssetId("manufacturerId", "BPNL00000003B0Q0"), specificAssetId("batchId", "BID12345678")); - return get(urlPathMatching(urlRegex)).willReturn(responseWithStatus(200).withBody( + return get(urlPathMatching(urlRegex)).willReturn(responseWithStatus(STATUS_CODE_OK).withBody( assetAdministrationShellResponse(submodelDescriptors, "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5", "EngineeringPlastics", "urn:uuid:9ce43b21-75e3-4cea-b13e-9a34f4f6822a", specificAssetIds))); } @@ -111,6 +113,7 @@ public static String specificAssetId(final String key, final String value) { """.formatted(key, value); } + @SuppressWarnings("PMD.UseObjectForClearerAPI") // used only for testing public static String submodelDescriptor(final String dataplaneUrl, final String assetId, final String dspEndpoint, final String idShort, final String submodelDescriptorId, final String semanticId) { final String href = dataplaneUrl + "/" + submodelDescriptorId; @@ -161,13 +164,13 @@ public static MappingBuilder getLookupShells200() { } public static MappingBuilder getLookupShells200(final String lookupShellsPath) { - return get(urlPathEqualTo(lookupShellsPath)).willReturn(responseWithStatus(200).withBody( + return get(urlPathEqualTo(lookupShellsPath)).willReturn(responseWithStatus(STATUS_CODE_OK).withBody( lookupShellsResponse(List.of("urn:uuid:21f7ebea-fa8a-410c-a656-bd9082e67dcf")))); } public static MappingBuilder getLookupShells200Empty() { return get(urlPathMatching(LOOKUP_SHELLS_PATH + ".*")).willReturn( - responseWithStatus(200).withBody(lookupShellsResponse(List.of()))); + responseWithStatus(STATUS_CODE_OK).withBody(lookupShellsResponse(List.of()))); } public static String lookupShellsResponse(final List shellIds) { @@ -182,10 +185,11 @@ public static String lookupShellsResponse(final List shellIds) { } public static MappingBuilder getLookupShells404() { - return get(urlPathEqualTo(LOOKUP_SHELLS_PATH)).willReturn(responseWithStatus(404)); + return get(urlPathEqualTo(LOOKUP_SHELLS_PATH)).willReturn(responseWithStatus(STATUS_CODE_NOT_FOUND)); } public static MappingBuilder getShellDescriptor404() { - return get(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*")).willReturn(responseWithStatus(404)); + return get(urlPathMatching(SHELL_DESCRIPTORS_PATH + ".*")).willReturn( + responseWithStatus(STATUS_CODE_NOT_FOUND)); } -} \ No newline at end of file +} diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java index 6c3453b6f5..9ef6e5862d 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java @@ -47,6 +47,7 @@ public final class SubmodelFacadeWiremockConfig { public static final String EDC_PROVIDER_DUMMY_URL = "https://edc.io/api/v1/dsp"; public static final String IRS_INTERNAL_CALLBACK_URL = "https://irs.test/internal/endpoint-data-reference"; public static final String EDC_PROVIDER_BPN = "BPNL00000003CRHK"; + public static final int STATUS_CODE_OK = 200; private SubmodelFacadeWiremockConfig() { } @@ -57,35 +58,37 @@ public static String prepareNegotiation() { "5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7"); } + @SuppressWarnings("PMD.UseObjectForClearerAPI") // used only for testing public static String prepareNegotiation(final String negotiationId, final String transferProcessId, final String contractAgreementId, final String edcAssetId) { - stubFor(post(urlPathEqualTo(PATH_CATALOG)).willReturn(WireMockConfig.responseWithStatus(200) + stubFor(post(urlPathEqualTo(PATH_CATALOG)).willReturn(WireMockConfig.responseWithStatus(STATUS_CODE_OK) .withBody(getCatalogResponse(edcAssetId, "USE", EDC_PROVIDER_BPN)))); stubFor(post(urlPathEqualTo(PATH_NEGOTIATE)).willReturn( - WireMockConfig.responseWithStatus(200).withBody(startNegotiationResponse(negotiationId)))); + WireMockConfig.responseWithStatus(STATUS_CODE_OK).withBody(startNegotiationResponse(negotiationId)))); final String negotiationState = "FINALIZED"; stubFor(get(urlPathEqualTo(PATH_NEGOTIATE + "/" + negotiationId)).willReturn( - WireMockConfig.responseWithStatus(200) + WireMockConfig.responseWithStatus(STATUS_CODE_OK) .withBody(getNegotiationConfirmedResponse(negotiationId, negotiationState, contractAgreementId)))); stubFor(get(urlPathEqualTo(PATH_NEGOTIATE + "/" + negotiationId + PATH_STATE)).willReturn( - WireMockConfig.responseWithStatus(200).withBody(getNegotiationStateResponse(negotiationState)))); + WireMockConfig.responseWithStatus(STATUS_CODE_OK) + .withBody(getNegotiationStateResponse(negotiationState)))); - stubFor(post(urlPathEqualTo(PATH_TRANSFER)).willReturn( - WireMockConfig.responseWithStatus(200).withBody(startTransferProcessResponse(transferProcessId)) + stubFor(post(urlPathEqualTo(PATH_TRANSFER)).willReturn(WireMockConfig.responseWithStatus(STATUS_CODE_OK) + .withBody(startTransferProcessResponse( + transferProcessId)) )); final String transferProcessState = "COMPLETED"; stubFor(get(urlPathEqualTo(PATH_TRANSFER + "/" + transferProcessId + PATH_STATE)).willReturn( - WireMockConfig.responseWithStatus(200).withBody(getTransferProcessStateResponse(transferProcessState)) - - )); + WireMockConfig.responseWithStatus(STATUS_CODE_OK) + .withBody(getTransferProcessStateResponse(transferProcessState)))); stubFor(get(urlPathEqualTo(PATH_TRANSFER + "/" + transferProcessId)).willReturn( - WireMockConfig.responseWithStatus(200) + WireMockConfig.responseWithStatus(STATUS_CODE_OK) .withBody( getTransferConfirmedResponse(transferProcessId, transferProcessState, edcAssetId, contractAgreementId)))); @@ -238,5 +241,4 @@ private static String createAtomicConstraint(final String leftOperand, final Str "odrl:rightOperand": "%s" }""".formatted(leftOperand, rightOperand); } - -} \ No newline at end of file +} From b557774f7254a6532fb133a1aacbe14aa0c70551 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Mon, 29 Jan 2024 15:27:14 +0100 Subject: [PATCH 11/22] feat(irs-api):[#344] Fix test execution and added test cases --- ...T.java => IrsWireMockIntegrationTest.java} | 125 ++++++++++++++---- .../DiscoveryServiceWiremockConfig.java | 4 + 2 files changed, 100 insertions(+), 29 deletions(-) rename irs-api/src/test/java/org/eclipse/tractusx/irs/{IrsWireMockIT.java => IrsWireMockIntegrationTest.java} (79%) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java similarity index 79% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java rename to irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java index 7de5396ebe..709da794ef 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIT.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java @@ -26,7 +26,6 @@ import static com.github.tomakehurst.wiremock.client.WireMock.containing; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; @@ -42,7 +41,9 @@ import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.EDC_DISCOVERY_PATH; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.TEST_BPN; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder404; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscovery200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscoveryEmpty200; import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.DATAPLANE_PUBLIC_PATH; import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.LOOKUP_SHELLS_TEMPLATE; import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.PUBLIC_LOOKUP_SHELLS_PATH; @@ -86,6 +87,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.DynamicPropertyRegistry; @@ -96,9 +98,10 @@ @WireMockTest(httpPort = 8085) @Testcontainers @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WireMockTestConfig.class) -@ContextConfiguration(initializers = IrsWireMockIT.MinioConfigInitializer.class) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +@ContextConfiguration(initializers = IrsWireMockIntegrationTest.MinioConfigInitializer.class) @ActiveProfiles("integrationtest") -class IrsWireMockIT { +class IrsWireMockIntegrationTest { public static final String SEMANTIC_HUB_URL = "http://semantic.hub/models"; public static final String EDC_URL = "http://edc.test"; private static final String ACCESS_KEY = "accessKey"; @@ -116,8 +119,7 @@ class IrsWireMockIT { @BeforeAll static void startContainer() { minioContainer.start(); - givenThat(get(urlPathEqualTo("/models")).willReturn( - responseWithStatus(200).withBodyFile("semantichub/all-models-page-IT.json"))); + successfulSemanticModelRequest(); } @AfterAll @@ -134,6 +136,7 @@ static void configureProperties(DynamicPropertyRegistry registry) { registry.add("digitalTwinRegistry.type", () -> "decentral"); registry.add("semanticshub.url", () -> SEMANTIC_HUB_URL); registry.add("semanticshub.modelJsonSchemaEndpoint", () -> SemanticHubWireMockConfig.SEMANTIC_HUB_SCHEMA_URL); + registry.add("semanticshub.defaultUrns", () -> ""); registry.add("irs-edc-client.controlplane.endpoint.data", () -> EDC_URL); registry.add("irs-edc-client.controlplane.endpoint.catalog", () -> PATH_CATALOG); registry.add("irs-edc-client.controlplane.endpoint.contract-negotiation", () -> PATH_NEGOTIATE); @@ -146,6 +149,9 @@ static void configureProperties(DynamicPropertyRegistry registry) { @Test void shouldStartApplicationAndCollectSemanticModels() throws SchemaNotFoundException { + // Arrange + successfulSemanticModelRequest(); + // Act final AspectModels allAspectModels = semanticHubService.getAllAspectModels(); @@ -156,40 +162,25 @@ void shouldStartApplicationAndCollectSemanticModels() throws SchemaNotFoundExcep @Test void shouldStartJob() { // Arrange - final String startId = "globalAssetId"; + final String globalAssetId = "globalAssetId"; + successfulSemanticModelRequest(); successfulSemanticHubRequests(); successfulDiscovery(); successfulRegistryNegotiation(); - successfulDtrRequest(startId); + successfulDtrRequest(globalAssetId); successfulAssetNegotiation(); successfulDataRequests(); successfulBpdmRequests(); - final RegisterJob request = RegisterJob.builder() - .key(PartChainIdentificationKey.builder() - .bpn(TEST_BPN) - .globalAssetId(startId) - .build()) - .depth(1) - .aspects(List.of("Batch", "SingleLevelBomAsBuilt")) - .collectAspects(true) - .lookupBPNs(true) - .direction(Direction.DOWNWARD) - .build(); + final RegisterJob request = jobRequest(globalAssetId, TEST_BPN); // Act final JobHandle jobHandle = irsService.registerItemJob(request); assertThat(jobHandle.getId()).isNotNull(); - Awaitility.await() - .timeout(Duration.ofSeconds(35)) - .pollInterval(Duration.ofSeconds(1)) - .until(() -> irsService.getJobForJobId(jobHandle.getId(), false) - .getJob() - .getState() - .equals(JobState.COMPLETED)); + waitForCompletion(jobHandle); Jobs jobForJobId = irsService.getJobForJobId(jobHandle.getId(), true); @@ -203,6 +194,82 @@ void shouldStartJob() { assertThat(jobForJobId.getTombstones()).isEmpty(); } + @Test + void shouldCreateTombstoneWhenDiscoveryServiceNotAvailable() { + // Arrange + successfulSemanticModelRequest(); + stubFor(postDiscoveryFinder404()); + final String globalAssetId = "globalAssetId"; + final RegisterJob request = jobRequest(globalAssetId, TEST_BPN); + + // Act + final JobHandle jobHandle = irsService.registerItemJob(request); + + // Assert + assertThat(jobHandle.getId()).isNotNull(); + waitForCompletion(jobHandle); + final Jobs jobForJobId = irsService.getJobForJobId(jobHandle.getId(), true); + + verify(1, postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + verify(0, postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + + assertThat(jobForJobId.getJob().getState()).isEqualTo(JobState.COMPLETED); + assertThat(jobForJobId.getShells()).isEmpty(); + assertThat(jobForJobId.getRelationships()).isEmpty(); + assertThat(jobForJobId.getTombstones()).hasSize(1); + } + + @Test + void shouldCreateTombstoneWhenEdcDiscoveryIsEmpty() { + // Arrange + successfulSemanticModelRequest(); + stubFor(postDiscoveryFinder200()); + stubFor(postEdcDiscoveryEmpty200()); + final String globalAssetId = "globalAssetId"; + final RegisterJob request = jobRequest(globalAssetId, TEST_BPN); + // Act + final JobHandle jobHandle = irsService.registerItemJob(request); + + // Assert + assertThat(jobHandle.getId()).isNotNull(); + waitForCompletion(jobHandle); + final Jobs jobForJobId = irsService.getJobForJobId(jobHandle.getId(), true); + + verify(1, postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + verify(1, postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + + assertThat(jobForJobId.getJob().getState()).isEqualTo(JobState.COMPLETED); + assertThat(jobForJobId.getShells()).isEmpty(); + assertThat(jobForJobId.getRelationships()).isEmpty(); + assertThat(jobForJobId.getTombstones()).hasSize(1); + } + + private static void successfulSemanticModelRequest() { + stubFor(get(urlPathEqualTo("/models")).willReturn( + responseWithStatus(200).withBodyFile("semantichub/all-models-page-IT.json"))); + } + + private static RegisterJob jobRequest(final String globalAssetId, final String bpn) { + return RegisterJob.builder() + .key(PartChainIdentificationKey.builder().bpn(bpn).globalAssetId(globalAssetId).build()) + .depth(1) + .aspects(List.of("Batch", "SingleLevelBomAsBuilt")) + .collectAspects(true) + .lookupBPNs(true) + .direction(Direction.DOWNWARD) + .build(); + } + + private void waitForCompletion(final JobHandle jobHandle) { + Awaitility.await() + .timeout(Duration.ofSeconds(35)) + .pollInterval(Duration.ofSeconds(1)) + .until(() -> irsService.getJobForJobId(jobHandle.getId(), false) + .getJob() + .getState() + .equals(JobState.COMPLETED)); + } + private void successfulRegistryNegotiation() { final String negotiationId = "1bbaec6e-c316-4e1e-8258-c07a648cc43c"; final String transferProcessId = "1b21e963-0bc5-422a-b30d-fd3511861d88"; @@ -254,11 +321,11 @@ private static void successfulBpdmRequests() { } private static void successfulDataRequests() { - givenThat(get(urlPathMatching( - DATAPLANE_PUBLIC_PATH + "/urn:uuid:f53db6ef-7a58-4326-9169-0ae198b85dbf")).willReturn( + stubFor(get( + urlPathMatching(DATAPLANE_PUBLIC_PATH + "/urn:uuid:f53db6ef-7a58-4326-9169-0ae198b85dbf")).willReturn( responseWithStatus(200).withBodyFile("integrationtesting/batch-1.json"))); - givenThat(get(urlPathMatching( - DATAPLANE_PUBLIC_PATH + "/urn:uuid:0e413809-966b-4107-aae5-aeb28bcdaadf")).willReturn( + stubFor(get( + urlPathMatching(DATAPLANE_PUBLIC_PATH + "/urn:uuid:0e413809-966b-4107-aae5-aeb28bcdaadf")).willReturn( responseWithStatus(200).withBodyFile("integrationtesting/singleLevelBomAsBuilt-1.json"))); } diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java index 6377a0d3d2..54297357ab 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java @@ -47,6 +47,10 @@ public static MappingBuilder postEdcDiscovery200() { return postEdcDiscovery200(TEST_BPN, List.of(CONTROLPLANE_PUBLIC_URL)); } + public static MappingBuilder postEdcDiscoveryEmpty200() { + return postEdcDiscovery200(TEST_BPN, List.of()); + } + public static MappingBuilder postEdcDiscovery200(final String bpn, final List edcUrls) { return post(urlPathEqualTo(EDC_DISCOVERY_PATH)).willReturn( responseWithStatus(STATUS_CODE_OK).withBody(edcDiscoveryResponse(bpn, edcUrls))); From 9d2e29422aa4f250d90ff9e26300bb2943962ac1 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Mon, 29 Jan 2024 15:41:53 +0100 Subject: [PATCH 12/22] chore(foss):[#344] Fix license headers --- .../eclipse/tractusx/irs/IrsWireMockIntegrationTest.java | 6 +----- .../java/org/eclipse/tractusx/irs/WireMockTestConfig.java | 1 + .../org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java | 1 + .../org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java | 1 + .../irs/semanticshub/SemanticHubWireMockConfig.java | 1 + .../DecentralDigitalTwinRegistryServiceWiremockTest.java | 1 + .../testing/wiremock/DiscoveryServiceWiremockConfig.java | 1 + .../tractusx/irs/testing/wiremock/DtrWiremockConfig.java | 1 + .../irs/testing/wiremock/SubmodelFacadeWiremockConfig.java | 1 + .../tractusx/irs/testing/wiremock/WireMockConfig.java | 1 + 10 files changed, 10 insertions(+), 5 deletions(-) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java index 709da794ef..0aa067bb31 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java @@ -1,9 +1,5 @@ /******************************************************************************** - * Copyright (c) 2021,2022,2023 - * 2022: ZF Friedrichshafen AG - * 2022: ISTOS GmbH - * 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * 2022,2023: BOSCH AG + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java index 5cc1adcf9d..24968aee88 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java @@ -1,4 +1,5 @@ /******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java index 8a1089c5ce..45bcb93a89 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java @@ -1,4 +1,5 @@ /******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java index fc963f6163..bc375f55b2 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java @@ -1,4 +1,5 @@ /******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java index 16120c02cb..cd250f8a7c 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java @@ -1,4 +1,5 @@ /******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java index 1072ea7e6d..bd512c7cde 100644 --- a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java @@ -1,4 +1,5 @@ /******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java index 54297357ab..585803c1b4 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java @@ -1,4 +1,5 @@ /******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java index 692c4dd798..17332ce160 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java @@ -1,4 +1,5 @@ /******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java index 9ef6e5862d..3269322ab1 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java @@ -1,4 +1,5 @@ /******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java index 21598577df..5da7750813 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/WireMockConfig.java @@ -1,4 +1,5 @@ /******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional From 60d78103ca6de599a36c29958a8002d2e64ed58a Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Mon, 29 Jan 2024 16:32:59 +0100 Subject: [PATCH 13/22] chore(foss):[#344] Update DEPENDENCIES --- DEPENDENCIES | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index cc0f92a3fe..9e90a62f07 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -325,11 +325,11 @@ maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.17, EPL-2.0 OR Apache-2.0, a maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.19, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.tractusx.irs/irs-api/0.0.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx maven/mavencentral/org.eclipse.tractusx.irs/irs-common/0.0.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx -maven/mavencentral/org.eclipse.tractusx.irs/irs-edc-client/1.5.1-SNAPSHOT, Apache-2.0, approved, automotive.tractusx -maven/mavencentral/org.eclipse.tractusx.irs/irs-models/1.5.1-SNAPSHOT, Apache-2.0, approved, automotive.tractusx +maven/mavencentral/org.eclipse.tractusx.irs/irs-edc-client/1.5.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx +maven/mavencentral/org.eclipse.tractusx.irs/irs-models/1.5.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx maven/mavencentral/org.eclipse.tractusx.irs/irs-policy-store/0.0.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx -maven/mavencentral/org.eclipse.tractusx.irs/irs-registry-client/1.5.1-SNAPSHOT, Apache-2.0, approved, automotive.tractusx -maven/mavencentral/org.eclipse.tractusx.irs/irs-testing/1.5.1-SNAPSHOT, Apache-2.0, approved, automotive.tractusx +maven/mavencentral/org.eclipse.tractusx.irs/irs-registry-client/1.5.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx +maven/mavencentral/org.eclipse.tractusx.irs/irs-testing/1.5.2-SNAPSHOT, Apache-2.0, approved, automotive.tractusx maven/mavencentral/org.glassfish.hk2.external/aopalliance-repackaged/3.0.4, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2.external/aopalliance-repackaged/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-api/3.0.4, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish @@ -473,7 +473,7 @@ maven/mavencentral/org.testcontainers/testcontainers/1.19.1, Apache-2.0 AND MIT, maven/mavencentral/org.typelevel/spire-macros_2.13/0.17.0, MIT, approved, clearlydefined maven/mavencentral/org.unbescape/unbescape/1.1.6.RELEASE, Apache-2.0, approved, CQ18904 maven/mavencentral/org.webjars/swagger-ui/5.2.0, Apache-2.0, approved, #10221 -maven/mavencentral/org.wiremock/wiremock-standalone/3.2.0, MIT AND Apache-2.0, approved, #10919 +maven/mavencentral/org.wiremock/wiremock-standalone/3.3.1, , restricted, clearlydefined maven/mavencentral/org.xerial.snappy/snappy-java/1.1.10.5, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #9098 maven/mavencentral/org.xmlunit/xmlunit-core/2.9.1, Apache-2.0, approved, #6272 maven/mavencentral/org.yaml/snakeyaml/1.33, Apache-2.0, approved, clearlydefined From 91c4e88f55333ac225f6d6c3c3be6f5d9bf13d61 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Mon, 29 Jan 2024 16:33:39 +0100 Subject: [PATCH 14/22] chore(foss):[#344] Update dash license-tool-plugin --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index d91480e11c..8be9e7d052 100644 --- a/pom.xml +++ b/pom.xml @@ -121,7 +121,7 @@ 4.3.0 3.3.0 3.1.0 - 1.0.3-SNAPSHOT + 1.1.0 1.1.10.5 @@ -158,10 +158,10 @@ - dash-licenses-snapshots - https://repo.eclipse.org/content/repositories/dash-licenses-snapshots/ + dash-licenses-releases + https://repo.eclipse.org/content/repositories/dash-licenses-releases/ - true + false From 44bed78d19ca957ff1c7a7da7ac6f58268685e21 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 30 Jan 2024 14:32:47 +0100 Subject: [PATCH 15/22] feat(irs-api):[#344] Add test case for recursive IRS flow --- .../irs/IrsWireMockIntegrationTest.java | 235 ++++++++---------- .../tractusx/irs/WireMockTestConfig.java | 127 ++++++++-- .../testing/wiremock/DtrWiremockConfig.java | 13 + .../SubmodelFacadeWiremockConfig.java | 9 +- 4 files changed, 236 insertions(+), 148 deletions(-) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java index 0aa067bb31..1b93697317 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java @@ -20,54 +20,46 @@ package org.eclipse.tractusx.irs; import static com.github.tomakehurst.wiremock.client.WireMock.containing; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.tractusx.irs.WireMockTestConfig.createEndpointDataReference; -import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig.bpdmResponse; -import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.batchSchemaResponse200; -import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.singleLevelBomAsBuiltSchemaResponse200; +import static org.eclipse.tractusx.irs.WireMockTestConfig.randomUUID; +import static org.eclipse.tractusx.irs.WireMockTestConfig.successfulDataRequests; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_PATH; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_URL; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.EDC_DISCOVERY_PATH; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.TEST_BPN; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder200; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder404; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscovery200; import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscoveryEmpty200; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.DATAPLANE_PUBLIC_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.DATAPLANE_PUBLIC_URL; import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.LOOKUP_SHELLS_TEMPLATE; import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.PUBLIC_LOOKUP_SHELLS_PATH; import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.PUBLIC_SHELL_DESCRIPTORS_PATH; import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.SHELL_DESCRIPTORS_TEMPLATE; import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getLookupShells200; import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getShellDescriptor200; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.lookupShellsResponse; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.submodelDescriptor; import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_CATALOG; import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_NEGOTIATE; import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_STATE; import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_TRANSFER; -import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; -import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.List; +import java.util.Objects; import com.github.tomakehurst.wiremock.junit5.WireMockTest; -import org.apache.commons.codec.binary.Base64; import org.awaitility.Awaitility; import org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig; import org.eclipse.tractusx.irs.component.JobHandle; import org.eclipse.tractusx.irs.component.Jobs; -import org.eclipse.tractusx.irs.component.PartChainIdentificationKey; import org.eclipse.tractusx.irs.component.RegisterJob; -import org.eclipse.tractusx.irs.component.enums.Direction; import org.eclipse.tractusx.irs.component.enums.JobState; +import org.eclipse.tractusx.irs.data.StringMapper; import org.eclipse.tractusx.irs.edc.client.EndpointDataReferenceStorage; import org.eclipse.tractusx.irs.semanticshub.AspectModels; import org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig; @@ -75,15 +67,17 @@ import org.eclipse.tractusx.irs.services.SemanticHubService; import org.eclipse.tractusx.irs.services.validation.SchemaNotFoundException; import org.eclipse.tractusx.irs.testing.containers.MinioContainer; +import org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig; import org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cache.CacheManager; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.DynamicPropertyRegistry; @@ -94,7 +88,6 @@ @WireMockTest(httpPort = 8085) @Testcontainers @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WireMockTestConfig.class) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) @ContextConfiguration(initializers = IrsWireMockIntegrationTest.MinioConfigInitializer.class) @ActiveProfiles("integrationtest") class IrsWireMockIntegrationTest { @@ -111,11 +104,19 @@ class IrsWireMockIntegrationTest { private SemanticHubService semanticHubService; @Autowired private EndpointDataReferenceStorage endpointDataReferenceStorage; + @Autowired + private CacheManager cacheManager; @BeforeAll static void startContainer() { minioContainer.start(); - successfulSemanticModelRequest(); + WireMockTestConfig.successfulSemanticModelRequest(); + } + + @AfterEach + void tearDown() { + cacheManager.getCacheNames() + .forEach(cacheName -> Objects.requireNonNull(cacheManager.getCache(cacheName)).clear()); } @AfterAll @@ -146,7 +147,7 @@ static void configureProperties(DynamicPropertyRegistry registry) { @Test void shouldStartApplicationAndCollectSemanticModels() throws SchemaNotFoundException { // Arrange - successfulSemanticModelRequest(); + WireMockTestConfig.successfulSemanticModelRequest(); // Act final AspectModels allAspectModels = semanticHubService.getAllAspectModels(); @@ -156,22 +157,23 @@ void shouldStartApplicationAndCollectSemanticModels() throws SchemaNotFoundExcep } @Test - void shouldStartJob() { + void shouldStopJobAfterDepthIsReached() { // Arrange - final String globalAssetId = "globalAssetId"; + final String globalAssetIdLevel1 = "globalAssetId"; + final String globalAssetIdLevel2 = "urn:uuid:6d505432-8b31-4966-9514-4b753372683f"; - successfulSemanticModelRequest(); - successfulSemanticHubRequests(); - successfulDiscovery(); - successfulRegistryNegotiation(); - successfulDtrRequest(globalAssetId); - successfulAssetNegotiation(); + WireMockTestConfig.successfulSemanticModelRequest(); + WireMockTestConfig.successfulSemanticHubRequests(); + WireMockTestConfig.successfulDiscovery(); - successfulDataRequests(); + successfulRegistryAndDataRequest(globalAssetIdLevel1, "Cathode", TEST_BPN, "integrationtesting/batch-1.json", + "integrationtesting/singleLevelBomAsBuilt-1.json"); + successfulRegistryAndDataRequest(globalAssetIdLevel2, "Polyamid", TEST_BPN, "integrationtesting/batch-2.json", + "integrationtesting/singleLevelBomAsBuilt-2.json"); - successfulBpdmRequests(); + WireMockTestConfig.successfulBpdmRequests(); - final RegisterJob request = jobRequest(globalAssetId, TEST_BPN); + final RegisterJob request = WireMockTestConfig.jobRequest(globalAssetIdLevel1, TEST_BPN, 1); // Act final JobHandle jobHandle = irsService.registerItemJob(request); @@ -181,8 +183,8 @@ void shouldStartJob() { Jobs jobForJobId = irsService.getJobForJobId(jobHandle.getId(), true); // Assert - verifyDiscoveryCalls(1); - verifyNegotiationCalls(3); + WireMockTestConfig.verifyDiscoveryCalls(1); + WireMockTestConfig.verifyNegotiationCalls(3); assertThat(jobForJobId.getJob().getState()).isEqualTo(JobState.COMPLETED); assertThat(jobForJobId.getShells()).hasSize(2); @@ -193,10 +195,10 @@ void shouldStartJob() { @Test void shouldCreateTombstoneWhenDiscoveryServiceNotAvailable() { // Arrange - successfulSemanticModelRequest(); + WireMockTestConfig.successfulSemanticModelRequest(); stubFor(postDiscoveryFinder404()); final String globalAssetId = "globalAssetId"; - final RegisterJob request = jobRequest(globalAssetId, TEST_BPN); + final RegisterJob request = WireMockTestConfig.jobRequest(globalAssetId, TEST_BPN, 1); // Act final JobHandle jobHandle = irsService.registerItemJob(request); @@ -218,11 +220,12 @@ void shouldCreateTombstoneWhenDiscoveryServiceNotAvailable() { @Test void shouldCreateTombstoneWhenEdcDiscoveryIsEmpty() { // Arrange - successfulSemanticModelRequest(); + WireMockTestConfig.successfulSemanticModelRequest(); stubFor(postDiscoveryFinder200()); stubFor(postEdcDiscoveryEmpty200()); final String globalAssetId = "globalAssetId"; - final RegisterJob request = jobRequest(globalAssetId, TEST_BPN); + final RegisterJob request = WireMockTestConfig.jobRequest(globalAssetId, TEST_BPN, 1); + // Act final JobHandle jobHandle = irsService.registerItemJob(request); @@ -231,8 +234,7 @@ void shouldCreateTombstoneWhenEdcDiscoveryIsEmpty() { waitForCompletion(jobHandle); final Jobs jobForJobId = irsService.getJobForJobId(jobHandle.getId(), true); - verify(1, postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); - verify(1, postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + WireMockTestConfig.verifyDiscoveryCalls(1); assertThat(jobForJobId.getJob().getState()).isEqualTo(JobState.COMPLETED); assertThat(jobForJobId.getShells()).isEmpty(); @@ -240,108 +242,91 @@ void shouldCreateTombstoneWhenEdcDiscoveryIsEmpty() { assertThat(jobForJobId.getTombstones()).hasSize(1); } - private static void successfulSemanticModelRequest() { - stubFor(get(urlPathEqualTo("/models")).willReturn( - responseWithStatus(200).withBodyFile("semantichub/all-models-page-IT.json"))); - } + @Test + void shouldStartRecursiveProcesses() { + // Arrange + final String globalAssetIdLevel1 = "urn:uuid:334cce52-1f52-4bc9-9dd1-410bbe497bbc"; + final String globalAssetIdLevel2 = "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5"; + final String globalAssetIdLevel3 = "urn:uuid:a314ad6b-77ea-417e-ae2d-193b3e249e99"; - private static RegisterJob jobRequest(final String globalAssetId, final String bpn) { - return RegisterJob.builder() - .key(PartChainIdentificationKey.builder().bpn(bpn).globalAssetId(globalAssetId).build()) - .depth(1) - .aspects(List.of("Batch", "SingleLevelBomAsBuilt")) - .collectAspects(true) - .lookupBPNs(true) - .direction(Direction.DOWNWARD) - .build(); - } + WireMockTestConfig.successfulSemanticModelRequest(); + WireMockTestConfig.successfulSemanticHubRequests(); + WireMockTestConfig.successfulDiscovery(); - private void waitForCompletion(final JobHandle jobHandle) { - Awaitility.await() - .timeout(Duration.ofSeconds(35)) - .pollInterval(Duration.ofSeconds(1)) - .until(() -> irsService.getJobForJobId(jobHandle.getId(), false) - .getJob() - .getState() - .equals(JobState.COMPLETED)); - } + successfulRegistryAndDataRequest(globalAssetIdLevel1, "Cathode", TEST_BPN, "integrationtesting/batch-1.json", + "integrationtesting/singleLevelBomAsBuilt-1.json"); + successfulRegistryAndDataRequest(globalAssetIdLevel2, "Polyamid", TEST_BPN, "integrationtesting/batch-2.json", + "integrationtesting/singleLevelBomAsBuilt-2.json"); + successfulRegistryAndDataRequest(globalAssetIdLevel3, "GenericChemical", TEST_BPN, + "integrationtesting/batch-3.json", "integrationtesting/singleLevelBomAsBuilt-3.json"); - private void successfulRegistryNegotiation() { - final String negotiationId = "1bbaec6e-c316-4e1e-8258-c07a648cc43c"; - final String transferProcessId = "1b21e963-0bc5-422a-b30d-fd3511861d88"; - final String edcAssetId = "registry-asset"; - final String contractAgreementId = SubmodelFacadeWiremockConfig.prepareNegotiation(negotiationId, - transferProcessId, - "7681f966-36ea-4542-b5ea-0d0db81967de:registry-asset:a6144a2e-c1b1-4ec6-96e1-a221da134e4f", edcAssetId); - endpointDataReferenceStorage.put(contractAgreementId, createEndpointDataReference(contractAgreementId)); - } + WireMockTestConfig.successfulBpdmRequests(); - private void successfulAssetNegotiation() { - final String negotiationId = "1bbaec6e-c316-4e1e-8258-c07a648cc43c"; - final String transferProcessId = "1b21e963-0bc5-422a-b30d-fd3511861d88"; - final String edcAssetId = "urn:uuid:f8196d6a-1664-4531-bdee-f15dbb1daf26"; - final String contractAgreementId = SubmodelFacadeWiremockConfig.prepareNegotiation(negotiationId, - transferProcessId, - "7681f966-36ea-4542-b5ea-0d0db81967de:urn:uuid:f8196d6a-1664-4531-bdee-f15dbb1daf26:a6144a2e-c1b1-4ec6-96e1-a221da134e4f", - edcAssetId); - endpointDataReferenceStorage.put(contractAgreementId, createEndpointDataReference(contractAgreementId)); - } + final RegisterJob request = WireMockTestConfig.jobRequest(globalAssetIdLevel1, TEST_BPN, 4); - private static void successfulDiscovery() { - stubFor(postDiscoveryFinder200()); - stubFor(postEdcDiscovery200()); - } - - private static String encodedId(final String secondDTR) { - return Base64.encodeBase64String(secondDTR.getBytes(StandardCharsets.UTF_8)); - } + // Act + final JobHandle jobHandle = irsService.registerItemJob(request); - private static void verifyDiscoveryCalls(final int times) { - verify(times, postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); - verify(times, postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); - } + // Assert + assertThat(jobHandle.getId()).isNotNull(); + waitForCompletion(jobHandle); + final Jobs jobForJobId = irsService.getJobForJobId(jobHandle.getId(), false); + System.out.println(StringMapper.mapToString(jobForJobId)); - private static void verifyNegotiationCalls(final int times) { - verify(times, postRequestedFor(urlPathEqualTo(PATH_NEGOTIATE))); - verify(times, postRequestedFor(urlPathEqualTo(PATH_CATALOG))); - verify(times * 2, getRequestedFor(urlPathMatching(PATH_NEGOTIATE + "/.*"))); - verify(times, getRequestedFor(urlPathMatching(PATH_NEGOTIATE + "/.*" + PATH_STATE))); - verify(times, postRequestedFor(urlPathEqualTo(PATH_TRANSFER))); - verify(times * 2, getRequestedFor(urlPathMatching(PATH_TRANSFER + "/.*"))); - verify(times, getRequestedFor(urlPathMatching(PATH_TRANSFER + "/.*" + PATH_STATE))); - } + assertThat(jobForJobId.getJob().getState()).isEqualTo(JobState.COMPLETED); + assertThat(jobForJobId.getShells()).hasSize(3); + assertThat(jobForJobId.getRelationships()).hasSize(2); + assertThat(jobForJobId.getTombstones()).isEmpty(); + assertThat(jobForJobId.getSubmodels()).hasSize(6); - private static void successfulBpdmRequests() { - stubFor(get(urlPathMatching("/legal-entities/.*")).willReturn( - responseWithStatus(200).withBody(bpdmResponse(TEST_BPN, "Company Name")))); + WireMockTestConfig.verifyDiscoveryCalls(1); + WireMockTestConfig.verifyNegotiationCalls(6); } - private static void successfulDataRequests() { - stubFor(get( - urlPathMatching(DATAPLANE_PUBLIC_PATH + "/urn:uuid:f53db6ef-7a58-4326-9169-0ae198b85dbf")).willReturn( - responseWithStatus(200).withBodyFile("integrationtesting/batch-1.json"))); - stubFor(get( - urlPathMatching(DATAPLANE_PUBLIC_PATH + "/urn:uuid:0e413809-966b-4107-aae5-aeb28bcdaadf")).willReturn( - responseWithStatus(200).withBodyFile("integrationtesting/singleLevelBomAsBuilt-1.json"))); + private void successfulRegistryAndDataRequest(final String globalAssetId, final String idShort, final String bpn, + final String batchFileName, final String sbomFileName) { + + final String edcAssetId = WireMockTestConfig.randomUUIDwithPrefix(); + final String batchId = WireMockTestConfig.randomUUIDwithPrefix(); + final String batch = submodelDescriptor(DATAPLANE_PUBLIC_URL, edcAssetId, + DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, "Batch", batchId, + "urn:samm:io.catenax.batch:2.0.0#Batch"); + successfulDataRequests(batchId, batchFileName); + + final String sbomId = WireMockTestConfig.randomUUIDwithPrefix(); + final String singleLevelBomAsBuilt = submodelDescriptor(DATAPLANE_PUBLIC_URL, edcAssetId, + DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, "SingleLevelBomAsBuilt", sbomId, + "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt"); + final List submodelDescriptors = List.of(batch, singleLevelBomAsBuilt); + successfulDataRequests(sbomId, sbomFileName); + successfulNegotiation(edcAssetId); + + final String shellId = WireMockTestConfig.randomUUIDwithPrefix(); + final String registryEdcAssetId = "registry-asset"; + successfulNegotiation(registryEdcAssetId); + stubFor(getLookupShells200(PUBLIC_LOOKUP_SHELLS_PATH, List.of(shellId)).withQueryParam("assetIds", + containing(globalAssetId))); + stubFor(getShellDescriptor200(PUBLIC_SHELL_DESCRIPTORS_PATH + WireMockTestConfig.encodedId(shellId), bpn, + submodelDescriptors, globalAssetId, shellId, idShort)); } - private static void successfulSemanticHubRequests() { - stubFor(batchSchemaResponse200()); - stubFor(singleLevelBomAsBuiltSchemaResponse200()); + private void successfulNegotiation(final String edcAssetId) { + final String negotiationId = randomUUID(); + final String transferProcessId = randomUUID(); + final String contractAgreementId = "%s:%s:%s".formatted(randomUUID(), edcAssetId, randomUUID()); + SubmodelFacadeWiremockConfig.prepareNegotiation(negotiationId, transferProcessId, contractAgreementId, + edcAssetId); + endpointDataReferenceStorage.put(contractAgreementId, createEndpointDataReference(contractAgreementId)); } - private static void successfulDtrRequest(final String startId) { - stubFor(getLookupShells200(PUBLIC_LOOKUP_SHELLS_PATH).withQueryParam("assetIds", containing(startId))); - stubFor(getShellDescriptor200( - PUBLIC_SHELL_DESCRIPTORS_PATH + encodedId("urn:uuid:21f7ebea-fa8a-410c-a656-bd9082e67dcf"))); - - final String secondDTR = "urn:uuid:6d505432-8b31-4966-9514-4b753372683f"; - stubFor(get(urlPathEqualTo(PUBLIC_LOOKUP_SHELLS_PATH)).withQueryParam("assetIds", - containing("urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5")) - .willReturn(responseWithStatus(200).withBody( - lookupShellsResponse(List.of(secondDTR))))); - - stubFor(getShellDescriptor200(PUBLIC_SHELL_DESCRIPTORS_PATH + encodedId(secondDTR))); + private void waitForCompletion(final JobHandle jobHandle) { + Awaitility.await() + .timeout(Duration.ofSeconds(35)) + .pollInterval(Duration.ofSeconds(1)) + .until(() -> irsService.getJobForJobId(jobHandle.getId(), false) + .getJob() + .getState() + .equals(JobState.COMPLETED)); } public static class MinioConfigInitializer diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java index 24968aee88..2db79977e6 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java @@ -19,24 +19,49 @@ ********************************************************************************/ package org.eclipse.tractusx.irs; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig.bpdmResponse; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.BPDM_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.DISCOVERY_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.DTR_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.EDC_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.NO_ERROR_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.SEMHUB_REST_TEMPLATE; +import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.batchSchemaResponse200; +import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.singleLevelBomAsBuiltSchemaResponse200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.EDC_DISCOVERY_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.TEST_BPN; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscovery200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.DATAPLANE_PUBLIC_PATH; import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.DATAPLANE_HOST; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_CATALOG; import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_DATAPLANE_PUBLIC; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_NEGOTIATE; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_STATE; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_TRANSFER; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.List; import java.util.Map; +import java.util.UUID; import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.irs.component.PartChainIdentificationKey; +import org.eclipse.tractusx.irs.component.RegisterJob; +import org.eclipse.tractusx.irs.component.enums.Direction; import org.eclipse.tractusx.irs.data.StringMapper; import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration; import org.eclipse.tractusx.irs.edc.client.model.EDRAuthCode; @@ -54,25 +79,6 @@ public class WireMockTestConfig { public static final int HTTP_PORT = 8085; private static final String PROXY_SERVER_HOST = "127.0.0.1"; - public static EndpointDataReference createEndpointDataReference(final String contractAgreementId) { - final EDRAuthCode edrAuthCode = EDRAuthCode.builder() - .cid(contractAgreementId) - .dad("test") - .exp(9999999999L) - .build(); - final String b64EncodedAuthCode = Base64.getUrlEncoder() - .encodeToString(StringMapper.mapToString(edrAuthCode) - .getBytes(StandardCharsets.UTF_8)); - final String jwtToken = "eyJhbGciOiJSUzI1NiJ9." + b64EncodedAuthCode + ".test"; - return EndpointDataReference.Builder.newInstance() - .authKey("testkey") - .authCode(jwtToken) - .properties( - Map.of(JsonLdConfiguration.NAMESPACE_EDC_CID, contractAgreementId)) - .endpoint(DATAPLANE_HOST + PATH_DATAPLANE_PUBLIC) - .build(); - } - @Primary @Profile("integrationtest") @Bean(DTR_REST_TEMPLATE) @@ -124,4 +130,87 @@ RestTemplate bpdmRestTemplate() { RestTemplate semanticHubRestTemplate() { return restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); } + + public static EndpointDataReference createEndpointDataReference(final String contractAgreementId) { + final EDRAuthCode edrAuthCode = EDRAuthCode.builder() + .cid(contractAgreementId) + .dad("test") + .exp(9999999999L) + .build(); + final String b64EncodedAuthCode = Base64.getUrlEncoder() + .encodeToString(StringMapper.mapToString(edrAuthCode) + .getBytes(StandardCharsets.UTF_8)); + final String jwtToken = "eyJhbGciOiJSUzI1NiJ9." + b64EncodedAuthCode + ".test"; + return EndpointDataReference.Builder.newInstance() + .authKey("testkey") + .authCode(jwtToken) + .properties( + Map.of(JsonLdConfiguration.NAMESPACE_EDC_CID, contractAgreementId)) + .endpoint(DATAPLANE_HOST + PATH_DATAPLANE_PUBLIC) + .build(); + } + + static void successfulSemanticModelRequest() { + stubFor(get(urlPathEqualTo("/models")).willReturn( + responseWithStatus(200).withBodyFile("semantichub/all-models-page-IT.json"))); + } + + static RegisterJob jobRequest(final String globalAssetId, final String bpn, final int depth) { + return RegisterJob.builder() + .key(PartChainIdentificationKey.builder().bpn(bpn).globalAssetId(globalAssetId).build()) + .depth(depth) + .aspects(List.of("Batch", "SingleLevelBomAsBuilt")) + .collectAspects(true) + .lookupBPNs(true) + .direction(Direction.DOWNWARD) + .build(); + } + + static void successfulDiscovery() { + stubFor(postDiscoveryFinder200()); + stubFor(postEdcDiscovery200()); + } + + static String encodedId(final String shellId) { + return org.apache.commons.codec.binary.Base64.encodeBase64String(shellId.getBytes(StandardCharsets.UTF_8)); + } + + static void verifyDiscoveryCalls(final int times) { + verify(times, postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); + verify(times, postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); + } + + static void verifyNegotiationCalls(final int times) { + verify(times, postRequestedFor(urlPathEqualTo(PATH_NEGOTIATE))); + verify(times, postRequestedFor(urlPathEqualTo(PATH_CATALOG))); + verify(times * 2, getRequestedFor(urlPathMatching(PATH_NEGOTIATE + "/.*"))); + verify(times, getRequestedFor(urlPathMatching(PATH_NEGOTIATE + "/.*" + PATH_STATE))); + verify(times, postRequestedFor(urlPathEqualTo(PATH_TRANSFER))); + verify(times * 2, getRequestedFor(urlPathMatching(PATH_TRANSFER + "/.*"))); + verify(times, getRequestedFor(urlPathMatching(PATH_TRANSFER + "/.*" + PATH_STATE))); + } + + static void successfulBpdmRequests() { + stubFor(get(urlPathMatching("/legal-entities/.*")).willReturn( + responseWithStatus(200).withBody(bpdmResponse(TEST_BPN, "Company Name")))); + } + + static void successfulDataRequests(final String assetId, final String fileName) { + stubFor(get(urlPathMatching(DATAPLANE_PUBLIC_PATH + "/" + assetId)).willReturn( + responseWithStatus(200).withBodyFile(fileName))); + } + + static void successfulSemanticHubRequests() { + stubFor(batchSchemaResponse200()); + stubFor(singleLevelBomAsBuiltSchemaResponse200()); + } + + static String randomUUIDwithPrefix() { + final String uuidPrefix = "urn:uuid:"; + return uuidPrefix + randomUUID(); + } + + static String randomUUID() { + return UUID.randomUUID().toString(); + } } diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java index 17332ce160..30367044e2 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java @@ -74,6 +74,14 @@ public static MappingBuilder getShellDescriptor200(final String urlRegex) { "EngineeringPlastics", "urn:uuid:9ce43b21-75e3-4cea-b13e-9a34f4f6822a", specificAssetIds))); } + @SuppressWarnings("PMD.UseObjectForClearerAPI") // used only for testing + public static MappingBuilder getShellDescriptor200(final String urlRegex, final String bpn, final List submodelDescriptors, + final String globalAssetId, final String shellId, final String idShort) { + final List specificAssetIds = List.of(specificAssetId("manufacturerId", bpn)); + return get(urlPathMatching(urlRegex)).willReturn(responseWithStatus(STATUS_CODE_OK).withBody( + assetAdministrationShellResponse(submodelDescriptors, globalAssetId, idShort, shellId, specificAssetIds))); + } + public static String assetAdministrationShellResponse(final List submodelDescriptors, final String globalAssetId, final String idShort, final String shellId, final List specificAssetIds) { @@ -169,6 +177,11 @@ public static MappingBuilder getLookupShells200(final String lookupShellsPath) { lookupShellsResponse(List.of("urn:uuid:21f7ebea-fa8a-410c-a656-bd9082e67dcf")))); } + public static MappingBuilder getLookupShells200(final String lookupShellsPath, final List shellIds) { + return get(urlPathEqualTo(lookupShellsPath)).willReturn(responseWithStatus(STATUS_CODE_OK).withBody( + lookupShellsResponse(shellIds))); + } + public static MappingBuilder getLookupShells200Empty() { return get(urlPathMatching(LOOKUP_SHELLS_PATH + ".*")).willReturn( responseWithStatus(STATUS_CODE_OK).withBody(lookupShellsResponse(List.of()))); diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java index 3269322ab1..361423cf05 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java @@ -54,13 +54,15 @@ private SubmodelFacadeWiremockConfig() { } public static String prepareNegotiation() { - return prepareNegotiation("1bbaec6e-c316-4e1e-8258-c07a648cc43c", "1b21e963-0bc5-422a-b30d-fd3511861d88", - "7681f966-36ea-4542-b5ea-0d0db81967de:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7:a6144a2e-c1b1-4ec6-96e1-a221da134e4f", + final String contractAgreementId = "7681f966-36ea-4542-b5ea-0d0db81967de:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7:a6144a2e-c1b1-4ec6-96e1-a221da134e4f"; + prepareNegotiation("1bbaec6e-c316-4e1e-8258-c07a648cc43c", "1b21e963-0bc5-422a-b30d-fd3511861d88", + contractAgreementId, "5a7ab616-989f-46ae-bdf2-32027b9f6ee6-31b614f5-ec14-4ed2-a509-e7b7780083e7"); + return contractAgreementId; } @SuppressWarnings("PMD.UseObjectForClearerAPI") // used only for testing - public static String prepareNegotiation(final String negotiationId, final String transferProcessId, + public static void prepareNegotiation(final String negotiationId, final String transferProcessId, final String contractAgreementId, final String edcAssetId) { stubFor(post(urlPathEqualTo(PATH_CATALOG)).willReturn(WireMockConfig.responseWithStatus(STATUS_CODE_OK) .withBody(getCatalogResponse(edcAssetId, @@ -93,7 +95,6 @@ public static String prepareNegotiation(final String negotiationId, final String .withBody( getTransferConfirmedResponse(transferProcessId, transferProcessState, edcAssetId, contractAgreementId)))); - return contractAgreementId; } private static String startTransferProcessResponse(final String transferProcessId) { From 607faa0bb3ae437f5a1f6584831d49388b293f32 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 30 Jan 2024 14:33:39 +0100 Subject: [PATCH 16/22] chore(docs):[#344] Add changes to CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 458cdcad76..acf6f5d589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added helper script for building documentation locally. +- Added Integration Tests for the entire IRS flow using stubbed responses of Discovery Service, Semantic Hub, EDC, Digital Twin Registry and BPDM Pool ### Changed - Updated license header to "Copyright (c) 2021,2024 Contributors to the Eclipse Foundation" From c455751fec4ee4a1af09010d0b89d5f4cd526633 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 30 Jan 2024 14:33:55 +0100 Subject: [PATCH 17/22] chore(foss):[#344] Update DEPENDENCIES --- DEPENDENCIES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 9e90a62f07..4e8646dda6 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -473,7 +473,7 @@ maven/mavencentral/org.testcontainers/testcontainers/1.19.1, Apache-2.0 AND MIT, maven/mavencentral/org.typelevel/spire-macros_2.13/0.17.0, MIT, approved, clearlydefined maven/mavencentral/org.unbescape/unbescape/1.1.6.RELEASE, Apache-2.0, approved, CQ18904 maven/mavencentral/org.webjars/swagger-ui/5.2.0, Apache-2.0, approved, #10221 -maven/mavencentral/org.wiremock/wiremock-standalone/3.3.1, , restricted, clearlydefined +maven/mavencentral/org.wiremock/wiremock-standalone/3.3.1, MIT AND Apache-2.0, approved, #12941 maven/mavencentral/org.xerial.snappy/snappy-java/1.1.10.5, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #9098 maven/mavencentral/org.xmlunit/xmlunit-core/2.9.1, Apache-2.0, approved, #6272 maven/mavencentral/org.yaml/snakeyaml/1.33, Apache-2.0, approved, clearlydefined From 2964eecd8e88d0d65a6b4eec751818cb610815c2 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 30 Jan 2024 14:34:25 +0100 Subject: [PATCH 18/22] feat(irs-api):[#344] Delete unused files --- .../__files/edc/responseCatalog.json | 119 ------------------ .../edc/responseGetNegotiationConfirmed.json | 11 -- .../__files/edc/responseStartNegotiation.json | 3 - .../edc/responseStartTransferprocess.json | 3 - 4 files changed, 136 deletions(-) delete mode 100644 irs-api/src/test/resources/__files/edc/responseCatalog.json delete mode 100644 irs-api/src/test/resources/__files/edc/responseGetNegotiationConfirmed.json delete mode 100644 irs-api/src/test/resources/__files/edc/responseStartNegotiation.json delete mode 100644 irs-api/src/test/resources/__files/edc/responseStartTransferprocess.json diff --git a/irs-api/src/test/resources/__files/edc/responseCatalog.json b/irs-api/src/test/resources/__files/edc/responseCatalog.json deleted file mode 100644 index e6ba0d04c1..0000000000 --- a/irs-api/src/test/resources/__files/edc/responseCatalog.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "id": "default", - "contractOffers": [ - { - "id": "3:afb3dca6-e7cc-42b6-98bb-c6f948121c7a", - "policy": { - "permissions": [ - { - "edctype": "dataspaceconnector:permission", - "uid": null, - "target": "urn:uuid:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-urn:uuid:31b614f5-ec14-4ed2-a509-e7b7780083e7", - "action": { - "type": "USE", - "includedIn": null, - "constraint": null - }, - "assignee": null, - "assigner": null, - "constraints": [], - "duties": [] - } - ], - "prohibitions": [], - "obligations": [], - "extensibleProperties": {}, - "inheritsFrom": null, - "assigner": null, - "assignee": null, - "target": "urn:uuid:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-urn:uuid:31b614f5-ec14-4ed2-a509-e7b7780083e7", - "@type": { - "@policytype": "set" - } - }, - "asset": { - "id": "urn:uuid:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-urn:uuid:31b614f5-ec14-4ed2-a509-e7b7780083e7", - "createdAt": 1669196292759, - "properties": { - "asset:prop:byteSize": null, - "asset:prop:description": "product description", - "asset:prop:contenttype": "application/json", - "asset:prop:policy-id": "use-eu", - "asset:prop:id": "urn:uuid:5a7ab616-989f-46ae-bdf2-32027b9f6ee6-urn:uuid:31b614f5-ec14-4ed2-a509-e7b7780083e7", - "asset:prop:fileName": null - } - }, - "assetId": null, - "provider": "urn:connector:provider", - "consumer": "urn:connector:consumer", - "offerStart": null, - "offerEnd": null, - "contractStart": null, - "contractEnd": null - }, - { - "id": "notification-receipt-cd:b3693bd7-192e-4b2f-b24b-a1d3e3518dee", - "policy": { - "permissions": [ - { - "edctype": "dataspaceconnector:permission", - "uid": null, - "target": "notification-receipt", - "action": { - "type": "USE", - "includedIn": null, - "constraint": null - }, - "assignee": null, - "assigner": null, - "constraints": [ - { - "edctype": "AtomicConstraint", - "leftExpression": { - "edctype": "dataspaceconnector:literalexpression", - "value": "idsc:PURPOSE" - }, - "rightExpression": { - "edctype": "dataspaceconnector:literalexpression", - "value": "Investigation" - }, - "operator": "EQ" - } - ], - "duties": [] - } - ], - "prohibitions": [], - "obligations": [], - "extensibleProperties": {}, - "inheritsFrom": null, - "assigner": null, - "assignee": null, - "target": "notification-receipt", - "@type": { - "@policytype": "set" - } - }, - "asset": { - "id": "notification-receipt", - "createdAt": 1680088494977, - "properties": { - "asset:prop:byteSize": null, - "asset:prop:name": "Asset to receive investigations", - "asset:prop:contenttype": "application/json", - "asset:prop:notificationtype": "investigation", - "asset:prop:notificationmethod": "receive", - "asset:prop:id": "notification-receipt", - "asset:prop:fileName": null - } - }, - "assetId": null, - "provider": "urn:connector:provider", - "consumer": "urn:connector:consumer", - "offerStart": null, - "offerEnd": null, - "contractStart": null, - "contractEnd": null - } - ] -} \ No newline at end of file diff --git a/irs-api/src/test/resources/__files/edc/responseGetNegotiationConfirmed.json b/irs-api/src/test/resources/__files/edc/responseGetNegotiationConfirmed.json deleted file mode 100644 index 4d0c6ae3cc..0000000000 --- a/irs-api/src/test/resources/__files/edc/responseGetNegotiationConfirmed.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "createdAt": 1669197004371, - "updatedAt": 1669197045765, - "contractAgreementId": "1bbaec6e-c316-4e1e-8258-c07a648cc43c", - "counterPartyAddress": "http://edc.io/BPNL0000000BB2OK/api/v1/ids/data", - "errorDetail": "", - "id": "1cbaec6e-c316-4e3e-8258-c07a648cc44a", - "protocol": "ids-multipart", - "state": "CONFIRMED", - "type": "CONSUMER" -} \ No newline at end of file diff --git a/irs-api/src/test/resources/__files/edc/responseStartNegotiation.json b/irs-api/src/test/resources/__files/edc/responseStartNegotiation.json deleted file mode 100644 index 083246511f..0000000000 --- a/irs-api/src/test/resources/__files/edc/responseStartNegotiation.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "1cbaec6e-c316-4e3e-8258-c07a648cc44a" -} \ No newline at end of file diff --git a/irs-api/src/test/resources/__files/edc/responseStartTransferprocess.json b/irs-api/src/test/resources/__files/edc/responseStartTransferprocess.json deleted file mode 100644 index 88f6783778..0000000000 --- a/irs-api/src/test/resources/__files/edc/responseStartTransferprocess.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "1b21e963-0bc5-422a-b30d-fd3511861d88" -} \ No newline at end of file From 505fa27daf9493d2357c6b79471957609ca30d6a Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 30 Jan 2024 14:34:43 +0100 Subject: [PATCH 19/22] feat(irs-api):[#344] Add test case for recursive IRS flow --- .../__files/integrationtesting/batch-1.json | 2 +- .../__files/integrationtesting/batch-2.json | 22 +++++++++++++++++++ .../__files/integrationtesting/batch-3.json | 22 +++++++++++++++++++ .../singleLevelBomAsBuilt-2.json | 16 ++++++++++++++ .../singleLevelBomAsBuilt-3.json | 4 ++++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 irs-api/src/test/resources/__files/integrationtesting/batch-2.json create mode 100644 irs-api/src/test/resources/__files/integrationtesting/batch-3.json create mode 100644 irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-2.json create mode 100644 irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-3.json diff --git a/irs-api/src/test/resources/__files/integrationtesting/batch-1.json b/irs-api/src/test/resources/__files/integrationtesting/batch-1.json index 76e6d99956..b044897ad0 100644 --- a/irs-api/src/test/resources/__files/integrationtesting/batch-1.json +++ b/irs-api/src/test/resources/__files/integrationtesting/batch-1.json @@ -17,6 +17,6 @@ "partTypeInformation": { "manufacturerPartId": "123-0.740-3434-A", "classification": "product", - "nameAtManufacturer": "Glue" + "nameAtManufacturer": "Cathode" } } \ No newline at end of file diff --git a/irs-api/src/test/resources/__files/integrationtesting/batch-2.json b/irs-api/src/test/resources/__files/integrationtesting/batch-2.json new file mode 100644 index 0000000000..d86f962cb3 --- /dev/null +++ b/irs-api/src/test/resources/__files/integrationtesting/batch-2.json @@ -0,0 +1,22 @@ +{ + "localIdentifiers": [ + { + "value": "BPNL00000000TEST", + "key": "manufacturerId" + }, + { + "value": "BID12345678", + "key": "batchId" + } + ], + "manufacturingInformation": { + "date": "2022-02-04T14:48:54", + "country": "HUR" + }, + "catenaXId": "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5", + "partTypeInformation": { + "manufacturerPartId": "123-0.740-3434-A", + "classification": "product", + "nameAtManufacturer": "Polyamid" + } +} \ No newline at end of file diff --git a/irs-api/src/test/resources/__files/integrationtesting/batch-3.json b/irs-api/src/test/resources/__files/integrationtesting/batch-3.json new file mode 100644 index 0000000000..f62643532a --- /dev/null +++ b/irs-api/src/test/resources/__files/integrationtesting/batch-3.json @@ -0,0 +1,22 @@ +{ + "localIdentifiers": [ + { + "value": "BPNL00000000TEST", + "key": "manufacturerId" + }, + { + "value": "BID12345678", + "key": "batchId" + } + ], + "manufacturingInformation": { + "date": "2022-02-04T14:48:54", + "country": "HUR" + }, + "catenaXId": "urn:uuid:a314ad6b-77ea-417e-ae2d-193b3e249e99", + "partTypeInformation": { + "manufacturerPartId": "123-0.740-3434-A", + "classification": "product", + "nameAtManufacturer": "Generic Chemical" + } +} \ No newline at end of file diff --git a/irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-2.json b/irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-2.json new file mode 100644 index 0000000000..594e51a4f2 --- /dev/null +++ b/irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-2.json @@ -0,0 +1,16 @@ +{ + "catenaXId": "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5", + "childItems": [ + { + "catenaXId": "urn:uuid:a314ad6b-77ea-417e-ae2d-193b3e249e99", + "quantity": { + "quantityNumber": 0.2014, + "measurementUnit": "unit:kilogram" + }, + "hasAlternatives": true, + "businessPartner": "BPNL00000000TEST", + "createdOn": "2022-02-03T14:48:54.709Z", + "lastModifiedOn": "2022-02-03T14:48:54.709Z" + } + ] +} \ No newline at end of file diff --git a/irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-3.json b/irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-3.json new file mode 100644 index 0000000000..69e7778525 --- /dev/null +++ b/irs-api/src/test/resources/__files/integrationtesting/singleLevelBomAsBuilt-3.json @@ -0,0 +1,4 @@ +{ + "catenaXId": "urn:uuid:a314ad6b-77ea-417e-ae2d-193b3e249e99", + "childItems": [] +} \ No newline at end of file From 8be241017e907ebe18c0e54b6bcef5f37ef35b68 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Thu, 1 Feb 2024 17:09:35 +0100 Subject: [PATCH 20/22] feat(testing):[#344] Renaming *WireMockConfig to *WireMockSupport, refactoring --- .../irs/IrsWireMockIntegrationTest.java | 122 +++++++-------- .../tractusx/irs/WireMockTestConfig.java | 116 -------------- .../eclipse/tractusx/irs/WiremockSupport.java | 142 ++++++++++++++++++ ...ckConfig.java => BpdmWireMockSupport.java} | 29 +++- .../tractusx/irs/bpdm/BpdmWiremockTest.java | 26 ++-- .../semanticshub/SemanticHubWiremockTest.java | 65 ++------ .../client/SubmodelFacadeWiremockTest.java | 8 +- ...igitalTwinRegistryServiceWiremockTest.java | 36 ++--- ...a => DiscoveryServiceWiremockSupport.java} | 4 +- ...ockConfig.java => DtrWiremockSupport.java} | 10 +- ...ava => SubmodelFacadeWiremockSupport.java} | 4 +- 11 files changed, 283 insertions(+), 279 deletions(-) create mode 100644 irs-api/src/test/java/org/eclipse/tractusx/irs/WiremockSupport.java rename irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/{BpdmWireMockConfig.java => BpdmWireMockSupport.java} (68%) rename irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/{DiscoveryServiceWiremockConfig.java => DiscoveryServiceWiremockSupport.java} (97%) rename irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/{DtrWiremockConfig.java => DtrWiremockSupport.java} (97%) rename irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/{SubmodelFacadeWiremockConfig.java => SubmodelFacadeWiremockSupport.java} (99%) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java index 1b93697317..5bd23a282a 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsWireMockIntegrationTest.java @@ -25,28 +25,25 @@ import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.irs.WireMockTestConfig.createEndpointDataReference; -import static org.eclipse.tractusx.irs.WireMockTestConfig.randomUUID; -import static org.eclipse.tractusx.irs.WireMockTestConfig.successfulDataRequests; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_URL; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.EDC_DISCOVERY_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.TEST_BPN; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder200; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder404; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscoveryEmpty200; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.DATAPLANE_PUBLIC_URL; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.LOOKUP_SHELLS_TEMPLATE; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.PUBLIC_LOOKUP_SHELLS_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.PUBLIC_SHELL_DESCRIPTORS_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.SHELL_DESCRIPTORS_TEMPLATE; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getLookupShells200; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getShellDescriptor200; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.submodelDescriptor; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_CATALOG; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_NEGOTIATE; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_STATE; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_TRANSFER; +import static org.eclipse.tractusx.irs.WiremockSupport.createEndpointDataReference; +import static org.eclipse.tractusx.irs.WiremockSupport.randomUUID; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_URL; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.EDC_DISCOVERY_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.TEST_BPN; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.postDiscoveryFinder200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.postDiscoveryFinder404; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.postEdcDiscoveryEmpty200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.LOOKUP_SHELLS_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.PUBLIC_LOOKUP_SHELLS_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.PUBLIC_SHELL_DESCRIPTORS_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.SHELL_DESCRIPTORS_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.getLookupShells200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.getShellDescriptor200; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockSupport.PATH_CATALOG; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockSupport.PATH_NEGOTIATE; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockSupport.PATH_STATE; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockSupport.PATH_TRANSFER; import java.time.Duration; import java.util.List; @@ -54,7 +51,7 @@ import com.github.tomakehurst.wiremock.junit5.WireMockTest; import org.awaitility.Awaitility; -import org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig; +import org.eclipse.tractusx.irs.bpdm.BpdmWireMockSupport; import org.eclipse.tractusx.irs.component.JobHandle; import org.eclipse.tractusx.irs.component.Jobs; import org.eclipse.tractusx.irs.component.RegisterJob; @@ -62,13 +59,13 @@ import org.eclipse.tractusx.irs.data.StringMapper; import org.eclipse.tractusx.irs.edc.client.EndpointDataReferenceStorage; import org.eclipse.tractusx.irs.semanticshub.AspectModels; -import org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig; +import org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockSupport; import org.eclipse.tractusx.irs.services.IrsItemGraphQueryService; import org.eclipse.tractusx.irs.services.SemanticHubService; import org.eclipse.tractusx.irs.services.validation.SchemaNotFoundException; import org.eclipse.tractusx.irs.testing.containers.MinioContainer; -import org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig; -import org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig; +import org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport; +import org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockSupport; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -110,7 +107,7 @@ class IrsWireMockIntegrationTest { @BeforeAll static void startContainer() { minioContainer.start(); - WireMockTestConfig.successfulSemanticModelRequest(); + WiremockSupport.successfulSemanticModelRequest(); } @AfterEach @@ -126,13 +123,13 @@ static void stopContainer() { @DynamicPropertySource static void configureProperties(DynamicPropertyRegistry registry) { - registry.add("bpdm.bpnEndpoint", () -> BpdmWireMockConfig.BPDM_TEST); + registry.add("bpdm.bpnEndpoint", () -> BpdmWireMockSupport.BPDM_URL_TEMPLATE); registry.add("digitalTwinRegistry.discoveryFinderUrl", () -> DISCOVERY_FINDER_URL); registry.add("digitalTwinRegistry.shellDescriptorTemplate", () -> SHELL_DESCRIPTORS_TEMPLATE); registry.add("digitalTwinRegistry.lookupShellsTemplate", () -> LOOKUP_SHELLS_TEMPLATE); registry.add("digitalTwinRegistry.type", () -> "decentral"); registry.add("semanticshub.url", () -> SEMANTIC_HUB_URL); - registry.add("semanticshub.modelJsonSchemaEndpoint", () -> SemanticHubWireMockConfig.SEMANTIC_HUB_SCHEMA_URL); + registry.add("semanticshub.modelJsonSchemaEndpoint", () -> SemanticHubWireMockSupport.SEMANTIC_HUB_SCHEMA_URL); registry.add("semanticshub.defaultUrns", () -> ""); registry.add("irs-edc-client.controlplane.endpoint.data", () -> EDC_URL); registry.add("irs-edc-client.controlplane.endpoint.catalog", () -> PATH_CATALOG); @@ -147,7 +144,7 @@ static void configureProperties(DynamicPropertyRegistry registry) { @Test void shouldStartApplicationAndCollectSemanticModels() throws SchemaNotFoundException { // Arrange - WireMockTestConfig.successfulSemanticModelRequest(); + WiremockSupport.successfulSemanticModelRequest(); // Act final AspectModels allAspectModels = semanticHubService.getAllAspectModels(); @@ -162,18 +159,18 @@ void shouldStopJobAfterDepthIsReached() { final String globalAssetIdLevel1 = "globalAssetId"; final String globalAssetIdLevel2 = "urn:uuid:6d505432-8b31-4966-9514-4b753372683f"; - WireMockTestConfig.successfulSemanticModelRequest(); - WireMockTestConfig.successfulSemanticHubRequests(); - WireMockTestConfig.successfulDiscovery(); + WiremockSupport.successfulSemanticModelRequest(); + WiremockSupport.successfulSemanticHubRequests(); + WiremockSupport.successfulDiscovery(); successfulRegistryAndDataRequest(globalAssetIdLevel1, "Cathode", TEST_BPN, "integrationtesting/batch-1.json", "integrationtesting/singleLevelBomAsBuilt-1.json"); successfulRegistryAndDataRequest(globalAssetIdLevel2, "Polyamid", TEST_BPN, "integrationtesting/batch-2.json", "integrationtesting/singleLevelBomAsBuilt-2.json"); - WireMockTestConfig.successfulBpdmRequests(); + BpdmWireMockSupport.bpdmWillReturnCompanyName(DiscoveryServiceWiremockSupport.TEST_BPN, "Company Name"); - final RegisterJob request = WireMockTestConfig.jobRequest(globalAssetIdLevel1, TEST_BPN, 1); + final RegisterJob request = WiremockSupport.jobRequest(globalAssetIdLevel1, TEST_BPN, 1); // Act final JobHandle jobHandle = irsService.registerItemJob(request); @@ -183,8 +180,8 @@ void shouldStopJobAfterDepthIsReached() { Jobs jobForJobId = irsService.getJobForJobId(jobHandle.getId(), true); // Assert - WireMockTestConfig.verifyDiscoveryCalls(1); - WireMockTestConfig.verifyNegotiationCalls(3); + WiremockSupport.verifyDiscoveryCalls(1); + WiremockSupport.verifyNegotiationCalls(3); assertThat(jobForJobId.getJob().getState()).isEqualTo(JobState.COMPLETED); assertThat(jobForJobId.getShells()).hasSize(2); @@ -195,10 +192,10 @@ void shouldStopJobAfterDepthIsReached() { @Test void shouldCreateTombstoneWhenDiscoveryServiceNotAvailable() { // Arrange - WireMockTestConfig.successfulSemanticModelRequest(); + WiremockSupport.successfulSemanticModelRequest(); stubFor(postDiscoveryFinder404()); final String globalAssetId = "globalAssetId"; - final RegisterJob request = WireMockTestConfig.jobRequest(globalAssetId, TEST_BPN, 1); + final RegisterJob request = WiremockSupport.jobRequest(globalAssetId, TEST_BPN, 1); // Act final JobHandle jobHandle = irsService.registerItemJob(request); @@ -220,11 +217,11 @@ void shouldCreateTombstoneWhenDiscoveryServiceNotAvailable() { @Test void shouldCreateTombstoneWhenEdcDiscoveryIsEmpty() { // Arrange - WireMockTestConfig.successfulSemanticModelRequest(); + WiremockSupport.successfulSemanticModelRequest(); stubFor(postDiscoveryFinder200()); stubFor(postEdcDiscoveryEmpty200()); final String globalAssetId = "globalAssetId"; - final RegisterJob request = WireMockTestConfig.jobRequest(globalAssetId, TEST_BPN, 1); + final RegisterJob request = WiremockSupport.jobRequest(globalAssetId, TEST_BPN, 1); // Act final JobHandle jobHandle = irsService.registerItemJob(request); @@ -234,7 +231,7 @@ void shouldCreateTombstoneWhenEdcDiscoveryIsEmpty() { waitForCompletion(jobHandle); final Jobs jobForJobId = irsService.getJobForJobId(jobHandle.getId(), true); - WireMockTestConfig.verifyDiscoveryCalls(1); + WiremockSupport.verifyDiscoveryCalls(1); assertThat(jobForJobId.getJob().getState()).isEqualTo(JobState.COMPLETED); assertThat(jobForJobId.getShells()).isEmpty(); @@ -249,9 +246,9 @@ void shouldStartRecursiveProcesses() { final String globalAssetIdLevel2 = "urn:uuid:7e4541ea-bb0f-464c-8cb3-021abccbfaf5"; final String globalAssetIdLevel3 = "urn:uuid:a314ad6b-77ea-417e-ae2d-193b3e249e99"; - WireMockTestConfig.successfulSemanticModelRequest(); - WireMockTestConfig.successfulSemanticHubRequests(); - WireMockTestConfig.successfulDiscovery(); + WiremockSupport.successfulSemanticModelRequest(); + WiremockSupport.successfulSemanticHubRequests(); + WiremockSupport.successfulDiscovery(); successfulRegistryAndDataRequest(globalAssetIdLevel1, "Cathode", TEST_BPN, "integrationtesting/batch-1.json", "integrationtesting/singleLevelBomAsBuilt-1.json"); @@ -260,9 +257,9 @@ void shouldStartRecursiveProcesses() { successfulRegistryAndDataRequest(globalAssetIdLevel3, "GenericChemical", TEST_BPN, "integrationtesting/batch-3.json", "integrationtesting/singleLevelBomAsBuilt-3.json"); - WireMockTestConfig.successfulBpdmRequests(); + BpdmWireMockSupport.bpdmWillReturnCompanyName(DiscoveryServiceWiremockSupport.TEST_BPN, "Company Name"); - final RegisterJob request = WireMockTestConfig.jobRequest(globalAssetIdLevel1, TEST_BPN, 4); + final RegisterJob request = WiremockSupport.jobRequest(globalAssetIdLevel1, TEST_BPN, 4); // Act final JobHandle jobHandle = irsService.registerItemJob(request); @@ -279,34 +276,29 @@ void shouldStartRecursiveProcesses() { assertThat(jobForJobId.getTombstones()).isEmpty(); assertThat(jobForJobId.getSubmodels()).hasSize(6); - WireMockTestConfig.verifyDiscoveryCalls(1); - WireMockTestConfig.verifyNegotiationCalls(6); + WiremockSupport.verifyDiscoveryCalls(1); + WiremockSupport.verifyNegotiationCalls(6); } private void successfulRegistryAndDataRequest(final String globalAssetId, final String idShort, final String bpn, final String batchFileName, final String sbomFileName) { - final String edcAssetId = WireMockTestConfig.randomUUIDwithPrefix(); - final String batchId = WireMockTestConfig.randomUUIDwithPrefix(); - final String batch = submodelDescriptor(DATAPLANE_PUBLIC_URL, edcAssetId, - DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, "Batch", batchId, - "urn:samm:io.catenax.batch:2.0.0#Batch"); - successfulDataRequests(batchId, batchFileName); - - final String sbomId = WireMockTestConfig.randomUUIDwithPrefix(); - final String singleLevelBomAsBuilt = submodelDescriptor(DATAPLANE_PUBLIC_URL, edcAssetId, - DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, "SingleLevelBomAsBuilt", sbomId, - "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt"); - final List submodelDescriptors = List.of(batch, singleLevelBomAsBuilt); - successfulDataRequests(sbomId, sbomFileName); + final String edcAssetId = WiremockSupport.randomUUIDwithPrefix(); + final String batch = WiremockSupport.submodelRequest(edcAssetId, "Batch", + "urn:samm:io.catenax.batch:2.0.0#Batch", batchFileName); + + final String singleLevelBomAsBuilt = WiremockSupport.submodelRequest(edcAssetId, "SingleLevelBomAsBuilt", + "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt", sbomFileName); + successfulNegotiation(edcAssetId); + final List submodelDescriptors = List.of(batch, singleLevelBomAsBuilt); - final String shellId = WireMockTestConfig.randomUUIDwithPrefix(); + final String shellId = WiremockSupport.randomUUIDwithPrefix(); final String registryEdcAssetId = "registry-asset"; successfulNegotiation(registryEdcAssetId); stubFor(getLookupShells200(PUBLIC_LOOKUP_SHELLS_PATH, List.of(shellId)).withQueryParam("assetIds", containing(globalAssetId))); - stubFor(getShellDescriptor200(PUBLIC_SHELL_DESCRIPTORS_PATH + WireMockTestConfig.encodedId(shellId), bpn, + stubFor(getShellDescriptor200(PUBLIC_SHELL_DESCRIPTORS_PATH + WiremockSupport.encodedId(shellId), bpn, submodelDescriptors, globalAssetId, shellId, idShort)); } @@ -314,7 +306,7 @@ private void successfulNegotiation(final String edcAssetId) { final String negotiationId = randomUUID(); final String transferProcessId = randomUUID(); final String contractAgreementId = "%s:%s:%s".formatted(randomUUID(), edcAssetId, randomUUID()); - SubmodelFacadeWiremockConfig.prepareNegotiation(negotiationId, transferProcessId, contractAgreementId, + SubmodelFacadeWiremockSupport.prepareNegotiation(negotiationId, transferProcessId, contractAgreementId, edcAssetId); endpointDataReferenceStorage.put(contractAgreementId, createEndpointDataReference(contractAgreementId)); } diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java index 2db79977e6..8c41604857 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/WireMockTestConfig.java @@ -19,52 +19,18 @@ ********************************************************************************/ package org.eclipse.tractusx.irs; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; -import static com.github.tomakehurst.wiremock.client.WireMock.verify; -import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig.bpdmResponse; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.BPDM_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.DISCOVERY_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.DTR_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.EDC_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.NO_ERROR_REST_TEMPLATE; import static org.eclipse.tractusx.irs.configuration.RestTemplateConfig.SEMHUB_REST_TEMPLATE; -import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.batchSchemaResponse200; -import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.singleLevelBomAsBuiltSchemaResponse200; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.EDC_DISCOVERY_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.TEST_BPN; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder200; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscovery200; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.DATAPLANE_PUBLIC_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.DATAPLANE_HOST; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_CATALOG; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_DATAPLANE_PUBLIC; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_NEGOTIATE; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_STATE; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_TRANSFER; -import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; -import java.nio.charset.StandardCharsets; -import java.util.Base64; import java.util.List; -import java.util.Map; -import java.util.UUID; import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.edc.policy.model.PolicyRegistrationTypes; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.irs.component.PartChainIdentificationKey; -import org.eclipse.tractusx.irs.component.RegisterJob; -import org.eclipse.tractusx.irs.component.enums.Direction; -import org.eclipse.tractusx.irs.data.StringMapper; -import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration; -import org.eclipse.tractusx.irs.edc.client.model.EDRAuthCode; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; @@ -131,86 +97,4 @@ RestTemplate semanticHubRestTemplate() { return restTemplateProxy(PROXY_SERVER_HOST, HTTP_PORT); } - public static EndpointDataReference createEndpointDataReference(final String contractAgreementId) { - final EDRAuthCode edrAuthCode = EDRAuthCode.builder() - .cid(contractAgreementId) - .dad("test") - .exp(9999999999L) - .build(); - final String b64EncodedAuthCode = Base64.getUrlEncoder() - .encodeToString(StringMapper.mapToString(edrAuthCode) - .getBytes(StandardCharsets.UTF_8)); - final String jwtToken = "eyJhbGciOiJSUzI1NiJ9." + b64EncodedAuthCode + ".test"; - return EndpointDataReference.Builder.newInstance() - .authKey("testkey") - .authCode(jwtToken) - .properties( - Map.of(JsonLdConfiguration.NAMESPACE_EDC_CID, contractAgreementId)) - .endpoint(DATAPLANE_HOST + PATH_DATAPLANE_PUBLIC) - .build(); - } - - static void successfulSemanticModelRequest() { - stubFor(get(urlPathEqualTo("/models")).willReturn( - responseWithStatus(200).withBodyFile("semantichub/all-models-page-IT.json"))); - } - - static RegisterJob jobRequest(final String globalAssetId, final String bpn, final int depth) { - return RegisterJob.builder() - .key(PartChainIdentificationKey.builder().bpn(bpn).globalAssetId(globalAssetId).build()) - .depth(depth) - .aspects(List.of("Batch", "SingleLevelBomAsBuilt")) - .collectAspects(true) - .lookupBPNs(true) - .direction(Direction.DOWNWARD) - .build(); - } - - static void successfulDiscovery() { - stubFor(postDiscoveryFinder200()); - stubFor(postEdcDiscovery200()); - } - - static String encodedId(final String shellId) { - return org.apache.commons.codec.binary.Base64.encodeBase64String(shellId.getBytes(StandardCharsets.UTF_8)); - } - - static void verifyDiscoveryCalls(final int times) { - verify(times, postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); - verify(times, postRequestedFor(urlPathEqualTo(EDC_DISCOVERY_PATH))); - } - - static void verifyNegotiationCalls(final int times) { - verify(times, postRequestedFor(urlPathEqualTo(PATH_NEGOTIATE))); - verify(times, postRequestedFor(urlPathEqualTo(PATH_CATALOG))); - verify(times * 2, getRequestedFor(urlPathMatching(PATH_NEGOTIATE + "/.*"))); - verify(times, getRequestedFor(urlPathMatching(PATH_NEGOTIATE + "/.*" + PATH_STATE))); - verify(times, postRequestedFor(urlPathEqualTo(PATH_TRANSFER))); - verify(times * 2, getRequestedFor(urlPathMatching(PATH_TRANSFER + "/.*"))); - verify(times, getRequestedFor(urlPathMatching(PATH_TRANSFER + "/.*" + PATH_STATE))); - } - - static void successfulBpdmRequests() { - stubFor(get(urlPathMatching("/legal-entities/.*")).willReturn( - responseWithStatus(200).withBody(bpdmResponse(TEST_BPN, "Company Name")))); - } - - static void successfulDataRequests(final String assetId, final String fileName) { - stubFor(get(urlPathMatching(DATAPLANE_PUBLIC_PATH + "/" + assetId)).willReturn( - responseWithStatus(200).withBodyFile(fileName))); - } - - static void successfulSemanticHubRequests() { - stubFor(batchSchemaResponse200()); - stubFor(singleLevelBomAsBuiltSchemaResponse200()); - } - - static String randomUUIDwithPrefix() { - final String uuidPrefix = "urn:uuid:"; - return uuidPrefix + randomUUID(); - } - - static String randomUUID() { - return UUID.randomUUID().toString(); - } } diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/WiremockSupport.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/WiremockSupport.java new file mode 100644 index 0000000000..9698272e7c --- /dev/null +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/WiremockSupport.java @@ -0,0 +1,142 @@ +/******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs; + +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.apache.commons.codec.binary.Base64.encodeBase64String; +import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockSupport.semanticHubWillReturnAllModels; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.DATAPLANE_PUBLIC_URL; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.submodelDescriptor; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.irs.component.PartChainIdentificationKey; +import org.eclipse.tractusx.irs.component.RegisterJob; +import org.eclipse.tractusx.irs.component.enums.Direction; +import org.eclipse.tractusx.irs.data.StringMapper; +import org.eclipse.tractusx.irs.edc.client.configuration.JsonLdConfiguration; +import org.eclipse.tractusx.irs.edc.client.model.EDRAuthCode; +import org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockSupport; +import org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport; +import org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport; +import org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockSupport; + +public class WiremockSupport { + public static EndpointDataReference createEndpointDataReference(final String contractAgreementId) { + final EDRAuthCode edrAuthCode = EDRAuthCode.builder() + .cid(contractAgreementId) + .dad("test") + .exp(9999999999L) + .build(); + final String b64EncodedAuthCode = Base64.getUrlEncoder() + .encodeToString(StringMapper.mapToString(edrAuthCode) + .getBytes(StandardCharsets.UTF_8)); + final String jwtToken = "eyJhbGciOiJSUzI1NiJ9." + b64EncodedAuthCode + ".test"; + return EndpointDataReference.Builder.newInstance() + .authKey("testkey") + .authCode(jwtToken) + .properties( + Map.of(JsonLdConfiguration.NAMESPACE_EDC_CID, contractAgreementId)) + .endpoint(SubmodelFacadeWiremockSupport.DATAPLANE_HOST + + SubmodelFacadeWiremockSupport.PATH_DATAPLANE_PUBLIC) + .build(); + } + + static void successfulSemanticModelRequest() { + semanticHubWillReturnAllModels("semantichub/all-models-page-IT.json"); + } + + static RegisterJob jobRequest(final String globalAssetId, final String bpn, final int depth) { + return RegisterJob.builder() + .key(PartChainIdentificationKey.builder().bpn(bpn).globalAssetId(globalAssetId).build()) + .depth(depth) + .aspects(List.of("Batch", "SingleLevelBomAsBuilt")) + .collectAspects(true) + .lookupBPNs(true) + .direction(Direction.DOWNWARD) + .build(); + } + + static void successfulDiscovery() { + stubFor(DiscoveryServiceWiremockSupport.postDiscoveryFinder200()); + stubFor(DiscoveryServiceWiremockSupport.postEdcDiscovery200()); + } + + static String encodedId(final String shellId) { + return encodeBase64String(shellId.getBytes(StandardCharsets.UTF_8)); + } + + static void verifyDiscoveryCalls(final int times) { + verify(times, postRequestedFor(urlPathEqualTo(DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_PATH))); + verify(times, postRequestedFor(urlPathEqualTo(DiscoveryServiceWiremockSupport.EDC_DISCOVERY_PATH))); + } + + static void verifyNegotiationCalls(final int times) { + verify(times, postRequestedFor(urlPathEqualTo(SubmodelFacadeWiremockSupport.PATH_NEGOTIATE))); + verify(times, postRequestedFor(urlPathEqualTo(SubmodelFacadeWiremockSupport.PATH_CATALOG))); + verify(times * 2, getRequestedFor(urlPathMatching(SubmodelFacadeWiremockSupport.PATH_NEGOTIATE + "/.*"))); + verify(times, getRequestedFor(urlPathMatching( + SubmodelFacadeWiremockSupport.PATH_NEGOTIATE + "/.*" + SubmodelFacadeWiremockSupport.PATH_STATE))); + verify(times, postRequestedFor(urlPathEqualTo(SubmodelFacadeWiremockSupport.PATH_TRANSFER))); + verify(times * 2, getRequestedFor(urlPathMatching(SubmodelFacadeWiremockSupport.PATH_TRANSFER + "/.*"))); + verify(times, getRequestedFor(urlPathMatching( + SubmodelFacadeWiremockSupport.PATH_TRANSFER + "/.*" + SubmodelFacadeWiremockSupport.PATH_STATE))); + } + + static void successfulDataRequests(final String assetId, final String fileName) { + stubFor(get(urlPathMatching(DtrWiremockSupport.DATAPLANE_PUBLIC_PATH + "/" + assetId)).willReturn( + responseWithStatus(200).withBodyFile(fileName))); + } + + static void successfulSemanticHubRequests() { + SemanticHubWireMockSupport.semanticHubWillReturnBatchSchema(); + SemanticHubWireMockSupport.semanticHubWillReturnSingleLevelBomAsBuiltSchema(); + } + + static String randomUUIDwithPrefix() { + final String uuidPrefix = "urn:uuid:"; + return uuidPrefix + randomUUID(); + } + + static String randomUUID() { + return UUID.randomUUID().toString(); + } + + static String submodelRequest(final String edcAssetId, final String SingleLevelBomAsBuilt, final String semanticId, + final String sbomFileName) { + final String sbomId = randomUUIDwithPrefix(); + final String submoodel = submodelDescriptor(DATAPLANE_PUBLIC_URL, edcAssetId, + DiscoveryServiceWiremockSupport.CONTROLPLANE_PUBLIC_URL, SingleLevelBomAsBuilt, sbomId, semanticId); + successfulDataRequests(sbomId, sbomFileName); + return submoodel; + } +} \ No newline at end of file diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockSupport.java similarity index 68% rename from irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java rename to irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockSupport.java index 45bcb93a89..d7af399fcc 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockConfig.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWireMockSupport.java @@ -19,14 +19,36 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.bpdm; +import static com.github.tomakehurst.wiremock.client.WireMock.exactly; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; + /** * WireMock configurations and requests used for testing BPDM flow. */ -public final class BpdmWireMockConfig { +public final class BpdmWireMockSupport { + + public static final String BPN_PATH = "/legal-entities/"; + public static final String BPDM_URL_TEMPLATE = "http://bpdm.test" + BPN_PATH + "{partnerId}?idType={idType}"; + + private BpdmWireMockSupport() { + } - public static final String BPDM_TEST = "http://bpdm.test/legal-entities/{partnerId}?idType={idType}"; + public static void bpdmWillReturnCompanyName(final String bpn, final String companyName) { + stubFor(get(urlPathEqualTo(BPN_PATH + bpn)).willReturn( + responseWithStatus(200).withBody(bpdmResponse(bpn, companyName)))); + } + + public static void bpdmWillNotFindCompanyName(final String bpn) { + stubFor(get(urlPathEqualTo(BPN_PATH + bpn)).willReturn(responseWithStatus(404))); + } - private BpdmWireMockConfig() { + public static void verifyBpdmWasCalledWithBPN(final String bpn, final int times) { + verify(exactly(times), getRequestedFor(urlPathEqualTo(BPN_PATH + bpn))); } public static String bpdmResponse(final String bpn, final String companyName) { @@ -84,4 +106,5 @@ public static String bpdmResponse(final String bpn, final String companyName) { } """.formatted(bpn, bpn, companyName); } + } \ No newline at end of file diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java index bc375f55b2..5041293e43 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java @@ -19,14 +19,12 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.bpdm; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig.BPDM_TEST; -import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockConfig.bpdmResponse; -import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; +import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockSupport.BPDM_URL_TEMPLATE; +import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockSupport.bpdmWillNotFindCompanyName; +import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockSupport.bpdmWillReturnCompanyName; +import static org.eclipse.tractusx.irs.bpdm.BpdmWireMockSupport.verifyBpdmWasCalledWithBPN; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import java.util.Optional; @@ -47,30 +45,34 @@ class BpdmWiremockTest { void setUp(WireMockRuntimeInfo wireMockRuntimeInfo) { final RestTemplate restTemplate = restTemplateProxy(PROXY_SERVER_HOST, wireMockRuntimeInfo.getHttpPort()); - bpdmFacade = new BpdmFacade(new BpdmClientImpl(restTemplate, BPDM_TEST)); + bpdmFacade = new BpdmFacade(new BpdmClientImpl(restTemplate, BPDM_URL_TEMPLATE)); } @Test void shouldResolveManufacturerName() { // Arrange - givenThat(get(urlPathEqualTo("/legal-entities/BPNL00000000TEST")).willReturn( - responseWithStatus(200).withBody(bpdmResponse("BPNL00000000TEST", "TEST_BPN_DFT_1")))); + final String bpn = "BPNL00000000TEST"; + bpdmWillReturnCompanyName(bpn, "TEST_BPN_DFT_1"); // Act - final Optional manufacturerName = bpdmFacade.findManufacturerName("BPNL00000000TEST"); + final Optional manufacturerName = bpdmFacade.findManufacturerName(bpn); // Assert assertThat(manufacturerName).isPresent().contains("TEST_BPN_DFT_1"); + verifyBpdmWasCalledWithBPN(bpn, 1); } @Test void shouldReturnEmptyOnNotFound() { // Arrange - givenThat(get(urlPathEqualTo("/legal-entities/BPNL00000000TEST")).willReturn(responseWithStatus(404))); + final String bpn = "BPNL00000000TEST"; + bpdmWillNotFindCompanyName(bpn); // Act & Assert // TODO fix implementation to not throw HttpClientErrorException$NotFound assertThatExceptionOfType(HttpClientErrorException.class).isThrownBy( - () -> bpdmFacade.findManufacturerName("BPNL00000000TEST")); + () -> bpdmFacade.findManufacturerName(bpn)); + verifyBpdmWasCalledWithBPN(bpn, 1); } + } diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java index 99ad8e8657..6558c3d523 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWiremockTest.java @@ -23,23 +23,12 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.semanticshub; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.exactly; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; -import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.SEMANTIC_HUB_SCHEMA_URL; -import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockConfig.batchSchemaResponse200; -import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; +import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockSupport.SEMANTIC_HUB_SCHEMA_URL; +import static org.eclipse.tractusx.irs.semanticshub.SemanticHubWireMockSupport.semanticHubWillReturnBatchSchema; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; -import com.github.tomakehurst.wiremock.client.MappingBuilder; import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; import com.github.tomakehurst.wiremock.junit5.WireMockTest; import org.eclipse.tractusx.irs.configuration.SemanticsHubConfiguration; @@ -53,15 +42,6 @@ class SemanticHubWiremockTest { private static final String PROXY_SERVER_HOST = "127.0.0.1"; private SemanticsHubFacade semanticsHubFacade; - private static MappingBuilder getAllModels200() { - return get(urlPathEqualTo("/models")).withHost(equalTo("semantic.hub")) - .willReturn(responseWithStatus(200).withBodyFile("all-models-page.json")); - } - - private static void verifyGetAllModels(final int times) { - verify(exactly(times), getRequestedFor(urlPathEqualTo("/models"))); - } - @BeforeEach void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { final RestTemplate restTemplate = restTemplateProxy(PROXY_SERVER_HOST, wireMockRuntimeInfo.getHttpPort()); @@ -77,39 +57,31 @@ void configureSystemUnderTest(WireMockRuntimeInfo wireMockRuntimeInfo) { @Test void shouldReturn1Page() throws SchemaNotFoundException { - givenThat(getAllModels200()); + SemanticHubWireMockSupport.semanticHubWillReturnAllModels("all-models-page.json"); final AspectModels allAspectModels = semanticsHubFacade.getAllAspectModels(); assertThat(allAspectModels.models()).isNotEmpty(); assertThat(allAspectModels.models().get(0).name()).isEqualTo("SerialPartTypization"); - verifyGetAllModels(1); + SemanticHubWireMockSupport.verifySemanticHubWasCalledForAllModels(1); } @Test void shouldReturn2Pages() throws SchemaNotFoundException { - givenThat(get(urlPathEqualTo("/models")).withHost(equalTo("semantic.hub")) - .withQueryParam("page", equalTo("0")) - .withQueryParam("pageSize", equalTo("10")) - .willReturn( - responseWithStatus(200).withBodyFile("all-models-page1.json"))); - givenThat(get(urlPathEqualTo("/models")).withHost(equalTo("semantic.hub")) - .withQueryParam("page", equalTo("1")) - .withQueryParam("pageSize", equalTo("10")) - .willReturn( - responseWithStatus(200).withBodyFile("all-models-page2.json"))); + SemanticHubWireMockSupport.semanticHubWillReturnPagedModels(0, 10, "all-models-page1.json"); + SemanticHubWireMockSupport.semanticHubWillReturnPagedModels(1, 10, "all-models-page2.json"); final AspectModels allAspectModels = semanticsHubFacade.getAllAspectModels(); assertThat(allAspectModels.models()).hasSize(20); assertThat(allAspectModels.models().get(0).name()).isEqualTo("SerialPartTypization"); - verifyGetAllModels(2); + SemanticHubWireMockSupport.verifySemanticHubWasCalledForAllModels(2); } @Test void shouldReturnJsonSchema() throws SchemaNotFoundException { // Arrange - stubFor(batchSchemaResponse200()); + semanticHubWillReturnBatchSchema(); // Act final String modelJsonSchema = semanticsHubFacade.getModelJsonSchema("urn:samm:io.catenax.batch:2.0.0#Batch"); @@ -117,30 +89,19 @@ void shouldReturnJsonSchema() throws SchemaNotFoundException { // Assert assertThat(modelJsonSchema).contains("urn_samm_io.catenax.batch_2.0.0_CatenaXIdTrait") .contains("A batch is a quantity of (semi-) finished products or (raw) material"); - verify(exactly(1), - getRequestedFor(urlPathMatching("/models/urn:samm:io.catenax.batch:2.0.0%23Batch/json-schema"))); + SemanticHubWireMockSupport.verifySemanticHubWasCalledForModel("urn:samm:io.catenax.batch:2.0.0%23Batch", 1); } @Test void shouldThrowSchemaExceptionWhenSchemaNotFound() { // Arrange - final String url = "/models/%s/json-schema".formatted( - "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0%23SingleLevelBomAsBuilt"); - final String errorBody = """ - { - "timestamp": "2024-01-24T12:06:23.390+00:00", - "status": 500, - "error": "Internal Server Error", - "path": "/api/v1/models/urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt/json-schema" - } - """; - System.out.println(url); - stubFor(get(urlPathEqualTo(url)).withHost(equalTo("semantic.hub")) - .willReturn(responseWithStatus(500).withBody(errorBody))); + final String semanticModel = "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0%23SingleLevelBomAsBuilt"; + SemanticHubWireMockSupport.semanticHubWillThrowErrorForSemanticModel(semanticModel); // Act & Assert assertThatExceptionOfType(SchemaNotFoundException.class).isThrownBy(() -> semanticsHubFacade.getModelJsonSchema( "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt")); - verify(exactly(1), getRequestedFor(urlPathEqualTo(url))); + SemanticHubWireMockSupport.verifySemanticHubWasCalledForModel(semanticModel, 1); } + } diff --git a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java index 7f0652c538..7f5a11e4be 100644 --- a/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java +++ b/irs-edc-client/src/test/java/org/eclipse/tractusx/irs/edc/client/SubmodelFacadeWiremockTest.java @@ -29,8 +29,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.eclipse.tractusx.irs.edc.client.testutil.TestMother.createEdcTransformer; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.DATAPLANE_HOST; -import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig.PATH_DATAPLANE_PUBLIC; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockSupport.DATAPLANE_HOST; +import static org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockSupport.PATH_DATAPLANE_PUBLIC; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import static org.mockito.Mockito.mock; @@ -70,7 +70,7 @@ import org.eclipse.tractusx.irs.edc.client.policy.Permission; import org.eclipse.tractusx.irs.edc.client.policy.PolicyCheckerService; import org.eclipse.tractusx.irs.edc.client.policy.PolicyType; -import org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockConfig; +import org.eclipse.tractusx.irs.testing.wiremock.SubmodelFacadeWiremockSupport; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.converter.HttpMessageConverter; @@ -242,7 +242,7 @@ void shouldThrowExceptionWhenResponse_500() { } private void prepareNegotiation() { - final String contractAgreementId = SubmodelFacadeWiremockConfig.prepareNegotiation(); + final String contractAgreementId = SubmodelFacadeWiremockSupport.prepareNegotiation(); final EndpointDataReference ref = createEndpointDataReference(contractAgreementId); storage.put(contractAgreementId, ref); } diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java index bd512c7cde..c82e73bb8b 100644 --- a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java @@ -28,24 +28,24 @@ import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.DISCOVERY_FINDER_URL; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.EDC_DISCOVERY_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.TEST_BPN; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder200; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postDiscoveryFinder404; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscovery200; -import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockConfig.postEdcDiscovery404; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.DATAPLANE_URL; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.LOOKUP_SHELLS_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.LOOKUP_SHELLS_TEMPLATE; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.SHELL_DESCRIPTORS_PATH; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.SHELL_DESCRIPTORS_TEMPLATE; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getLookupShells200; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getLookupShells200Empty; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getLookupShells404; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getShellDescriptor200; -import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockConfig.getShellDescriptor404; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.DISCOVERY_FINDER_URL; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.EDC_DISCOVERY_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.TEST_BPN; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.postDiscoveryFinder200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.postDiscoveryFinder404; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.postEdcDiscovery200; +import static org.eclipse.tractusx.irs.testing.wiremock.DiscoveryServiceWiremockSupport.postEdcDiscovery404; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.DATAPLANE_URL; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.LOOKUP_SHELLS_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.LOOKUP_SHELLS_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.SHELL_DESCRIPTORS_PATH; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.SHELL_DESCRIPTORS_TEMPLATE; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.getLookupShells200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.getLookupShells200Empty; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.getLookupShells404; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.getShellDescriptor200; +import static org.eclipse.tractusx.irs.testing.wiremock.DtrWiremockSupport.getShellDescriptor404; import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.restTemplateProxy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockSupport.java similarity index 97% rename from irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java rename to irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockSupport.java index 585803c1b4..0d11ffb12e 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DiscoveryServiceWiremockSupport.java @@ -30,7 +30,7 @@ /** * WireMock configurations and requests used for testing the Discovery Service flow. */ -public final class DiscoveryServiceWiremockConfig { +public final class DiscoveryServiceWiremockSupport { public static final String CONTROLPLANE_PUBLIC_URL = "https://test.edc.io"; public static final String EDC_DISCOVERY_PATH = "/edcDiscovery"; public static final String TEST_BPN = "BPNL00000000TEST"; @@ -41,7 +41,7 @@ public final class DiscoveryServiceWiremockConfig { public static final int STATUS_CODE_OK = 200; public static final int STATUS_CODE_NOT_FOUND = 404; - private DiscoveryServiceWiremockConfig() { + private DiscoveryServiceWiremockSupport() { } public static MappingBuilder postEdcDiscovery200() { diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockSupport.java similarity index 97% rename from irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java rename to irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockSupport.java index 30367044e2..f269e1713b 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/DtrWiremockSupport.java @@ -31,7 +31,7 @@ /** * WireMock configurations and requests used for testing the decentralized DigitalTwinRegistry flow. */ -public final class DtrWiremockConfig { +public final class DtrWiremockSupport { public static final String DATAPLANE_URL = "http://dataplane.test"; public static final String DATAPLANE_PUBLIC_PATH = "/api/public"; public static final String DATAPLANE_PUBLIC_URL = DATAPLANE_URL + DATAPLANE_PUBLIC_PATH; @@ -44,7 +44,7 @@ public final class DtrWiremockConfig { public static final int STATUS_CODE_OK = 200; public static final int STATUS_CODE_NOT_FOUND = 404; - private DtrWiremockConfig() { + private DtrWiremockSupport() { } public static MappingBuilder getShellDescriptor200() { @@ -53,16 +53,16 @@ public static MappingBuilder getShellDescriptor200() { public static MappingBuilder getShellDescriptor200(final String urlRegex) { final String materialForRecycling = submodelDescriptor(DATAPLANE_PUBLIC_URL, - "urn:uuid:19b0338f-6d03-4198-b3b8-5c43f8958d60", DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, + "urn:uuid:19b0338f-6d03-4198-b3b8-5c43f8958d60", DiscoveryServiceWiremockSupport.CONTROLPLANE_PUBLIC_URL, "MaterialForRecycling", "urn:uuid:cf06d5d5-e3f8-4bd4-bfcf-81815310701f", "urn:bamm:io.catenax.material_for_recycling:1.1.0#MaterialForRecycling"); final String batch = submodelDescriptor(DATAPLANE_PUBLIC_URL, "urn:uuid:234edd2f-0223-47c7-9fe4-3984ab14c4f9", - DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, "Batch", + DiscoveryServiceWiremockSupport.CONTROLPLANE_PUBLIC_URL, "Batch", "urn:uuid:f53db6ef-7a58-4326-9169-0ae198b85dbf", "urn:samm:io.catenax.batch:2.0.0#Batch"); final String singleLevelBomAsBuilt = submodelDescriptor(DATAPLANE_PUBLIC_URL, - "urn:uuid:234edd2f-0223-47c7-9fe4-3984ab14c4f9", DiscoveryServiceWiremockConfig.CONTROLPLANE_PUBLIC_URL, + "urn:uuid:234edd2f-0223-47c7-9fe4-3984ab14c4f9", DiscoveryServiceWiremockSupport.CONTROLPLANE_PUBLIC_URL, "SingleLevelBomAsBuilt", "urn:uuid:0e413809-966b-4107-aae5-aeb28bcdaadf", "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt"); diff --git a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockSupport.java similarity index 99% rename from irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java rename to irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockSupport.java index 361423cf05..cd38948422 100644 --- a/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockConfig.java +++ b/irs-testing/src/main/java/org/eclipse/tractusx/irs/testing/wiremock/SubmodelFacadeWiremockSupport.java @@ -29,7 +29,7 @@ /** * WireMock configurations and requests used for testing the EDC Flow. */ -public final class SubmodelFacadeWiremockConfig { +public final class SubmodelFacadeWiremockSupport { public static final String PATH_CATALOG = "/catalog/request"; public static final String PATH_NEGOTIATE = "/contractnegotiations"; public static final String PATH_TRANSFER = "/transferprocesses"; @@ -50,7 +50,7 @@ public final class SubmodelFacadeWiremockConfig { public static final String EDC_PROVIDER_BPN = "BPNL00000003CRHK"; public static final int STATUS_CODE_OK = 200; - private SubmodelFacadeWiremockConfig() { + private SubmodelFacadeWiremockSupport() { } public static String prepareNegotiation() { From d3235875590df719999b70b554a009e322566f81 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Thu, 1 Feb 2024 17:10:38 +0100 Subject: [PATCH 21/22] feat(testing):[#344] Renaming *WireMockConfig to *WireMockSupport, refactoring --- .../SemanticHubWireMockConfig.java | 53 ------------ .../SemanticHubWireMockSupport.java | 84 +++++++++++++++++++ 2 files changed, 84 insertions(+), 53 deletions(-) delete mode 100644 irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java create mode 100644 irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockSupport.java diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java deleted file mode 100644 index cd250f8a7c..0000000000 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockConfig.java +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -package org.eclipse.tractusx.irs.semanticshub; - -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; -import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; - -import com.github.tomakehurst.wiremock.client.MappingBuilder; - -/** - * WireMock configurations and requests used for testing Semantic Hub fLow. - */ -public final class SemanticHubWireMockConfig { - public static final String BATCH_URN = "urn:samm:io.catenax.batch:2.0.0%23Batch"; - public static final String SEMANTIC_HUB_SCHEMA_URL = "http://semantic.hub/models/{urn}/json-schema"; - private static final String SINGLE_LEVEL_BOM_AS_BUILT_URN = "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0%23SingleLevelBomAsBuilt"; - - private SemanticHubWireMockConfig() { - } - - public static MappingBuilder batchSchemaResponse200() { - return schemaResponse200("/models/" + BATCH_URN + "/json-schema", "semantichub/batch-2.0.0-schema.json"); - } - - public static MappingBuilder singleLevelBomAsBuiltSchemaResponse200() { - return schemaResponse200("/models/" + SINGLE_LEVEL_BOM_AS_BUILT_URN + "/json-schema", - "semantichub/singleLevelBomAsBuilt-2.0.0-schema.json"); - } - - private static MappingBuilder schemaResponse200(final String urlRegex, final String fileName) { - return get(urlPathMatching(urlRegex)).withHost(equalTo("semantic.hub")) - .willReturn(responseWithStatus(200).withBodyFile(fileName)); - } -} \ No newline at end of file diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockSupport.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockSupport.java new file mode 100644 index 0000000000..640755a10e --- /dev/null +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/semanticshub/SemanticHubWireMockSupport.java @@ -0,0 +1,84 @@ +/******************************************************************************** + * Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +package org.eclipse.tractusx.irs.semanticshub; + +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.exactly; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.eclipse.tractusx.irs.testing.wiremock.WireMockConfig.responseWithStatus; + +/** + * WireMock configurations and requests used for testing Semantic Hub fLow. + */ +public final class SemanticHubWireMockSupport { + public static final String BATCH_URN = "urn:samm:io.catenax.batch:2.0.0%23Batch"; + private static final String SINGLE_LEVEL_BOM_AS_BUILT_URN = "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0%23SingleLevelBomAsBuilt"; + public static final String SCHEMA_PATH_PLACEHOLDER = "/models/%s/json-schema"; + public static final String SEMANTIC_HUB_SCHEMA_URL = + "http://semantic.hub" + SCHEMA_PATH_PLACEHOLDER.formatted("{urn}"); + public static final String MODELS_PATH = "/models"; + + private SemanticHubWireMockSupport() { + } + + public static void semanticHubWillReturnBatchSchema() { + schemaResponse200(SCHEMA_PATH_PLACEHOLDER.formatted(BATCH_URN), "semantichub/batch-2.0.0-schema.json"); + } + + public static void semanticHubWillReturnSingleLevelBomAsBuiltSchema() { + schemaResponse200(SCHEMA_PATH_PLACEHOLDER.formatted(SINGLE_LEVEL_BOM_AS_BUILT_URN), + "semantichub/singleLevelBomAsBuilt-2.0.0-schema.json"); + } + + private static void schemaResponse200(final String urlRegex, final String fileName) { + stubFor(get(urlPathMatching(urlRegex)).withHost(equalTo("semantic.hub")) + .willReturn(responseWithStatus(200).withBodyFile(fileName))); + } + + static void semanticHubWillReturnPagedModels(final int page, final int pageSize, final String fileName) { + stubFor(get(urlPathEqualTo(MODELS_PATH)).withHost(equalTo("semantic.hub")) + .withQueryParam("page", equalTo(String.valueOf(page))) + .withQueryParam("pageSize", equalTo(String.valueOf(pageSize))) + .willReturn(responseWithStatus(200).withBodyFile(fileName))); + } + + public static void semanticHubWillReturnAllModels(final String fileName) { + stubFor(get(urlPathEqualTo(MODELS_PATH)).withHost(equalTo("semantic.hub")) + .willReturn(responseWithStatus(200).withBodyFile(fileName))); + } + + static void semanticHubWillThrowErrorForSemanticModel(final String semanticModel) { + final String url = SCHEMA_PATH_PLACEHOLDER.formatted(semanticModel); + stubFor(get(urlPathEqualTo(url)).willReturn(responseWithStatus(500))); + } + + static void verifySemanticHubWasCalledForModel(final String model, final int times) { + verify(exactly(times), getRequestedFor(urlPathMatching(SCHEMA_PATH_PLACEHOLDER.formatted(model)))); + } + + static void verifySemanticHubWasCalledForAllModels(final int times) { + verify(exactly(times), getRequestedFor(urlPathEqualTo(MODELS_PATH))); + } +} \ No newline at end of file From c7c4aaf8c7116001f311eda7e7a9b0dba9ab4703 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Fri, 2 Feb 2024 10:55:04 +0100 Subject: [PATCH 22/22] docs(testing):[#344] Add issue id to todos --- .../eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java | 2 +- ...ecentralDigitalTwinRegistryServiceWiremockTest.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java index 5041293e43..b0c63f0713 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/bpdm/BpdmWiremockTest.java @@ -69,7 +69,7 @@ void shouldReturnEmptyOnNotFound() { bpdmWillNotFindCompanyName(bpn); // Act & Assert - // TODO fix implementation to not throw HttpClientErrorException$NotFound + // TODO (#405) fix implementation to not throw HttpClientErrorException$NotFound assertThatExceptionOfType(HttpClientErrorException.class).isThrownBy( () -> bpdmFacade.findManufacturerName(bpn)); verifyBpdmWasCalledWithBPN(bpn, 1); diff --git a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java index c82e73bb8b..7c6bee5b80 100644 --- a/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java +++ b/irs-registry-client/src/test/java/org/eclipse/tractusx/irs/registryclient/decentral/DecentralDigitalTwinRegistryServiceWiremockTest.java @@ -122,7 +122,7 @@ void shouldThrowHttpClientExceptionInCaseOfDiscoveryError() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert - // TODO fix implementation to not throw HttpClientErrorException$NotFound + // TODO (#405) fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); @@ -136,7 +136,7 @@ void shouldThrowHttpClientExceptionInCaseOfEdcDiscoveryError() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert - // TODO fix implementation to not throw HttpClientErrorException$NotFound + // TODO (#405) fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); @@ -152,7 +152,7 @@ void shouldThrowHttpClientExceptionInCaseOfLookupShellsError() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert - // TODO fix implementation to not throw HttpClientErrorException$NotFound + // TODO (#405) fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); @@ -170,7 +170,7 @@ void shouldThrowHttpClientExceptionInCaseOfShellDescriptorsError() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert - // TODO fix implementation to not throw HttpClientErrorException$NotFound + // TODO (#405) fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH))); @@ -189,7 +189,7 @@ void shouldThrowExceptionOnEmptyShells() { final List testId = List.of(new DigitalTwinRegistryKey("testId", TEST_BPN)); // Act & Assert - // TODO fix implementation to not throw HttpClientErrorException$NotFound + // TODO (#405) fix implementation to not throw HttpClientErrorException$NotFound assertThatThrownBy(() -> decentralDigitalTwinRegistryService.fetchShells(testId)).isInstanceOf( HttpClientErrorException.class); verify(exactly(1), postRequestedFor(urlPathEqualTo(DISCOVERY_FINDER_PATH)));