diff --git a/api/management-api/src/main/java/org/eclipse/tractusx/bdrs/api/management/ManagementApiExtension.java b/api/management-api/src/main/java/org/eclipse/tractusx/bdrs/api/management/ManagementApiExtension.java index 12e95da..cad4998 100644 --- a/api/management-api/src/main/java/org/eclipse/tractusx/bdrs/api/management/ManagementApiExtension.java +++ b/api/management-api/src/main/java/org/eclipse/tractusx/bdrs/api/management/ManagementApiExtension.java @@ -57,7 +57,6 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - webServer.addPortMapping(CONTEXT_NAME, PORT, PATH); webService.registerResource(CONTEXT_NAME, new ManagementApiController(store)); webService.registerResource(CONTEXT_NAME, new AuthenticationRequestFilter(authService)); } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 31a7d90..9598a9c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,6 +5,7 @@ format.version = "1.1" edc = "0.5.0" nimbus = "9.37.3" restAssured = "5.4.0" +jupiter = "5.4.0" [libraries] edc-core-jetty = { module = "org.eclipse.edc:jetty-core", version.ref = "edc" } @@ -24,6 +25,7 @@ edc-junit = { module = "org.eclipse.edc:junit", version.ref = "edc" } # Third party libs nimbus-jwt = { module = "com.nimbusds:nimbus-jose-jwt", version.ref = "nimbus" } restAssured = { module = "io.rest-assured:rest-assured", version.ref = "restAssured" } +junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "jupiter" } [plugins] shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..d64cd49 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/settings.gradle.kts b/settings.gradle.kts index 5159fa2..646df04 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -49,3 +49,5 @@ include(":core:core-services") include(":api:directory-api") include(":api:management-api") include(":runtimes:server") +include(":system-tests:test-server") +include(":system-tests:test-directory") diff --git a/system-tests/test-directory/build.gradle.kts b/system-tests/test-directory/build.gradle.kts new file mode 100644 index 0000000..76161e8 --- /dev/null +++ b/system-tests/test-directory/build.gradle.kts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * 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 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + */ + +plugins { + java +} + +dependencies { + + testImplementation(libs.edc.junit) + testImplementation(libs.junit.jupiter.api) + testImplementation(libs.restAssured) + + testCompileOnly(project(":system-tests:test-server")) +} + diff --git a/system-tests/test-directory/src/test/java/org/eclipse/tractusx/bdrs/test/directory/E2EDirectoryTest.java b/system-tests/test-directory/src/test/java/org/eclipse/tractusx/bdrs/test/directory/E2EDirectoryTest.java new file mode 100644 index 0000000..3ce171f --- /dev/null +++ b/system-tests/test-directory/src/test/java/org/eclipse/tractusx/bdrs/test/directory/E2EDirectoryTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * 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 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.bdrs.test.directory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.restassured.specification.RequestSpecification; +import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +import static io.restassured.RestAssured.config; +import static io.restassured.RestAssured.given; +import static io.restassured.config.DecoderConfig.ContentDecoder.DEFLATE; +import static io.restassured.config.DecoderConfig.decoderConfig; +import static io.restassured.http.ContentType.JSON; +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; + +/** + * Performs end-to-end testing of the BPN Directory. + */ +public class E2EDirectoryTest { + private static final URI apiEndpoint = URI.create("http://localhost:" + getFreePort() + "/api"); + private static final URI managementEndpoint = URI.create("http://localhost:" + getFreePort() + "/management/v1"); + private static final String BPN_DIRECTORY = "bpn-directory"; + + private static final String AUTH_KEY = "1234"; + + private static final String BPN1 = "BPN12345"; + private static final String DID1 = "did:web:localhost/foo"; + + private static final String BPN2 = "BPN67890"; + private static final String DID2 = "did:web:localhost/bar"; + private static final String UPDATED_DID2 = "did:web:localhost/baz"; + + @RegisterExtension + protected static EdcRuntimeExtension runtime = + new EdcRuntimeExtension( + ":system-tests:test-server", + "bdrs", + Map.of("web.http.port", String.valueOf(apiEndpoint.getPort()), + "web.http.management.port", String.valueOf(managementEndpoint.getPort()), + "web.http.management.path", String.valueOf(managementEndpoint.getPath()), + "edc.api.auth.key", AUTH_KEY) + ); + + private ObjectMapper mapper; + + @Test + void verifyPublicBpnDirectoryRequest() throws IOException { + seedServer(BPN1, DID1); + var result = getBpnDirectory(apiRequest()); + assertThat(result.get(BPN1)).isEqualTo(DID1); + } + + @Test + void verifyManagementApi() throws IOException { + seedServer(BPN1, DID1); + seedServer(BPN2, DID2); + + // verify BPNs are returned + var result = getBpnDirectory(managementRequest()); + + assertThat(result.get(BPN1)).isEqualTo(DID1); + assertThat(result.get(BPN2)).isEqualTo(DID2); + + // verify delete + managementRequest() + .when() + .delete(BPN_DIRECTORY + "/" + BPN1) + .then() + .statusCode(204); + + result = getBpnDirectory(managementRequest()); + + assertThat(result.get(BPN1)).isNull(); + assertThat(result.get(BPN2)).isEqualTo(DID2); + + // verify update + var content = Map.of("bpn", BPN2, "did", UPDATED_DID2); + managementRequest() + .body(content) + .when() + .put(BPN_DIRECTORY) + .then() + .statusCode(204); + + result = getBpnDirectory(managementRequest()); + + assertThat(result.get(BPN2)).isEqualTo(UPDATED_DID2); + } + + @BeforeEach + void setUp() { + mapper = new ObjectMapper(); + } + + private void seedServer(String bpn, String did) { + var content = Map.of("bpn", bpn, "did", did); + managementRequest() + .body(content) + .when() + .post(BPN_DIRECTORY) + .then() + .statusCode(204); + } + + private Map getBpnDirectory(RequestSpecification spec) throws IOException { + return deserialize(spec + .config(config().decoderConfig(decoderConfig().contentDecoders(DEFLATE))) + .when() + .get(BPN_DIRECTORY) + .then() + .statusCode(200). + extract() + .response() + .asByteArray()); + } + + + private RequestSpecification apiRequest() { + return given().baseUri(apiEndpoint.toString()) + .headers(Map.of()); + } + + private RequestSpecification managementRequest() { + return given().baseUri(managementEndpoint.toString()) + .headers(Map.of("x-api-key", AUTH_KEY)) + .contentType(JSON); + } + + private Map deserialize(byte[] response) throws IOException { + var stream = new GZIPInputStream(new ByteArrayInputStream(response)); + var decompressed = stream.readAllBytes(); + //noinspection unchecked + return mapper.readValue(decompressed, Map.class); + } + +} diff --git a/system-tests/test-server/build.gradle.kts b/system-tests/test-server/build.gradle.kts new file mode 100644 index 0000000..646efad --- /dev/null +++ b/system-tests/test-server/build.gradle.kts @@ -0,0 +1,46 @@ +/* + * + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * 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 + * + */ + +plugins { + id("application") + alias(libs.plugins.shadow) +} + +dependencies { + api(libs.bundles.bdrs.boot) + api(project(":core:core-services")) + api(project(":api:directory-api")) + api(project(":api:management-api")) +} + +tasks.withType { + exclude("**/pom.properties", "**/pom.xm") + mergeServiceFiles() + archiveFileName.set("${project.name}.jar") +} + +application { + mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") +} + +edcBuild { + publish.set(false) +}