From 363cb77d8491e3e540d3a0a8b58ec24326e4be75 Mon Sep 17 00:00:00 2001 From: Daniel Kec Date: Thu, 8 Aug 2024 14:54:44 +0200 Subject: [PATCH 1/3] LRA testing feature #8469 --- examples/microprofile/lra/pom.xml | 29 ++++++ .../example/lra/LRAExampleResourceTest.java | 90 +++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 examples/microprofile/lra/src/test/java/io/helidon/microprofile/example/lra/LRAExampleResourceTest.java diff --git a/examples/microprofile/lra/pom.xml b/examples/microprofile/lra/pom.xml index 44916df6..4c340538 100644 --- a/examples/microprofile/lra/pom.xml +++ b/examples/microprofile/lra/pom.xml @@ -59,6 +59,35 @@ runtime true + + + org.junit.jupiter + junit-jupiter-api + test + + + io.helidon.microprofile.lra + helidon-microprofile-lra-testing + test + + 4.1.0-SNAPSHOT + + + org.hamcrest + hamcrest-all + test + + + io.helidon.microprofile.testing + helidon-microprofile-testing-junit5 + test + + + org.awaitility + awaitility + 4.2.0 + test + diff --git a/examples/microprofile/lra/src/test/java/io/helidon/microprofile/example/lra/LRAExampleResourceTest.java b/examples/microprofile/lra/src/test/java/io/helidon/microprofile/example/lra/LRAExampleResourceTest.java new file mode 100644 index 00000000..d77d05da --- /dev/null +++ b/examples/microprofile/lra/src/test/java/io/helidon/microprofile/example/lra/LRAExampleResourceTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ + +package io.helidon.microprofile.example.lra; + +import java.time.Duration; + +import io.helidon.lra.coordinator.Lra; +import io.helidon.microprofile.testing.junit5.AddBean; +import io.helidon.microprofile.testing.junit5.HelidonTest; +import io.helidon.microprofile.testing.lra.TestLraCoordinator; + +import jakarta.inject.Inject; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.lra.annotation.LRAStatus; +import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; +import org.junit.jupiter.api.Test; + +import static org.awaitility.Awaitility.await; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +@HelidonTest +@AddBean(TestLraCoordinator.class) +public class LRAExampleResourceTest { + + @Inject + private TestLraCoordinator coordinator; + + @Inject + private WebTarget target; + + @Test + public void testComplete() { + try (Response res = target + .path("/example/start-example") + .request() + .put(Entity.entity("lra rocks!", MediaType.TEXT_PLAIN_TYPE))) { + assertThat(res.getStatus(), is(200)); + String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER); + Lra lra = coordinator.lra(lraId); + assertThat(lra.status(), is(LRAStatus.Closed)); + } + } + + @Test + public void testCompensation() { + try (Response res = target + .path("/example/start-example") + .request() + .put(Entity.entity("BOOM", MediaType.TEXT_PLAIN_TYPE))) { + assertThat(res.getStatus(), is(500)); + String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER); + Lra lra = coordinator.lra(lraId); + assertThat(lra.status(), is(LRAStatus.Cancelled)); + } + } + + @Test + public void testTimeout() { + try (Response res = target + .path("/example/start-example") + .request() + .put(Entity.entity("TIMEOUT", MediaType.TEXT_PLAIN_TYPE))) { + assertThat(res.getStatus(), is(200)); + String lraId = res.getHeaderString(LRA.LRA_HTTP_CONTEXT_HEADER); + Lra lra = coordinator.lra(lraId); + await() + .atMost(Duration.ofSeconds(15)) + .until(() -> lra.status() == LRAStatus.Cancelled); + assertThat(lra.status(), is(LRAStatus.Cancelled)); + } + } +} From 9c112e4adc4a68d37edb82de3fe3f353d95693be Mon Sep 17 00:00:00 2001 From: Daniel Kec Date: Thu, 5 Dec 2024 15:53:55 +0100 Subject: [PATCH 2/3] * LRA test coordinator example * Run tests on random ports --- examples/integrations/cdi/pokemons/pom.xml | 10 ++++ .../src/main/resources/logging.properties | 27 ++++++++++ .../integrations/cdi/pokemon/MainTest.java | 54 ++++++------------- examples/microprofile/lra/pom.xml | 2 - 4 files changed, 53 insertions(+), 40 deletions(-) create mode 100644 examples/integrations/cdi/pokemons/src/main/resources/logging.properties diff --git a/examples/integrations/cdi/pokemons/pom.xml b/examples/integrations/cdi/pokemons/pom.xml index b4b12ffa..3fbd0445 100644 --- a/examples/integrations/cdi/pokemons/pom.xml +++ b/examples/integrations/cdi/pokemons/pom.xml @@ -62,6 +62,11 @@ jakarta.transaction jakarta.transaction-api + + io.helidon.logging + helidon-logging-jul + runtime + @@ -133,6 +138,11 @@ + + io.helidon.microprofile.testing + helidon-microprofile-testing-junit5 + test + org.junit.jupiter junit-jupiter-api diff --git a/examples/integrations/cdi/pokemons/src/main/resources/logging.properties b/examples/integrations/cdi/pokemons/src/main/resources/logging.properties new file mode 100644 index 00000000..63d9d8f9 --- /dev/null +++ b/examples/integrations/cdi/pokemons/src/main/resources/logging.properties @@ -0,0 +1,27 @@ +# +# Copyright (c) 2024 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://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. +# + +# Example Logging Configuration File +# For more information see $JAVA_HOME/jre/lib/logging.properties + +# Send messages to the console +handlers=io.helidon.logging.jul.HelidonConsoleHandler + +# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread +java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n + +# Global logging level. Can be overridden by specific loggers +.level=INFO \ No newline at end of file diff --git a/examples/integrations/cdi/pokemons/src/test/java/io/helidon/examples/integrations/cdi/pokemon/MainTest.java b/examples/integrations/cdi/pokemons/src/test/java/io/helidon/examples/integrations/cdi/pokemon/MainTest.java index ec72ed29..f344b6fa 100644 --- a/examples/integrations/cdi/pokemons/src/test/java/io/helidon/examples/integrations/cdi/pokemon/MainTest.java +++ b/examples/integrations/cdi/pokemons/src/test/java/io/helidon/examples/integrations/cdi/pokemon/MainTest.java @@ -16,63 +16,45 @@ package io.helidon.examples.integrations.cdi.pokemon; -import io.helidon.microprofile.server.Server; +import io.helidon.microprofile.testing.junit5.HelidonTest; -import jakarta.enterprise.inject.se.SeContainer; -import jakarta.enterprise.inject.spi.CDI; import jakarta.json.JsonArray; -import jakarta.ws.rs.client.Client; -import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +@HelidonTest class MainTest { - private static Server server; - private static Client client; - - @BeforeAll - public static void startTheServer() { - client = ClientBuilder.newClient(); - server = Server.create().start(); - } - - @AfterAll - static void destroyClass() { - CDI current = CDI.current(); - ((SeContainer) current).close(); - } @Test - void testPokemonTypes() { - JsonArray types = client.target(getConnectionString("/type")) + void testPokemonTypes(WebTarget client) { + JsonArray types = client.path("/type") .request() .get(JsonArray.class); assertThat(types.size(), is(18)); } @Test - void testPokemon() { - assertThat(getPokemonCount(), is(6)); + void testPokemon(WebTarget client) { + assertThat(getPokemonCount(client), is(6)); - Pokemon pokemon = client.target(getConnectionString("/pokemon/1")) + Pokemon pokemon = client.path("/pokemon/1") .request() .get(Pokemon.class); assertThat(pokemon.getName(), is("Bulbasaur")); - pokemon = client.target(getConnectionString("/pokemon/name/Charmander")) + pokemon = client.path("/pokemon/name/Charmander") .request() .get(Pokemon.class); assertThat(pokemon.getType(), is(10)); - try (Response response = client.target(getConnectionString("/pokemon/1")) + try (Response response = client.path("/pokemon/1") .request() .get()) { assertThat(response.getStatus(), is(200)); @@ -82,29 +64,25 @@ void testPokemon() { test.setType(1); test.setId(100); test.setName("Test"); - try (Response response = client.target(getConnectionString("/pokemon")) + try (Response response = client.path("/pokemon") .request() .post(Entity.entity(test, MediaType.APPLICATION_JSON))) { assertThat(response.getStatus(), is(204)); - assertThat(getPokemonCount(), is(7)); + assertThat(getPokemonCount(client), is(7)); } - try (Response response = client.target(getConnectionString("/pokemon/100")) + try (Response response = client.path("/pokemon/100") .request() .delete()) { assertThat(response.getStatus(), is(204)); - assertThat(getPokemonCount(), is(6)); + assertThat(getPokemonCount(client), is(6)); } } - private int getPokemonCount() { - JsonArray pokemons = client.target(getConnectionString("/pokemon")) + private int getPokemonCount(WebTarget client) { + JsonArray pokemons = client.path("/pokemon") .request() .get(JsonArray.class); return pokemons.size(); } - - private String getConnectionString(String path) { - return "http://localhost:" + server.port() + path; - } } diff --git a/examples/microprofile/lra/pom.xml b/examples/microprofile/lra/pom.xml index 4c340538..5a8a0ca4 100644 --- a/examples/microprofile/lra/pom.xml +++ b/examples/microprofile/lra/pom.xml @@ -69,8 +69,6 @@ io.helidon.microprofile.lra helidon-microprofile-lra-testing test - - 4.1.0-SNAPSHOT org.hamcrest From 227d3d7186eedf74190938f63e3f9a9455818783 Mon Sep 17 00:00:00 2001 From: Daniel Kec Date: Thu, 5 Dec 2024 16:43:47 +0100 Subject: [PATCH 3/3] Review issues --- .../cdi/pokemons/src/main/resources/logging.properties | 2 +- examples/microprofile/lra/pom.xml | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/integrations/cdi/pokemons/src/main/resources/logging.properties b/examples/integrations/cdi/pokemons/src/main/resources/logging.properties index 63d9d8f9..ce88d5b1 100644 --- a/examples/integrations/cdi/pokemons/src/main/resources/logging.properties +++ b/examples/integrations/cdi/pokemons/src/main/resources/logging.properties @@ -24,4 +24,4 @@ handlers=io.helidon.logging.jul.HelidonConsoleHandler java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n # Global logging level. Can be overridden by specific loggers -.level=INFO \ No newline at end of file +.level=INFO diff --git a/examples/microprofile/lra/pom.xml b/examples/microprofile/lra/pom.xml index 5a8a0ca4..d93f0167 100644 --- a/examples/microprofile/lra/pom.xml +++ b/examples/microprofile/lra/pom.xml @@ -36,6 +36,10 @@ Microprofile Long Running Actions Example + + 4.2.0 + + io.helidon.microprofile.bundles @@ -83,7 +87,7 @@ org.awaitility awaitility - 4.2.0 + ${version.lib.awaitility} test