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

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 9d2306bce947ddf58a8dcc185c302cf02c41316a
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Aug 2 09:08:09 2019 +0200

    CAMEL-12003: Add failFast option to mock endpoint
---
 .../src/main/docs/dataset-component.adoc           |  3 +-
 .../camel/component/dataset/DataSetEndpoint.java   |  7 +-
 .../apache/camel/component/mock/MockEndpoint.java  | 79 +++++++++++++++++++---
 .../component/dataset/DataSetProducerTest.java     | 28 +++-----
 .../camel/component/mock/MockEndpointTest.java     |  3 +-
 .../dsl/DataSetEndpointBuilderFactory.java         | 30 ++++++++
 6 files changed, 114 insertions(+), 36 deletions(-)

diff --git a/components/camel-dataset/src/main/docs/dataset-component.adoc 
b/components/camel-dataset/src/main/docs/dataset-component.adoc
index 0abd769..d9fc80c 100644
--- a/components/camel-dataset/src/main/docs/dataset-component.adoc
+++ b/components/camel-dataset/src/main/docs/dataset-component.adoc
@@ -78,7 +78,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (18 parameters):
+=== Query Parameters (19 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -92,6 +92,7 @@ with the following path and query parameters:
 | *consumeDelay* (producer) | Allows a delay to be specified which causes a 
delay when a message is consumed by the producer (to simulate slow processing) 
| 0 | long
 | *assertPeriod* (producer) | Sets a grace period after which the mock 
endpoint will re-assert to ensure the preliminary assertion is still valid. 
This is used for example to assert that exactly a number of messages arrives. 
For example if expectedMessageCount(int) was set to 5, then the assertion is 
satisfied when 5 or more message arrives. To ensure that exactly 5 messages 
arrives, then you would need to wait a little period to ensure no further 
message arrives. This is what you can us [...]
 | *expectedCount* (producer) | Specifies the expected number of message 
exchanges that should be received by this endpoint. Beware: If you want to 
expect that 0 messages, then take extra care, as 0 matches when the tests 
starts, so you need to set a assert period time to let the test run for a while 
to make sure there are still no messages arrived; for that use 
setAssertPeriod(long). An alternative is to use NotifyBuilder, and use the 
notifier to know when Camel is done routing some mess [...]
+| *failFast* (producer) | Sets whether assertIsSatisfied() should fail fast at 
the first detected failed expectation while it may otherwise wait for all 
expected messages to arrive before performing expectations verifications. Is by 
default true. Set to false to use behavior as in Camel 2.x. | false | boolean
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy 
(on the first message). By starting lazy you can use this to allow CamelContext 
and routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and [...]
 | *reportGroup* (producer) | A number that is used to turn on throughput 
logging based on groups of the size. |  | int
 | *resultMinimumWaitTime* (producer) | Sets the minimum expected amount of 
time (in millis) the assertIsSatisfied() will wait on a latch until it is 
satisfied | 0 | long
diff --git 
a/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetEndpoint.java
 
b/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetEndpoint.java
index c72ab14..49074ed 100644
--- 
a/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetEndpoint.java
+++ 
b/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetEndpoint.java
@@ -45,7 +45,7 @@ import org.slf4j.LoggerFactory;
  * Camel will use the throughput logger when sending dataset's.
  */
 @UriEndpoint(firstVersion = "1.3.0", scheme = "dataset", title = "Dataset", 
syntax = "dataset:name",
-    label = "core,testing", excludeProperties = "failFast", lenientProperties 
= true)
+    label = "core,testing", lenientProperties = true)
 public class DataSetEndpoint extends MockEndpoint implements Service {
     private final transient Logger log;
     private final AtomicInteger receivedCounter = new AtomicInteger();
@@ -70,8 +70,6 @@ public class DataSetEndpoint extends MockEndpoint implements 
Service {
         this.log = LoggerFactory.getLogger(endpointUri);
         // optimize as we dont need to copy the exchange
         setCopyOnExchange(false);
-        // fail fast mode is not possible with dataset endpoints
-        setFailFast(false);
     }
 
     public static void assertEquals(String description, Object expected, 
Object actual, Exchange exchange) {
@@ -299,9 +297,6 @@ public class DataSetEndpoint extends MockEndpoint 
implements Service {
             reporter = createReporter();
         }
 
-        // fail fast mode is not possible with dataset endpoints
-        setFailFast(false);
-
         log.info(this + " expecting " + getExpectedCount() + " messages");
     }
 
diff --git 
a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockEndpoint.java
 
b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockEndpoint.java
index 45b2f19..a7a613f 100644
--- 
a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockEndpoint.java
+++ 
b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockEndpoint.java
@@ -780,11 +780,19 @@ public class MockEndpoint extends DefaultEndpoint 
implements BrowsableEndpoint,
         for (int i = 0; i < predicates.length; i++) {
             final int messageIndex = i;
             final Predicate predicate = predicates[i];
-            final AssertionClause clause = new AssertionClause(this) {
+            final AssertionClause clause = new AssertionClauseTask(this) {
+                @Override
+                public void assertOnIndex(int index) {
+                    if (messageIndex == index) {
+                        addPredicate(predicate);
+                        applyAssertionOn(MockEndpoint.this, index, 
assertExchangeReceived(index));
+                    }
+                }
+
                 public void run() {
-                    addPredicate(predicate);
-                    // TODO: Is this correct
-                    applyAssertionOn(MockEndpoint.this, messageIndex, 
assertExchangeReceived(messageIndex));
+                    for (int i = 0; i < getReceivedExchanges().size(); i++) {
+                        assertOnIndex(i);
+                    }
                 }
             };
             expects(clause);
@@ -939,6 +947,7 @@ public class MockEndpoint extends DefaultEndpoint 
implements BrowsableEndpoint,
     public void expectsAscending(final Expression expression) {
         expects(new Runnable() {
             public void run() {
+                // TODO: Task
                 assertMessagesAscending(expression);
             }
         });
@@ -949,8 +958,14 @@ public class MockEndpoint extends DefaultEndpoint 
implements BrowsableEndpoint,
      * of the given expression such as a user generated counter value
      */
     public AssertionClause expectsAscending() {
-        // TODO: Task
-        final AssertionClause clause = new AssertionClause(this) {
+        final AssertionClause clause = new AssertionClauseTask(this) {
+            @Override
+            public void assertOnIndex(int index) {
+                // TODO: Make this smarter
+                // just run from top again
+                run();
+            }
+
             public void run() {
                 assertMessagesAscending(createExpression(getCamelContext()));
             }
@@ -997,9 +1012,26 @@ public class MockEndpoint extends DefaultEndpoint 
implements BrowsableEndpoint,
      *                {@link Object#hashCode()}
      */
     public void expectsNoDuplicates(final Expression expression) {
-        expects(new Runnable() {
+        expects(new AssertionTask() {
+            private Map<Object, Exchange> map = new HashMap<>();
+
+            @Override
+            public void assertOnIndex(int index) {
+                List<Exchange> list = getReceivedExchanges();
+                Exchange e2 = list.get(index);
+                Object key = expression.evaluate(e2, Object.class);
+                Exchange e1 = map.get(key);
+                if (e1 != null) {
+                    fail("Duplicate message found on message " + index + " has 
value: " + key + " for expression: " + expression + ". Exchanges: " + e1 + " 
and " + e2);
+                } else {
+                    map.put(key, e2);
+                }
+            }
+
             public void run() {
-                assertNoDuplicates(expression);
+                for (int i = 0; i < getReceivedExchanges().size(); i++) {
+                    assertOnIndex(i);
+                }
             }
         });
     }
@@ -1009,10 +1041,30 @@ public class MockEndpoint extends DefaultEndpoint 
implements BrowsableEndpoint,
      * the expression to determine the message ID
      */
     public AssertionClause expectsNoDuplicates() {
-        // TODO: Task
-        final AssertionClause clause = new AssertionClause(this) {
+        final AssertionClause clause = new AssertionClauseTask(this) {
+            private Map<Object, Exchange> map = new HashMap<>();
+            private Expression exp;
+
+            @Override
+            public void assertOnIndex(int index) {
+                if (exp == null) {
+                    exp = createExpression(getCamelContext());
+                }
+                List<Exchange> list = getReceivedExchanges();
+                Exchange e2 = list.get(index);
+                Object key = exp.evaluate(e2, Object.class);
+                Exchange e1 = map.get(key);
+                if (e1 != null) {
+                    fail("Duplicate message found on message " + index + " has 
value: " + key + " for expression: " + exp + ". Exchanges: " + e1 + " and " + 
e2);
+                } else {
+                    map.put(key, e2);
+                }
+            }
+
             public void run() {
-                assertNoDuplicates(createExpression(getCamelContext()));
+                for (int i = 0; i < getReceivedExchanges().size(); i++) {
+                    assertOnIndex(i);
+                }
             }
         };
         expects(clause);
@@ -1060,6 +1112,11 @@ public class MockEndpoint extends DefaultEndpoint 
implements BrowsableEndpoint,
         }
     }
 
+    /**
+     * Asserts among all the current received exchanges that there are no 
duplicate message
+     *
+     * @param expression  the expression to use for duplication check
+     */
     public void assertNoDuplicates(Expression expression) {
         Map<Object, Exchange> map = new HashMap<>();
         List<Exchange> list = getReceivedExchanges();
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/dataset/DataSetProducerTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/dataset/DataSetProducerTest.java
index 0f48c5b..0aa7f24 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/component/dataset/DataSetProducerTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/dataset/DataSetProducerTest.java
@@ -20,7 +20,6 @@ import javax.naming.Context;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
-import org.apache.camel.NoSuchHeaderException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.Assert;
@@ -168,11 +167,8 @@ public class DataSetProducerTest extends 
ContextTestSupport {
             assertMockEndpointsSatisfied();
         } catch (AssertionError assertionError) {
             // Check as much of the string as possible - but the ExchangeID at 
the end will be unique
-            String expectedErrorString = dataSetUriWithDataSetIndexSetToStrict
-                    + " Failed due to caught exception: "
-                    + NoSuchHeaderException.class.getName()
-                    + ": No '" + Exchange.DATASET_INDEX
-                    + "' header available of type: java.lang.Long. Exchange";
+            String expectedErrorString = "Caught exception on " + 
dataSetUriWithDataSetIndexSetToStrict + " due to:"
+                    + " No '" + Exchange.DATASET_INDEX + "' header available 
of type: java.lang.Long";
             String actualErrorString = assertionError.getMessage();
             if (actualErrorString.startsWith(expectedErrorString)) {
                 // This is what we expect
@@ -323,10 +319,9 @@ public class DataSetProducerTest extends 
ContextTestSupport {
             assertMockEndpointsSatisfied();
         } catch (AssertionError assertionError) {
             // Check as much of the string as possible - but the ExchangeID at 
the end will be unique
-            String expectedErrorString = dataSetUri + " Failed due to caught 
exception: "
-                    + AssertionError.class.getName()
-                    + ": Header: " + Exchange.DATASET_INDEX + " does not 
match. Expected: "
-                    + size / 2 + " but was: " + (size / 2 + 10) + " on 
Exchange";
+            String expectedErrorString = "Caught exception on " + dataSetUri + 
" due to: "
+                    + "Header: " + Exchange.DATASET_INDEX + " does not match. 
Expected: "
+                    + size / 2 + " but was: " + (size / 2 + 10);
             String actualErrorString = assertionError.getMessage();
             if (actualErrorString.startsWith(expectedErrorString)) {
                 // This is what we expect
@@ -397,10 +392,9 @@ public class DataSetProducerTest extends 
ContextTestSupport {
             assertMockEndpointsSatisfied();
         } catch (AssertionError assertionError) {
             // Check as much of the string as possible - but the ExchangeID at 
the end will be unique
-            String expectedErrorString = 
dataSetUriWithDataSetIndexSetToLenient + " Failed due to caught exception: "
-                    + AssertionError.class.getName()
-                    + ": Header: " + Exchange.DATASET_INDEX + " does not 
match. Expected: "
-                    + size / 2 + " but was: " + (size / 2 + 10) + " on 
Exchange";
+            String expectedErrorString = "Caught exception on " + 
dataSetUriWithDataSetIndexSetToLenient + " due to: "
+                    + "Header: " + Exchange.DATASET_INDEX + " does not match. 
Expected: "
+                    + size / 2 + " but was: " + (size / 2 + 10);
             String actualErrorString = assertionError.getMessage();
             if (actualErrorString.startsWith(expectedErrorString)) {
                 // This is what we expect
@@ -443,9 +437,9 @@ public class DataSetProducerTest extends ContextTestSupport 
{
             assertMockEndpointsSatisfied();
         } catch (AssertionError assertionError) {
             // Check as much of the string as possible - but the ExchangeID at 
the end will be unique
-            String expectedErrorString = dataSetUriWithDataSetIndexSetToStrict 
+ " Failed due to caught exception: "
-                    + AssertionError.class.getName() + ": Header: " + 
Exchange.DATASET_INDEX
-                    + " does not match. Expected: " + size / 2 + " but was: " 
+ (size / 2 + 10) + " on Exchange";
+            String expectedErrorString = "Caught exception on " + 
dataSetUriWithDataSetIndexSetToStrict + " due to: "
+                    + "Header: " + Exchange.DATASET_INDEX + " does not match. 
Expected: "
+                    + size / 2 + " but was: " + (size / 2 + 10);
             String actualErrorString = assertionError.getMessage();
             if (actualErrorString.startsWith(expectedErrorString)) {
                 // This is what we expect
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/mock/MockEndpointTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/mock/MockEndpointTest.java
index ac8c3e4..550cd1f 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/component/mock/MockEndpointTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/mock/MockEndpointTest.java
@@ -810,10 +810,11 @@ public class MockEndpointTest extends ContextTestSupport {
     @Test
     public void testExpectedExchangePattern() throws Exception {
         MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedMessageCount(1);
+        mock.expectedMessageCount(2);
         mock.expectedExchangePattern(ExchangePattern.InOnly);
 
         template.sendBody("direct:a", "Hello World");
+        template.sendBody("direct:a", "Bye World");
 
         assertMockEndpointsSatisfied();
 
diff --git 
a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/DataSetEndpointBuilderFactory.java
 
b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/DataSetEndpointBuilderFactory.java
index e22be35..f56d310 100644
--- 
a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/DataSetEndpointBuilderFactory.java
+++ 
b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/DataSetEndpointBuilderFactory.java
@@ -346,6 +346,36 @@ public interface DataSetEndpointBuilderFactory {
             return this;
         }
         /**
+         * Sets whether assertIsSatisfied() should fail fast at the first
+         * detected failed expectation while it may otherwise wait for all
+         * expected messages to arrive before performing expectations
+         * verifications. Is by default true. Set to false to use behavior as 
in
+         * Camel 2.x.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Group: producer
+         */
+        default DataSetEndpointProducerBuilder failFast(boolean failFast) {
+            setProperty("failFast", failFast);
+            return this;
+        }
+        /**
+         * Sets whether assertIsSatisfied() should fail fast at the first
+         * detected failed expectation while it may otherwise wait for all
+         * expected messages to arrive before performing expectations
+         * verifications. Is by default true. Set to false to use behavior as 
in
+         * Camel 2.x.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Group: producer
+         */
+        default DataSetEndpointProducerBuilder failFast(String failFast) {
+            setProperty("failFast", failFast);
+            return this;
+        }
+        /**
          * Whether the producer should be started lazy (on the first message).
          * By starting lazy you can use this to allow CamelContext and routes 
to
          * startup in situations where a producer may otherwise fail during

Reply via email to