From 1644d1413fcf52e99ea257277d346b06c9835648 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Thu, 12 Jan 2023 18:11:48 +0100 Subject: [PATCH 1/3] Let callers specify some debug options --- .../jvnet/hudson/test/RealJenkinsRule.java | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java b/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java index 87c520229..408f9f27b 100644 --- a/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java +++ b/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java @@ -186,6 +186,11 @@ public final class RealJenkinsRule implements TestRule { private Map loggers = new HashMap<>(); + private int debugPort = 0; + private boolean debugServer = true; + + private boolean debugSuspend; + // TODO may need to be relaxed for Gradle-based plugins private static final Pattern SNAPSHOT_INDEX_JELLY = Pattern.compile("(file:/.+/target)/classes/index.jelly"); @@ -330,6 +335,53 @@ public RealJenkinsRule withHttpListenAddress(String httpListenAddress) { return this; } + /** + * Allows usage of a static debug port instead of a random one. + * + * This allows to use predefined debug configurations in the IDE. + * + * Typical usage is in a base test class where multiple named controller instances are defined with fixed ports + * + *
+     * public RealJenkinsRule cc1 = new RealJenkinsRule().withName("cc1").withDebugPort(4001).withDebugServer(false);
+     *
+     * public RealJenkinsRule cc2 = new RealJenkinsRule().withName("cc2").withDebugPort(4002).withDebugServer(false);
+     * 
+ * + * Then have debug configurations in the IDE set for ports + * - 5005 (test VM) - debugger mode "attach to remote vm" + * - 4001 (cc1) - debugger mode "listen to remote vm" + * - 4002 (cc2) - debugger mode "listen to remote vm" + * + * This allows for debugger to reconnect in scenarios where restarts of controllers are involved. + * + * @param debugPort + */ + public RealJenkinsRule withDebugPort(int debugPort) { + this.debugPort = debugPort; + return this; + } + /** + * Allows to use debug in server mode or client mode. Client mode is friendlier to controller restarts. + * + * @see #withDebugPort(int). + * + * @param debugServer true to use server=y, false to use server=n + */ + public RealJenkinsRule withDebugServer(boolean debugServer) { + this.debugServer = debugServer; + return this; + } + + /** + * Whether to suspend the controller VM on startup until debugger is connected. Defaults to false. + * @param debugSuspend true to suspend the controller VM on startup until debugger is connected. + */ + public RealJenkinsRule withDebugSuspend(boolean debugSuspend) { + this.debugSuspend = debugSuspend; + return this; + } + /** * The intended use case for this is to use the plugins bundled into the war {@link RealJenkinsRule#withWar(File)} * instead of the plugins in the pom. A typical scenario for this feature is a test which does not live inside a @@ -562,7 +614,10 @@ public void startJenkins() throws Throwable { portFile = new File(home, "jenkins-port.txt"); argv.add("-Dwinstone.portFileName=" + portFile); if (new DisableOnDebug(null).isDebugging()) { - argv.add("-agentlib:jdwp=transport=dt_socket,server=y"); + argv.add("-agentlib:jdwp=transport=dt_socket" + + ",server=" + (debugServer ? "y" : "n") + + ",suspend=" + (debugSuspend ? "y" : "n") + + (debugPort > 0 ? ",address=" + httpListenAddress + ":" + debugPort : "")); } argv.addAll(javaOptions); From 42cf870ad4f9a2e002e86f87a3aa187e6714e53b Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Fri, 13 Jan 2023 09:00:35 +0100 Subject: [PATCH 2/3] Fix reviews; add validation for debugPort value --- .../jvnet/hudson/test/RealJenkinsRule.java | 19 +++++++++++-------- .../hudson/test/RealJenkinsRuleTest.java | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java b/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java index 408f9f27b..2f5aad829 100644 --- a/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java +++ b/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java @@ -188,7 +188,6 @@ public final class RealJenkinsRule implements TestRule { private int debugPort = 0; private boolean debugServer = true; - private boolean debugSuspend; // TODO may need to be relaxed for Gradle-based plugins @@ -337,9 +336,9 @@ public RealJenkinsRule withHttpListenAddress(String httpListenAddress) { /** * Allows usage of a static debug port instead of a random one. - * + *

* This allows to use predefined debug configurations in the IDE. - * + *

* Typical usage is in a base test class where multiple named controller instances are defined with fixed ports * *

@@ -349,15 +348,19 @@ public RealJenkinsRule withHttpListenAddress(String httpListenAddress) {
      * 
* * Then have debug configurations in the IDE set for ports - * - 5005 (test VM) - debugger mode "attach to remote vm" - * - 4001 (cc1) - debugger mode "listen to remote vm" - * - 4002 (cc2) - debugger mode "listen to remote vm" - * + *
    + *
  • 5005 (test VM) - debugger mode "attach to remote vm"
  • + *
  • 4001 (cc1) - debugger mode "listen to remote vm"
  • + *
  • 4002 (cc2) - debugger mode "listen to remote vm"
  • + *
+ *

* This allows for debugger to reconnect in scenarios where restarts of controllers are involved. * - * @param debugPort + * @param debugPort the TCP port to use for debugging this Jenkins instance. Between 0 (random) and 65536 (excluded). */ public RealJenkinsRule withDebugPort(int debugPort) { + if (debugPort < 0) throw new IllegalArgumentException("debugPort must be positive"); + if (!(debugPort < 65536)) throw new IllegalArgumentException("debugPort must be a valid TCP port (< 65536)"); this.debugPort = debugPort; return this; } diff --git a/src/test/java/org/jvnet/hudson/test/RealJenkinsRuleTest.java b/src/test/java/org/jvnet/hudson/test/RealJenkinsRuleTest.java index 4fb38f153..945bf4c7c 100644 --- a/src/test/java/org/jvnet/hudson/test/RealJenkinsRuleTest.java +++ b/src/test/java/org/jvnet/hudson/test/RealJenkinsRuleTest.java @@ -72,7 +72,7 @@ public class RealJenkinsRuleTest { // TODO addPlugins does not currently take effect when used inside test method - @Rule public RealJenkinsRule rr = new RealJenkinsRule().addPlugins("plugins/structs.hpi"); + @Rule public RealJenkinsRule rr = new RealJenkinsRule().addPlugins("plugins/structs.hpi").withDebugPort(4001).withDebugServer(false); @Rule public RealJenkinsRule rrWithFailure = new RealJenkinsRule().addPlugins("plugins/failure.hpi"); @Test public void smokes() throws Throwable { From cc3d386b26893938ac0ae069d618502de3a88b02 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Fri, 13 Jan 2023 07:50:27 -0500 Subject: [PATCH 3/3] Javadoc fix --- src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java b/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java index 2f5aad829..bd4428d17 100644 --- a/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java +++ b/src/main/java/org/jvnet/hudson/test/RealJenkinsRule.java @@ -367,7 +367,7 @@ public RealJenkinsRule withDebugPort(int debugPort) { /** * Allows to use debug in server mode or client mode. Client mode is friendlier to controller restarts. * - * @see #withDebugPort(int). + * @see #withDebugPort(int) * * @param debugServer true to use server=y, false to use server=n */