This is an automated email from the ASF dual-hosted git repository.
apupier pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 7e959e4c42be CAMEL-25667: fix flaky FtpRecursiveDepth*IT tests
7e959e4c42be is described below
commit 7e959e4c42be8b18da1922fda373158e40806e28
Author: Aurélien Pupier <[email protected]>
AuthorDate: Wed Oct 14 21:08:07 2026 +0200
CAMEL-25667: fix flaky FtpRecursiveDepth*IT tests
The three FtpRecursiveDepth*IT tests uploaded files to the FTP server
inside the test method while the consumer route was already running.
This created a race condition: the FTP consumer could start its first
directory poll before all files had been uploaded, causing it to see
only a partial file tree. Because the default post-processing strategy
moves consumed files to a .camel/ subdirectory rather than deleting
them, a subsequent poll could then pick up previously-consumed files
again, resulting in duplicate or missing messages in the mock endpoint.
Fix: mark each consumer route autoStartup(false), upload all test
files synchronously first, then start the route explicitly via
context.getRouteController().startRoute(...). This ensures the
consumer's first poll always sees the complete, stable directory tree.
The same pattern is already used by FtpSimpleConsumeAbsoluteIT,
FtpSimpleConsumeStreamingWithMultipleFilesIT, and others in the same
test suite. FromFtpRecursiveNoopIT was already safe because it uploads
in doPostSetup() before routes start.
Co-authored-by: IBM Bob 2.2.1 <[email protected]>
Signed-off-by: Aurélien Pupier <[email protected]>
---
.../file/remote/integration/FtpRecursiveDepth2IT.java | 17 ++++++++++-------
.../file/remote/integration/FtpRecursiveDepth3IT.java | 13 +++++++++----
.../file/remote/integration/FtpRecursiveDepthIT.java | 13 +++++++++----
3 files changed, 28 insertions(+), 15 deletions(-)
diff --git
a/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepth2IT.java
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepth2IT.java
index 91685807392c..e5ea4b462307 100644
---
a/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepth2IT.java
+++
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepth2IT.java
@@ -16,8 +16,6 @@
*/
package org.apache.camel.component.file.remote.integration;
-import java.util.concurrent.TimeUnit;
-
import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
@@ -31,9 +29,8 @@ public class FtpRecursiveDepth2IT extends
FtpServerTestSupport {
@Test
public void testDepthMin2Max99() throws Exception {
- MockEndpoint mock = getMockEndpoint("mock:result");
- mock.expectedBodiesReceivedInAnyOrder("a2", "b2", "a3", "b3");
-
+ // Upload all files before starting the consumer to avoid a race where
+ // the route picks up files mid-upload and produces inconsistent
results.
template.sendBodyAndHeader("ftp://admin@localhost:{{ftp.server.port}}/depth2?password=admin",
"a", Exchange.FILE_NAME,
"a.txt");
template.sendBodyAndHeader("ftp://admin@localhost:{{ftp.server.port}}/depth2?password=admin",
"b", Exchange.FILE_NAME,
@@ -47,7 +44,12 @@ public class FtpRecursiveDepth2IT extends
FtpServerTestSupport {
template.sendBodyAndHeader("ftp://admin@localhost:{{ftp.server.port}}/depth2/bar/foo?password=admin",
"b3",
Exchange.FILE_NAME, "b3.txt");
- MockEndpoint.assertIsSatisfied(context, 20, TimeUnit.SECONDS);
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedBodiesReceivedInAnyOrder("a2", "b2", "a3", "b3");
+
+ context.getRouteController().startRoute("ftp-recursive-depth2");
+
+ MockEndpoint.assertIsSatisfied(context);
}
@Override
@@ -55,7 +57,8 @@ public class FtpRecursiveDepth2IT extends
FtpServerTestSupport {
return new RouteBuilder() {
@Override
public void configure() {
- from(getFtpUrl() +
"&minDepth=2&maxDepth=99").convertBodyTo(String.class).to("mock:result");
+ from(getFtpUrl() +
"&minDepth=2&maxDepth=99").routeId("ftp-recursive-depth2").autoStartup(false)
+ .convertBodyTo(String.class).to("mock:result");
}
};
}
diff --git
a/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepth3IT.java
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepth3IT.java
index 9a1f22ecfefe..89a0fd1c51b0 100644
---
a/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepth3IT.java
+++
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepth3IT.java
@@ -29,9 +29,8 @@ public class FtpRecursiveDepth3IT extends
FtpServerTestSupport {
@Test
public void testDepthMin1Max1() throws Exception {
- MockEndpoint mock = getMockEndpoint("mock:result");
- mock.expectedBodiesReceivedInAnyOrder("a", "b");
-
+ // Upload all files before starting the consumer to avoid a race where
+ // the route picks up files mid-upload and produces inconsistent
results.
template.sendBodyAndHeader("ftp://admin@localhost:{{ftp.server.port}}/depth3?password=admin",
"a", Exchange.FILE_NAME,
"a.txt");
template.sendBodyAndHeader("ftp://admin@localhost:{{ftp.server.port}}/depth3?password=admin",
"b", Exchange.FILE_NAME,
@@ -45,6 +44,11 @@ public class FtpRecursiveDepth3IT extends
FtpServerTestSupport {
template.sendBodyAndHeader("ftp://admin@localhost:{{ftp.server.port}}/depth3/bar/foo?password=admin",
"b3",
Exchange.FILE_NAME, "b.txt");
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedBodiesReceivedInAnyOrder("a", "b");
+
+ context.getRouteController().startRoute("ftp-recursive-depth3");
+
MockEndpoint.assertIsSatisfied(context);
}
@@ -53,7 +57,8 @@ public class FtpRecursiveDepth3IT extends
FtpServerTestSupport {
return new RouteBuilder() {
@Override
public void configure() {
- from(getFtpUrl() +
"&minDepth=1&maxDepth=1").convertBodyTo(String.class).to("mock:result");
+ from(getFtpUrl() +
"&minDepth=1&maxDepth=1").routeId("ftp-recursive-depth3").autoStartup(false)
+ .convertBodyTo(String.class).to("mock:result");
}
};
}
diff --git
a/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepthIT.java
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepthIT.java
index 0e71eb9ca7b6..abd4af82d460 100644
---
a/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepthIT.java
+++
b/components/camel-ftp/src/test/java/org/apache/camel/component/file/remote/integration/FtpRecursiveDepthIT.java
@@ -29,9 +29,8 @@ public class FtpRecursiveDepthIT extends FtpServerTestSupport
{
@Test
public void testDepth() throws Exception {
- MockEndpoint mock = getMockEndpoint("mock:result");
- mock.expectedBodiesReceivedInAnyOrder("a2", "b2");
-
+ // Upload all files before starting the consumer to avoid a race where
+ // the route picks up files mid-upload and produces inconsistent
results.
template.sendBodyAndHeader("ftp://admin@localhost:{{ftp.server.port}}/depth?password=admin",
"a", Exchange.FILE_NAME,
"a.txt");
template.sendBodyAndHeader("ftp://admin@localhost:{{ftp.server.port}}/depth?password=admin",
"b", Exchange.FILE_NAME,
@@ -47,6 +46,11 @@ public class FtpRecursiveDepthIT extends
FtpServerTestSupport {
template.sendBodyAndHeader("ftp://admin@localhost:{{ftp.server.port}}/depth/bar/foo?password=admin",
"b3",
Exchange.FILE_NAME, "b.txt");
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedBodiesReceivedInAnyOrder("a2", "b2");
+
+ context.getRouteController().startRoute("ftp-recursive-depth");
+
// only expect 2 of the 6 sent, those at depth 2
MockEndpoint.assertIsSatisfied(context);
}
@@ -56,7 +60,8 @@ public class FtpRecursiveDepthIT extends FtpServerTestSupport
{
return new RouteBuilder() {
@Override
public void configure() {
- from(getFtpUrl() +
"&minDepth=2&maxDepth=2").convertBodyTo(String.class).to("mock:result");
+ from(getFtpUrl() +
"&minDepth=2&maxDepth=2").routeId("ftp-recursive-depth").autoStartup(false)
+ .convertBodyTo(String.class).to("mock:result");
}
};
}