This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new 8ebe489  Improve MicroProfile Fault Tolerance extension test coverage
8ebe489 is described below

commit 8ebe489c7b17ec147865ecb71822e8758d7ac04b
Author: James Netherton <[email protected]>
AuthorDate: Tue Mar 29 14:54:38 2022 +0100

    Improve MicroProfile Fault Tolerance extension test coverage
    
    Fixes #3677
---
 integration-tests/microprofile/pom.xml             | 44 +++++++++--
 .../it/faulttolerance/GreetingBean.java            | 65 +++++++++++++++
 ....java => MicroProfileFaultToleranceHelper.java} | 26 +++---
 .../MicroProfileFaultToleranceRoutes.java          | 92 ++++++++++++++++++++--
 .../MicroprofileFaultToleranceResource.java        | 39 ++++++++-
 .../MicroprofileFaultToleranceTest.java            | 60 +++++++++-----
 6 files changed, 275 insertions(+), 51 deletions(-)

diff --git a/integration-tests/microprofile/pom.xml 
b/integration-tests/microprofile/pom.xml
index 456eaa0..c53a42b 100644
--- a/integration-tests/microprofile/pom.xml
+++ b/integration-tests/microprofile/pom.xml
@@ -33,23 +33,31 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-microprofile-fault-tolerance</artifactId>
+            <artifactId>camel-quarkus-bean</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-microprofile-health</artifactId>
+            <artifactId>camel-quarkus-direct</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-microprofile-metrics</artifactId>
+            <artifactId>camel-quarkus-log</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-direct</artifactId>
+            <artifactId>camel-quarkus-microprofile-fault-tolerance</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-log</artifactId>
+            <artifactId>camel-quarkus-microprofile-health</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-microprofile-metrics</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-mock</artifactId>
         </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
@@ -114,6 +122,19 @@
                 <!-- The following dependencies guarantee that this module is 
built after them. You can update them by running `mvn process-resources 
-Pformat -N` from the source tree root directory -->
                 <dependency>
                     <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-bean-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
                     <artifactId>camel-quarkus-direct-deployment</artifactId>
                     <version>${project.version}</version>
                     <type>pom</type>
@@ -177,6 +198,19 @@
                         </exclusion>
                     </exclusions>
                 </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-mock-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
             </dependencies>
         </profile>
     </profiles>
diff --git 
a/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/GreetingBean.java
 
b/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/GreetingBean.java
new file mode 100644
index 0000000..3053a27
--- /dev/null
+++ 
b/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/GreetingBean.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.quarkus.component.microprofile.it.faulttolerance;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
+import org.eclipse.microprofile.faulttolerance.Fallback;
+import org.eclipse.microprofile.faulttolerance.Timeout;
+
+import static 
org.apache.camel.quarkus.component.microprofile.it.faulttolerance.MicroProfileFaultToleranceRoutes.EXCEPTION_MESSAGE;
+import static 
org.apache.camel.quarkus.component.microprofile.it.faulttolerance.MicroProfileFaultToleranceRoutes.FALLBACK_RESULT;
+import static 
org.apache.camel.quarkus.component.microprofile.it.faulttolerance.MicroProfileFaultToleranceRoutes.RESULT;
+
+@ApplicationScoped
+public class GreetingBean {
+
+    @Fallback(fallbackMethod = "fallbackGreeting")
+    public String greetWithFallback() {
+        AtomicInteger counter = 
MicroProfileFaultToleranceHelper.getCounter("beanFallback");
+        if (counter.incrementAndGet() == 1) {
+            throw new IllegalStateException(EXCEPTION_MESSAGE);
+        }
+        return RESULT;
+    }
+
+    @Timeout(250)
+    public String greetWithDelay() throws InterruptedException {
+        AtomicInteger counter = 
MicroProfileFaultToleranceHelper.getCounter("beanTimeout");
+        if (counter.incrementAndGet() == 1) {
+            Thread.sleep(500);
+            return "Nothing to see here, method invocation timed out!";
+        }
+        return RESULT;
+    }
+
+    @CircuitBreaker(failureRatio = 1.0, requestVolumeThreshold = 1, delay = 0)
+    public String greetWithCircuitBreaker() {
+        AtomicInteger counter = 
MicroProfileFaultToleranceHelper.getCounter("beanThreshold");
+        if (counter.incrementAndGet() == 1) {
+            throw new IllegalStateException(EXCEPTION_MESSAGE);
+        }
+        return RESULT;
+    }
+
+    public String fallbackGreeting() {
+        return FALLBACK_RESULT;
+    }
+}
diff --git 
a/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceResource.java
 
b/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroProfileFaultToleranceHelper.java
similarity index 59%
copy from 
integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceResource.java
copy to 
integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroProfileFaultToleranceHelper.java
index 348a870..63071b4 100644
--- 
a/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceResource.java
+++ 
b/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroProfileFaultToleranceHelper.java
@@ -16,25 +16,19 @@
  */
 package org.apache.camel.quarkus.component.microprofile.it.faulttolerance;
 
-import javax.inject.Inject;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
 
-import org.apache.camel.ProducerTemplate;
+public class MicroProfileFaultToleranceHelper {
 
-@Path("/microprofile-fault-tolerance")
-public class MicroprofileFaultToleranceResource {
+    private static final Map<String, AtomicInteger> COUNTERS = new 
ConcurrentHashMap();
 
-    @Inject
-    ProducerTemplate producerTemplate;
+    private MicroProfileFaultToleranceHelper() {
+        // Utility class
+    }
 
-    @Path("/route/{route}")
-    @POST
-    @Produces(MediaType.TEXT_PLAIN)
-    public String triggerFaultToleranceRoute(String body, @PathParam("route") 
String route) {
-        return producerTemplate.requestBody("direct:" + route, body, 
String.class);
+    public static AtomicInteger getCounter(String name) {
+        return COUNTERS.computeIfAbsent(name, key -> new AtomicInteger());
     }
 }
diff --git 
a/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroProfileFaultToleranceRoutes.java
 
b/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroProfileFaultToleranceRoutes.java
index 3dca95a..2ac31d6 100644
--- 
a/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroProfileFaultToleranceRoutes.java
+++ 
b/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroProfileFaultToleranceRoutes.java
@@ -16,23 +16,47 @@
  */
 package org.apache.camel.quarkus.component.microprofile.it.faulttolerance;
 
+import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Named;
+
 import org.apache.camel.builder.RouteBuilder;
+import org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException;
 
+@ApplicationScoped
 public class MicroProfileFaultToleranceRoutes extends RouteBuilder {
 
+    public static final String EXCEPTION_MESSAGE = "Simulated Exception";
     public static final String FALLBACK_RESULT = "Fallback response";
     public static final String RESULT = "Hello Camel Quarkus MicroProfile 
Fault Tolerance";
-    private static final AtomicInteger COUNTER = new AtomicInteger();
-    private static final AtomicInteger TIMEOUT_COUNTER = new AtomicInteger();
+
+    @Inject
+    GreetingBean greetingBean;
 
     @Override
     public void configure() throws Exception {
-        from("direct:faultTolerance")
+        from("direct:faultToleranceWithBulkhead")
                 .circuitBreaker()
+                .faultToleranceConfiguration().bulkheadEnabled(true).end()
                 .process(exchange -> {
-                    if (COUNTER.incrementAndGet() == 1) {
+                    AtomicInteger counter = 
MicroProfileFaultToleranceHelper.getCounter("bulkhead");
+                    if (counter.incrementAndGet() == 1) {
+                        throw new IllegalStateException(EXCEPTION_MESSAGE);
+                    }
+                    exchange.getMessage().setBody(RESULT);
+                })
+                .onFallback()
+                .setBody().constant(FALLBACK_RESULT)
+                .end();
+
+        from("direct:faultToleranceWithFallback")
+                .circuitBreaker()
+                .process(exchange -> {
+                    AtomicInteger counter = 
MicroProfileFaultToleranceHelper.getCounter("fallback");
+                    if (counter.incrementAndGet() == 1) {
                         throw new IllegalStateException("Simulated Exception");
                     }
                     exchange.getMessage().setBody(RESULT);
@@ -41,18 +65,72 @@ public class MicroProfileFaultToleranceRoutes extends 
RouteBuilder {
                 .setBody().constant(FALLBACK_RESULT)
                 .end();
 
+        from("direct:faultToleranceWithThreshold")
+                .circuitBreaker()
+                
.faultToleranceConfiguration().failureRatio(100).successThreshold(1).requestVolumeThreshold(1).delay(0).end()
+                .process(exchange -> {
+                    AtomicInteger counter = 
MicroProfileFaultToleranceHelper.getCounter("threshold");
+                    if (counter.incrementAndGet() == 1) {
+                        throw new IllegalStateException("Simulated Exception");
+                    }
+                    exchange.getMessage().setBody("Nothing to see here. 
Circuit breaker is open...");
+                })
+                .end()
+                .setBody().simple(RESULT);
+
         from("direct:faultToleranceWithTimeout")
                 .circuitBreaker()
                 
.faultToleranceConfiguration().timeoutEnabled(true).timeoutDuration(500).end()
                 .process(exchange -> {
-                    if (TIMEOUT_COUNTER.incrementAndGet() == 1) {
+                    AtomicInteger counter = 
MicroProfileFaultToleranceHelper.getCounter("timeout");
+                    if (counter.incrementAndGet() == 1) {
                         Thread.sleep(1000);
                     }
-                    exchange.getMessage().setBody("Regular hi " + 
exchange.getMessage().getBody(String.class));
+                    exchange.getMessage().setBody(RESULT);
                 })
                 .onFallback()
-                .setBody().simple("Sorry ${body}, had to fallback!")
+                .setBody().simple(FALLBACK_RESULT)
                 .end();
 
+        from("direct:faultToleranceWithTimeoutCustomExecutor")
+                .circuitBreaker()
+                
.faultToleranceConfiguration().timeoutEnabled(true).timeoutScheduledExecutorService("myThreadPool")
+                .timeoutDuration(500).end()
+                .process(exchange -> {
+                    AtomicInteger counter = 
MicroProfileFaultToleranceHelper.getCounter("timeoutCustomExecutor");
+                    if (counter.incrementAndGet() == 1) {
+                        Thread.sleep(1000);
+                    }
+                    exchange.getMessage().setBody(RESULT);
+                })
+                .onFallback()
+                .setBody().simple(FALLBACK_RESULT)
+                .end();
+
+        from("direct:inheritErrorHandler")
+                
.errorHandler(deadLetterChannel("mock:dead").maximumRedeliveries(3).redeliveryDelay(0))
+                .circuitBreaker().inheritErrorHandler(true)
+                .to("mock:start")
+                .throwException(new 
IllegalArgumentException(EXCEPTION_MESSAGE)).end()
+                .to("mock:end");
+
+        from("direct:circuitBreakerBean")
+                .bean(greetingBean, "greetWithCircuitBreaker");
+
+        from("direct:fallbackBean")
+                .bean(greetingBean, "greetWithFallback");
+
+        from("direct:timeoutBean")
+                .doTry()
+                .bean(greetingBean, "greetWithDelay")
+                .doCatch(TimeoutException.class)
+                .setBody().constant(FALLBACK_RESULT)
+                .end();
+    }
+
+    @Named("myThreadPool")
+    public ScheduledExecutorService myThreadPool() {
+        return getCamelContext().getExecutorServiceManager()
+                .newScheduledThreadPool(this, "myThreadPool", 2);
     }
 }
diff --git 
a/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceResource.java
 
b/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceResource.java
index 348a870..3193d54 100644
--- 
a/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceResource.java
+++ 
b/integration-tests/microprofile/src/main/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceResource.java
@@ -23,7 +23,9 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
 
 @Path("/microprofile-fault-tolerance")
 public class MicroprofileFaultToleranceResource {
@@ -31,10 +33,43 @@ public class MicroprofileFaultToleranceResource {
     @Inject
     ProducerTemplate producerTemplate;
 
+    @Inject
+    CamelContext context;
+
     @Path("/route/{route}")
     @POST
     @Produces(MediaType.TEXT_PLAIN)
-    public String triggerFaultToleranceRoute(String body, @PathParam("route") 
String route) {
-        return producerTemplate.requestBody("direct:" + route, body, 
String.class);
+    public String triggerFaultToleranceRoute(@PathParam("route") String route) 
{
+        return producerTemplate.requestBody("direct:" + route, null, 
String.class);
+    }
+
+    @Path("/faultToleranceWithThreshold/{route}")
+    @POST
+    @Produces(MediaType.TEXT_PLAIN)
+    public String faultToleranceWithThreshold(@PathParam("route") String 
route) {
+        try {
+            return producerTemplate.requestBody("direct:" + route, null, 
String.class);
+        } catch (Exception e) {
+            return e.getCause().getMessage();
+        }
+    }
+
+    @Path("/inheritErrorHandler")
+    @POST
+    public void inheritErrorHandler() throws Exception {
+        MockEndpoint start = context.getEndpoint("mock:start", 
MockEndpoint.class);
+        start.expectedMessageCount(4);
+
+        MockEndpoint end = context.getEndpoint("mock:end", MockEndpoint.class);
+        end.expectedMessageCount(0);
+
+        MockEndpoint dead = context.getEndpoint("mock:dead", 
MockEndpoint.class);
+        dead.expectedMessageCount(1);
+
+        producerTemplate.requestBody("direct:inheritErrorHandler", null, 
String.class);
+
+        start.assertIsSatisfied(5000);
+        end.assertIsSatisfied(5000);
+        dead.assertIsSatisfied(5000);
     }
 }
diff --git 
a/integration-tests/microprofile/src/test/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceTest.java
 
b/integration-tests/microprofile/src/test/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceTest.java
index ff610c2..4d5378c 100644
--- 
a/integration-tests/microprofile/src/test/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceTest.java
+++ 
b/integration-tests/microprofile/src/test/java/org/apache/camel/quarkus/component/microprofile/it/faulttolerance/MicroprofileFaultToleranceTest.java
@@ -18,46 +18,64 @@ package 
org.apache.camel.quarkus.component.microprofile.it.faulttolerance;
 
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
-import org.hamcrest.Matchers;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static 
org.apache.camel.quarkus.component.microprofile.it.faulttolerance.MicroProfileFaultToleranceRoutes.EXCEPTION_MESSAGE;
+import static org.hamcrest.Matchers.is;
 
 @QuarkusTest
 class MicroprofileFaultToleranceTest {
 
-    @Test
-    public void testCamelMicroProfileFaultToleranceFallback() {
-
+    @ParameterizedTest
+    @MethodSource("routeUris")
+    public void testCamelMicroProfileFaultTolerance(String route) {
         // First request should trigger the fallback response
-        RestAssured.post("/microprofile-fault-tolerance/route/faultTolerance")
+        RestAssured.post("/microprofile-fault-tolerance/route/" + route)
                 .then()
                 .statusCode(200)
-                
.body(Matchers.is(MicroProfileFaultToleranceRoutes.FALLBACK_RESULT));
+                .body(is(MicroProfileFaultToleranceRoutes.FALLBACK_RESULT));
 
         // Next request(s) should trigger the expected response
-        RestAssured.post("/microprofile-fault-tolerance/route/faultTolerance")
+        RestAssured.post("/microprofile-fault-tolerance/route/" + route)
                 .then()
                 .statusCode(200)
-                .body(Matchers.is(MicroProfileFaultToleranceRoutes.RESULT));
+                .body(is(MicroProfileFaultToleranceRoutes.RESULT));
     }
 
-    @Test
-    public void testCamelMicroProfileFaultToleranceFallbackWithTimeout() {
-
-        // First request should trigger the fallback response
-        RestAssured.given()
-                .body("Joe")
-                
.post("/microprofile-fault-tolerance/route/faultToleranceWithTimeout")
+    @ParameterizedTest
+    @ValueSource(strings = { "faultToleranceWithThreshold", 
"circuitBreakerBean" })
+    public void testCamelMicroProfileFaultToleranceWithThreshold(String route) 
{
+        // First request should trigger an exception and open the circuit 
breaker
+        
RestAssured.post("/microprofile-fault-tolerance/faultToleranceWithThreshold/" + 
route)
                 .then()
                 .statusCode(200)
-                .body(Matchers.is("Sorry Joe, had to fallback!"));
+                .body(is(EXCEPTION_MESSAGE));
 
-        // Next request(s) should trigger the expected response
-        RestAssured.given()
-                .body("Mary")
-                
.post("/microprofile-fault-tolerance/route/faultToleranceWithTimeout")
+        // Next request(s) should close the circuit breaker and trigger the 
expected response
+        
RestAssured.post("/microprofile-fault-tolerance/faultToleranceWithThreshold/" + 
route)
                 .then()
                 .statusCode(200)
-                .body(Matchers.is("Regular hi Mary"));
+                .body(is(MicroProfileFaultToleranceRoutes.RESULT));
+    }
+
+    @Test
+    public void testCamelMicroProfileFaultToleranceInheritErrorHandler() {
+        RestAssured.post("/microprofile-fault-tolerance/inheritErrorHandler")
+                .then()
+                .statusCode(204);
     }
 
+    public static String[] routeUris() {
+        return new String[] {
+                "faultToleranceWithFallback",
+                "faultToleranceWithBulkhead",
+                "faultToleranceWithTimeout",
+                "faultToleranceWithTimeoutCustomExecutor",
+                "fallbackBean",
+                "timeoutBean",
+        };
+    }
 }

Reply via email to