You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/08/02 14:46:28 UTC

[camel] branch master updated (a394c76 -> 521de3b)

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

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


    from a394c76  Removed unused imports
     new d8627e2  CAMEL-12003: Add failFast option to mock endpoint
     new 081e0f0  Regen
     new b054f70  CAMEL-12003: Add failFast option to mock endpoint
     new 61909c2  CAMEL-12003: Add failFast option to mock endpoint
     new 9d2306b  CAMEL-12003: Add failFast option to mock endpoint
     new c38bd5a  CAMEL-12003: Add failFast option to mock endpoint
     new 71ba693  CAMEL-12003: camel-test getMockEndpoint should lookup mock endpoints and favour the mock queue name as matching.
     new 521de3b  Regen

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../main/docs/atmosphere-websocket-component.adoc  |   2 +-
 .../src/main/docs/dataset-component.adoc           |   3 +-
 .../src/main/docs/dataset-test-component.adoc      |   3 +-
 .../camel-mock/src/main/docs/mock-component.adoc   |   3 +-
 .../camel/component/mock/AssertionClause.java      |  12 +-
 .../camel/component/mock/AssertionClauseTask.java} |  23 +-
 .../apache/camel/component/mock/AssertionTask.java |  19 +-
 .../apache/camel/component/mock/MockEndpoint.java  | 354 +++++++++++++++------
 .../apache/camel/test/junit4/CamelTestSupport.java |  88 +++--
 ...impleMockTest.java => GetMockEndpointTest.java} |   4 +-
 .../component/dataset/DataSetProducerTest.java     |  28 +-
 .../camel/component/mock/MockEndpointTest.java     |   3 +-
 .../AtmosphereWebsocketEndpointBuilderFactory.java |  48 +--
 .../dsl/DataSetEndpointBuilderFactory.java         |  30 ++
 .../ROOT/pages/atmosphere-websocket-component.adoc |   2 +-
 .../modules/ROOT/pages/jetty-component.adoc        |   2 +-
 .../modules/ROOT/pages/mock-component.adoc         |   3 +-
 17 files changed, 425 insertions(+), 202 deletions(-)
 copy components/{camel-cassandraql/src/main/java/org/apache/camel/component/cassandra/CassandraConstants.java => camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClauseTask.java} (67%)
 copy core/camel-api/src/main/java/org/apache/camel/WrappedFile.java => components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java (71%)
 copy components/camel-test/src/test/java/org/apache/camel/test/patterns/{SimpleMockTest.java => GetMockEndpointTest.java} (92%)


[camel] 05/08: CAMEL-12003: Add failFast option to mock endpoint

Posted by da...@apache.org.
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 <cl...@gmail.com>
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


[camel] 02/08: Regen

Posted by da...@apache.org.
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 081e0f020342f41a2b187620c4a3275d2645ee42
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Aug 2 07:24:38 2019 +0200

    Regen
---
 .../main/docs/atmosphere-websocket-component.adoc  |  2 +-
 .../camel-jetty/src/main/docs/jetty-component.adoc |  2 +-
 .../AtmosphereWebsocketEndpointBuilderFactory.java | 48 +++++++++++-----------
 .../dsl/JettyHttpEndpointBuilder9Factory.java      | 16 ++++----
 .../ROOT/pages/atmosphere-websocket-component.adoc |  2 +-
 .../modules/ROOT/pages/jetty-component.adoc        |  2 +-
 .../modules/ROOT/pages/mock-component.adoc         |  3 +-
 7 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/components/camel-atmosphere-websocket/src/main/docs/atmosphere-websocket-component.adoc b/components/camel-atmosphere-websocket/src/main/docs/atmosphere-websocket-component.adoc
index 8d56b7b..0bc2824 100644
--- a/components/camel-atmosphere-websocket/src/main/docs/atmosphere-websocket-component.adoc
+++ b/components/camel-atmosphere-websocket/src/main/docs/atmosphere-websocket-component.adoc
@@ -85,7 +85,7 @@ with the following path and query parameters:
 | Name | Description | Default | Type
 | *sendToAll* (common) | Whether to send to all (broadcast) or send to a single receiver. | false | boolean
 | *useStreaming* (common) | To enable streaming to send data as multiple text fragments. | false | boolean
-| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
+| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
 | *headerFilterStrategy* (common) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
 | *httpBinding* (common) | To use a custom HttpBinding to control the mapping between Camel message and HttpClient. |  | HttpBinding
 | *async* (consumer) | Configure the consumer to work in async mode | false | boolean
diff --git a/components/camel-jetty/src/main/docs/jetty-component.adoc b/components/camel-jetty/src/main/docs/jetty-component.adoc
index 1095244..c3d1349 100644
--- a/components/camel-jetty/src/main/docs/jetty-component.adoc
+++ b/components/camel-jetty/src/main/docs/jetty-component.adoc
@@ -126,7 +126,7 @@ with the following path and query parameters:
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
+| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
 | *headerFilterStrategy* (common) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
 | *httpBinding* (common) | To use a custom HttpBinding to control the mapping between Camel message and HttpClient. |  | HttpBinding
 | *async* (consumer) | Configure the consumer to work in async mode | false | boolean
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/AtmosphereWebsocketEndpointBuilderFactory.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/AtmosphereWebsocketEndpointBuilderFactory.java
index 68f3a06..617fd03 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/AtmosphereWebsocketEndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/AtmosphereWebsocketEndpointBuilderFactory.java
@@ -103,10 +103,10 @@ public interface AtmosphereWebsocketEndpointBuilderFactory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http producer will by default cache the response
-         * body stream. If setting this option to true, then the producers will
-         * not cache the response body stream but use the response stream as-is
-         * as the message body.
+         * multiple times. The http/http4 producer will by default cache the
+         * response body stream. If setting this option to true, then the
+         * producers will not cache the response body stream but use the
+         * response stream as-is as the message body.
          * 
          * The option is a: <code>boolean</code> type.
          * 
@@ -130,10 +130,10 @@ public interface AtmosphereWebsocketEndpointBuilderFactory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http producer will by default cache the response
-         * body stream. If setting this option to true, then the producers will
-         * not cache the response body stream but use the response stream as-is
-         * as the message body.
+         * multiple times. The http/http4 producer will by default cache the
+         * response body stream. If setting this option to true, then the
+         * producers will not cache the response body stream but use the
+         * response stream as-is as the message body.
          * 
          * The option will be converted to a <code>boolean</code> type.
          * 
@@ -806,10 +806,10 @@ public interface AtmosphereWebsocketEndpointBuilderFactory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http producer will by default cache the response
-         * body stream. If setting this option to true, then the producers will
-         * not cache the response body stream but use the response stream as-is
-         * as the message body.
+         * multiple times. The http/http4 producer will by default cache the
+         * response body stream. If setting this option to true, then the
+         * producers will not cache the response body stream but use the
+         * response stream as-is as the message body.
          * 
          * The option is a: <code>boolean</code> type.
          * 
@@ -833,10 +833,10 @@ public interface AtmosphereWebsocketEndpointBuilderFactory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http producer will by default cache the response
-         * body stream. If setting this option to true, then the producers will
-         * not cache the response body stream but use the response stream as-is
-         * as the message body.
+         * multiple times. The http/http4 producer will by default cache the
+         * response body stream. If setting this option to true, then the
+         * producers will not cache the response body stream but use the
+         * response stream as-is as the message body.
          * 
          * The option will be converted to a <code>boolean</code> type.
          * 
@@ -1187,10 +1187,10 @@ public interface AtmosphereWebsocketEndpointBuilderFactory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http producer will by default cache the response
-         * body stream. If setting this option to true, then the producers will
-         * not cache the response body stream but use the response stream as-is
-         * as the message body.
+         * multiple times. The http/http4 producer will by default cache the
+         * response body stream. If setting this option to true, then the
+         * producers will not cache the response body stream but use the
+         * response stream as-is as the message body.
          * 
          * The option is a: <code>boolean</code> type.
          * 
@@ -1214,10 +1214,10 @@ public interface AtmosphereWebsocketEndpointBuilderFactory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http producer will by default cache the response
-         * body stream. If setting this option to true, then the producers will
-         * not cache the response body stream but use the response stream as-is
-         * as the message body.
+         * multiple times. The http/http4 producer will by default cache the
+         * response body stream. If setting this option to true, then the
+         * producers will not cache the response body stream but use the
+         * response stream as-is as the message body.
          * 
          * The option will be converted to a <code>boolean</code> type.
          * 
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JettyHttpEndpointBuilder9Factory.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JettyHttpEndpointBuilder9Factory.java
index 6195b7f..711247d 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JettyHttpEndpointBuilder9Factory.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JettyHttpEndpointBuilder9Factory.java
@@ -54,10 +54,10 @@ public interface JettyHttpEndpointBuilder9Factory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http producer will by default cache the response
-         * body stream. If setting this option to true, then the producers will
-         * not cache the response body stream but use the response stream as-is
-         * as the message body.
+         * multiple times. The http/http4 producer will by default cache the
+         * response body stream. If setting this option to true, then the
+         * producers will not cache the response body stream but use the
+         * response stream as-is as the message body.
          * 
          * The option is a: <code>boolean</code> type.
          * 
@@ -81,10 +81,10 @@ public interface JettyHttpEndpointBuilder9Factory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http producer will by default cache the response
-         * body stream. If setting this option to true, then the producers will
-         * not cache the response body stream but use the response stream as-is
-         * as the message body.
+         * multiple times. The http/http4 producer will by default cache the
+         * response body stream. If setting this option to true, then the
+         * producers will not cache the response body stream but use the
+         * response stream as-is as the message body.
          * 
          * The option will be converted to a <code>boolean</code> type.
          * 
diff --git a/docs/components/modules/ROOT/pages/atmosphere-websocket-component.adoc b/docs/components/modules/ROOT/pages/atmosphere-websocket-component.adoc
index 8d56b7b..0bc2824 100644
--- a/docs/components/modules/ROOT/pages/atmosphere-websocket-component.adoc
+++ b/docs/components/modules/ROOT/pages/atmosphere-websocket-component.adoc
@@ -85,7 +85,7 @@ with the following path and query parameters:
 | Name | Description | Default | Type
 | *sendToAll* (common) | Whether to send to all (broadcast) or send to a single receiver. | false | boolean
 | *useStreaming* (common) | To enable streaming to send data as multiple text fragments. | false | boolean
-| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
+| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
 | *headerFilterStrategy* (common) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
 | *httpBinding* (common) | To use a custom HttpBinding to control the mapping between Camel message and HttpClient. |  | HttpBinding
 | *async* (consumer) | Configure the consumer to work in async mode | false | boolean
diff --git a/docs/components/modules/ROOT/pages/jetty-component.adoc b/docs/components/modules/ROOT/pages/jetty-component.adoc
index 1095244..c3d1349 100644
--- a/docs/components/modules/ROOT/pages/jetty-component.adoc
+++ b/docs/components/modules/ROOT/pages/jetty-component.adoc
@@ -126,7 +126,7 @@ with the following path and query parameters:
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
+| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
 | *headerFilterStrategy* (common) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
 | *httpBinding* (common) | To use a custom HttpBinding to control the mapping between Camel message and HttpClient. |  | HttpBinding
 | *async* (consumer) | Configure the consumer to work in async mode | false | boolean
diff --git a/docs/components/modules/ROOT/pages/mock-component.adoc b/docs/components/modules/ROOT/pages/mock-component.adoc
index 9a11ced..409a9e2 100644
--- a/docs/components/modules/ROOT/pages/mock-component.adoc
+++ b/docs/components/modules/ROOT/pages/mock-component.adoc
@@ -112,7 +112,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (12 parameters):
+=== Query Parameters (13 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -120,6 +120,7 @@ with the following path and query parameters:
 | Name | Description | Default | Type
 | *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


[camel] 01/08: CAMEL-12003: Add failFast option to mock endpoint

Posted by da...@apache.org.
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 d8627e2a9ad60131cc71753ef25ae77e5ae3f51a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Aug 2 07:24:31 2019 +0200

    CAMEL-12003: Add failFast option to mock endpoint
---
 .../camel-mock/src/main/docs/mock-component.adoc   |   3 +-
 .../apache/camel/component/mock/AssertionTask.java |  31 ++++
 .../apache/camel/component/mock/MockEndpoint.java  | 166 ++++++++++++++-------
 3 files changed, 148 insertions(+), 52 deletions(-)

diff --git a/components/camel-mock/src/main/docs/mock-component.adoc b/components/camel-mock/src/main/docs/mock-component.adoc
index 9a11ced..409a9e2 100644
--- a/components/camel-mock/src/main/docs/mock-component.adoc
+++ b/components/camel-mock/src/main/docs/mock-component.adoc
@@ -112,7 +112,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (12 parameters):
+=== Query Parameters (13 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -120,6 +120,7 @@ with the following path and query parameters:
 | Name | Description | Default | Type
 | *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-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java
new file mode 100644
index 0000000..16daf49
--- /dev/null
+++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java
@@ -0,0 +1,31 @@
+/*
+ * 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.component.mock;
+
+/**
+ * Assertion task that supports fail fast mode by running the assertion asap on the n'th received message.
+ */
+public abstract class AssertionTask implements Runnable {
+
+    /**
+     * Asserts on the n'th received message
+     *
+     * @param index the n'th received message
+     */
+    abstract void assertOnIndex(int index);
+
+}
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 8a9826f..cdb42de 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
@@ -102,6 +102,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
     private volatile List<Throwable> failures;
     private volatile List<Runnable> tests;
     private volatile CountDownLatch latch;
+    private volatile AssertionError failFastAssertionError;
     private volatile int expectedMinimumCount;
     private volatile List<?> expectedBodyValues;
     private volatile List<Object> actualBodyValues;
@@ -130,6 +131,8 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
     private int retainLast;
     @UriParam(label = "producer")
     private int reportGroup;
+    @UriParam(label = "producer")
+    private boolean failFast = true;
     @UriParam(label = "producer,advanced", defaultValue = "true")
     private boolean copyOnExchange = true;
 
@@ -181,7 +184,6 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
         }
     }
 
-
     /**
      * Asserts that all the expectations on any {@link MockEndpoint} instances registered
      * in the given context are valid
@@ -299,7 +301,6 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
         doInit();
     }
 
-
     // Testing API
     // -------------------------------------------------------------------------
 
@@ -399,18 +400,28 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
             if (expectedCount != getReceivedCounter()) {
                 waitForCompleteLatch();
             }
-            assertEquals("Received message count", expectedCount, getReceivedCounter());
+            if (failFastAssertionError == null) {
+                assertEquals("Received message count", expectedCount, getReceivedCounter());
+            }
         } else if (expectedMinimumCount > 0 && getReceivedCounter() < expectedMinimumCount) {
             waitForCompleteLatch();
         }
 
+        if (failFastAssertionError != null) {
+            throw failFastAssertionError;
+        }
+
         if (expectedMinimumCount >= 0) {
             int receivedCounter = getReceivedCounter();
             assertTrue("Received message count " + receivedCounter + ", expected at least " + expectedMinimumCount, expectedMinimumCount <= receivedCounter);
         }
 
         for (Runnable test : tests) {
-            test.run();
+            // skip tasks which we have already been running in fail fast mode
+            boolean skip = failFast && test instanceof AssertionTask;
+            if (!skip) {
+                test.run();
+            }
         }
 
         for (Throwable failure : failures) {
@@ -528,26 +539,31 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
         if (expectedHeaderValues == null) {
             expectedHeaderValues = getCamelContext().getHeadersMapFactory().newMap();
             // we just wants to expects to be called once
-            expects(new Runnable() {
-                public void run() {
-                    for (int i = 0; i < getReceivedExchanges().size(); i++) {
-                        Exchange exchange = getReceivedExchange(i);
-                        for (Map.Entry<String, Object> entry : expectedHeaderValues.entrySet()) {
-                            String key = entry.getKey();
-                            Object expectedValue = entry.getValue();
-
-                            // we accept that an expectedValue of null also means that the header may be absent
-                            if (expectedValue != null) {
-                                assertTrue("Exchange " + i + " has no headers", exchange.getIn().hasHeaders());
-                                boolean hasKey = exchange.getIn().getHeaders().containsKey(key);
-                                assertTrue("No header with name " + key + " found for message: " + i, hasKey);
-                            }
-
-                            Object actualValue = exchange.getIn().getHeader(key);
-                            actualValue = extractActualValue(exchange, actualValue, expectedValue);
+            expects(new AssertionTask() {
+                @Override
+                void assertOnIndex(int i) {
+                    Exchange exchange = getReceivedExchange(i);
+                    for (Map.Entry<String, Object> entry : expectedHeaderValues.entrySet()) {
+                        String key = entry.getKey();
+                        Object expectedValue = entry.getValue();
 
-                            assertEquals("Header with name " + key + " for message: " + i, expectedValue, actualValue);
+                        // we accept that an expectedValue of null also means that the header may be absent
+                        if (expectedValue != null) {
+                            assertTrue("Exchange " + i + " has no headers", exchange.getIn().hasHeaders());
+                            boolean hasKey = exchange.getIn().getHeaders().containsKey(key);
+                            assertTrue("No header with name " + key + " found for message: " + i, hasKey);
                         }
+
+                        Object actualValue = exchange.getIn().getHeader(key);
+                        actualValue = extractActualValue(exchange, actualValue, expectedValue);
+
+                        assertEquals("Header with name " + key + " for message: " + i, expectedValue, actualValue);
+                    }
+                }
+
+                public void run() {
+                    for (int i = 0; i < getReceivedExchanges().size(); i++) {
+                        assertOnIndex(i);
                     }
                 }
             });
@@ -617,26 +633,31 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
         }
         expectedPropertyValues.put(name, value);
 
-        expects(new Runnable() {
-            public void run() {
-                for (int i = 0; i < getReceivedExchanges().size(); i++) {
-                    Exchange exchange = getReceivedExchange(i);
-                    for (Map.Entry<String, Object> entry : expectedPropertyValues.entrySet()) {
-                        String key = entry.getKey();
-                        Object expectedValue = entry.getValue();
+        expects(new AssertionTask() {
+            @Override
+            void assertOnIndex(int i) {
+                Exchange exchange = getReceivedExchange(i);
+                for (Map.Entry<String, Object> entry : expectedPropertyValues.entrySet()) {
+                    String key = entry.getKey();
+                    Object expectedValue = entry.getValue();
+
+                    // we accept that an expectedValue of null also means that the property may be absent
+                    if (expectedValue != null) {
+                        assertTrue("Exchange " + i + " has no properties", !exchange.getProperties().isEmpty());
+                        boolean hasKey = exchange.getProperties().containsKey(key);
+                        assertTrue("No property with name " + key + " found for message: " + i, hasKey);
+                    }
 
-                        // we accept that an expectedValue of null also means that the property may be absent
-                        if (expectedValue != null) {
-                            assertTrue("Exchange " + i + " has no properties", !exchange.getProperties().isEmpty());
-                            boolean hasKey = exchange.getProperties().containsKey(key);
-                            assertTrue("No property with name " + key + " found for message: " + i, hasKey);
-                        }
+                    Object actualValue = exchange.getProperty(key);
+                    actualValue = extractActualValue(exchange, actualValue, expectedValue);
 
-                        Object actualValue = exchange.getProperty(key);
-                        actualValue = extractActualValue(exchange, actualValue, expectedValue);
+                    assertEquals("Property with name " + key + " for message: " + i, expectedValue, actualValue);
+                }
+            }
 
-                        assertEquals("Property with name " + key + " for message: " + i, expectedValue, actualValue);
-                    }
+            public void run() {
+                for (int i = 0; i < getReceivedExchanges().size(); i++) {
+                    assertOnIndex(i);
                 }
             }
         });
@@ -706,20 +727,25 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
         this.expectedBodyValues = bodies;
         this.actualBodyValues = new ArrayList<>();
 
-        expects(new Runnable() {
-            public void run() {
-                for (int i = 0; i < expectedBodyValues.size(); i++) {
-                    Exchange exchange = getReceivedExchange(i);
-                    assertTrue("No exchange received for counter: " + i, exchange != null);
+        expects(new AssertionTask() {
+            @Override
+            void assertOnIndex(int i) {
+                Exchange exchange = getReceivedExchange(i);
+                assertTrue("No exchange received for counter: " + i, exchange != null);
 
-                    Object expectedBody = expectedBodyValues.get(i);
-                    Object actualBody = null;
-                    if (i < actualBodyValues.size()) {
-                        actualBody = actualBodyValues.get(i);
-                    }
-                    actualBody = extractActualValue(exchange, actualBody, expectedBody);
+                Object expectedBody = expectedBodyValues.get(i);
+                Object actualBody = null;
+                if (i < actualBodyValues.size()) {
+                    actualBody = actualBodyValues.get(i);
+                }
+                actualBody = extractActualValue(exchange, actualBody, expectedBody);
+
+                assertEquals("Body of message: " + i, expectedBody, actualBody);
+            }
 
-                    assertEquals("Body of message: " + i, expectedBody, actualBody);
+            public void run() {
+                for (int i = 0; i < expectedBodyValues.size(); i++) {
+                    assertOnIndex(i);
                 }
             }
         });
@@ -1314,6 +1340,21 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
         this.copyOnExchange = copyOnExchange;
     }
 
+    public boolean isFailFast() {
+        return failFast;
+    }
+
+    /**
+     * Sets whether {@link #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 <tt>true</tt>. Set to <tt>false</tt> to use behavior as in Camel 2.x.
+     */
+    public void setFailFast(boolean failFast) {
+        this.failFast = failFast;
+    }
+
     // Implementation methods
     // -------------------------------------------------------------------------
     protected void doInit() {
@@ -1325,6 +1366,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
         failures = new CopyOnWriteArrayList<>();
         tests = new CopyOnWriteArrayList<>();
         latch = null;
+        failFastAssertionError = null;
         sleepForEmptyTest = 0;
         resultWaitTime = 0;
         resultMinimumWaitTime = 0L;
@@ -1351,6 +1393,28 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
                 copy = ExchangeHelper.createCopy(exchange, true);
             }
             performAssertions(exchange, copy);
+
+            if (failFast) {
+                // fail fast mode so check n'th expectations as soon as possible
+                int index = getReceivedCounter() - 1;
+                for (Runnable test : tests) {
+                    // only assertion tasks can support fail fast mode
+                    if (test instanceof AssertionTask) {
+                        AssertionTask task = (AssertionTask) test;
+                        try {
+                            log.debug("Running assertOnIndex({}) on task: {}", index, task);
+                            task.assertOnIndex(index);
+                        } catch (AssertionError e) {
+                            failFastAssertionError = e;
+                            // signal latch we are done as we are failing fast
+                            log.debug("Assertion failed fast on " + index + " received exchange due to " + e.getMessage());
+                            while (latch != null && latch.getCount() > 0) {
+                                latch.countDown();
+                            }
+                        }
+                    }
+                }
+            }
         } catch (Throwable e) {
             // must catch java.lang.Throwable as AssertionError extends java.lang.Error
             failures.add(e);


[camel] 03/08: CAMEL-12003: Add failFast option to mock endpoint

Posted by da...@apache.org.
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 b054f70029f74abb1edf09a49efb13b591f65c0e
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Aug 2 07:45:43 2019 +0200

    CAMEL-12003: Add failFast option to mock endpoint
---
 ...AssertionTask.java => AssertionClauseTask.java} | 23 +++-----
 .../apache/camel/component/mock/AssertionTask.java |  4 +-
 .../apache/camel/component/mock/MockEndpoint.java  | 61 +++++++++++++++-------
 3 files changed, 53 insertions(+), 35 deletions(-)

diff --git a/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClauseTask.java
similarity index 67%
copy from components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java
copy to components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClauseTask.java
index 16daf49..572f3d0 100644
--- a/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java
+++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClauseTask.java
@@ -1,13 +1,13 @@
-/*
+/**
  * 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
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
  * 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.
@@ -16,16 +16,9 @@
  */
 package org.apache.camel.component.mock;
 
-/**
- * Assertion task that supports fail fast mode by running the assertion asap on the n'th received message.
- */
-public abstract class AssertionTask implements Runnable {
-
-    /**
-     * Asserts on the n'th received message
-     *
-     * @param index the n'th received message
-     */
-    abstract void assertOnIndex(int index);
+public abstract class AssertionClauseTask extends AssertionClause implements AssertionTask {
 
+    public AssertionClauseTask(MockEndpoint mock) {
+        super(mock);
+    }
 }
diff --git a/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java
index 16daf49..347ba0d 100644
--- a/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java
+++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionTask.java
@@ -19,13 +19,13 @@ package org.apache.camel.component.mock;
 /**
  * Assertion task that supports fail fast mode by running the assertion asap on the n'th received message.
  */
-public abstract class AssertionTask implements Runnable {
+public interface AssertionTask extends Runnable {
 
     /**
      * Asserts on the n'th received message
      *
      * @param index the n'th received message
      */
-    abstract void assertOnIndex(int index);
+    public void assertOnIndex(int index);
 
 }
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 cdb42de..3465f1c 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
@@ -541,7 +541,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
             // we just wants to expects to be called once
             expects(new AssertionTask() {
                 @Override
-                void assertOnIndex(int i) {
+                public void assertOnIndex(int i) {
                     Exchange exchange = getReceivedExchange(i);
                     for (Map.Entry<String, Object> entry : expectedHeaderValues.entrySet()) {
                         String key = entry.getKey();
@@ -635,7 +635,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
 
         expects(new AssertionTask() {
             @Override
-            void assertOnIndex(int i) {
+            public void assertOnIndex(int i) {
                 Exchange exchange = getReceivedExchange(i);
                 for (Map.Entry<String, Object> entry : expectedPropertyValues.entrySet()) {
                     String key = entry.getKey();
@@ -729,7 +729,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
 
         expects(new AssertionTask() {
             @Override
-            void assertOnIndex(int i) {
+            public void assertOnIndex(int i) {
                 Exchange exchange = getReceivedExchange(i);
                 assertTrue("No exchange received for counter: " + i, exchange != null);
 
@@ -783,6 +783,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
             final AssertionClause clause = new AssertionClause(this) {
                 public void run() {
                     addPredicate(predicate);
+                    // TODO: Is this correct
                     applyAssertionOn(MockEndpoint.this, messageIndex, assertExchangeReceived(messageIndex));
                 }
             };
@@ -809,16 +810,23 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      */
     public AssertionClause expectedBodyReceived() {
         expectedMessageCount(1);
-        final AssertionClause clause = new AssertionClause(this) {
-            public void run() {
-                Exchange exchange = getReceivedExchange(0);
-                assertTrue("No exchange received for counter: " + 0, exchange != null);
+        final AssertionClause clause = new AssertionClauseTask(this) {
+            @Override
+            public void assertOnIndex(int index) {
+                if (index == 0) {
+                    Exchange exchange = getReceivedExchange(index);
+                    assertTrue("No exchange received for counter: " + index, exchange != null);
 
-                Object actualBody = exchange.getIn().getBody();
-                Expression exp = createExpression(getCamelContext());
-                Object expectedBody = exp.evaluate(exchange, Object.class);
+                    Object actualBody = exchange.getIn().getBody();
+                    Expression exp = createExpression(getCamelContext());
+                    Object expectedBody = exp.evaluate(exchange, Object.class);
 
-                assertEquals("Body of message: " + 0, expectedBody, actualBody);
+                    assertEquals("Body of message: " + index, expectedBody, actualBody);
+                }
+            }
+
+            public void run() {
+                assertOnIndex(0);
             }
         };
         expects(clause);
@@ -941,6 +949,7 @@ 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) {
             public void run() {
                 assertMessagesAscending(createExpression(getCamelContext()));
@@ -967,6 +976,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * of the given expression such as a user generated counter value
      */
     public AssertionClause expectsDescending() {
+        // TODO: Task
         final AssertionClause clause = new AssertionClause(this) {
             public void run() {
                 assertMessagesDescending(createExpression(getCamelContext()));
@@ -999,6 +1009,7 @@ 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) {
             public void run() {
                 assertNoDuplicates(createExpression(getCamelContext()));
@@ -1012,6 +1023,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * Asserts that the messages have ascending values of the given expression
      */
     public void assertMessagesAscending(Expression expression) {
+        // TODO: Task
         assertMessagesSorted(expression, true);
     }
 
@@ -1019,6 +1031,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * Asserts that the messages have descending values of the given expression
      */
     public void assertMessagesDescending(Expression expression) {
+        // TODO: Task
         assertMessagesSorted(expression, false);
     }
 
@@ -1076,9 +1089,16 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * @return the assertion clause
      */
     public AssertionClause message(final int messageIndex) {
-        final AssertionClause clause = new AssertionClause(this) {
+        final AssertionClause clause = new AssertionClauseTask(this) {
+            @Override
+            public void assertOnIndex(int index) {
+                if (index == messageIndex) {
+                    applyAssertionOn(MockEndpoint.this, index, assertExchangeReceived(index));
+                }
+            }
+
             public void run() {
-                applyAssertionOn(MockEndpoint.this, messageIndex, assertExchangeReceived(messageIndex));
+                assertOnIndex(messageIndex);
             }
         };
         expects(clause);
@@ -1091,12 +1111,15 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * @return the assertion clause
      */
     public AssertionClause allMessages() {
-        final AssertionClause clause = new AssertionClause(this) {
+        final AssertionClause clause = new AssertionClauseTask(this) {
+            @Override
+            public void assertOnIndex(int index) {
+                applyAssertionOn(MockEndpoint.this, index, assertExchangeReceived(index));
+            }
+
             public void run() {
-                List<Exchange> list = getReceivedExchanges();
-                int index = 0;
-                for (Exchange exchange : list) {
-                    applyAssertionOn(MockEndpoint.this, index++, exchange);
+                for (int i = 0; i < getReceivedCounter(); i++) {
+                    assertOnIndex(i);
                 }
             }
         };
@@ -1411,6 +1434,8 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
                             while (latch != null && latch.getCount() > 0) {
                                 latch.countDown();
                             }
+                            // we are failing fast
+                            break;
                         }
                     }
                 }


[camel] 06/08: CAMEL-12003: Add failFast option to mock endpoint

Posted by da...@apache.org.
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 c38bd5a7a3728592c7564af3c45bf7149c9f32a4
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Aug 2 16:20:04 2019 +0200

    CAMEL-12003: Add failFast option to mock endpoint
---
 .../camel/component/mock/AssertionClauseTask.java  |  3 ++
 .../apache/camel/component/mock/MockEndpoint.java  | 58 ++++++++++++++--------
 2 files changed, 41 insertions(+), 20 deletions(-)

diff --git a/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClauseTask.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClauseTask.java
index 572f3d0..b613908 100644
--- a/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClauseTask.java
+++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClauseTask.java
@@ -16,6 +16,9 @@
  */
 package org.apache.camel.component.mock;
 
+/**
+ * An {@link AssertionClause} that bridges with fail fast mode ({@link AssertionTask}).
+ */
 public abstract class AssertionClauseTask extends AssertionClause implements AssertionTask {
 
     public AssertionClauseTask(MockEndpoint mock) {
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 a7a613f..fb0ecff 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
@@ -945,9 +945,13 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * of the given expression such as a user generated counter value
      */
     public void expectsAscending(final Expression expression) {
-        expects(new Runnable() {
+        expects(new AssertionTask() {
+            @Override
+            public void assertOnIndex(int index) {
+                assertMessagesSorted(expression, true, index);
+            }
+
             public void run() {
-                // TODO: Task
                 assertMessagesAscending(expression);
             }
         });
@@ -961,9 +965,7 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
         final AssertionClause clause = new AssertionClauseTask(this) {
             @Override
             public void assertOnIndex(int index) {
-                // TODO: Make this smarter
-                // just run from top again
-                run();
+                assertMessagesSorted(createExpression(getCamelContext()), true, index);
             }
 
             public void run() {
@@ -979,7 +981,12 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * of the given expression such as a user generated counter value
      */
     public void expectsDescending(final Expression expression) {
-        expects(new Runnable() {
+        expects(new AssertionTask() {
+            @Override
+            public void assertOnIndex(int index) {
+                assertMessagesSorted(expression, false, index);
+            }
+
             public void run() {
                 assertMessagesDescending(expression);
             }
@@ -991,8 +998,12 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * of the given expression such as a user generated counter value
      */
     public AssertionClause expectsDescending() {
-        // TODO: Task
-        final AssertionClause clause = new AssertionClause(this) {
+        final AssertionClause clause = new AssertionClauseTask(this) {
+            @Override
+            public void assertOnIndex(int index) {
+                assertMessagesSorted(createExpression(getCamelContext()), false, index);
+            }
+
             public void run() {
                 assertMessagesDescending(createExpression(getCamelContext()));
             }
@@ -1075,7 +1086,6 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * Asserts that the messages have ascending values of the given expression
      */
     public void assertMessagesAscending(Expression expression) {
-        // TODO: Task
         assertMessagesSorted(expression, true);
     }
 
@@ -1083,35 +1093,43 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
      * Asserts that the messages have descending values of the given expression
      */
     public void assertMessagesDescending(Expression expression) {
-        // TODO: Task
         assertMessagesSorted(expression, false);
     }
 
     protected void assertMessagesSorted(Expression expression, boolean ascending) {
+        List<Exchange> list = getReceivedExchanges();
+        for (int i = 0; i < list.size(); i++) {
+            assertMessagesSorted(expression, ascending, i);
+        }
+    }
+
+    protected void assertMessagesSorted(Expression expression, boolean ascending, int index) {
         String type = ascending ? "ascending" : "descending";
         ExpressionComparator comparator = new ExpressionComparator(expression);
-        List<Exchange> list = getReceivedExchanges();
-        for (int i = 1; i < list.size(); i++) {
-            int j = i - 1;
-            Exchange e1 = list.get(j);
-            Exchange e2 = list.get(i);
+
+        int prev = index - 1;
+        if (prev > 0) {
+            List<Exchange> list = getReceivedExchanges();
+            Exchange e1 = list.get(prev);
+            Exchange e2 = list.get(index);
             int result = comparator.compare(e1, e2);
             if (result == 0) {
-                fail("Messages not " + type + ". Messages" + j + " and " + i + " are equal with value: "
-                    + expression.evaluate(e1, Object.class) + " for expression: " + expression + ". Exchanges: " + e1 + " and " + e2);
+                fail("Messages not " + type + ". Messages" + prev + " and " + index + " are equal with value: "
+                        + expression.evaluate(e1, Object.class) + " for expression: " + expression + ". Exchanges: " + e1 + " and " + e2);
             } else {
                 if (!ascending) {
                     result = result * -1;
                 }
                 if (result > 0) {
-                    fail("Messages not " + type + ". Message " + j + " has value: " + expression.evaluate(e1, Object.class)
-                        + " and message " + i + " has value: " + expression.evaluate(e2, Object.class) + " for expression: "
-                        + expression + ". Exchanges: " + e1 + " and " + e2);
+                    fail("Messages not " + type + ". Message " + prev + " has value: " + expression.evaluate(e1, Object.class)
+                            + " and message " + index + " has value: " + expression.evaluate(e2, Object.class) + " for expression: "
+                            + expression + ". Exchanges: " + e1 + " and " + e2);
                 }
             }
         }
     }
 
+
     /**
      * Asserts among all the current received exchanges that there are no duplicate message
      *


[camel] 04/08: CAMEL-12003: Add failFast option to mock endpoint

Posted by da...@apache.org.
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 61909c2199f708db50bc9999d7d8795d751b2b2c
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Aug 2 08:27:22 2019 +0200

    CAMEL-12003: Add failFast option to mock endpoint
---
 .../src/main/docs/dataset-test-component.adoc          |  3 ++-
 .../camel/component/dataset/DataSetEndpoint.java       |  7 ++++++-
 .../apache/camel/component/mock/AssertionClause.java   | 12 +++++++-----
 .../org/apache/camel/component/mock/MockEndpoint.java  | 18 +++++++++++++-----
 4 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/components/camel-dataset/src/main/docs/dataset-test-component.adoc b/components/camel-dataset/src/main/docs/dataset-test-component.adoc
index 78f9597..82cca82 100644
--- a/components/camel-dataset/src/main/docs/dataset-test-component.adoc
+++ b/components/camel-dataset/src/main/docs/dataset-test-component.adoc
@@ -73,7 +73,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (16 parameters):
+=== Query Parameters (17 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -85,6 +85,7 @@ with the following path and query parameters:
 | *timeout* (producer) | The timeout to use when polling for message bodies from the URI | 2000 | 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 49074ed..c72ab14 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", lenientProperties = true)
+    label = "core,testing", excludeProperties = "failFast", lenientProperties = true)
 public class DataSetEndpoint extends MockEndpoint implements Service {
     private final transient Logger log;
     private final AtomicInteger receivedCounter = new AtomicInteger();
@@ -70,6 +70,8 @@ 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) {
@@ -297,6 +299,9 @@ 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/AssertionClause.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClause.java
index 3009090..16b9503 100644
--- a/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClause.java
+++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/AssertionClause.java
@@ -100,11 +100,13 @@ public abstract class AssertionClause extends MockExpressionClauseSupport<MockVa
         for (Predicate predicate : predicates) {
             currentIndex = index;
 
-            Object value = exchange.getMessage().getBody();
-            // if the value is StreamCache then ensure its readable before evaluating any predicates
-            // by resetting it (this is also what StreamCachingAdvice does)
-            if (value instanceof StreamCache) {
-                ((StreamCache) value).reset();
+            if (exchange != null) {
+                Object value = exchange.getMessage().getBody();
+                // if the value is StreamCache then ensure its readable before evaluating any predicates
+                // by resetting it (this is also what StreamCachingAdvice does)
+                if (value instanceof StreamCache) {
+                    ((StreamCache) value).reset();
+                }
             }
 
             PredicateAssertHelper.assertMatches(predicate, "Assertion error at index " + index + " on mock " + endpoint.getEndpointUri() + " with predicate: ", exchange);
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 3465f1c..45b2f19 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
@@ -426,8 +426,8 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
 
         for (Throwable failure : failures) {
             if (failure != null) {
-                log.error("Caught on " + getEndpointUri() + " Exception: " + failure, failure);
-                fail("Failed due to caught exception: " + failure);
+                log.error("Caught exception on " + getEndpointUri() + " due to: " + failure.getMessage(), failure);
+                fail(failure);
             }
         }
     }
@@ -1114,11 +1114,13 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
         final AssertionClause clause = new AssertionClauseTask(this) {
             @Override
             public void assertOnIndex(int index) {
-                applyAssertionOn(MockEndpoint.this, index, assertExchangeReceived(index));
+                if (index < getReceivedExchanges().size()) {
+                    applyAssertionOn(MockEndpoint.this, index, assertExchangeReceived(index));
+                }
             }
 
             public void run() {
-                for (int i = 0; i < getReceivedCounter(); i++) {
+                for (int i = 0; i < getReceivedExchanges().size(); i++) {
                     assertOnIndex(i);
                 }
             }
@@ -1603,7 +1605,13 @@ public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint,
                 log.debug("{} failed and received[{}]: {}", getEndpointUri(), ++index, exchange);
             }
         }
-        throw new AssertionError(getEndpointUri() + " " + message);
+        if (message instanceof Throwable) {
+            Throwable cause = (Throwable) message;
+            String msg = "Caught exception on " + getEndpointUri() + " due to: " + cause.getMessage();
+            throw new AssertionError(msg, cause);
+        } else {
+            throw new AssertionError(getEndpointUri() + " " + message);
+        }
     }
 
     public int getExpectedMinimumCount() {


[camel] 07/08: CAMEL-12003: camel-test getMockEndpoint should lookup mock endpoints and favour the mock queue name as matching.

Posted by da...@apache.org.
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 71ba69336a94d1cb8d656cf22c07aaa0c2d8f2eb
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Aug 2 16:45:56 2019 +0200

    CAMEL-12003: camel-test getMockEndpoint should lookup mock endpoints and favour the mock queue name as matching.
---
 .../apache/camel/test/junit4/CamelTestSupport.java | 88 +++++++++++++++-------
 .../camel/test/patterns/GetMockEndpointTest.java   | 46 +++++++++++
 2 files changed, 106 insertions(+), 28 deletions(-)

diff --git a/components/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java b/components/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
index 964610f..118805e 100644
--- a/components/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
+++ b/components/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
@@ -59,6 +59,7 @@ import org.apache.camel.Processor;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.Route;
 import org.apache.camel.RoutesBuilder;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.Service;
 import org.apache.camel.ServiceStatus;
 import org.apache.camel.api.management.JmxSystemPropertyKeys;
@@ -86,6 +87,7 @@ import org.apache.camel.support.EndpointHelper;
 import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.StopWatch;
 import org.apache.camel.util.TimeUtils;
+import org.apache.camel.util.URISupport;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
@@ -131,8 +133,9 @@ public abstract class CamelTestSupport extends TestSupport {
 
     /**
      * Use the RouteBuilder or not
+     *
      * @return <tt>true</tt> then {@link CamelContext} will be auto started,
-     *        <tt>false</tt> then {@link CamelContext} will <b>not</b> be auto started (you will have to start it manually)
+     * <tt>false</tt> then {@link CamelContext} will <b>not</b> be auto started (you will have to start it manually)
      */
     public boolean isUseRouteBuilder() {
         return useRouteBuilder;
@@ -218,17 +221,17 @@ public abstract class CamelTestSupport extends TestSupport {
 
     /**
      * Used for filtering routes routes matching the given pattern, which follows the following rules:
-     *
+     * <p>
      * - Match by route id
      * - Match by route input endpoint uri
-     *
+     * <p>
      * The matching is using exact match, by wildcard and regular expression.
-     *
+     * <p>
      * For example to only include routes which starts with foo in their route id's, use: include=foo&#42;
      * And to exclude routes which starts from JMS endpoints, use: exclude=jms:&#42;
-     *
+     * <p>
      * Multiple patterns can be separated by comma, for example to exclude both foo and bar routes, use: exclude=foo&#42;,bar&#42;
-     *
+     * <p>
      * Exclude takes precedence over include.
      */
     public String getRouteFilterIncludePattern() {
@@ -237,17 +240,17 @@ public abstract class CamelTestSupport extends TestSupport {
 
     /**
      * Used for filtering routes routes matching the given pattern, which follows the following rules:
-     *
+     * <p>
      * - Match by route id
      * - Match by route input endpoint uri
-     *
+     * <p>
      * The matching is using exact match, by wildcard and regular expression.
-     *
+     * <p>
      * For example to only include routes which starts with foo in their route id's, use: include=foo&#42;
      * And to exclude routes which starts from JMS endpoints, use: exclude=jms:&#42;
-     *
+     * <p>
      * Multiple patterns can be separated by comma, for example to exclude both foo and bar routes, use: exclude=foo&#42;,bar&#42;
-     *
+     * <p>
      * Exclude takes precedence over include.
      */
     public String getRouteFilterExcludePattern() {
@@ -359,7 +362,7 @@ public abstract class CamelTestSupport extends TestSupport {
         boolean springBoot = hasClassAnnotation("org.springframework.boot.test.context.SpringBootTest");
         if (springBoot) {
             throw new RuntimeException("Spring Boot detected: The CamelTestSupport/CamelSpringTestSupport class is not intended for Camel testing with Spring Boot."
-                + " Prefer to not extend this class, but use @RunWith(CamelSpringBootRunner.class) instead.");
+                    + " Prefer to not extend this class, but use @RunWith(CamelSpringBootRunner.class) instead.");
         }
     }
 
@@ -373,7 +376,7 @@ public abstract class CamelTestSupport extends TestSupport {
             disableJMX();
         }
 
-        context = (ModelCamelContext)createCamelContext();
+        context = (ModelCamelContext) createCamelContext();
         threadCamelContext.set(context);
 
         assertNotNull("No context found!", context);
@@ -496,8 +499,8 @@ public abstract class CamelTestSupport extends TestSupport {
             ManagedCamelContext mc = context != null ? context.getExtension(ManagedCamelContext.class) : null;
             ManagedCamelContextMBean managedCamelContext = mc != null ? mc.getManagedCamelContext() : null;
             if (managedCamelContext == null) {
-                log.warn("Cannot dump route coverage to file as JMX is not enabled. "  
-                    + "Add camel-management-impl JAR as dependency and/or override useJmx() method to enable JMX in the unit test classes.");
+                log.warn("Cannot dump route coverage to file as JMX is not enabled. "
+                        + "Add camel-management-impl JAR as dependency and/or override useJmx() method to enable JMX in the unit test classes.");
             } else {
                 logCoverageSummary(managedCamelContext);
 
@@ -737,7 +740,7 @@ public abstract class CamelTestSupport extends TestSupport {
 
     /**
      * Applies the {@link CamelBeanPostProcessor} to this instance.
-     *
+     * <p>
      * Derived classes using IoC / DI frameworks may wish to turn this into a NoOp such as for CDI
      * we would just use CDI to inject this
      */
@@ -811,7 +814,7 @@ public abstract class CamelTestSupport extends TestSupport {
             camelContextService.start();
         } else {
             if (context instanceof DefaultCamelContext) {
-                DefaultCamelContext defaultCamelContext = (DefaultCamelContext)context;
+                DefaultCamelContext defaultCamelContext = (DefaultCamelContext) context;
                 if (!defaultCamelContext.isStarted()) {
                     defaultCamelContext.start();
                 }
@@ -832,8 +835,8 @@ public abstract class CamelTestSupport extends TestSupport {
         }
         if (registry != null) {
             String msg = "createRegistry() from camel-test is deprecated. Use createCamelRegistry if you want to control which registry to use, however"
-                + " if you need to bind beans to the registry then this is possible already with the bind method on registry,"
-                + " and there is no need to override this method.";
+                    + " if you need to bind beans to the registry then this is possible already with the bind method on registry,"
+                    + " and there is no need to override this method.";
             LOG.warn(msg);
         } else {
             registry = createCamelRegistry();
@@ -857,7 +860,7 @@ public abstract class CamelTestSupport extends TestSupport {
 
     /**
      * Override to use a custom {@link Registry}.
-     *
+     * <p>
      * However if you need to bind beans to the registry then this is possible already with the bind method on registry,"
      * and there is no need to override this method.
      */
@@ -935,7 +938,7 @@ public abstract class CamelTestSupport extends TestSupport {
      * @see #createRouteBuilder()
      */
     protected RoutesBuilder[] createRouteBuilders() throws Exception {
-        return new RoutesBuilder[] {createRouteBuilder()};
+        return new RoutesBuilder[]{createRouteBuilder()};
     }
 
     /**
@@ -970,21 +973,50 @@ public abstract class CamelTestSupport extends TestSupport {
 
     /**
      * Resolves the {@link MockEndpoint} using a URI of the form <code>mock:someName</code>, optionally
-     * creating it if it does not exist.
+     * creating it if it does not exist. This implementation will lookup existing mock endpoints and match
+     * on the mock queue name, eg mock:foo and mock:foo?retainFirst=5 would match as the queue name is foo.
      *
-     * @param uri      the URI which typically starts with "mock:" and has some name
-     * @param create   whether or not to allow the endpoint to be created if it doesn't exist
+     * @param uri    the URI which typically starts with "mock:" and has some name
+     * @param create whether or not to allow the endpoint to be created if it doesn't exist
      * @return the mock endpoint or an {@link NoSuchEndpointException} is thrown if it could not be resolved
      * @throws NoSuchEndpointException is the mock endpoint does not exists
      */
     protected MockEndpoint getMockEndpoint(String uri, boolean create) throws NoSuchEndpointException {
+        // look for existing mock endpoints that has the same queue name, and to do that we need to
+        // normalize uri and strip out query parameters and whatnot
+        String n;
+        try {
+            n = URISupport.normalizeUri(uri);
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeException(e);
+        }
+        // strip query
+        int idx = n.indexOf('?');
+        if (idx != -1) {
+            n = n.substring(0, idx);
+        }
+        final String target = n;
+
+        // lookup endpoints in registry and try to find it
+        MockEndpoint found = (MockEndpoint) context.getEndpointRegistry().values().stream()
+                .filter(e -> e instanceof MockEndpoint)
+                .filter(e -> {
+                    String t = e.getEndpointUri();
+                    // strip query
+                    int idx2 = t.indexOf('?');
+                    if (idx2 != -1) {
+                        t = t.substring(0, idx2);
+                    }
+                    return t.startsWith(target);
+                }).findFirst().orElse(null);
+
+        if (found != null) {
+            return found;
+        }
+
         if (create) {
             return resolveMandatoryEndpoint(uri, MockEndpoint.class);
         } else {
-            Endpoint endpoint = context.hasEndpoint(uri);
-            if (endpoint instanceof MockEndpoint) {
-                return (MockEndpoint) endpoint;
-            }
             throw new NoSuchEndpointException(String.format("MockEndpoint %s does not exist.", uri));
         }
     }
diff --git a/components/camel-test/src/test/java/org/apache/camel/test/patterns/GetMockEndpointTest.java b/components/camel-test/src/test/java/org/apache/camel/test/patterns/GetMockEndpointTest.java
new file mode 100644
index 0000000..50387a0
--- /dev/null
+++ b/components/camel-test/src/test/java/org/apache/camel/test/patterns/GetMockEndpointTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.test.patterns;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class GetMockEndpointTest extends CamelTestSupport {
+
+    @Test
+    public void testMock() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                        .to("mock:result?failFast=false");
+            }
+        };
+    }
+
+}


[camel] 08/08: Regen

Posted by da...@apache.org.
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 521de3ba2c2e212537be1f3142cb1f30f1baa638
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Aug 2 16:46:07 2019 +0200

    Regen
---
 .../camel-jetty/src/main/docs/jetty-component.adoc       |  2 +-
 .../endpoint/dsl/JettyHttpEndpointBuilder9Factory.java   | 16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/components/camel-jetty/src/main/docs/jetty-component.adoc b/components/camel-jetty/src/main/docs/jetty-component.adoc
index c3d1349..1095244 100644
--- a/components/camel-jetty/src/main/docs/jetty-component.adoc
+++ b/components/camel-jetty/src/main/docs/jetty-component.adoc
@@ -126,7 +126,7 @@ with the following path and query parameters:
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
+| *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
 | *headerFilterStrategy* (common) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
 | *httpBinding* (common) | To use a custom HttpBinding to control the mapping between Camel message and HttpClient. |  | HttpBinding
 | *async* (consumer) | Configure the consumer to work in async mode | false | boolean
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JettyHttpEndpointBuilder9Factory.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JettyHttpEndpointBuilder9Factory.java
index 711247d..6195b7f 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JettyHttpEndpointBuilder9Factory.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/JettyHttpEndpointBuilder9Factory.java
@@ -54,10 +54,10 @@ public interface JettyHttpEndpointBuilder9Factory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http/http4 producer will by default cache the
-         * response body stream. If setting this option to true, then the
-         * producers will not cache the response body stream but use the
-         * response stream as-is as the message body.
+         * multiple times. The http producer will by default cache the response
+         * body stream. If setting this option to true, then the producers will
+         * not cache the response body stream but use the response stream as-is
+         * as the message body.
          * 
          * The option is a: <code>boolean</code> type.
          * 
@@ -81,10 +81,10 @@ public interface JettyHttpEndpointBuilder9Factory {
          * reading the stream multiple times. If you use Servlet to bridge/proxy
          * an endpoint then consider enabling this option to improve
          * performance, in case you do not need to read the message payload
-         * multiple times. The http/http4 producer will by default cache the
-         * response body stream. If setting this option to true, then the
-         * producers will not cache the response body stream but use the
-         * response stream as-is as the message body.
+         * multiple times. The http producer will by default cache the response
+         * body stream. If setting this option to true, then the producers will
+         * not cache the response body stream but use the response stream as-is
+         * as the message body.
          * 
          * The option will be converted to a <code>boolean</code> type.
          *