diff --git a/test/src/main/java/org/jvnet/hudson/test/ChannelShutdownListener.java b/test/src/main/java/org/jvnet/hudson/test/ChannelShutdownListener.java new file mode 100644 index 0000000000000000000000000000000000000000..935aeca28fdebc4f8823b03a0c1b00dd58310155 --- /dev/null +++ b/test/src/main/java/org/jvnet/hudson/test/ChannelShutdownListener.java @@ -0,0 +1,42 @@ +package org.jvnet.hudson.test; + +import hudson.Extension; +import hudson.model.Computer; +import hudson.model.TaskListener; +import hudson.remoting.Channel; +import hudson.remoting.VirtualChannel; +import hudson.slaves.ComputerListener; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Runs at the end of the test to cleanup any live channels. + * +* @author Kohsuke Kawaguchi +*/ +@Extension +public class ChannelShutdownListener extends ComputerListener implements EndOfTestListener { + /** + * Remember channels that are created, to release them at the end. + */ + private List channels = new ArrayList(); + + @Override + public synchronized void onOnline(Computer c, TaskListener listener) throws IOException, InterruptedException { + VirtualChannel ch = c.getChannel(); + if (ch instanceof Channel) { + channels.add((Channel)ch); + } + } + + @Override + public synchronized void onTearDown() throws Exception { + for (Channel c : channels) + c.close(); + for (Channel c : channels) + c.join(); + channels.clear(); + } +} diff --git a/test/src/main/java/org/jvnet/hudson/test/EndOfTestListener.java b/test/src/main/java/org/jvnet/hudson/test/EndOfTestListener.java new file mode 100644 index 0000000000000000000000000000000000000000..e6d9c143cfd99c3f15a0f99bf8bbe527e517d06f --- /dev/null +++ b/test/src/main/java/org/jvnet/hudson/test/EndOfTestListener.java @@ -0,0 +1,16 @@ +package org.jvnet.hudson.test; + +import hudson.ExtensionPoint; + +/** + * Gets notified before the test completes to perform additional cleanup. + * + * @author Kohsuke Kawaguchi + * @since 1.520 + */ +public interface EndOfTestListener extends ExtensionPoint { + /** + * Called for clean up. + */ + void onTearDown() throws Exception; +} diff --git a/test/src/main/java/org/jvnet/hudson/test/HudsonTestCase.java b/test/src/main/java/org/jvnet/hudson/test/HudsonTestCase.java index de931754e81dd17f85293407615e41ab5892ca1e..013ec8574e8b04d4a8871d1098b83022ee6779d1 100644 --- a/test/src/main/java/org/jvnet/hudson/test/HudsonTestCase.java +++ b/test/src/main/java/org/jvnet/hudson/test/HudsonTestCase.java @@ -57,8 +57,6 @@ import hudson.model.*; import hudson.model.Executor; import hudson.model.Node.Mode; import hudson.model.Queue.Executable; -import hudson.remoting.Channel; -import hudson.remoting.VirtualChannel; import hudson.remoting.Which; import hudson.security.ACL; import hudson.security.AbstractPasswordBasedSecurityRealm; @@ -77,7 +75,6 @@ import hudson.tasks.BuildWrapper; import hudson.tasks.BuildWrapperDescriptor; import hudson.tasks.Builder; import hudson.tasks.Mailer; -import hudson.tasks.Mailer.DescriptorImpl; import hudson.tasks.Maven; import hudson.tasks.Maven.MavenInstallation; import hudson.tasks.Publisher; @@ -177,7 +174,6 @@ import com.gargoylesoftware.htmlunit.DefaultCssErrorHandler; import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.WebRequestSettings; -import com.gargoylesoftware.htmlunit.WebResponse; import com.gargoylesoftware.htmlunit.html.DomNode; import com.gargoylesoftware.htmlunit.html.HtmlButton; import com.gargoylesoftware.htmlunit.html.HtmlElement; @@ -234,11 +230,6 @@ public abstract class HudsonTestCase extends TestCase implements RootAction { */ private List clients = new ArrayList(); - /** - * Remember channels that are created, to release them at the end. - */ - private List channels = new ArrayList(); - /** * JavaScript "debugger" that provides you information about the JavaScript call stack * and the current values of the local variables in those stack frame. @@ -390,6 +381,9 @@ public abstract class HudsonTestCase extends TestCase implements RootAction { @Override protected void tearDown() throws Exception { try { + for (EndOfTestListener tl : jenkins.getExtensionList(EndOfTestListener.class)) + tl.onTearDown(); + if (timeoutTimer!=null) { timeoutTimer.cancel(); timeoutTimer = null; @@ -402,15 +396,6 @@ public abstract class HudsonTestCase extends TestCase implements RootAction { client.closeAllWindows(); } clients.clear(); - - synchronized(channels) { - for (Channel c : channels) - c.close(); - for (Channel c : channels) - c.join(); - channels.clear(); - } - } finally { if (server!=null) server.stop(); @@ -545,22 +530,6 @@ public abstract class HudsonTestCase extends TestCase implements RootAction { return realm; } - @TestExtension - public static class ComputerListenerImpl extends ComputerListener { - @Override - public void onOnline(Computer c, TaskListener listener) throws IOException, InterruptedException { - VirtualChannel ch = c.getChannel(); - if (ch instanceof Channel) - TestEnvironment.get().testCase.addChannel((Channel)ch); - } - } - - private void addChannel(Channel ch) { - synchronized (channels) { - channels.add(ch); - } - } - /** * Returns the older default Maven, while still allowing specification of other bundled Mavens. */ diff --git a/test/src/main/java/org/jvnet/hudson/test/JenkinsRule.java b/test/src/main/java/org/jvnet/hudson/test/JenkinsRule.java index 2f9c76d6a81d32422445ca7e6cfb03c185d5f545..cbd42e1ee4153ac21f263ade43ed859c67dfcdea 100644 --- a/test/src/main/java/org/jvnet/hudson/test/JenkinsRule.java +++ b/test/src/main/java/org/jvnet/hudson/test/JenkinsRule.java @@ -88,13 +88,10 @@ import hudson.model.TaskListener; import hudson.model.UpdateSite; import hudson.model.User; import hudson.model.View; -import hudson.remoting.Channel; -import hudson.remoting.VirtualChannel; import hudson.remoting.Which; import hudson.security.ACL; import hudson.security.AbstractPasswordBasedSecurityRealm; import hudson.security.GroupDetails; -import hudson.security.SecurityRealm; import hudson.security.csrf.CrumbIssuer; import hudson.slaves.CommandLauncher; import hudson.slaves.ComputerConnector; @@ -135,6 +132,7 @@ import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.Statement; +import org.jvnet.hudson.test.recipes.Recipe; import org.jvnet.hudson.test.rhino.JavaScriptDebugger; import org.kohsuke.stapler.ClassDescriptor; import org.kohsuke.stapler.DataBoundConstructor; @@ -173,6 +171,7 @@ import java.lang.management.ThreadInfo; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; @@ -229,8 +228,6 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction { private Description testDescription; - private static JenkinsRule CURRENT = null; - /** * Points to the same object as {@link #jenkins} does. */ @@ -264,11 +261,6 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction { */ private List clients = new ArrayList(); - /** - * Remember channels that are created, to release them at the end. - */ - private List channels = new ArrayList(); - /** * JavaScript "debugger" that provides you information about the JavaScript call stack * and the current values of the local variables in those stack frame. @@ -392,8 +384,11 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction { /** * Override to tear down your specific external resource. */ - protected void after() { + protected void after() throws Exception { try { + for (EndOfTestListener tl : jenkins.getExtensionList(EndOfTestListener.class)) + tl.onTearDown(); + if (timeoutTimer!=null) { timeoutTimer.cancel(); timeoutTimer = null; @@ -411,20 +406,6 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction { } clients.clear(); - for (Channel c : channels) - try { - c.close(); - } catch (IOException e) { - // ignore - } - for (Channel c : channels) - try { - c.join(); - } catch (InterruptedException e) { - // ignore - } - channels.clear(); - } finally { try { server.stop(); @@ -476,7 +457,6 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction { Thread t = Thread.currentThread(); String o = t.getName(); t.setName("Executing "+ testDescription.getDisplayName()); - CURRENT = JenkinsRule.this; before(); try { System.out.println("=== Starting " + testDescription.getDisplayName()); @@ -503,7 +483,6 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction { after(); testDescription = null; t.setName(o); - CURRENT = null; } } }; @@ -615,16 +594,6 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction { return realm; } - @TestExtension - public static class ComputerListenerImpl extends ComputerListener { - @Override - public void onOnline(Computer c, TaskListener listener) throws IOException, InterruptedException { - VirtualChannel ch = c.getChannel(); - if (ch instanceof Channel) - CURRENT.channels.add((Channel)ch); - } - } - /** * Returns the older default Maven, while still allowing specification of other bundled Mavens.