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

gnodet 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 fea8f33be983 CAMEL-26818: Run export/dependency/transform tests in 
parallel (#29701)
fea8f33be983 is described below

commit fea8f33be983f84fa6a418fd65d03720da648c2c
Author: Guillaume Nodet <[email protected]>
AuthorDate: Fri Nov 13 10:30:34 2026 +0100

    CAMEL-26818: Run export/dependency/transform tests in parallel (#29701)
    
    * CAMEL-26818: Run export/dependency/transform tests in parallel
    
    The serial-test execution (a single fork running @UsesWorkingDirectory tests
    one class at a time) prevents the export/dependency/transform tests from
    running in parallel with the other forks and with each other.
    
    The root cause is that all these tests share the .camel-jbang work directory
    (relative to the Maven working directory), so they can't run concurrently.
    
    Fix: add CamelHome.useWorkDir(Path) / resetWorkDir() so tests can redirect 
the
    work directory to a per-test temporary directory (the same pattern that 
already
    exists for the home directory via CamelHome.useHomeDir). The commands that
    hardcoded CommandLineHelper.CAMEL_JBANG_WORK_DIR as a string constant are
    updated to call CommandLineHelper.getWorkDir() dynamically, so the override
    takes effect.
    
    CamelCommandBaseTestSupport gains useTestWorkDir(), which creates a fresh
    temporary work directory and restores the previous one in @AfterEach.
    
    The @UsesWorkingDirectory annotation is removed from 11 test classes that 
now
    use useTestWorkDir(): DependencyCopyTest, DependencyListTest,
    DependencyUpdateTest, ExportMainJibTest, ExportMainJkubeTest, ExportTest,
    InitTest, QuarkusPlatformLookupTest, TransformRouteTest, TransformTest,
    RouteActionJavaSourceTest. These classes extend CamelCommandBaseTestSupport
    (ExportMainJibTest, ExportMainJkubeTest, ExportTest, InitTest, TransformTest
    and QuarkusPlatformLookupTest did not before).
    
    Three tests keep the annotation and remain serial:
    - RunExportGoldenTest: its golden expected files contain the literal path
      .camel-jbang/compile, so the test must run with the default work directory
    - EvalSimpleTest: runs a live Camel CLI from outside this JVM, needs the 
real
      home directory; disabled on CI anyway
    - LoadTest: starts a Camel context in this JVM and talks to it via the CLI
      connector, which reads the action files from the user home
    
    Co-authored-by: gnodet <[email protected]>
    
    * CAMEL-26818: Address review comments
---
 .../camel/dsl/jbang/core/commands/Debug.java       |  5 ++---
 .../dsl/jbang/core/commands/DependencyList.java    | 10 +++++----
 .../apache/camel/dsl/jbang/core/commands/Run.java  |  6 +++---
 .../dsl/jbang/core/commands/SBOMGenerator.java     |  8 ++++---
 .../dsl/jbang/core/commands/TransformRoute.java    |  2 +-
 .../core/commands/action/ActionBaseCommand.java    |  2 +-
 .../commands/action/CamelRouteStructureAction.java |  2 +-
 .../core/commands/CamelCommandBaseTestSupport.java | 25 ++++++++++++++++++++++
 .../jbang/core/commands/DependencyCopyTest.java    |  9 +++++++-
 .../jbang/core/commands/DependencyListTest.java    |  3 ++-
 .../jbang/core/commands/DependencyUpdateTest.java  |  2 +-
 .../dsl/jbang/core/commands/ExportMainJibTest.java |  7 ++++--
 .../jbang/core/commands/ExportMainJkubeTest.java   |  7 ++++--
 .../camel/dsl/jbang/core/commands/ExportTest.java  |  7 ++++--
 .../camel/dsl/jbang/core/commands/InitTest.java    |  8 ++++---
 .../core/commands/QuarkusPlatformLookupTest.java   | 11 ++++++++--
 .../jbang/core/commands/TransformRouteTest.java    |  9 +++++++-
 .../dsl/jbang/core/commands/TransformTest.java     |  8 ++++---
 .../jbang/core/commands/UsesWorkingDirectory.java  |  3 ++-
 .../commands/action/RouteActionJavaSourceTest.java | 13 ++++++++---
 .../camel/dsl/jbang/run/common/CamelHome.java      | 25 ++++++++++++++++++++--
 .../camel/dsl/jbang/run/common/RuntimeUtil.java    |  2 +-
 22 files changed, 133 insertions(+), 41 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
index b53fbe031956..658235b62d7a 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
@@ -78,7 +78,6 @@ import org.codehaus.plexus.util.xml.Xpp3Dom;
 import org.jline.jansi.Ansi;
 import org.jline.jansi.AnsiConsole;
 
-import static 
org.apache.camel.dsl.jbang.core.common.CommandLineHelper.CAMEL_JBANG_WORK_DIR;
 import static org.apache.camel.util.IOHelper.buffered;
 
 @CommandDefinition(name = "debug", description = "Debug local Camel 
integration", generateHelp = true,
@@ -438,7 +437,7 @@ public class Debug extends Run {
                 // the process (and those it started) stops with this JVM, 
then the files of the run are removed
                 ChildProcess.stopOnExit(processRef::get, () -> {
                     removeDir(Paths.get(RUN_PLATFORM_DIR));
-                    removeDir(Paths.get(CAMEL_JBANG_WORK_DIR));
+                    removeDir(CommandLineHelper.getWorkDir());
                     
Files.deleteIfExists(Paths.get("camel-jbang-debug-pom.xml"));
                 });
 
@@ -545,7 +544,7 @@ public class Debug extends Run {
                 // the process (and those it started) stops with this JVM, 
then the files of the run are removed
                 ChildProcess.stopOnExit(processRef::get, () -> {
                     removeDir(Paths.get(RUN_PLATFORM_DIR));
-                    removeDir(Paths.get(CAMEL_JBANG_WORK_DIR));
+                    removeDir(CommandLineHelper.getWorkDir());
                     
Files.deleteIfExists(Paths.get("camel-jbang-debug-pom.xml"));
                 });
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyList.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyList.java
index a408004e888b..4e71dedf833f 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyList.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyList.java
@@ -55,7 +55,9 @@ import static 
org.apache.camel.dsl.jbang.run.common.CamelJBangConstants.*;
                            "  camel dependency list hello.java --output=gav" })
 public class DependencyList extends Export {
 
-    protected static final String EXPORT_DIR = 
CommandLineHelper.CAMEL_JBANG_WORK_DIR + "/export";
+    protected static String tempExportDir() {
+        return CommandLineHelper.getWorkDir().resolve("export").toString();
+    }
 
     public static class OutputFormatCompletionCandidates extends 
CompletionCandidates {
 
@@ -107,7 +109,7 @@ public class DependencyList extends Export {
         Integer answer = doExport();
         if (answer == 0) {
             // read pom.xml
-            Path pom = Paths.get(EXPORT_DIR).resolve("pom.xml");
+            Path pom = Paths.get(tempExportDir()).resolve("pom.xml");
             if (Files.exists(pom)) {
                 DocumentBuilderFactory dbf = 
XmlHelper.createDocumentBuilderFactory();
                 DocumentBuilder db = dbf.newDocumentBuilder();
@@ -210,7 +212,7 @@ public class DependencyList extends Export {
                 }
             }
             // cleanup dir after complete
-            Path buildDir = Paths.get(EXPORT_DIR);
+            Path buildDir = Paths.get(tempExportDir());
             try {
                 Files.walk(buildDir)
                         .sorted(Comparator.reverseOrder())
@@ -278,7 +280,7 @@ public class DependencyList extends Export {
         }
 
         // use temporary export dir
-        exportDir = EXPORT_DIR;
+        exportDir = tempExportDir();
         if (gav == null) {
             gav = "org.example.project:camel-jbang-dummy:1.0";
         }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index 77ad57b08a54..ea79a74c211b 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -1426,7 +1426,7 @@ public class Run extends CamelCommand implements 
CommandLifecycle {
 
         String content = 
TemplateHelper.processTemplate("run-custom-camel-version.ftl", model);
 
-        String fn = CommandLineHelper.CAMEL_JBANG_WORK_DIR + 
"/CustomCamelJBang.java";
+        String fn = 
CommandLineHelper.getWorkDir().resolve("CustomCamelJBang.java").toString();
         Files.writeString(Paths.get(fn), content);
 
         List<String> cmds;
@@ -1451,7 +1451,7 @@ public class Run extends CamelCommand implements 
CommandLifecycle {
         // need to use jbang command to specify camel version
         List<String> jbangArgs = new ArrayList<>();
         jbangArgs.add("jbang");
-        jbangArgs.add(CommandLineHelper.CAMEL_JBANG_WORK_DIR + 
"/CustomCamelJBang.java");
+        
jbangArgs.add(CommandLineHelper.getWorkDir().resolve("CustomCamelJBang.java").toString());
 
         jbangArgs.addAll(cmds);
 
@@ -1489,7 +1489,7 @@ public class Run extends CamelCommand implements 
CommandLifecycle {
     }
 
     private String loadFromCode(String code, String name, boolean file) throws 
IOException {
-        String fn = CommandLineHelper.CAMEL_JBANG_WORK_DIR + "/" + name + 
".java";
+        String fn = CommandLineHelper.getWorkDir().resolve(name + 
".java").toString();
         if (!file) {
             // need to replace single quote as double quotes (from input 
string)
             code = code.replace("'", "\"");
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/SBOMGenerator.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/SBOMGenerator.java
index c9b1ec3138c7..5f033f3d3bc7 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/SBOMGenerator.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/SBOMGenerator.java
@@ -46,7 +46,9 @@ import static 
org.apache.camel.dsl.jbang.run.common.CamelJBangConstants.*;
                            "  camel sbom hello.java --sbom-output-format=xml" 
})
 public class SBOMGenerator extends Export {
 
-    protected static final String EXPORT_DIR = 
CommandLineHelper.CAMEL_JBANG_WORK_DIR + "/export";
+    protected static String tempExportDir() {
+        return CommandLineHelper.getWorkDir().resolve("export").toString();
+    }
 
     protected static final String CYCLONEDX_FORMAT = "cyclonedx";
     protected static final String SPDX_FORMAT = "spdx";
@@ -105,7 +107,7 @@ public class SBOMGenerator extends Export {
 
         Integer answer = doExport();
         if (answer == 0) {
-            Path buildDir = Paths.get(EXPORT_DIR);
+            Path buildDir = Paths.get(tempExportDir());
             List<String> mvnProgramCall;
             if (FileUtil.isWindows()) {
                 mvnProgramCall = List.of("cmd", "/c", "mvn");
@@ -197,7 +199,7 @@ public class SBOMGenerator extends Export {
         }
 
         // use temporary export dir
-        exportDir = EXPORT_DIR;
+        exportDir = tempExportDir();
         if (gav == null) {
             gav = "org.example.project:camel-jbang-run:1.0";
         }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
index 47615aa15093..9007c4785b10 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
@@ -121,7 +121,7 @@ public class TransformRoute extends CamelCommand {
         String dump = output;
         // if no output then we want to print to console, so we need to write 
to a hidden file, and dump that file afterwards
         if (output == null || "clipboard".equals(output)) {
-            dump = CommandLineHelper.CAMEL_JBANG_WORK_DIR + 
"/transform-output." + format;
+            dump = CommandLineHelper.getWorkDir().resolve("transform-output." 
+ format).toString();
         }
         Files.deleteIfExists(Path.of(dump));
         final String target = dump;
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java
index fdd1f89ff806..fcabf8b6750f 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java
@@ -262,7 +262,7 @@ abstract class ActionBaseCommand extends CamelCommand {
             }
         }
 
-        Path workDir = Path.of(CommandLineHelper.CAMEL_JBANG_WORK_DIR, 
workDirPrefix + ProcessHandle.current().pid());
+        Path workDir = CommandLineHelper.getWorkDir().resolve(workDirPrefix + 
ProcessHandle.current().pid());
         PathUtils.deleteDirectory(workDir);
         final String target = workDir.toString();
         // anything this boot dumps must be newer than this: guards readers 
against a stale dump left over from a
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelRouteStructureAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelRouteStructureAction.java
index 8f55697b8701..af6353e04730 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelRouteStructureAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelRouteStructureAction.java
@@ -219,7 +219,7 @@ public class CamelRouteStructureAction extends 
ActionBaseCommand {
         }
 
         // a file of its own, as several commands may run at the same time
-        Path output = Path.of(CommandLineHelper.CAMEL_JBANG_WORK_DIR,
+        Path output = CommandLineHelper.getWorkDir().resolve(
                 "structure-output-" + ProcessHandle.current().pid() + ".json");
         PathUtils.deleteFile(output);
         final String target = output.toString();
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelCommandBaseTestSupport.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelCommandBaseTestSupport.java
index 5992dc8a319e..9f7215175b83 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelCommandBaseTestSupport.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelCommandBaseTestSupport.java
@@ -22,6 +22,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 
 import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
+import org.apache.camel.dsl.jbang.run.common.CamelHome;
 import org.apache.camel.dsl.jbang.run.common.StringPrinter;
 import org.apache.camel.util.FileUtil;
 import org.junit.jupiter.api.AfterEach;
@@ -33,6 +34,7 @@ public class CamelCommandBaseTestSupport {
 
     private Path previousHome;
     private Path testHome;
+    private Path testWorkDir;
 
     @BeforeEach
     public void setup() throws Exception {
@@ -70,6 +72,24 @@ public class CamelCommandBaseTestSupport {
         CommandLineHelper.useHomeDir(home.toString());
     }
 
+    /**
+     * Gives the test a working directory of its own: a temporary directory 
that replaces the shared
+     * {@code .camel-jbang} directory that {@code camel run}, {@code camel 
export}, and others create. With an isolated
+     * directory per test instance, tests annotated with {@link 
UsesWorkingDirectory} can run in parallel forks instead
+     * of one at a time in the serial-test execution.
+     *
+     * @return             the working directory
+     * @throws IOException if the temp directory cannot be created
+     */
+    protected Path useTestWorkDir() throws IOException {
+        if (testWorkDir != null) {
+            FileUtil.removeDir(testWorkDir.toFile());
+        }
+        testWorkDir = Files.createTempDirectory("camel-jbang-work");
+        CamelHome.useWorkDir(testWorkDir);
+        return testWorkDir;
+    }
+
     @AfterEach
     public void restoreHomeDir() {
         if (previousHome != null) {
@@ -80,6 +100,11 @@ public class CamelCommandBaseTestSupport {
             FileUtil.removeDir(testHome.toFile());
             testHome = null;
         }
+        if (testWorkDir != null) {
+            FileUtil.removeDir(testWorkDir.toFile());
+            testWorkDir = null;
+            CamelHome.resetWorkDir();
+        }
     }
 
     public static String quarkusExtRegistry() {
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyCopyTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyCopyTest.java
index d7dfc6595895..b70d69896cc2 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyCopyTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyCopyTest.java
@@ -28,6 +28,7 @@ import org.apache.camel.tooling.maven.MavenArtifact;
 import org.apache.camel.tooling.maven.MavenDownloader;
 import org.apache.camel.tooling.maven.MavenGav;
 import org.apache.camel.tooling.maven.MavenResolutionException;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 
@@ -43,7 +44,6 @@ import static org.mockito.Mockito.spy;
  * camel dependency copy: the JARs of the dependencies of the integration, 
copied to a directory. The dependencies are
  * not downloaded: each resolves to a JAR of its own.
  */
-@UsesWorkingDirectory
 class DependencyCopyTest extends CamelCommandBaseTestSupport {
 
     @TempDir
@@ -55,6 +55,13 @@ class DependencyCopyTest extends CamelCommandBaseTestSupport 
{
     @TempDir
     Path lib;
 
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+        useTestWorkDir();
+    }
+
     @Test
     void copiesTheJarsOfTheDependencies() throws Exception {
         assertThat(command(resolver(null)).doCall()).isZero();
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyListTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyListTest.java
index a2c1e958426c..a4867637fb26 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyListTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyListTest.java
@@ -36,14 +36,15 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
-@UsesWorkingDirectory
 class DependencyListTest extends CamelCommandBaseTestSupport {
 
     private File workingDir;
 
     @BeforeEach
+    @Override
     public void setup() throws Exception {
         super.setup();
+        useTestWorkDir();
         workingDir = Files.createTempDirectory("camel-export").toFile();
     }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdateTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdateTest.java
index 652b8bdf1a1a..b56e6faf8945 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdateTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/DependencyUpdateTest.java
@@ -38,7 +38,6 @@ import org.junit.jupiter.params.provider.MethodSource;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-@UsesWorkingDirectory
 class DependencyUpdateTest extends CamelCommandBaseTestSupport {
 
     private File workingDir;
@@ -47,6 +46,7 @@ class DependencyUpdateTest extends 
CamelCommandBaseTestSupport {
     @Override
     public void setup() throws Exception {
         super.setup();
+        useTestWorkDir();
         workingDir = 
Files.createTempDirectory("camel-dependency-update-tests").toFile();
     }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJibTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJibTest.java
index 1ec4814da054..d43a0a1975ef 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJibTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJibTest.java
@@ -38,13 +38,16 @@ import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
 @UsesWorkingDirectory
-class ExportMainJibTest {
+class ExportMainJibTest extends CamelCommandBaseTestSupport {
 
     private File workingDir;
     private File profile = new File(".", "application.properties");
 
     @BeforeEach
-    public void setup() throws IOException {
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+        useTestWorkDir();
         workingDir = Files.createTempDirectory("camel-export").toFile();
     }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJkubeTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJkubeTest.java
index 5b89a38b76a4..e48b70a3d5c0 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJkubeTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJkubeTest.java
@@ -38,13 +38,16 @@ import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
 @UsesWorkingDirectory
-class ExportMainJkubeTest {
+class ExportMainJkubeTest extends CamelCommandBaseTestSupport {
 
     private File workingDir;
     private File profile = new File(".", "application.properties");
 
     @BeforeEach
-    public void setup() throws IOException {
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+        useTestWorkDir();
         workingDir = Files.createTempDirectory("camel-export").toFile();
     }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
index aa0d73df9422..039c4d886ff1 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
@@ -57,7 +57,7 @@ import org.slf4j.LoggerFactory;
 import static org.assertj.core.api.Assertions.assertThat;
 
 @UsesWorkingDirectory
-class ExportTest {
+class ExportTest extends CamelCommandBaseTestSupport {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(ExportTest.class);
 
@@ -70,8 +70,11 @@ class ExportTest {
     private File workingDir;
 
     @BeforeEach
-    public void setup() throws IOException {
+    @Override
+    public void setup() throws Exception {
+        super.setup();
         LOG.info("Preparing ExportTest");
+        useTestWorkDir();
         workingDir = Files.createTempDirectory("camel-export").toFile();
     }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/InitTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/InitTest.java
index a5bda57d172e..66c9d74bedf7 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/InitTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/InitTest.java
@@ -36,13 +36,15 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@UsesWorkingDirectory
-class InitTest {
+class InitTest extends CamelCommandBaseTestSupport {
 
     private Path workingDir;
 
     @BeforeEach
-    public void beforeEach() throws IOException {
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+        useTestWorkDir();
         Path base = Paths.get("target");
         workingDir = Files.createTempDirectory(base, "camel-init");
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/QuarkusPlatformLookupTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/QuarkusPlatformLookupTest.java
index c0b298e65fcb..77300006e0ef 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/QuarkusPlatformLookupTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/QuarkusPlatformLookupTest.java
@@ -29,6 +29,7 @@ import org.apache.camel.dsl.jbang.run.common.RuntimeType;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.model.Model;
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -41,8 +42,7 @@ import static 
org.assertj.core.api.Assertions.assertThatThrownBy;
  * When camel export looks up the Quarkus Platform in the Quarkus Extension 
Registry: for the Quarkus runtime, which
  * runs on it, and not for the other runtimes (CAMEL-26673).
  */
-@UsesWorkingDirectory
-class QuarkusPlatformLookupTest {
+class QuarkusPlatformLookupTest extends CamelCommandBaseTestSupport {
 
     private static final String ROUTE = 
"src/test/resources/golden/yaml/hello.camel.yaml";
 
@@ -52,6 +52,13 @@ class QuarkusPlatformLookupTest {
     // the Quarkus Platform that the registry of the tests has for this Camel 
version
     private static final String REGISTRY_QUARKUS_VERSION = "3.35.3";
 
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+        useTestWorkDir();
+    }
+
     @ParameterizedTest
     @EnumSource(value = RuntimeType.class, names = { "main", "springBoot" })
     void runtimeOtherThanQuarkusDoesNotNeedTheRegistry(RuntimeType runtime, 
@TempDir Path dir) throws Exception {
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformRouteTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformRouteTest.java
index 4c0d9c9cd670..54aa9bb0f516 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformRouteTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformRouteTest.java
@@ -26,6 +26,7 @@ import 
org.apache.camel.dsl.jbang.core.commands.exceptionhandler.CliExecutionExc
 import org.apache.camel.dsl.jbang.core.common.CliException;
 import org.apache.camel.dsl.jbang.core.common.CliExitCode;
 import org.apache.camel.dsl.jbang.core.common.CommandLineTestHelper;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 
@@ -36,9 +37,15 @@ import static org.assertj.core.api.Assertions.catchThrowable;
 /**
  * camel transform route: a route in another DSL, printed or written to a file 
or directory.
  */
-@UsesWorkingDirectory
 class TransformRouteTest extends CamelCommandBaseTestSupport {
 
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+        useTestWorkDir();
+    }
+
     private static final String YAML = """
             - route:
                 id: hello
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformTest.java
index bed4718d4932..1ae395e3f172 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/TransformTest.java
@@ -32,13 +32,15 @@ import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-@UsesWorkingDirectory
-class TransformTest {
+class TransformTest extends CamelCommandBaseTestSupport {
 
     private Path workingDir;
 
     @BeforeEach
-    public void setup() throws IOException {
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+        useTestWorkDir();
         Path base = Paths.get("target");
         workingDir = Files.createTempDirectory(base, "camel-transform");
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/UsesWorkingDirectory.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/UsesWorkingDirectory.java
index 474219263da0..9fb024310c7e 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/UsesWorkingDirectory.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/UsesWorkingDirectory.java
@@ -26,7 +26,8 @@ import org.junit.jupiter.api.Tag;
 
 /**
  * A test that uses the working directory of the build: the {@code 
.camel-jbang} directory that camel run, export,
- * dependency, transform and others create and delete, or a local {@code 
camel-cli.properties}.
+ * dependency, transform and others create and delete, a local {@code 
camel-cli.properties}, or the
+ * {@code ./application.properties} file in the module directory.
  * <p/>
  * The test forks run in parallel and share the working directory, so these 
tests run after them in a fork of their own,
  * one class at a time (the {@code serial-test} execution in pom.xml).
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/RouteActionJavaSourceTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/RouteActionJavaSourceTest.java
index c95e88cce13e..a6afcbe84787 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/RouteActionJavaSourceTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/RouteActionJavaSourceTest.java
@@ -23,8 +23,8 @@ import java.util.List;
 import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.diagram.RouteDiagramLayoutEngine.RouteInfo;
+import org.apache.camel.dsl.jbang.core.commands.CamelCommandBaseTestSupport;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
-import org.apache.camel.dsl.jbang.core.commands.UsesWorkingDirectory;
 import org.apache.camel.dsl.jbang.core.common.CliException;
 import org.apache.camel.dsl.jbang.core.common.CliExitCode;
 import org.apache.camel.dsl.jbang.run.common.StringPrinter;
@@ -33,6 +33,7 @@ import org.apache.camel.model.ModelCamelContext;
 import org.apache.camel.util.json.JsonArray;
 import org.apache.camel.util.json.JsonObject;
 import org.apache.camel.util.json.Jsoner;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 
@@ -44,8 +45,14 @@ import static 
org.assertj.core.api.Assertions.assertThatThrownBy;
  * routes are dumped from a CamelContext that is never started, so nothing is 
compiled and a source that does not
  * compile (here: a processor class that does not exist) still gets its 
diagram.
  */
-@UsesWorkingDirectory
-class RouteActionJavaSourceTest {
+class RouteActionJavaSourceTest extends CamelCommandBaseTestSupport {
+
+    @BeforeEach
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+        useTestWorkDir();
+    }
 
     private static final String ORDERS = """
             import org.apache.camel.builder.RouteBuilder;
diff --git 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/CamelHome.java
 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/CamelHome.java
index 49af245d3a36..13afb2ef2ede 100644
--- 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/CamelHome.java
+++ 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/CamelHome.java
@@ -30,6 +30,7 @@ public final class CamelHome {
     public static final String CAMEL_JBANG_WORK_DIR = ".camel-jbang";
 
     private static volatile Path homeDir = 
Paths.get(HomeHelper.resolveHomeDir());
+    private static volatile Path workDir;
 
     private CamelHome() {
     }
@@ -63,11 +64,31 @@ public final class CamelHome {
     }
 
     /**
-     * Gets the Camel CLI working directory.
+     * Gets the Camel CLI working directory. By default this is the {@value 
#CAMEL_JBANG_WORK_DIR} directory in the
+     * current working directory; it can be overridden with {@link 
#useWorkDir(Path)} so that parallel test instances
+     * each have an isolated directory of their own.
      *
      * @return file pointing to the working directory.
      */
     public static Path getWorkDir() {
-        return Paths.get(CAMEL_JBANG_WORK_DIR);
+        Path override = workDir;
+        return override != null ? override : Paths.get(CAMEL_JBANG_WORK_DIR);
+    }
+
+    /**
+     * Override the working directory. Unit tests call this in {@code 
@BeforeEach} to give each test instance an
+     * isolated directory, then call {@link #resetWorkDir()} in {@code 
@AfterEach} to restore the default.
+     *
+     * @param workDir the working directory to use.
+     */
+    public static void useWorkDir(Path workDir) {
+        CamelHome.workDir = workDir;
+    }
+
+    /**
+     * Reset the working directory to the default ({@value 
#CAMEL_JBANG_WORK_DIR} in the current working directory).
+     */
+    public static void resetWorkDir() {
+        CamelHome.workDir = null;
     }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/RuntimeUtil.java
 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/RuntimeUtil.java
index 8d84034ed326..0dbf65de65de 100644
--- 
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/RuntimeUtil.java
+++ 
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/RuntimeUtil.java
@@ -141,7 +141,7 @@ public final class RuntimeUtil {
             }
             content = content + System.lineSeparator() + sj;
 
-            name = CamelHome.CAMEL_JBANG_WORK_DIR + "/log4j2.properties";
+            name = 
CamelHome.getWorkDir().resolve("log4j2.properties").toString();
             Files.writeString(Paths.get(name), content);
             // the categories are part of what the command asks for
             location = Path.of(name).toAbsolutePath().toUri() + "#" + 
content.hashCode();

Reply via email to